mirror of https://github.com/apache/cloudstack.git
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.
This commit is contained in:
parent
c652ff45df
commit
8cb03ddb23
|
|
@ -4338,6 +4338,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
VolumeTO volume;
|
||||
StorageFilerTO filerTo;
|
||||
Set<String> mountedDatastoresAtSource = new HashSet<String>();
|
||||
List<VolumeObjectTO> volumeToList = new ArrayList<VolumeObjectTO>();
|
||||
Map<Long, Integer> volumeDeviceKey = new HashMap<Long, Integer>();
|
||||
|
||||
Map<VolumeTO, StorageFilerTO> volToFiler = cmd.getVolumeToFiler();
|
||||
String tgtHost = cmd.getTargetHost();
|
||||
|
|
@ -4402,9 +4404,11 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
volume.getPath() + ".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);
|
||||
|
|
@ -4436,6 +4440,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<VolumeTO, StorageFilerTO> 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())) {
|
||||
|
|
@ -4445,7 +4465,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
}
|
||||
|
||||
state = State.Stopping;
|
||||
List<VolumeObjectTO> volumeToList = null;
|
||||
return new MigrateWithStorageAnswer(cmd, volumeToList);
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof RemoteException) {
|
||||
|
|
@ -4552,7 +4571,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
}
|
||||
|
||||
private int getVirtualDiskInfo(VirtualMachineMO vmMo, String srcDiskName) throws Exception {
|
||||
Pair<VirtualDisk, String> deviceInfo = vmMo.getDiskDevice(srcDiskName, false);
|
||||
Pair<VirtualDisk, String> deviceInfo = vmMo.getDiskDevice(srcDiskName, true);
|
||||
if(deviceInfo == null) {
|
||||
throw new Exception("No such disk device: " + srcDiskName);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -33,6 +34,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 org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
|
@ -143,7 +145,7 @@ public class VmwareStorageMotionStrategy implements DataMotionStrategy {
|
|||
". " + 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());
|
||||
|
||||
|
|
@ -178,7 +180,7 @@ public class VmwareStorageMotionStrategy implements DataMotionStrategy {
|
|||
". " + answer.getDetails());
|
||||
} else {
|
||||
// Update the volume details after migration.
|
||||
updateVolumesAfterMigration(volumeToPool);
|
||||
updateVolumesAfterMigration(volumeToPool, answer.getVolumeTos());
|
||||
}
|
||||
|
||||
return answer;
|
||||
|
|
@ -188,20 +190,28 @@ public class VmwareStorageMotionStrategy implements DataMotionStrategy {
|
|||
}
|
||||
}
|
||||
|
||||
private void updateVolumesAfterMigration(Map<VolumeInfo, DataStore> volumeToPool) {
|
||||
private void updateVolumesAfterMigration(Map<VolumeInfo, DataStore> volumeToPool, List<VolumeObjectTO> volumeTos) {
|
||||
for (Map.Entry<VolumeInfo, DataStore> 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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue