mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
CLOUDSTACK-8319. For both 'MigrateVolume' and 'MigrateVMWithVolumes, ensure VM's vconfiguration files are migrated along with VM's root volume.
This commit is contained in:
parent
adc836cc5e
commit
bdd28a45ed
@ -22,6 +22,7 @@ package com.cloud.agent.api.storage;
|
|||||||
import com.cloud.agent.api.Command;
|
import com.cloud.agent.api.Command;
|
||||||
import com.cloud.agent.api.to.StorageFilerTO;
|
import com.cloud.agent.api.to.StorageFilerTO;
|
||||||
import com.cloud.storage.StoragePool;
|
import com.cloud.storage.StoragePool;
|
||||||
|
import com.cloud.storage.Volume;
|
||||||
|
|
||||||
public class MigrateVolumeCommand extends Command {
|
public class MigrateVolumeCommand extends Command {
|
||||||
|
|
||||||
@ -29,6 +30,7 @@ public class MigrateVolumeCommand extends Command {
|
|||||||
String volumePath;
|
String volumePath;
|
||||||
StorageFilerTO pool;
|
StorageFilerTO pool;
|
||||||
String attachedVmName;
|
String attachedVmName;
|
||||||
|
Volume.Type volumeType;
|
||||||
|
|
||||||
public MigrateVolumeCommand(long volumeId, String volumePath, StoragePool pool, int timeout) {
|
public MigrateVolumeCommand(long volumeId, String volumePath, StoragePool pool, int timeout) {
|
||||||
this.volumeId = volumeId;
|
this.volumeId = volumeId;
|
||||||
@ -37,11 +39,12 @@ public class MigrateVolumeCommand extends Command {
|
|||||||
this.setWait(timeout);
|
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.volumeId = volumeId;
|
||||||
this.volumePath = volumePath;
|
this.volumePath = volumePath;
|
||||||
this.pool = new StorageFilerTO(pool);
|
this.pool = new StorageFilerTO(pool);
|
||||||
this.attachedVmName = attachedVmName;
|
this.attachedVmName = attachedVmName;
|
||||||
|
this.volumeType = volumeType;
|
||||||
this.setWait(timeout);
|
this.setWait(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,4 +68,8 @@ public class MigrateVolumeCommand extends Command {
|
|||||||
public String getAttachedVmName() {
|
public String getAttachedVmName() {
|
||||||
return attachedVmName;
|
return attachedVmName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Volume.Type getVolumeType() {
|
||||||
|
return volumeType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -389,7 +389,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
|
|||||||
|
|
||||||
VolumeInfo volume = (VolumeInfo)srcData;
|
VolumeInfo volume = (VolumeInfo)srcData;
|
||||||
StoragePool destPool = (StoragePool)dataStoreMgr.getDataStore(destData.getDataStore().getId(), DataStoreRole.Primary);
|
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);
|
EndPoint ep = selector.select(srcData, StorageAction.MIGRATEVOLUME);
|
||||||
Answer answer = null;
|
Answer answer = null;
|
||||||
if (ep == null) {
|
if (ep == null) {
|
||||||
|
|||||||
@ -3023,7 +3023,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||||||
List<VirtualMachineRelocateSpecDiskLocator> diskLocators = new ArrayList<VirtualMachineRelocateSpecDiskLocator>();
|
List<VirtualMachineRelocateSpecDiskLocator> diskLocators = new ArrayList<VirtualMachineRelocateSpecDiskLocator>();
|
||||||
VirtualMachineRelocateSpecDiskLocator diskLocator = null;
|
VirtualMachineRelocateSpecDiskLocator diskLocator = null;
|
||||||
|
|
||||||
boolean isFirstDs = true;
|
|
||||||
String tgtDsName = "";
|
String tgtDsName = "";
|
||||||
String tgtDsHost;
|
String tgtDsHost;
|
||||||
String tgtDsPath;
|
String tgtDsPath;
|
||||||
@ -3112,9 +3111,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||||||
morTgtDatastore = morDsAtSource;
|
morTgtDatastore = morDsAtSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isFirstDs) {
|
if (volume.getType() == Volume.Type.ROOT) {
|
||||||
relocateSpec.setDatastore(morTgtDatastore);
|
relocateSpec.setDatastore(morTgtDatastore);
|
||||||
isFirstDs = false;
|
|
||||||
}
|
}
|
||||||
diskLocator = new VirtualMachineRelocateSpecDiskLocator();
|
diskLocator = new VirtualMachineRelocateSpecDiskLocator();
|
||||||
diskLocator.setDatastore(morTgtDatastore);
|
diskLocator.setDatastore(morTgtDatastore);
|
||||||
@ -3124,6 +3122,18 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||||||
diskLocators.add(diskLocator);
|
diskLocators.add(diskLocator);
|
||||||
volumeDeviceKey.put(volume.getId(), diskId);
|
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<Pair<Integer, ManagedObjectReference>> diskDatastores = vmMo.getAllDiskDatastores();
|
||||||
|
for (Pair<Integer, ManagedObjectReference> 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);
|
relocateSpec.getDisk().addAll(diskLocators);
|
||||||
|
|
||||||
// Prepare network at target before migration
|
// Prepare network at target before migration
|
||||||
@ -3225,6 +3235,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||||||
private Answer execute(MigrateVolumeCommand cmd) {
|
private Answer execute(MigrateVolumeCommand cmd) {
|
||||||
String volumePath = cmd.getVolumePath();
|
String volumePath = cmd.getVolumePath();
|
||||||
StorageFilerTO poolTo = cmd.getPool();
|
StorageFilerTO poolTo = cmd.getPool();
|
||||||
|
Volume.Type volumeType = cmd.getVolumeType();
|
||||||
|
|
||||||
if (s_logger.isInfoEnabled()) {
|
if (s_logger.isInfoEnabled()) {
|
||||||
s_logger.info("Executing resource MigrateVolumeCommand: " + _gson.toJson(cmd));
|
s_logger.info("Executing resource MigrateVolumeCommand: " + _gson.toJson(cmd));
|
||||||
@ -3271,9 +3282,23 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||||||
diskLocator = new VirtualMachineRelocateSpecDiskLocator();
|
diskLocator = new VirtualMachineRelocateSpecDiskLocator();
|
||||||
diskLocator.setDatastore(morDs);
|
diskLocator.setDatastore(morDs);
|
||||||
diskLocator.setDiskId(diskId);
|
diskLocator.setDiskId(diskId);
|
||||||
|
|
||||||
diskLocators.add(diskLocator);
|
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<Pair<Integer, ManagedObjectReference>> diskDatastores = vmMo.getAllDiskDatastores();
|
||||||
|
for (Pair<Integer, ManagedObjectReference> 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
|
// Change datastore
|
||||||
if (!vmMo.changeDatastore(relocateSpec)) {
|
if (!vmMo.changeDatastore(relocateSpec)) {
|
||||||
@ -3286,13 +3311,11 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||||||
// In case of a linked clone VM, if VM's disks are not consolidated,
|
// 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.
|
// further volume operations on the ROOT volume such as volume snapshot etc. will result in DB inconsistencies.
|
||||||
String apiVersion = HypervisorHostHelper.getVcenterApiVersion(vmMo.getContext());
|
String apiVersion = HypervisorHostHelper.getVcenterApiVersion(vmMo.getContext());
|
||||||
if (apiVersion.compareTo("5.0") >= 0) {
|
|
||||||
if (!vmMo.consolidateVmDisks()) {
|
if (!vmMo.consolidateVmDisks()) {
|
||||||
s_logger.warn("VM disk consolidation failed after storage migration.");
|
s_logger.warn("VM disk consolidation failed after storage migration.");
|
||||||
} else {
|
} else {
|
||||||
s_logger.debug("Successfully consolidated disks of VM " + vmName + ".");
|
s_logger.debug("Successfully consolidated disks of VM " + vmName + ".");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Update and return volume path because that could have changed after migration
|
// Update and return volume path because that could have changed after migration
|
||||||
if (!targetDsMo.fileExists(fullVolumePath)) {
|
if (!targetDsMo.fileExists(fullVolumePath)) {
|
||||||
|
|||||||
@ -2069,6 +2069,26 @@ public class VirtualMachineMO extends BaseMO {
|
|||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Pair<Integer, ManagedObjectReference>> getAllDiskDatastores() throws Exception {
|
||||||
|
List<Pair<Integer, ManagedObjectReference>> disks = new ArrayList<Pair<Integer, ManagedObjectReference>>();
|
||||||
|
|
||||||
|
List<VirtualDevice> 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<Integer, ManagedObjectReference>(new Integer(device.getKey()), diskBackingInfo.getDatastore()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return disks;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public List<Pair<String, ManagedObjectReference>> getDiskDatastorePathChain(VirtualDisk disk, boolean followChain) throws Exception {
|
public List<Pair<String, ManagedObjectReference>> getDiskDatastorePathChain(VirtualDisk disk, boolean followChain) throws Exception {
|
||||||
VirtualDeviceBackingInfo backingInfo = disk.getBacking();
|
VirtualDeviceBackingInfo backingInfo = disk.getBacking();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user