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 <sureshkumar.anapa...@gmail.com>
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

Reply via email to