@@ -2474,6 +2474,26 @@ private boolean needMoveVolume(VolumeVO existingVolume, VolumeInfo newVolume) {
2474
2474
return !storeForExistingStoreScope .isSameScope (storeForNewStoreScope );
2475
2475
}
2476
2476
2477
+ private synchronized void checkAndSetAttaching (Long volumeId , Long hostId ) {
2478
+ VolumeInfo volumeToAttach = volFactory .getVolume (volumeId );
2479
+
2480
+ if (volumeToAttach .isAttachedVM ()) {
2481
+ throw new CloudRuntimeException ("volume: " + volumeToAttach .getName () + " is already attached to a VM: " + volumeToAttach .getAttachedVmName ());
2482
+ }
2483
+ if (volumeToAttach .getState ().equals (Volume .State .Ready )) {
2484
+ volumeToAttach .stateTransit (Volume .Event .AttachRequested );
2485
+ } else {
2486
+ String error = null ;
2487
+ if (hostId == null ) {
2488
+ error = "Please try attach operation after starting VM once" ;
2489
+ } else {
2490
+ error = "Volume: " + volumeToAttach .getName () + " is in " + volumeToAttach .getState () + ". It should be in Ready state" ;
2491
+ }
2492
+ s_logger .error (error );
2493
+ throw new CloudRuntimeException (error );
2494
+ }
2495
+ }
2496
+
2477
2497
private VolumeVO sendAttachVolumeCommand (UserVmVO vm , VolumeVO volumeToAttach , Long deviceId ) {
2478
2498
String errorMsg = "Failed to attach volume " + volumeToAttach .getName () + " to VM " + vm .getHostName ();
2479
2499
boolean sendCommand = vm .getState () == State .Running ;
@@ -2504,112 +2524,128 @@ private VolumeVO sendAttachVolumeCommand(UserVmVO vm, VolumeVO volumeToAttach, L
2504
2524
// volumeToAttachStoragePool should be null if the VM we are attaching the disk to has never been started before
2505
2525
DataStore dataStore = volumeToAttachStoragePool != null ? dataStoreMgr .getDataStore (volumeToAttachStoragePool .getId (), DataStoreRole .Primary ) : null ;
2506
2526
2507
- // if we don't have a host, the VM we are attaching the disk to has never been started before
2508
- if (host != null ) {
2509
- try {
2510
- volService .grantAccess (volFactory .getVolume (volumeToAttach .getId ()), host , dataStore );
2511
- }
2512
- catch (Exception e ) {
2513
- volService .revokeAccess (volFactory .getVolume (volumeToAttach .getId ()), host , dataStore );
2527
+ checkAndSetAttaching (volumeToAttach .getId (), hostId );
2528
+
2529
+ boolean attached = false ;
2530
+ try {
2531
+ // if we don't have a host, the VM we are attaching the disk to has never been started before
2532
+ if (host != null ) {
2533
+ try {
2534
+ volService .grantAccess (volFactory .getVolume (volumeToAttach .getId ()), host , dataStore );
2535
+ }
2536
+ catch (Exception e ) {
2537
+ volService .revokeAccess (volFactory .getVolume (volumeToAttach .getId ()), host , dataStore );
2514
2538
2515
- throw new CloudRuntimeException (e .getMessage ());
2539
+ throw new CloudRuntimeException (e .getMessage ());
2540
+ }
2516
2541
}
2517
- }
2518
2542
2519
- if (sendCommand ) {
2520
- if (host != null && host .getHypervisorType () == HypervisorType .KVM &&
2521
- volumeToAttachStoragePool .isManaged () &&
2522
- volumeToAttach .getPath () == null ) {
2523
- volumeToAttach .setPath (volumeToAttach .get_iScsiName ());
2543
+ if (sendCommand ) {
2544
+ if (host != null && host .getHypervisorType () == HypervisorType .KVM &&
2545
+ volumeToAttachStoragePool .isManaged () &&
2546
+ volumeToAttach .getPath () == null ) {
2547
+ volumeToAttach .setPath (volumeToAttach .get_iScsiName ());
2524
2548
2525
- _volsDao .update (volumeToAttach .getId (), volumeToAttach );
2526
- }
2549
+ _volsDao .update (volumeToAttach .getId (), volumeToAttach );
2550
+ }
2527
2551
2528
- DataTO volTO = volFactory .getVolume (volumeToAttach .getId ()).getTO ();
2552
+ DataTO volTO = volFactory .getVolume (volumeToAttach .getId ()).getTO ();
2529
2553
2530
- deviceId = getDeviceId (vm , deviceId );
2554
+ deviceId = getDeviceId (vm , deviceId );
2531
2555
2532
- DiskTO disk = storageMgr .getDiskWithThrottling (volTO , volumeToAttach .getVolumeType (), deviceId , volumeToAttach .getPath (),
2533
- vm .getServiceOfferingId (), volumeToAttach .getDiskOfferingId ());
2556
+ DiskTO disk = storageMgr .getDiskWithThrottling (volTO , volumeToAttach .getVolumeType (), deviceId , volumeToAttach .getPath (),
2557
+ vm .getServiceOfferingId (), volumeToAttach .getDiskOfferingId ());
2534
2558
2535
- AttachCommand cmd = new AttachCommand (disk , vm .getInstanceName ());
2559
+ AttachCommand cmd = new AttachCommand (disk , vm .getInstanceName ());
2536
2560
2537
- ChapInfo chapInfo = volService .getChapInfo (volFactory .getVolume (volumeToAttach .getId ()), dataStore );
2561
+ ChapInfo chapInfo = volService .getChapInfo (volFactory .getVolume (volumeToAttach .getId ()), dataStore );
2538
2562
2539
- Map <String , String > details = new HashMap <String , String >();
2563
+ Map <String , String > details = new HashMap <String , String >();
2540
2564
2541
- disk .setDetails (details );
2565
+ disk .setDetails (details );
2542
2566
2543
- details .put (DiskTO .MANAGED , String .valueOf (volumeToAttachStoragePool .isManaged ()));
2544
- details .put (DiskTO .STORAGE_HOST , volumeToAttachStoragePool .getHostAddress ());
2545
- details .put (DiskTO .STORAGE_PORT , String .valueOf (volumeToAttachStoragePool .getPort ()));
2546
- details .put (DiskTO .VOLUME_SIZE , String .valueOf (volumeToAttach .getSize ()));
2547
- details .put (DiskTO .IQN , volumeToAttach .get_iScsiName ());
2548
- details .put (DiskTO .MOUNT_POINT , volumeToAttach .get_iScsiName ());
2549
- details .put (DiskTO .PROTOCOL_TYPE , (volumeToAttach .getPoolType () != null ) ? volumeToAttach .getPoolType ().toString () : null );
2567
+ details .put (DiskTO .MANAGED , String .valueOf (volumeToAttachStoragePool .isManaged ()));
2568
+ details .put (DiskTO .STORAGE_HOST , volumeToAttachStoragePool .getHostAddress ());
2569
+ details .put (DiskTO .STORAGE_PORT , String .valueOf (volumeToAttachStoragePool .getPort ()));
2570
+ details .put (DiskTO .VOLUME_SIZE , String .valueOf (volumeToAttach .getSize ()));
2571
+ details .put (DiskTO .IQN , volumeToAttach .get_iScsiName ());
2572
+ details .put (DiskTO .MOUNT_POINT , volumeToAttach .get_iScsiName ());
2573
+ details .put (DiskTO .PROTOCOL_TYPE , (volumeToAttach .getPoolType () != null ) ? volumeToAttach .getPoolType ().toString () : null );
2550
2574
2551
- if (chapInfo != null ) {
2552
- details .put (DiskTO .CHAP_INITIATOR_USERNAME , chapInfo .getInitiatorUsername ());
2553
- details .put (DiskTO .CHAP_INITIATOR_SECRET , chapInfo .getInitiatorSecret ());
2554
- details .put (DiskTO .CHAP_TARGET_USERNAME , chapInfo .getTargetUsername ());
2555
- details .put (DiskTO .CHAP_TARGET_SECRET , chapInfo .getTargetSecret ());
2556
- }
2557
- _userVmDao .loadDetails (vm );
2558
- Map <String , String > controllerInfo = new HashMap <String , String >();
2559
- controllerInfo .put (VmDetailConstants .ROOT_DISK_CONTROLLER , vm .getDetail (VmDetailConstants .ROOT_DISK_CONTROLLER ));
2560
- controllerInfo .put (VmDetailConstants .DATA_DISK_CONTROLLER , vm .getDetail (VmDetailConstants .DATA_DISK_CONTROLLER ));
2561
- cmd .setControllerInfo (controllerInfo );
2562
- s_logger .debug ("Attach volume id:" + volumeToAttach .getId () + " on VM id:" + vm .getId () + " has controller info:" + controllerInfo );
2575
+ if (chapInfo != null ) {
2576
+ details .put (DiskTO .CHAP_INITIATOR_USERNAME , chapInfo .getInitiatorUsername ());
2577
+ details .put (DiskTO .CHAP_INITIATOR_SECRET , chapInfo .getInitiatorSecret ());
2578
+ details .put (DiskTO .CHAP_TARGET_USERNAME , chapInfo .getTargetUsername ());
2579
+ details .put (DiskTO .CHAP_TARGET_SECRET , chapInfo .getTargetSecret ());
2580
+ }
2581
+ _userVmDao .loadDetails (vm );
2582
+ Map <String , String > controllerInfo = new HashMap <String , String >();
2583
+ controllerInfo .put (VmDetailConstants .ROOT_DISK_CONTROLLER , vm .getDetail (VmDetailConstants .ROOT_DISK_CONTROLLER ));
2584
+ controllerInfo .put (VmDetailConstants .DATA_DISK_CONTROLLER , vm .getDetail (VmDetailConstants .DATA_DISK_CONTROLLER ));
2585
+ cmd .setControllerInfo (controllerInfo );
2586
+ s_logger .debug ("Attach volume id:" + volumeToAttach .getId () + " on VM id:" + vm .getId () + " has controller info:" + controllerInfo );
2563
2587
2564
- try {
2565
- answer = (AttachAnswer )_agentMgr .send (hostId , cmd );
2566
- } catch (Exception e ) {
2567
- if (host !=null ) {
2568
- volService .revokeAccess (volFactory .getVolume (volumeToAttach .getId ()), host , dataStore );
2588
+ try {
2589
+ answer = (AttachAnswer )_agentMgr .send (hostId , cmd );
2590
+ } catch (Exception e ) {
2591
+ if (host !=null ) {
2592
+ volService .revokeAccess (volFactory .getVolume (volumeToAttach .getId ()), host , dataStore );
2593
+ }
2594
+ throw new CloudRuntimeException (errorMsg + " due to: " + e .getMessage ());
2569
2595
}
2570
- throw new CloudRuntimeException (errorMsg + " due to: " + e .getMessage ());
2571
2596
}
2572
- }
2573
2597
2574
- if (!sendCommand || (answer != null && answer .getResult ())) {
2575
- // Mark the volume as attached
2576
- if (sendCommand ) {
2577
- DiskTO disk = answer .getDisk ();
2578
- _volsDao .attachVolume (volumeToAttach .getId (), vm .getId (), disk .getDiskSeq ());
2598
+ if (!sendCommand || (answer != null && answer .getResult ())) {
2599
+ // Mark the volume as attached
2600
+ if (sendCommand ) {
2601
+ DiskTO disk = answer .getDisk ();
2602
+ _volsDao .attachVolume (volumeToAttach .getId (), vm .getId (), disk .getDiskSeq ());
2579
2603
2580
- volumeToAttach = _volsDao .findById (volumeToAttach .getId ());
2604
+ volumeToAttach = _volsDao .findById (volumeToAttach .getId ());
2581
2605
2582
- if (volumeToAttachStoragePool .isManaged () && volumeToAttach .getPath () == null ) {
2583
- volumeToAttach .setPath (answer .getDisk ().getPath ());
2606
+ if (volumeToAttachStoragePool .isManaged () && volumeToAttach .getPath () == null ) {
2607
+ volumeToAttach .setPath (answer .getDisk ().getPath ());
2584
2608
2585
- _volsDao .update (volumeToAttach .getId (), volumeToAttach );
2586
- }
2587
- } else {
2588
- deviceId = getDeviceId (vm , deviceId );
2609
+ _volsDao .update (volumeToAttach .getId (), volumeToAttach );
2610
+ }
2611
+ } else {
2612
+ deviceId = getDeviceId (vm , deviceId );
2589
2613
2590
- _volsDao .attachVolume (volumeToAttach .getId (), vm .getId (), deviceId );
2591
- }
2614
+ _volsDao .attachVolume (volumeToAttach .getId (), vm .getId (), deviceId );
2615
+ }
2592
2616
2593
- // insert record for disk I/O statistics
2594
- VmDiskStatisticsVO diskstats = _vmDiskStatsDao .findBy (vm .getAccountId (), vm .getDataCenterId (), vm .getId (), volumeToAttach .getId ());
2595
- if (diskstats == null ) {
2596
- diskstats = new VmDiskStatisticsVO (vm .getAccountId (), vm .getDataCenterId (), vm .getId (), volumeToAttach .getId ());
2597
- _vmDiskStatsDao .persist (diskstats );
2598
- }
2617
+ // insert record for disk I/O statistics
2618
+ VmDiskStatisticsVO diskstats = _vmDiskStatsDao .findBy (vm .getAccountId (), vm .getDataCenterId (), vm .getId (), volumeToAttach .getId ());
2619
+ if (diskstats == null ) {
2620
+ diskstats = new VmDiskStatisticsVO (vm .getAccountId (), vm .getDataCenterId (), vm .getId (), volumeToAttach .getId ());
2621
+ _vmDiskStatsDao .persist (diskstats );
2622
+ }
2599
2623
2600
- return _volsDao .findById (volumeToAttach .getId ());
2601
- } else {
2602
- if (answer != null ) {
2603
- String details = answer .getDetails ();
2604
- if (details != null && !details .isEmpty ()) {
2605
- errorMsg += "; " + details ;
2624
+ attached = true ;
2625
+ } else {
2626
+ if (answer != null ) {
2627
+ String details = answer .getDetails ();
2628
+ if (details != null && !details .isEmpty ()) {
2629
+ errorMsg += "; " + details ;
2630
+ }
2631
+ }
2632
+ if (host != null ) {
2633
+ volService .revokeAccess (volFactory .getVolume (volumeToAttach .getId ()), host , dataStore );
2606
2634
}
2635
+ throw new CloudRuntimeException (errorMsg );
2607
2636
}
2608
- if (host != null ) {
2609
- volService .revokeAccess (volFactory .getVolume (volumeToAttach .getId ()), host , dataStore );
2637
+ } finally {
2638
+ Volume .Event ev = Volume .Event .OperationFailed ;
2639
+ VolumeInfo volInfo = volFactory .getVolume (volumeToAttach .getId ());
2640
+ if (attached ) {
2641
+ ev = Volume .Event .OperationSucceeded ;
2642
+ s_logger .debug ("Volume: " + volInfo .getName () + " successfully attached to VM: " + volInfo .getAttachedVmName ());
2643
+ } else {
2644
+ s_logger .debug ("Volume: " + volInfo .getName () + " failed to attach to VM: " + volInfo .getAttachedVmName ());
2610
2645
}
2611
- throw new CloudRuntimeException ( errorMsg );
2646
+ volInfo . stateTransit ( ev );
2612
2647
}
2648
+ return _volsDao .findById (volumeToAttach .getId ());
2613
2649
}
2614
2650
2615
2651
private int getMaxDataVolumesSupported (UserVmVO vm ) {
0 commit comments