From 88b576164789391430d779af74ed3a7ee3be87fb Mon Sep 17 00:00:00 2001 From: Likitha Shetty Date: Tue, 25 Feb 2014 18:10:52 +0530 Subject: [PATCH] CLOUDSTACK-6146. [VMware] [ESXi 5.5] Live VM migration of an already migrated VM (with storage) across clusters fails In vCenter 5.5, once a volume is migrated the VMDKs are renamed to match the name of the VM. Update volume path for every volume belonging to the VM to the corresponding new disk filename. Conflicts: plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java plugins/hypervisors/vmware/src/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java --- .../vmware/resource/VmwareResource.java | 25 +++++++++++-- .../motion/VmwareStorageMotionStrategy.java | 36 ++++++++++++------- 2 files changed, 45 insertions(+), 16 deletions(-) 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 3b631ac495b..9e1210515df 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -2988,6 +2988,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa VolumeTO volume; StorageFilerTO filerTo; Set mountedDatastoresAtSource = new HashSet(); + List volumeToList = new ArrayList(); + Map volumeDeviceKey = new HashMap(); Map volToFiler = cmd.getVolumeToFiler(); String tgtHost = cmd.getTargetHost(); @@ -3049,9 +3051,11 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa ".vmdk"); diskLocator = new VirtualMachineRelocateSpecDiskLocator(); diskLocator.setDatastore(morDsAtSource); - diskLocator.setDiskId(getVirtualDiskInfo(vmMo, volume.getPath() + ".vmdk")); + int diskId = getVirtualDiskInfo(vmMo, volume.getPath() + ".vmdk"); + diskLocator.setDiskId(diskId); diskLocators.add(diskLocator); + volumeDeviceKey.put(volume.getId(), diskId); } relocateSpec.getDisk().addAll(diskLocators); @@ -3083,6 +3087,22 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa s_logger.debug("Successfully migrated storage of VM " + vmName + " to target datastore(s)"); } + // Update and return volume path for every disk because that could have changed after migration + for (Entry entry : volToFiler.entrySet()) { + volume = entry.getKey(); + long volumeId = volume.getId(); + VirtualDisk[] disks = vmMo.getAllDiskDevice(); + for (VirtualDisk disk : disks) { + if (volumeDeviceKey.get(volumeId) == disk.getKey()) { + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setId(volumeId); + newVol.setPath(vmMo.getVmdkFileBaseName(disk)); + volumeToList.add(newVol); + break; + } + } + } + // Change host ManagedObjectReference morPool = tgtHyperHost.getHyperHostOwnerResourcePool(); if (!vmMo.migrate(morPool, tgtHyperHost.getMor())) { @@ -3092,7 +3112,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } state = State.Stopping; - List volumeToList = null; return new MigrateWithStorageAnswer(cmd, volumeToList); } catch (Throwable e) { if (e instanceof RemoteException) { @@ -3198,7 +3217,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } private int getVirtualDiskInfo(VirtualMachineMO vmMo, String srcDiskName) throws Exception { - Pair deviceInfo = vmMo.getDiskDevice(srcDiskName, false); + Pair deviceInfo = vmMo.getDiskDevice(srcDiskName, true); if (deviceInfo == null) { throw new Exception("No such disk device: " + srcDiskName); } diff --git a/plugins/hypervisors/vmware/src/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java b/plugins/hypervisors/vmware/src/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java index e1527f96b15..09f10688a68 100644 --- a/plugins/hypervisors/vmware/src/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java +++ b/plugins/hypervisors/vmware/src/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java @@ -20,6 +20,7 @@ package org.apache.cloudstack.storage.motion; import java.util.HashMap; +import java.util.List; import java.util.Map; import javax.inject.Inject; @@ -36,6 +37,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.to.VolumeObjectTO; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; @@ -145,7 +147,7 @@ public class VmwareStorageMotionStrategy implements DataMotionStrategy { throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost + ". " + migrateWithStorageAnswer.getDetails()); } else { // Update the volume details after migration. - updateVolumesAfterMigration(volumeToPool); + updateVolumesAfterMigration(volumeToPool, migrateWithStorageAnswer.getVolumeTos()); } s_logger.debug("Storage migration of VM " + vm.getInstanceName() + " completed successfully. Migrated to host " + destHost.getName()); @@ -179,7 +181,7 @@ public class VmwareStorageMotionStrategy implements DataMotionStrategy { throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost + ". " + answer.getDetails()); } else { // Update the volume details after migration. - updateVolumesAfterMigration(volumeToPool); + updateVolumesAfterMigration(volumeToPool, answer.getVolumeTos()); } return answer; @@ -189,20 +191,28 @@ public class VmwareStorageMotionStrategy implements DataMotionStrategy { } } - private void updateVolumesAfterMigration(Map volumeToPool) { + private void updateVolumesAfterMigration(Map volumeToPool, List volumeTos) { for (Map.Entry entry : volumeToPool.entrySet()) { + boolean updated = false; VolumeInfo volume = entry.getKey(); StoragePool pool = (StoragePool)entry.getValue(); - - VolumeVO volumeVO = volDao.findById(volume.getId()); - Long oldPoolId = volumeVO.getPoolId(); - volumeVO.setLastPoolId(oldPoolId); - volumeVO.setFolder(pool.getPath()); - volumeVO.setPodId(pool.getPodId()); - volumeVO.setPoolId(pool.getId()); - - volDao.update(volume.getId(), volumeVO); - s_logger.debug("Volume path was successfully updated for volume " + volume.getName() + " after it was migrated."); + for (VolumeObjectTO volumeTo : volumeTos) { + if (volume.getId() == volumeTo.getId()) { + VolumeVO volumeVO = volDao.findById(volume.getId()); + Long oldPoolId = volumeVO.getPoolId(); + volumeVO.setPath(volumeTo.getPath()); + volumeVO.setLastPoolId(oldPoolId); + volumeVO.setFolder(pool.getPath()); + volumeVO.setPodId(pool.getPodId()); + volumeVO.setPoolId(pool.getId()); + volDao.update(volume.getId(), volumeVO); + updated = true; + break; + } + } + if (!updated) { + s_logger.error("Volume path wasn't updated for volume " + volume + " after it was migrated."); + } } } }