Skip to content

Commit 3e1d851

Browse files
Fix export snapshot and template to secondary storage to export only required disk (apache#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 (cherry picked from commit df0c004) Signed-off-by: Rohit Yadav <[email protected]>
1 parent f9ca968 commit 3e1d851

File tree

2 files changed

+66
-24
lines changed

2 files changed

+66
-24
lines changed

plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,10 +1231,11 @@ private Ternary<String, Long, Long> createTemplateFromVolume(VmwareContext conte
12311231

12321232
DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter());
12331233
ManagedObjectReference morPool = hyperHost.getHyperHostOwnerResourcePool();
1234-
vmMo.createFullCloneWithSpecificDisk(templateUniqueName, dcMo.getVmFolder(), morPool, VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first()), volumeDeviceInfo);
1235-
clonedVm = dcMo.findVm(templateUniqueName);
1236-
1237-
clonedVm.tagAsWorkerVM();
1234+
VirtualDisk requiredDisk = volumeDeviceInfo.first();
1235+
clonedVm = vmMo.createFullCloneWithSpecificDisk(templateUniqueName, dcMo.getVmFolder(), morPool, requiredDisk);
1236+
if (clonedVm == null) {
1237+
throw new Exception(String.format("Failed to clone VM with name %s during create template from volume operation", templateUniqueName));
1238+
}
12381239
clonedVm.exportVm(secondaryMountPoint + "/" + installPath, templateUniqueName, false, false);
12391240

12401241
// Get VMDK filename
@@ -1818,14 +1819,11 @@ private Pair<String, String[]> exportVolumeToSecondaryStorage(VmwareContext cont
18181819
// 4 MB is the minimum requirement for VM memory in VMware
18191820
DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter());
18201821
ManagedObjectReference morPool = hyperHost.getHyperHostOwnerResourcePool();
1821-
vmMo.createFullCloneWithSpecificDisk(exportName, dcMo.getVmFolder(), morPool, VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first()), volumeDeviceInfo);
1822-
clonedVm = dcMo.findVm(exportName);
1822+
VirtualDisk requiredDisk = volumeDeviceInfo.first();
1823+
clonedVm = vmMo.createFullCloneWithSpecificDisk(exportName, dcMo.getVmFolder(), morPool, requiredDisk);
18231824
if (clonedVm == null) {
1824-
String msg = "Failed to clone VM. volume path: " + volumePath;
1825-
s_logger.error(msg);
1826-
throw new Exception(msg);
1825+
throw new Exception(String.format("Failed to clone VM with name %s during export volume operation", exportName));
18271826
}
1828-
clonedVm.tagAsWorkerVM();
18291827
vmMo = clonedVm;
18301828
}
18311829
vmMo.exportVm(exportPath, exportName, false, false);

vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java

Lines changed: 58 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -741,43 +741,87 @@ public boolean hasSnapshot() throws Exception {
741741
return false;
742742
}
743743

744-
public boolean createFullCloneWithSpecificDisk(String cloneName, ManagedObjectReference morFolder, ManagedObjectReference morResourcePool, ManagedObjectReference morDs, Pair<VirtualDisk, String> volumeDeviceInfo)
744+
public VirtualMachineMO createFullCloneWithSpecificDisk(String cloneName, ManagedObjectReference morFolder, ManagedObjectReference morResourcePool, VirtualDisk requiredDisk)
745745
throws Exception {
746746

747747
assert (morFolder != null);
748748
assert (morResourcePool != null);
749-
assert (morDs != null);
750-
VirtualDisk requiredDisk = volumeDeviceInfo.first();
749+
VirtualMachineRuntimeInfo runtimeInfo = getRuntimeInfo();
750+
HostMO hostMo = new HostMO(_context, runtimeInfo.getHost());
751+
DatacenterMO dcMo = new DatacenterMO(_context, hostMo.getHyperHostDatacenter());
752+
DatastoreMO dsMo = new DatastoreMO(_context, morResourcePool);
751753

752754
VirtualMachineRelocateSpec rSpec = new VirtualMachineRelocateSpec();
753-
List<VirtualMachineRelocateSpecDiskLocator> diskLocator = new ArrayList<VirtualMachineRelocateSpecDiskLocator>(1);
754-
VirtualMachineRelocateSpecDiskLocator loc = new VirtualMachineRelocateSpecDiskLocator();
755-
loc.setDatastore(morDs);
756-
loc.setDiskId(requiredDisk.getKey());
757-
loc.setDiskMoveType(VirtualMachineRelocateDiskMoveOptions.MOVE_ALL_DISK_BACKINGS_AND_DISALLOW_SHARING.value());
758-
diskLocator.add(loc);
759-
760-
rSpec.setDiskMoveType(VirtualMachineRelocateDiskMoveOptions.MOVE_ALL_DISK_BACKINGS_AND_DISALLOW_SHARING.value());
761-
rSpec.getDisk().addAll(diskLocator);
755+
756+
VirtualDisk[] vmDisks = getAllDiskDevice();
757+
VirtualMachineConfigSpec vmConfigSpec = new VirtualMachineConfigSpec();
758+
s_logger.debug(String.format("Removing the disks other than the required disk with key %s to the cloned VM", requiredDisk.getKey()));
759+
for (VirtualDisk disk : vmDisks) {
760+
s_logger.debug(String.format("Original disk with key %s found in the VM %s", disk.getKey(), getName()));
761+
if (requiredDisk.getKey() != disk.getKey()) {
762+
VirtualDeviceConfigSpec virtualDeviceConfigSpec = new VirtualDeviceConfigSpec();
763+
virtualDeviceConfigSpec.setDevice(disk);
764+
virtualDeviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.REMOVE);
765+
vmConfigSpec.getDeviceChange().add(virtualDeviceConfigSpec);
766+
}
767+
}
762768
rSpec.setPool(morResourcePool);
763769

