@@ -2474,6 +2474,26 @@ private boolean needMoveVolume(VolumeVO existingVolume, VolumeInfo newVolume) {
24742474 return !storeForExistingStoreScope .isSameScope (storeForNewStoreScope );
24752475 }
24762476
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+
24772497 private VolumeVO sendAttachVolumeCommand (UserVmVO vm , VolumeVO volumeToAttach , Long deviceId ) {
24782498 String errorMsg = "Failed to attach volume " + volumeToAttach .getName () + " to VM " + vm .getHostName ();
24792499 boolean sendCommand = vm .getState () == State .Running ;
@@ -2504,112 +2524,128 @@ private VolumeVO sendAttachVolumeCommand(UserVmVO vm, VolumeVO volumeToAttach, L
25042524 // volumeToAttachStoragePool should be null if the VM we are attaching the disk to has never been started before
25052525 DataStore dataStore = volumeToAttachStoragePool != null ? dataStoreMgr .getDataStore (volumeToAttachStoragePool .getId (), DataStoreRole .Primary ) : null ;
25062526
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 );
25142538
2515- throw new CloudRuntimeException (e .getMessage ());
2539+ throw new CloudRuntimeException (e .getMessage ());
2540+ }
25162541 }
2517- }
25182542
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 ());
25242548
2525- _volsDao .update (volumeToAttach .getId (), volumeToAttach );
2526- }
2549+ _volsDao .update (volumeToAttach .getId (), volumeToAttach );
2550+ }
25272551
2528- DataTO volTO = volFactory .getVolume (volumeToAttach .getId ()).getTO ();
2552+ DataTO volTO = volFactory .getVolume (volumeToAttach .getId ()).getTO ();
25292553
2530- deviceId = getDeviceId (vm , deviceId );
2554+ deviceId = getDeviceId (vm , deviceId );
25312555
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 ());
25342558
2535- AttachCommand cmd = new AttachCommand (disk , vm .getInstanceName ());
2559+ AttachCommand cmd = new AttachCommand (disk , vm .getInstanceName ());
25362560
2537- ChapInfo chapInfo = volService .getChapInfo (volFactory .getVolume (volumeToAttach .getId ()), dataStore );
2561+ ChapInfo chapInfo = volService .getChapInfo (volFactory .getVolume (volumeToAttach .getId ()), dataStore );
25382562
2539- Map <String , String > details = new HashMap <String , String >();
2563+ Map <String , String > details = new HashMap <String , String >();
25402564
2541- disk .setDetails (details );
2565+ disk .setDetails (details );
25422566
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 );
25502574
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 );
25632587
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 ());
25692595 }
2570- throw new CloudRuntimeException (errorMsg + " due to: " + e .getMessage ());
25712596 }
2572- }
25732597
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 ());
25792603
2580- volumeToAttach = _volsDao .findById (volumeToAttach .getId ());
2604+ volumeToAttach = _volsDao .findById (volumeToAttach .getId ());
25812605
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 ());
25842608
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 );
25892613
2590- _volsDao .attachVolume (volumeToAttach .getId (), vm .getId (), deviceId );
2591- }
2614+ _volsDao .attachVolume (volumeToAttach .getId (), vm .getId (), deviceId );
2615+ }
25922616
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+ }
25992623
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 );
26062634 }
2635+ throw new CloudRuntimeException (errorMsg );
26072636 }
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 ());
26102645 }
2611- throw new CloudRuntimeException ( errorMsg );
2646+ volInfo . stateTransit ( ev );
26122647 }
2648+ return _volsDao .findById (volumeToAttach .getId ());
26132649 }
26142650
26152651 private int getMaxDataVolumesSupported (UserVmVO vm ) {
0 commit comments