mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
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
This commit is contained in:
parent
4b3376469d
commit
e9003fafcd
@ -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) {
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user