764770
VirtualMachineCloneSpec cloneSpec = new VirtualMachineCloneSpec();
765771
cloneSpec.setPowerOn(false);
766772
cloneSpec.setTemplate(false);
767773
cloneSpec.setLocation(rSpec);
774+
cloneSpec.setMemory(false);
775+
cloneSpec.setConfig(vmConfigSpec);
768776

769777
ManagedObjectReference morTask = _context.getService().cloneVMTask(_mor, morFolder, cloneName, cloneSpec);
770778

771779
boolean result = _context.getVimClient().waitForTask(morTask);
772780
if (result) {
773781
_context.waitForTaskProgressDone(morTask);
782+
VirtualMachineMO clonedVm = dcMo.findVm(cloneName);
783+
if (clonedVm == null) {
784+
s_logger.error(String.format("Failed to clone VM %s", cloneName));
785+
return null;
786+
}
774787
s_logger.debug(String.format("Cloned VM: %s as %s", getName(), cloneName));
775-
return true;
788+
clonedVm.tagAsWorkerVM();
789+
makeSureVMHasOnlyRequiredDisk(clonedVm, requiredDisk, dsMo, dcMo);
790+
return clonedVm;
776791
} else {
777792
s_logger.error("VMware cloneVM_Task failed due to " + TaskMO.getTaskFailureInfo(_context, morTask));
793+
return null;
778794
}
795+
}
779796

780-
return false;
797+
private void makeSureVMHasOnlyRequiredDisk(VirtualMachineMO clonedVm, VirtualDisk requiredDisk, DatastoreMO dsMo, DatacenterMO dcMo) throws Exception {
798+
799+
String vmName = clonedVm.getName();
800+
VirtualDisk[] vmDisks = clonedVm.getAllDiskDevice();
801+
s_logger.debug(String.format("Checking if VM %s is created only with required Disk, if not detach the remaining disks", vmName));
802+
if (vmDisks.length == 1) {
803+
s_logger.debug(String.format("VM %s is created only with required Disk", vmName));
804+
return;
805+
}
806+
807+
VirtualDisk requiredCloneDisk = null;
808+
for (VirtualDisk vmDisk: vmDisks) {
809+
if (vmDisk.getKey() == requiredDisk.getKey()) {
810+
requiredCloneDisk = vmDisk;
811+
break;
812+
}
813+
}
814+
if (requiredCloneDisk == null) {
815+
s_logger.error(String.format("Failed to identify required disk in VM %s", vmName));
816+
throw new CloudRuntimeException(String.format("VM %s is not created with required disk", vmName));
817+
}
818+
819+
String baseName = VmwareHelper.getDiskDeviceFileName(requiredCloneDisk);
820+
s_logger.debug(String.format("Detaching all disks for the VM: %s except disk with base name: %s, key=%d", vmName, baseName, requiredCloneDisk.getKey()));
821+
List<String> detachedDisks = clonedVm.detachAllDisksExcept(baseName, null);
822+
for (String diskPath : detachedDisks) {
823+
dsMo.deleteFile(diskPath, dcMo.getMor(), true, null);
824+
}
781825
}
782826

783827
public boolean createFullClone(String cloneName, ManagedObjectReference morFolder, ManagedObjectReference morResourcePool, ManagedObjectReference morDs)

0 commit comments

Comments
 (0)