mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Fix export snapshot and template to secondary storage to export only required disk (#5510)
* Fix export snapshot and export template to secondary storage in VMware to export only one required disk * Move clone operation into virtual machine mo * Code refactored for readability * Added disk key check even for successful clone operation * Delete dettached disks from cloned VM and added few logs
This commit is contained in:
parent
32051fb5fa
commit
df0c0045b5
@ -1241,10 +1241,11 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
|||||||
|
|
||||||
DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter());
|
DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter());
|
||||||
ManagedObjectReference morPool = hyperHost.getHyperHostOwnerResourcePool();
|
ManagedObjectReference morPool = hyperHost.getHyperHostOwnerResourcePool();
|
||||||
vmMo.createFullCloneWithSpecificDisk(templateUniqueName, dcMo.getVmFolder(), morPool, VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first()), volumeDeviceInfo);
|
VirtualDisk requiredDisk = volumeDeviceInfo.first();
|
||||||
clonedVm = dcMo.findVm(templateUniqueName);
|
clonedVm = vmMo.createFullCloneWithSpecificDisk(templateUniqueName, dcMo.getVmFolder(), morPool, requiredDisk);
|
||||||
|
if (clonedVm == null) {
|
||||||
clonedVm.tagAsWorkerVM();
|
throw new Exception(String.format("Failed to clone VM with name %s during create template from volume operation", templateUniqueName));
|
||||||
|
}
|
||||||
clonedVm.exportVm(secondaryMountPoint + "/" + installPath, templateUniqueName, false, false);
|
clonedVm.exportVm(secondaryMountPoint + "/" + installPath, templateUniqueName, false, false);
|
||||||
|
|
||||||
// Get VMDK filename
|
// Get VMDK filename
|
||||||
@ -1828,14 +1829,11 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
|||||||
// 4 MB is the minimum requirement for VM memory in VMware
|
// 4 MB is the minimum requirement for VM memory in VMware
|
||||||
DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter());
|
DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter());
|
||||||
ManagedObjectReference morPool = hyperHost.getHyperHostOwnerResourcePool();
|
ManagedObjectReference morPool = hyperHost.getHyperHostOwnerResourcePool();
|
||||||
vmMo.createFullCloneWithSpecificDisk(exportName, dcMo.getVmFolder(), morPool, VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first()), volumeDeviceInfo);
|
VirtualDisk requiredDisk = volumeDeviceInfo.first();
|
||||||
clonedVm = dcMo.findVm(exportName);
|
clonedVm = vmMo.createFullCloneWithSpecificDisk(exportName, dcMo.getVmFolder(), morPool, requiredDisk);
|
||||||
if (clonedVm == null) {
|
if (clonedVm == null) {
|
||||||
String msg = "Failed to clone VM. volume path: " + volumePath;
|
throw new Exception(String.format("Failed to clone VM with name %s during export volume operation", exportName));
|
||||||
s_logger.error(msg);
|
|
||||||
throw new Exception(msg);
|
|
||||||
}
|
}
|
||||||
clonedVm.tagAsWorkerVM();
|
|
||||||
vmMo = clonedVm;
|
vmMo = clonedVm;
|
||||||
}
|
}
|
||||||
vmMo.exportVm(exportPath, exportName, false, false);
|
vmMo.exportVm(exportPath, exportName, false, false);
|
||||||
|
|||||||
@ -751,43 +751,87 @@ public class VirtualMachineMO extends BaseMO {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean createFullCloneWithSpecificDisk(String cloneName, ManagedObjectReference morFolder, ManagedObjectReference morResourcePool, ManagedObjectReference morDs, Pair<VirtualDisk, String> volumeDeviceInfo)
|
public VirtualMachineMO createFullCloneWithSpecificDisk(String cloneName, ManagedObjectReference morFolder, ManagedObjectReference morResourcePool, VirtualDisk requiredDisk)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
assert (morFolder != null);
|
assert (morFolder != null);
|
||||||
assert (morResourcePool != null);
|
assert (morResourcePool != null);
|
||||||
assert (morDs != null);
|
VirtualMachineRuntimeInfo runtimeInfo = getRuntimeInfo();
|
||||||
VirtualDisk requiredDisk = volumeDeviceInfo.first();
|
HostMO hostMo = new HostMO(_context, runtimeInfo.getHost());
|
||||||
|
DatacenterMO dcMo = new DatacenterMO(_context, hostMo.getHyperHostDatacenter());
|
||||||
|
DatastoreMO dsMo = new DatastoreMO(_context, morResourcePool);
|
||||||
|
|
||||||
VirtualMachineRelocateSpec rSpec = new VirtualMachineRelocateSpec();
|
VirtualMachineRelocateSpec rSpec = new VirtualMachineRelocateSpec();
|
||||||
List<VirtualMachineRelocateSpecDiskLocator> diskLocator = new ArrayList<VirtualMachineRelocateSpecDiskLocator>(1);
|
|
||||||
VirtualMachineRelocateSpecDiskLocator loc = new VirtualMachineRelocateSpecDiskLocator();
|
|
||||||
loc.setDatastore(morDs);
|
|
||||||
loc.setDiskId(requiredDisk.getKey());
|
|
||||||
loc.setDiskMoveType(VirtualMachineRelocateDiskMoveOptions.MOVE_ALL_DISK_BACKINGS_AND_DISALLOW_SHARING.value());
|
|
||||||
diskLocator.add(loc);
|
|
||||||
|
|
||||||
rSpec.setDiskMoveType(VirtualMachineRelocateDiskMoveOptions.MOVE_ALL_DISK_BACKINGS_AND_DISALLOW_SHARING.value());
|
VirtualDisk[] vmDisks = getAllDiskDevice();
|
||||||
rSpec.getDisk().addAll(diskLocator);
|
VirtualMachineConfigSpec vmConfigSpec = new VirtualMachineConfigSpec();
|
||||||
|
s_logger.debug(String.format("Removing the disks other than the required disk with key %s to the cloned VM", requiredDisk.getKey()));
|
||||||
|
for (VirtualDisk disk : vmDisks) {
|
||||||
|
s_logger.debug(String.format("Original disk with key %s found in the VM %s", disk.getKey(), getName()));
|
||||||
|
if (requiredDisk.getKey() != disk.getKey()) {
|
||||||
|
VirtualDeviceConfigSpec virtualDeviceConfigSpec = new VirtualDeviceConfigSpec();
|
||||||
|
virtualDeviceConfigSpec.setDevice(disk);
|
||||||
|
virtualDeviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.REMOVE);
|
||||||
|
vmConfigSpec.getDeviceChange().add(virtualDeviceConfigSpec);
|
||||||
|
}
|
||||||
|
}
|
||||||
rSpec.setPool(morResourcePool);
|
rSpec.setPool(morResourcePool);
|
||||||
|
|
||||||
VirtualMachineCloneSpec cloneSpec = new VirtualMachineCloneSpec();
|
VirtualMachineCloneSpec cloneSpec = new VirtualMachineCloneSpec();
|
||||||
cloneSpec.setPowerOn(false);
|
cloneSpec.setPowerOn(false);
|
||||||
cloneSpec.setTemplate(false);
|
cloneSpec.setTemplate(false);
|
||||||
cloneSpec.setLocation(rSpec);
|
cloneSpec.setLocation(rSpec);
|
||||||
|
cloneSpec.setMemory(false);
|
||||||
|
cloneSpec.setConfig(vmConfigSpec);
|
||||||
|
|
||||||
ManagedObjectReference morTask = _context.getService().cloneVMTask(_mor, morFolder, cloneName, cloneSpec);
|
ManagedObjectReference morTask = _context.getService().cloneVMTask(_mor, morFolder, cloneName, cloneSpec);
|
||||||
|
|
||||||
boolean result = _context.getVimClient().waitForTask(morTask);
|
boolean result = _context.getVimClient().waitForTask(morTask);
|
||||||
if (result) {
|
if (result) {
|
||||||
_context.waitForTaskProgressDone(morTask);
|
_context.waitForTaskProgressDone(morTask);
|
||||||
|
VirtualMachineMO clonedVm = dcMo.findVm(cloneName);
|
||||||
|
if (clonedVm == null) {
|
||||||
|
s_logger.error(String.format("Failed to clone VM %s", cloneName));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
s_logger.debug(String.format("Cloned VM: %s as %s", getName(), cloneName));
|
s_logger.debug(String.format("Cloned VM: %s as %s", getName(), cloneName));
|
||||||
return true;
|
clonedVm.tagAsWorkerVM();
|
||||||
|
makeSureVMHasOnlyRequiredDisk(clonedVm, requiredDisk, dsMo, dcMo);
|
||||||
|
return clonedVm;
|
||||||
} else {
|
} else {
|
||||||
s_logger.error("VMware cloneVM_Task failed due to " + TaskMO.getTaskFailureInfo(_context, morTask));
|
s_logger.error("VMware cloneVM_Task failed due to " + TaskMO.getTaskFailureInfo(_context, morTask));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeSureVMHasOnlyRequiredDisk(VirtualMachineMO clonedVm, VirtualDisk requiredDisk, DatastoreMO dsMo, DatacenterMO dcMo) throws Exception {
|
||||||
|
|
||||||
|
String vmName = clonedVm.getName();
|
||||||
|
VirtualDisk[] vmDisks = clonedVm.getAllDiskDevice();
|
||||||
|
s_logger.debug(String.format("Checking if VM %s is created only with required Disk, if not detach the remaining disks", vmName));
|
||||||
|
if (vmDisks.length == 1) {
|
||||||
|
s_logger.debug(String.format("VM %s is created only with required Disk", vmName));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
VirtualDisk requiredCloneDisk = null;
|
||||||
|
for (VirtualDisk vmDisk: vmDisks) {
|
||||||
|
if (vmDisk.getKey() == requiredDisk.getKey()) {
|
||||||
|
requiredCloneDisk = vmDisk;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (requiredCloneDisk == null) {
|
||||||
|
s_logger.error(String.format("Failed to identify required disk in VM %s", vmName));
|
||||||
|
throw new CloudRuntimeException(String.format("VM %s is not created with required disk", vmName));
|
||||||
|
}
|
||||||
|
|
||||||
|
String baseName = VmwareHelper.getDiskDeviceFileName(requiredCloneDisk);
|
||||||
|
s_logger.debug(String.format("Detaching all disks for the VM: %s except disk with base name: %s, key=%d", vmName, baseName, requiredCloneDisk.getKey()));
|
||||||
|
List<String> detachedDisks = clonedVm.detachAllDisksExcept(baseName, null);
|
||||||
|
for (String diskPath : detachedDisks) {
|
||||||
|
dsMo.deleteFile(diskPath, dcMo.getMor(), true, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean createFullClone(String cloneName, ManagedObjectReference morFolder, ManagedObjectReference morResourcePool, ManagedObjectReference morDs, Storage.ProvisioningType diskProvisioningType)
|
public boolean createFullClone(String cloneName, ManagedObjectReference morFolder, ManagedObjectReference morResourcePool, ManagedObjectReference morDs, Storage.ProvisioningType diskProvisioningType)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user