This is an automated email from the ASF dual-hosted git repository.
rohit pushed a commit to branch 4.11
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/4.11 by this push:
new e9003fa CLOUDSTACK-8609: [VMware] VM is not accessible after
migration across clusters (#2091)
e9003fa is described below
commit e9003fafcd9309937cd4ef79c55c9fb9489c401d
Author: sureshanaparti <[email protected]>
AuthorDate: Wed Aug 22 01:06:09 2018 +0530
CLOUDSTACK-8609: [VMware] VM is not accessible after migration across
clusters (#2091)
[VMware] VM is not accessible after migration across clusters.
Once a VM is successfully started, don't delete the files associated with
the unregistered VM, if the files are in a storage that is being used by the
new VM.
Attempt to unregister a VM in another DC, only if there is a host
associated with a VM.
This closes #556
---
.../hypervisor/vmware/resource/VmwareResource.java | 35 ++++++++++++++++------
.../hypervisor/vmware/mo/VirtualMachineMO.java | 33 ++++++++++++++++++++
2 files changed, 59 insertions(+), 9 deletions(-)
diff --git
a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
index ef21dd7..ee14077 100644
---
a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
+++
b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
@@ -1668,6 +1668,7 @@ public class VmwareResource implements
StoragePoolResource, ServerResource, Vmwa
String existingVmName = null;
VirtualMachineFileInfo existingVmFileInfo = null;
VirtualMachineFileLayoutEx existingVmFileLayout = null;
+ List<DatastoreMO> existingDatastores = new ArrayList<DatastoreMO>();
Pair<String, String> names = composeVmNames(vmSpec);
String vmInternalCSName = names.first();
@@ -1790,6 +1791,7 @@ public class VmwareResource implements
StoragePoolResource, ServerResource, Vmwa
existingVmName = existingVmInDc.getName();
existingVmFileInfo = existingVmInDc.getFileInfo();
existingVmFileLayout = existingVmInDc.getFileLayout();
+ existingDatastores = existingVmInDc.getAllDatastores();
existingVmInDc.unregisterVm();
}
Pair<ManagedObjectReference, DatastoreMO>
rootDiskDataStoreDetails = null;
@@ -2256,7 +2258,18 @@ public class VmwareResource implements
StoragePoolResource, ServerResource, Vmwa
// Since VM was successfully powered-on, if there was an existing
VM in a different cluster that was unregistered, delete all the files
associated with it.
if (existingVmName != null && existingVmFileLayout != null) {
- deleteUnregisteredVmFiles(existingVmFileLayout, dcMo, true);
+ List<String> vmDatastoreNames = new ArrayList<String>();
+ for (DatastoreMO vmDatastore : vmMo.getAllDatastores()) {
+ vmDatastoreNames.add(vmDatastore.getName());
+ }
+ // Don't delete files that are in a datastore that is being
used by the new VM as well (zone-wide datastore).
+ List<String> skipDatastores = new ArrayList<String>();
+ for (DatastoreMO existingDatastore : existingDatastores) {
+ if
(vmDatastoreNames.contains(existingDatastore.getName())) {
+ skipDatastores.add(existingDatastore.getName());
+ }
+ }
+ deleteUnregisteredVmFiles(existingVmFileLayout, dcMo, true,
skipDatastores);
}
return startAnswer;
@@ -2944,7 +2957,14 @@ public class VmwareResource implements
StoragePoolResource, ServerResource, Vmwa
}
}
- private void deleteUnregisteredVmFiles(VirtualMachineFileLayoutEx
vmFileLayout, DatacenterMO dcMo, boolean deleteDisks) throws Exception {
+ private void checkAndDeleteDatastoreFile(String filePath, List<String>
skipDatastores, DatastoreMO dsMo, DatacenterMO dcMo) throws Exception {
+ if (dsMo != null && dcMo != null && (skipDatastores == null ||
!skipDatastores.contains(dsMo.getName()))) {
+ s_logger.debug("Deleting file: " + filePath);
+ dsMo.deleteFile(filePath, dcMo.getMor(), true);
+ }
+ }
+
+ private void deleteUnregisteredVmFiles(VirtualMachineFileLayoutEx
vmFileLayout, DatacenterMO dcMo, boolean deleteDisks, List<String>
skipDatastores) throws Exception {
s_logger.debug("Deleting files associated with an existing VM that was
unregistered");
DatastoreFile vmFolder = null;
try {
@@ -2957,8 +2977,7 @@ public class VmwareResource implements
StoragePoolResource, ServerResource, Vmwa
else if (file.getType().equals("config"))
vmFolder = new
DatastoreFile(fileInDatastore.getDatastoreName(), fileInDatastore.getDir());
DatastoreMO dsMo = new DatastoreMO(dcMo.getContext(),
dcMo.findDatastore(fileInDatastore.getDatastoreName()));
- s_logger.debug("Deleting file: " + file.getName());
- dsMo.deleteFile(file.getName(), dcMo.getMor(), true,
VmwareManager.s_vmwareSearchExcludeFolder.value());
+ checkAndDeleteDatastoreFile(file.getName(), skipDatastores,
dsMo, dcMo);
}
// Delete files that are present in the VM folder - this will take
care of the VM disks as well.
DatastoreMO vmFolderDsMo = new DatastoreMO(dcMo.getContext(),
dcMo.findDatastore(vmFolder.getDatastoreName()));
@@ -2966,14 +2985,12 @@ public class VmwareResource implements
StoragePoolResource, ServerResource, Vmwa
if (deleteDisks) {
for (String file : files) {
String vmDiskFileFullPath = String.format("%s/%s",
vmFolder.getPath(), file);
- s_logger.debug("Deleting file: " + vmDiskFileFullPath);
- vmFolderDsMo.deleteFile(vmDiskFileFullPath, dcMo.getMor(),
true, VmwareManager.s_vmwareSearchExcludeFolder.value());
+ checkAndDeleteDatastoreFile(vmDiskFileFullPath,
skipDatastores, vmFolderDsMo, dcMo);
}
}
// Delete VM folder
if (deleteDisks || files.length == 0) {
- s_logger.debug("Deleting folder: " + vmFolder.getPath());
- vmFolderDsMo.deleteFolder(vmFolder.getPath(), dcMo.getMor());
+ checkAndDeleteDatastoreFile(vmFolder.getPath(),
skipDatastores, vmFolderDsMo, dcMo);
}
} catch (Exception e) {
String message = "Failed to delete files associated with an
existing VM that was unregistered due to " +
VmwareHelper.getExceptionMessage(e);
@@ -4908,7 +4925,7 @@ public class VmwareResource implements
StoragePoolResource, ServerResource, Vmwa
VirtualMachineFileLayoutEx vmFileLayout =
vmMo.getFileLayout();
context.getService().unregisterVM(vmMo.getMor());
if (cmd.getCleanupVmFiles()) {
- deleteUnregisteredVmFiles(vmFileLayout, dataCenterMo,
false);
+ deleteUnregisteredVmFiles(vmFileLayout, dataCenterMo,
false, null);
}
return new Answer(cmd, true, "unregister succeeded");
} catch (Exception e) {
diff --git
a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
index 0078793..b700b6d 100644
--- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
+++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
@@ -34,6 +34,7 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
+import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;
import com.google.gson.Gson;
@@ -932,6 +933,38 @@ public class VirtualMachineMO extends BaseMO {
return networks;
}
+ public List<DatastoreMO> getAllDatastores() throws Exception {
+ PropertySpec pSpec = new PropertySpec();
+ pSpec.setType("Datastore");
+ pSpec.getPathSet().add("name");
+
+ TraversalSpec vmDatastoreTraversal = new TraversalSpec();
+ vmDatastoreTraversal.setType("VirtualMachine");
+ vmDatastoreTraversal.setPath("datastore");
+ vmDatastoreTraversal.setName("vmDatastoreTraversal");
+
+ ObjectSpec oSpec = new ObjectSpec();
+ oSpec.setObj(_mor);
+ oSpec.setSkip(Boolean.TRUE);
+ oSpec.getSelectSet().add(vmDatastoreTraversal);
+
+ PropertyFilterSpec pfSpec = new PropertyFilterSpec();
+ pfSpec.getPropSet().add(pSpec);
+ pfSpec.getObjectSet().add(oSpec);
+ List<PropertyFilterSpec> pfSpecArr = new
ArrayList<PropertyFilterSpec>();
+ pfSpecArr.add(pfSpec);
+
+ List<ObjectContent> ocs =
_context.getService().retrieveProperties(_context.getPropertyCollector(),
pfSpecArr);
+
+ List<DatastoreMO> datastores = new ArrayList<DatastoreMO>();
+ if (CollectionUtils.isNotEmpty(ocs)) {
+ for (ObjectContent oc : ocs) {
+ datastores.add(new DatastoreMO(_context, oc.getObj()));
+ }
+ }
+ return datastores;
+ }
+
/**
* Retrieve path info to access VM files via vSphere web interface
* @return [0] vm-name, [1] data-center-name, [2] datastore-name