diff --git a/core/src/com/cloud/agent/api/storage/MigrateVolumeCommand.java b/core/src/com/cloud/agent/api/storage/MigrateVolumeCommand.java index e5ba2117810..b409944b77f 100644 --- a/core/src/com/cloud/agent/api/storage/MigrateVolumeCommand.java +++ b/core/src/com/cloud/agent/api/storage/MigrateVolumeCommand.java @@ -22,6 +22,7 @@ package com.cloud.agent.api.storage; import com.cloud.agent.api.Command; import com.cloud.agent.api.to.StorageFilerTO; import com.cloud.storage.StoragePool; +import com.cloud.storage.Volume; public class MigrateVolumeCommand extends Command { @@ -29,6 +30,7 @@ public class MigrateVolumeCommand extends Command { String volumePath; StorageFilerTO pool; String attachedVmName; + Volume.Type volumeType; public MigrateVolumeCommand(long volumeId, String volumePath, StoragePool pool, int timeout) { this.volumeId = volumeId; @@ -37,11 +39,12 @@ public class MigrateVolumeCommand extends Command { this.setWait(timeout); } - public MigrateVolumeCommand(long volumeId, String volumePath, StoragePool pool, String attachedVmName, int timeout) { + public MigrateVolumeCommand(long volumeId, String volumePath, StoragePool pool, String attachedVmName, Volume.Type volumeType, int timeout) { this.volumeId = volumeId; this.volumePath = volumePath; this.pool = new StorageFilerTO(pool); this.attachedVmName = attachedVmName; + this.volumeType = volumeType; this.setWait(timeout); } @@ -65,4 +68,8 @@ public class MigrateVolumeCommand extends Command { public String getAttachedVmName() { return attachedVmName; } + + public Volume.Type getVolumeType() { + return volumeType; + } } \ No newline at end of file diff --git a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java index 17ab00e1e38..84df7ff0046 100644 --- a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java +++ b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java @@ -389,7 +389,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy { VolumeInfo volume = (VolumeInfo)srcData; StoragePool destPool = (StoragePool)dataStoreMgr.getDataStore(destData.getDataStore().getId(), DataStoreRole.Primary); - MigrateVolumeCommand command = new MigrateVolumeCommand(volume.getId(), volume.getPath(), destPool, volume.getAttachedVmName(), waitInterval); + MigrateVolumeCommand command = new MigrateVolumeCommand(volume.getId(), volume.getPath(), destPool, volume.getAttachedVmName(), volume.getVolumeType(), waitInterval); EndPoint ep = selector.select(srcData, StorageAction.MIGRATEVOLUME); Answer answer = null; if (ep == null) { diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 0d37f51e0f5..f90a666bf8c 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -3023,7 +3023,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa List diskLocators = new ArrayList(); VirtualMachineRelocateSpecDiskLocator diskLocator = null; - boolean isFirstDs = true; String tgtDsName = ""; String tgtDsHost; String tgtDsPath; @@ -3112,9 +3111,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa morTgtDatastore = morDsAtSource; } - if (isFirstDs) { + if (volume.getType() == Volume.Type.ROOT) { relocateSpec.setDatastore(morTgtDatastore); - isFirstDs = false; } diskLocator = new VirtualMachineRelocateSpecDiskLocator(); diskLocator.setDatastore(morTgtDatastore); @@ -3124,6 +3122,18 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa diskLocators.add(diskLocator); volumeDeviceKey.put(volume.getId(), diskId); } + // If a target datastore is provided for the VM, then by default all volumes associated with the VM will be migrated to that target datastore. + // Hence set the existing datastore as target datastore for volumes that are not to be migrated. + List> diskDatastores = vmMo.getAllDiskDatastores(); + for (Pair diskDatastore : diskDatastores) { + if (!volumeDeviceKey.containsValue(diskDatastore.first().intValue())) { + diskLocator = new VirtualMachineRelocateSpecDiskLocator(); + diskLocator.setDiskId(diskDatastore.first().intValue()); + diskLocator.setDatastore(diskDatastore.second()); + diskLocators.add(diskLocator); + } + } + relocateSpec.getDisk().addAll(diskLocators); // Prepare network at target before migration @@ -3225,6 +3235,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa private Answer execute(MigrateVolumeCommand cmd) { String volumePath = cmd.getVolumePath(); StorageFilerTO poolTo = cmd.getPool(); + Volume.Type volumeType = cmd.getVolumeType(); if (s_logger.isInfoEnabled()) { s_logger.info("Executing resource MigrateVolumeCommand: " + _gson.toJson(cmd)); @@ -3271,9 +3282,23 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa diskLocator = new VirtualMachineRelocateSpecDiskLocator(); diskLocator.setDatastore(morDs); diskLocator.setDiskId(diskId); - diskLocators.add(diskLocator); - relocateSpec.getDisk().add(diskLocator); + if (cmd.getVolumeType() == Volume.Type.ROOT) { + relocateSpec.setDatastore(morDs); + // If a target datastore is provided for the VM, then by default all volumes associated with the VM will be migrated to that target datastore. + // Hence set the existing datastore as target datastore for volumes that are not to be migrated. + List> diskDatastores = vmMo.getAllDiskDatastores(); + for (Pair diskDatastore : diskDatastores) { + if (diskDatastore.first().intValue() != diskId) { + diskLocator = new VirtualMachineRelocateSpecDiskLocator(); + diskLocator.setDiskId(diskDatastore.first().intValue()); + diskLocator.setDatastore(diskDatastore.second()); + diskLocators.add(diskLocator); + } + } + } + + relocateSpec.getDisk().addAll(diskLocators); // Change datastore if (!vmMo.changeDatastore(relocateSpec)) { @@ -3286,12 +3311,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa // In case of a linked clone VM, if VM's disks are not consolidated, // further volume operations on the ROOT volume such as volume snapshot etc. will result in DB inconsistencies. String apiVersion = HypervisorHostHelper.getVcenterApiVersion(vmMo.getContext()); - if (apiVersion.compareTo("5.0") >= 0) { - if (!vmMo.consolidateVmDisks()) { - s_logger.warn("VM disk consolidation failed after storage migration."); - } else { - s_logger.debug("Successfully consolidated disks of VM " + vmName + "."); - } + if (!vmMo.consolidateVmDisks()) { + s_logger.warn("VM disk consolidation failed after storage migration."); + } else { + s_logger.debug("Successfully consolidated disks of VM " + vmName + "."); } // Update and return volume path because that could have changed after migration diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java index 5f180e1d204..2798d548d71 100644 --- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java +++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java @@ -2069,6 +2069,26 @@ public class VirtualMachineMO extends BaseMO { return builder; } + public List> getAllDiskDatastores() throws Exception { + List> disks = new ArrayList>(); + + List devices = _context.getVimClient().getDynamicProperty(_mor, "config.hardware.device"); + if (devices != null && devices.size() > 0) { + for (VirtualDevice device : devices) { + if (device instanceof VirtualDisk) { + VirtualDeviceBackingInfo backingInfo = ((VirtualDisk)device).getBacking(); + if (backingInfo instanceof VirtualDiskFlatVer2BackingInfo) { + VirtualDiskFlatVer2BackingInfo diskBackingInfo = (VirtualDiskFlatVer2BackingInfo)backingInfo; + disks.add(new Pair(new Integer(device.getKey()), diskBackingInfo.getDatastore())); + } + } + } + } + + return disks; + } + + @Deprecated public List> getDiskDatastorePathChain(VirtualDisk disk, boolean followChain) throws Exception { VirtualDeviceBackingInfo backingInfo = disk.getBacking();