diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java index b6f207acf10..b73d25050c0 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java @@ -930,12 +930,12 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { String prevSnapshotUuid, String prevBackupUuid, String workerVmName, Integer nfsVersion) throws Exception { String backupUuid = UUID.randomUUID().toString(); - exportVolumeToSecondaryStroage(vmMo, volumePath, secStorageUrl, getSnapshotRelativeDirInSecStorage(accountId, volumeId), backupUuid, workerVmName, nfsVersion); + exportVolumeToSecondaryStorage(vmMo, volumePath, secStorageUrl, getSnapshotRelativeDirInSecStorage(accountId, volumeId), backupUuid, workerVmName, nfsVersion, true); return backupUuid + "/" + backupUuid; } - private void exportVolumeToSecondaryStroage(VirtualMachineMO vmMo, String volumePath, String secStorageUrl, String secStorageDir, String exportName, String workerVmName, - Integer nfsVersion) throws Exception { + private void exportVolumeToSecondaryStorage(VirtualMachineMO vmMo, String volumePath, String secStorageUrl, String secStorageDir, String exportName, String workerVmName, + Integer nfsVersion, boolean clonedWorkerVMNeeded) throws Exception { String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl, nfsVersion); String exportPath = secondaryMountPoint + "/" + secStorageDir + "/" + exportName; @@ -961,16 +961,19 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { throw new Exception(msg); } - // 4 MB is the minimum requirement for VM memory in VMware - vmMo.cloneFromCurrentSnapshot(workerVmName, 0, 4, volumeDeviceInfo.second(), VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first())); - clonedVm = vmMo.getRunningHost().findVmOnHyperHost(workerVmName); - if (clonedVm == null) { - String msg = "Unable to create dummy VM to export volume. volume path: " + volumePath; - s_logger.error(msg); - throw new Exception(msg); + if (clonedWorkerVMNeeded) { + // 4 MB is the minimum requirement for VM memory in VMware + vmMo.cloneFromCurrentSnapshot(workerVmName, 0, 4, volumeDeviceInfo.second(), VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first())); + clonedVm = vmMo.getRunningHost().findVmOnHyperHost(workerVmName); + if (clonedVm == null) { + String msg = "Unable to create dummy VM to export volume. volume path: " + volumePath; + s_logger.error(msg); + throw new Exception(msg); + } + clonedVm.exportVm(exportPath, exportName, false, false); //Note: volss: not to create ova. + } else { + vmMo.exportVm(exportPath, exportName, false, false); } - - clonedVm.exportVm(exportPath, exportName, false, false); //Note: volss: not to create ova. } finally { if (clonedVm != null) { clonedVm.detachAllDisks(); @@ -998,6 +1001,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { throw new Exception(msg); } + boolean clonedWorkerVMNeeded = true; vmMo = hyperHost.findVmOnHyperHost(vmName); if (vmMo == null) { // create a dummy worker vm for attaching the volume @@ -1014,16 +1018,19 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { String datastoreVolumePath = getVolumePathInDatastore(dsMo, volumePath + ".vmdk", searchExcludedFolders); workerVm.attachDisk(new String[] {datastoreVolumePath}, morDs); vmMo = workerVm; + clonedWorkerVMNeeded = false; + } else { + vmMo.createSnapshot(exportName, "Temporary snapshot for copy-volume command", false, false); } - vmMo.createSnapshot(exportName, "Temporary snapshot for copy-volume command", false, false); - - exportVolumeToSecondaryStroage(vmMo, volumePath, secStorageUrl, "volumes/" + volumeFolder, exportName, hostService.getWorkerName(hyperHost.getContext(), cmd, 1), - nfsVersion); + exportVolumeToSecondaryStorage(vmMo, volumePath, secStorageUrl, "volumes/" + volumeFolder, exportName, hostService.getWorkerName(hyperHost.getContext(), cmd, 1), + nfsVersion, clonedWorkerVMNeeded); return new Pair(volumeFolder, exportName); } finally { - vmMo.removeSnapshot(exportName, false); + if (vmMo != null && vmMo.getSnapshotMor(exportName) != null) { + vmMo.removeSnapshot(exportName, false); + } if (workerVm != null) { //detach volume and destroy worker vm workerVm.detachAllDisks(); diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java index 82cd4ca23d3..9d6aca4f03c 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java @@ -983,6 +983,7 @@ public class VmwareStorageProcessor implements StorageProcessor { throw new Exception(msg); } + boolean clonedWorkerVMNeeded = true; vmMo = hyperHost.findVmOnHyperHost(vmName); if (vmMo == null || VmwareResource.getVmState(vmMo) == PowerState.PowerOff) { // create a dummy worker vm for attaching the volume @@ -999,15 +1000,18 @@ public class VmwareStorageProcessor implements StorageProcessor { String datastoreVolumePath = getVolumePathInDatastore(dsMo, volumePath + ".vmdk", searchExcludedFolders); workerVm.attachDisk(new String[] {datastoreVolumePath}, morDs); vmMo = workerVm; + clonedWorkerVMNeeded = false; + } else { + vmMo.createSnapshot(exportName, "Temporary snapshot for copy-volume command", false, false); } - vmMo.createSnapshot(exportName, "Temporary snapshot for copy-volume command", false, false); - - exportVolumeToSecondaryStroage(vmMo, volumePath, secStorageUrl, destVolumePath, exportName, hostService.getWorkerName(hyperHost.getContext(), cmd, 1), _nfsVersion); + exportVolumeToSecondaryStorage(vmMo, volumePath, secStorageUrl, destVolumePath, exportName, hostService.getWorkerName(hyperHost.getContext(), cmd, 1), _nfsVersion, clonedWorkerVMNeeded); return new Pair<>(destVolumePath, exportName); } finally { - vmMo.removeSnapshot(exportName, false); + if (vmMo != null && vmMo.getSnapshotMor(exportName) != null) { + vmMo.removeSnapshot(exportName, false); + } if (workerVm != null) { //detach volume and destroy worker vm workerVm.detachAllDisks(); @@ -1657,8 +1661,8 @@ public class VmwareStorageProcessor implements StorageProcessor { } // return Pair - private Pair exportVolumeToSecondaryStroage(VirtualMachineMO vmMo, String volumePath, String secStorageUrl, String secStorageDir, - String exportName, String workerVmName, Integer nfsVersion) throws Exception { + private Pair exportVolumeToSecondaryStorage(VirtualMachineMO vmMo, String volumePath, String secStorageUrl, String secStorageDir, + String exportName, String workerVmName, Integer nfsVersion, boolean clonedWorkerVMNeeded) throws Exception { String secondaryMountPoint = mountService.getMountPoint(secStorageUrl, nfsVersion); String exportPath = secondaryMountPoint + "/" + secStorageDir + "/" + exportName; @@ -1684,14 +1688,18 @@ public class VmwareStorageProcessor implements StorageProcessor { throw new Exception(msg); } - // 4 MB is the minimum requirement for VM memory in VMware - Pair cloneResult = - vmMo.cloneFromCurrentSnapshot(workerVmName, 0, 4, volumeDeviceInfo.second(), VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first())); - clonedVm = cloneResult.first(); - String disks[] = cloneResult.second(); - - clonedVm.exportVm(exportPath, exportName, false, false); - return new Pair<>(volumeDeviceInfo.second(), disks); + String diskDevice = volumeDeviceInfo.second(); + String disks[] = vmMo.getCurrentSnapshotDiskChainDatastorePaths(diskDevice); + if (clonedWorkerVMNeeded) { + // 4 MB is the minimum requirement for VM memory in VMware + Pair cloneResult = + vmMo.cloneFromCurrentSnapshot(workerVmName, 0, 4, diskDevice, VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first())); + clonedVm = cloneResult.first(); + clonedVm.exportVm(exportPath, exportName, false, false); + } else { + vmMo.exportVm(exportPath, exportName, false, false); + } + return new Pair<>(diskDevice, disks); } finally { if (clonedVm != null) { clonedVm.detachAllDisks(); @@ -1706,7 +1714,7 @@ public class VmwareStorageProcessor implements StorageProcessor { Integer nfsVersion) throws Exception { String backupUuid = UUID.randomUUID().toString(); - Pair snapshotInfo = exportVolumeToSecondaryStroage(vmMo, volumePath, secStorageUrl, installPath, backupUuid, workerVmName, nfsVersion); + Pair snapshotInfo = exportVolumeToSecondaryStorage(vmMo, volumePath, secStorageUrl, installPath, backupUuid, workerVmName, nfsVersion, true); return new Ternary<>(backupUuid, snapshotInfo.first(), snapshotInfo.second()); }