From cd2ea3b84433f5b89a6da3ecb2e6fa15cf069617 Mon Sep 17 00:00:00 2001 From: Likitha Shetty Date: Mon, 12 Aug 2013 15:40:35 +0530 Subject: [PATCH] CLOUDSTACK-4244. Unable to attach a volume to a VM deployed in Stopped (startvm=false) state. While attaching a volume to a VM, create volume on the hypervisor only if the VM has been started on the it. --- .../com/cloud/storage/VolumeManagerImpl.java | 84 ++++++++++++------- 1 file changed, 53 insertions(+), 31 deletions(-) diff --git a/server/src/com/cloud/storage/VolumeManagerImpl.java b/server/src/com/cloud/storage/VolumeManagerImpl.java index f818e406575..5c0ec66bf84 100644 --- a/server/src/com/cloud/storage/VolumeManagerImpl.java +++ b/server/src/com/cloud/storage/VolumeManagerImpl.java @@ -1836,42 +1836,64 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { deviceId = getDeviceId(vmId, deviceId); VolumeInfo volumeOnPrimaryStorage = volume; - if (volume.getState().equals(Volume.State.Allocated) - || volume.getState() == Volume.State.Uploaded) { - try { - volumeOnPrimaryStorage = createVolumeOnPrimaryStorage(vm, rootVolumeOfVm, volume, rootDiskHyperType); - } catch (NoTransitionException e) { - s_logger.debug("Failed to create volume on primary storage", e); - throw new CloudRuntimeException("Failed to create volume on primary storage", e); + + // Check if volume is stored on secondary storage + boolean isVolumeOnSec = false; + VolumeInfo volOnSecondary = volFactory.getVolume(volume.getId(), DataStoreRole.Image); + if (volOnSecondary != null) { + isVolumeOnSec = true; + if(volOnSecondary.getState() != Volume.State.Uploaded) { + throw new InvalidParameterValueException("Volume is not uploaded yet. Please try this operation once the volume is uploaded"); + } + } + + boolean createVolumeOnBackend = true; + if (rootVolumeOfVm.getState() == Volume.State.Allocated) { + createVolumeOnBackend = false; + if(isVolumeOnSec) { + throw new CloudRuntimeException("Cant attach uploaded volume to the vm which is not created. Please start it and then retry"); } } - // reload the volume from db - volumeOnPrimaryStorage = volFactory.getVolume(volumeOnPrimaryStorage.getId()); - boolean moveVolumeNeeded = needMoveVolume(rootVolumeOfVm, volumeOnPrimaryStorage); - - if (moveVolumeNeeded) { - PrimaryDataStoreInfo primaryStore = (PrimaryDataStoreInfo)volumeOnPrimaryStorage.getDataStore(); - if (primaryStore.isLocal()) { - throw new CloudRuntimeException( - "Failed to attach local data volume " - + volume.getName() - + " to VM " - + vm.getDisplayName() - + " as migration of local data volume is not allowed"); + // Create volume on the backend only when VM's root volume is allocated + if (createVolumeOnBackend) { + if (volume.getState().equals(Volume.State.Allocated) + || volume.getState() == Volume.State.Uploaded) { + try { + volumeOnPrimaryStorage = createVolumeOnPrimaryStorage(vm, rootVolumeOfVm, volume, rootDiskHyperType); + } catch (NoTransitionException e) { + s_logger.debug("Failed to create volume on primary storage", e); + throw new CloudRuntimeException("Failed to create volume on primary storage", e); + } } - StoragePoolVO vmRootVolumePool = _storagePoolDao - .findById(rootVolumeOfVm.getPoolId()); - try { - volumeOnPrimaryStorage = moveVolume(volumeOnPrimaryStorage, - vmRootVolumePool.getDataCenterId(), - vmRootVolumePool.getPodId(), - vmRootVolumePool.getClusterId(), - dataDiskHyperType); - } catch (ConcurrentOperationException e) { - s_logger.debug("move volume failed", e); - throw new CloudRuntimeException("move volume failed", e); + // reload the volume from db + volumeOnPrimaryStorage = volFactory.getVolume(volumeOnPrimaryStorage.getId()); + boolean moveVolumeNeeded = needMoveVolume(rootVolumeOfVm, volumeOnPrimaryStorage); + + if (moveVolumeNeeded) { + PrimaryDataStoreInfo primaryStore = (PrimaryDataStoreInfo)volumeOnPrimaryStorage.getDataStore(); + if (primaryStore.isLocal()) { + throw new CloudRuntimeException( + "Failed to attach local data volume " + + volume.getName() + + " to VM " + + vm.getDisplayName() + + " as migration of local data volume is not allowed"); + } + StoragePoolVO vmRootVolumePool = _storagePoolDao + .findById(rootVolumeOfVm.getPoolId()); + + try { + volumeOnPrimaryStorage = moveVolume(volumeOnPrimaryStorage, + vmRootVolumePool.getDataCenterId(), + vmRootVolumePool.getPodId(), + vmRootVolumePool.getClusterId(), + dataDiskHyperType); + } catch (ConcurrentOperationException e) { + s_logger.debug("move volume failed", e); + throw new CloudRuntimeException("move volume failed", e); + } } }