From 32701f027a9bafca154af7eec7677e7557c911a2 Mon Sep 17 00:00:00 2001 From: Devdeep Singh Date: Fri, 9 Aug 2013 12:11:51 +0530 Subject: [PATCH] CLOUDSTACK-2670. Migrate volume doesn't allow migration of volumes of a stopped vm. The findStoragePoolsForMigration and migrateVolume api were explicitly blocking moving a volume if the instance to which it was attached was stopped. Updated the check for the same. --- .../cloud/server/ManagementServerImpl.java | 145 ++++++++++-------- .../com/cloud/storage/VolumeManagerImpl.java | 6 - 2 files changed, 77 insertions(+), 74 deletions(-) diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 67496de3e4b..cdf7b6fab49 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -1244,18 +1244,6 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe // Volume must be attached to an instance for live migration. List allPools = new ArrayList(); List suitablePools = new ArrayList(); - Long instanceId = volume.getInstanceId(); - VMInstanceVO vm = null; - if (instanceId != null) { - vm = _vmInstanceDao.findById(instanceId); - } - - // Check that the VM is in correct state. - if (vm == null || vm.getState() != State.Running) { - s_logger.info("Volume " + volume + " isn't attached to any running vm. Only volumes attached to a running" + - " VM can be migrated."); - return new Pair, List>(allPools, suitablePools); - } // Volume must be in Ready state to be migrated. if (!Volume.State.Ready.equals(volume.getState())) { @@ -1268,70 +1256,91 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe return new Pair, List>(allPools, suitablePools); } - // Check if the underlying hypervisor supports storage motion. - boolean storageMotionSupported = false; - Long hostId = vm.getHostId(); - if (hostId != null) { - HostVO host = _hostDao.findById(hostId); - HypervisorCapabilitiesVO capabilities = null; - if (host != null) { - capabilities = _hypervisorCapabilitiesDao.findByHypervisorTypeAndVersion(host.getHypervisorType(), - host.getHypervisorVersion()); - } else { - s_logger.error("Details of the host on which the vm " + vm + ", to which volume "+ volume + " is " - + "attached, couldn't be retrieved."); - } - - if (capabilities != null) { - storageMotionSupported = capabilities.isStorageMotionSupported(); - } else { - s_logger.error("Capabilities for host " + host + " couldn't be retrieved."); - } + Long instanceId = volume.getInstanceId(); + VMInstanceVO vm = null; + if (instanceId != null) { + vm = _vmInstanceDao.findById(instanceId); } - if (storageMotionSupported) { - // Source pool of the volume. - StoragePoolVO srcVolumePool = _poolDao.findById(volume.getPoolId()); + if (vm == null) { + s_logger.info("Volume " + volume + " isn't attached to any vm. Looking for storage pools in the " + + "zone to which this volumes can be migrated."); + } else if (vm.getState() != State.Running) { + s_logger.info("Volume " + volume + " isn't attached to any running vm. Looking for storage pools in the " + + "cluster to which this volumes can be migrated."); + } else { + s_logger.info("Volume " + volume + " is attached to any running vm. Looking for storage pools in the " + + "cluster to which this volumes can be migrated."); + boolean storageMotionSupported = false; + // Check if the underlying hypervisor supports storage motion. + Long hostId = vm.getHostId(); + if (hostId != null) { + HostVO host = _hostDao.findById(hostId); + HypervisorCapabilitiesVO capabilities = null; + if (host != null) { + capabilities = _hypervisorCapabilitiesDao.findByHypervisorTypeAndVersion(host.getHypervisorType(), + host.getHypervisorVersion()); + } else { + s_logger.error("Details of the host on which the vm " + vm + ", to which volume "+ volume + " is " + + "attached, couldn't be retrieved."); + } - // Get all the pools available. Only shared pools are considered because only a volume on a shared pools - // can be live migrated while the virtual machine stays on the same host. - List storagePools = null; - if (srcVolumePool.getClusterId() == null) { - storagePools = _poolDao.findZoneWideStoragePoolsByTags(volume.getDataCenterId(), null); - } else { - storagePools = _poolDao.findPoolsByTags(volume.getDataCenterId(), srcVolumePool.getPodId(), srcVolumePool.getClusterId(), null); - } - - storagePools.remove(srcVolumePool); - for (StoragePoolVO pool : storagePools) { - if (pool.isShared()) { - allPools.add((StoragePool)dataStoreMgr.getPrimaryDataStore(pool.getId())); + if (capabilities != null) { + storageMotionSupported = capabilities.isStorageMotionSupported(); + } else { + s_logger.error("Capabilities for host " + host + " couldn't be retrieved."); } } - // Get all the suitable pools. - // Exclude the current pool from the list of pools to which the volume can be migrated. - ExcludeList avoid = new ExcludeList(); - avoid.addPool(srcVolumePool.getId()); - - // Volume stays in the same cluster after migration. - DataCenterDeployment plan = new DataCenterDeployment(volume.getDataCenterId(), srcVolumePool.getPodId(), - srcVolumePool.getClusterId(), null, null, null); - VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); - - DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId()); - DiskProfile diskProfile = new DiskProfile(volume, diskOffering, profile.getHypervisorType()); - - // Call the storage pool allocator to find the list of storage pools. - for (StoragePoolAllocator allocator : _storagePoolAllocators) { - List pools = allocator.allocateToPool(diskProfile, profile, plan, avoid, - StoragePoolAllocator.RETURN_UPTO_ALL); - if (pools != null && !pools.isEmpty()) { - suitablePools.addAll(pools); - break; - } + if (!storageMotionSupported) { + s_logger.info("Volume " + volume + " is attached to a running vm and the hypervisor doesn't support" + + " storage motion."); + return new Pair, List>(allPools, suitablePools); } } + + // Source pool of the volume. + StoragePoolVO srcVolumePool = _poolDao.findById(volume.getPoolId()); + // Get all the pools available. Only shared pools are considered because only a volume on a shared pools + // can be live migrated while the virtual machine stays on the same host. + List storagePools = null; + if (srcVolumePool.getClusterId() == null) { + storagePools = _poolDao.findZoneWideStoragePoolsByTags(volume.getDataCenterId(), null); + } else { + storagePools = _poolDao.findPoolsByTags(volume.getDataCenterId(), srcVolumePool.getPodId(), + srcVolumePool.getClusterId(), null); + } + + storagePools.remove(srcVolumePool); + for (StoragePoolVO pool : storagePools) { + if (pool.isShared()) { + allPools.add((StoragePool)dataStoreMgr.getPrimaryDataStore(pool.getId())); + } + } + + // Get all the suitable pools. + // Exclude the current pool from the list of pools to which the volume can be migrated. + ExcludeList avoid = new ExcludeList(); + avoid.addPool(srcVolumePool.getId()); + + // Volume stays in the same cluster after migration. + DataCenterDeployment plan = new DataCenterDeployment(volume.getDataCenterId(), srcVolumePool.getPodId(), + srcVolumePool.getClusterId(), null, null, null); + VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); + + DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId()); + DiskProfile diskProfile = new DiskProfile(volume, diskOffering, profile.getHypervisorType()); + + // Call the storage pool allocator to find the list of storage pools. + for (StoragePoolAllocator allocator : _storagePoolAllocators) { + List pools = allocator.allocateToPool(diskProfile, profile, plan, avoid, + StoragePoolAllocator.RETURN_UPTO_ALL); + if (pools != null && !pools.isEmpty()) { + suitablePools.addAll(pools); + break; + } + } + return new Pair, List>(allPools, suitablePools); } diff --git a/server/src/com/cloud/storage/VolumeManagerImpl.java b/server/src/com/cloud/storage/VolumeManagerImpl.java index 5cf7b8dc5dd..0c1ae228d1c 100644 --- a/server/src/com/cloud/storage/VolumeManagerImpl.java +++ b/server/src/com/cloud/storage/VolumeManagerImpl.java @@ -2166,12 +2166,6 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { } } - // If the disk is not attached to any VM then it can be moved. Otherwise, it needs to be attached to a vm - // running on a hypervisor that supports storage motion so that it be be migrated. - if (instanceId != null && !liveMigrateVolume) { - throw new InvalidParameterValueException("Volume needs to be detached from VM"); - } - if (liveMigrateVolume && !cmd.isLiveMigrate()) { throw new InvalidParameterValueException("The volume " + vol + "is attached to a vm and for migrating it " + "the parameter livemigrate should be specified");