diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java index 7b6accf5357..d8076fd5d68 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java @@ -531,6 +531,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co // FIXME: Fix long checkPointId2 = _checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostDetails.get("guid"), workerName2)); cmd.setContextParam("worker2", workerName2); cmd.setContextParam("checkpoint2", String.valueOf(checkPointId2)); + cmd.setContextParam("searchexludefolders", _vmwareMgr.s_vmwareSearchExcludeFolder.value()); } return new Pair(Boolean.TRUE, cmdTarget.first().getId()); diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java index 65963eb25bd..4a4d2ea7a53 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java @@ -39,6 +39,9 @@ public interface VmwareManager { public static final ConfigKey s_vmwareCleanOldWorderVMs = new ConfigKey("Advanced", Boolean.class, "vmware.clean.old.worker.vms", "false", "If a worker vm is older then twice the 'job.expire.minutes' + 'job.cancel.threshold.minutes' , remove it.", true, ConfigKey.Scope.Global); + static final ConfigKey s_vmwareSearchExcludeFolder = new ConfigKey("Advanced", String.class, "vmware.search.exclude.folders", null, + "Comma seperated list of Datastore Folders to exclude from VMWare search", true, ConfigKey.Scope.Global); + String composeWorkerName(); String getSystemVMIsoFileNameOnDatastore(); diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java index c003b442ffe..53e3239113e 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java @@ -229,7 +229,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw @Override public ConfigKey[] getConfigKeys() { - return new ConfigKey[] {s_vmwareNicHotplugWaitTimeout, s_vmwareCleanOldWorderVMs, templateCleanupInterval}; + return new ConfigKey[] {s_vmwareNicHotplugWaitTimeout, s_vmwareCleanOldWorderVMs, templateCleanupInterval, s_vmwareSearchExcludeFolder}; } @Override diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java index 3158ad47925..00298cedc75 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java @@ -307,6 +307,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { String snapshotUuid = cmd.getSnapshotUuid(); // not null: Precondition. String prevSnapshotUuid = cmd.getPrevSnapshotUuid(); String prevBackupUuid = cmd.getPrevBackupUuid(); + String searchExcludedFolders = cmd.getContextParam("searchexludefolders"); VirtualMachineMO workerVm = null; String workerVMName = null; String volumePath = cmd.getVolumePath(); @@ -344,7 +345,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { workerVm = vmMo; // attach volume to worker VM - String datastoreVolumePath = getVolumePathInDatastore(dsMo, volumePath + ".vmdk"); + String datastoreVolumePath = getVolumePathInDatastore(dsMo, volumePath + ".vmdk", searchExcludedFolders); vmMo.attachDisk(new String[] {datastoreVolumePath}, morDs); } } @@ -986,6 +987,8 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { VirtualMachineMO workerVm = null; VirtualMachineMO vmMo = null; String exportName = UUID.randomUUID().toString(); + String searchExcludedFolders = cmd.getContextParam("searchexludefolders"); + try { ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, poolId); @@ -1009,7 +1012,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { } //attach volume to worker VM - String datastoreVolumePath = getVolumePathInDatastore(dsMo, volumePath + ".vmdk"); + String datastoreVolumePath = getVolumePathInDatastore(dsMo, volumePath + ".vmdk", searchExcludedFolders); workerVm.attachDisk(new String[] {datastoreVolumePath}, morDs); vmMo = workerVm; } @@ -1030,8 +1033,8 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { } } - private String getVolumePathInDatastore(DatastoreMO dsMo, String volumeFileName) throws Exception { - String datastoreVolumePath = dsMo.searchFileInSubFolders(volumeFileName, true); + private String getVolumePathInDatastore(DatastoreMO dsMo, String volumeFileName, String searchExcludeFolders) throws Exception { + String datastoreVolumePath = dsMo.searchFileInSubFolders(volumeFileName, true, searchExcludeFolders); if (datastoreVolumePath == null) { throw new CloudRuntimeException("Unable to find file " + volumeFileName + " in datastore " + dsMo.getName()); } 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 b8a3495dd6a..ccb5d0f7abb 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 @@ -645,7 +645,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa ManagedObjectReference vmFolderMor = dataCenterMo.getVmFolder(); //2nd param - String vmxFilePath = dsMo.searchFileInSubFolders(vmName + ".vmx", false); + String vmxFilePath = dsMo.searchFileInSubFolders(vmName + ".vmx", false, VmwareManager.s_vmwareSearchExcludeFolder.value()); // 5th param ManagedObjectReference morPool = hyperHost.getHyperHostOwnerResourcePool(); @@ -1683,7 +1683,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa assert (vmSpec.getMinSpeed() != null) && (rootDiskDataStoreDetails != null); boolean vmFolderExists = rootDiskDataStoreDetails.second().folderExists(String.format("[%s]", rootDiskDataStoreDetails.second().getName()), vmNameOnVcenter); - String vmxFileFullPath = dsRootVolumeIsOn.searchFileInSubFolders(vmNameOnVcenter + ".vmx", false); + String vmxFileFullPath = dsRootVolumeIsOn.searchFileInSubFolders(vmNameOnVcenter + ".vmx", false, VmwareManager.s_vmwareSearchExcludeFolder.value()); if (vmFolderExists && vmxFileFullPath != null) { // VM can be registered only if .vmx is present. registerVm(vmNameOnVcenter, dsRootVolumeIsOn); vmMo = hyperHost.findVmOnHyperHost(vmInternalCSName); @@ -2360,7 +2360,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa DatastoreFile file = new DatastoreFile(disks[i]); if (!isManaged && file.getDir() != null && file.getDir().isEmpty()) { s_logger.info("Perform run-time datastore folder upgrade. sync " + disks[i] + " to VM folder"); - disks[i] = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, file.getFileBaseName()); + disks[i] = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, file.getFileBaseName(), VmwareManager.s_vmwareSearchExcludeFolder.value()); } } return disks; @@ -2370,13 +2370,13 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa if (isManaged) { if (volumeTO.getVolumeType() == Volume.Type.ROOT) { - datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, volumeTO.getName()); + datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, volumeTO.getName(), VmwareManager.s_vmwareSearchExcludeFolder.value()); } else { datastoreDiskPath = dsMo.getDatastorePath(dsMo.getName() + ".vmdk"); } } else { - datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, volumeTO.getPath()); + datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, volumeTO.getPath(), VmwareManager.s_vmwareSearchExcludeFolder.value()); } if (!dsMo.fileExists(datastoreDiskPath)) { @@ -2802,7 +2802,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa 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); + dsMo.deleteFile(file.getName(), dcMo.getMor(), true, VmwareManager.s_vmwareSearchExcludeFolder.value()); } // 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())); @@ -2811,7 +2811,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa 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); + vmFolderDsMo.deleteFile(vmDiskFileFullPath, dcMo.getMor(), true, VmwareManager.s_vmwareSearchExcludeFolder.value()); } } // Delete VM folder diff --git a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageLayoutHelper.java b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageLayoutHelper.java index 4096333c493..fc79a4b0faf 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageLayoutHelper.java +++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageLayoutHelper.java @@ -67,6 +67,11 @@ public class VmwareStorageLayoutHelper { } public static String findVolumeDatastoreFullPath(DatastoreMO dsMo, String vmName, String vmdkFileName) throws Exception { + return findVolumeDatastoreFullPath(dsMo, vmName, vmdkFileName, null); + } + + public static String findVolumeDatastoreFullPath(DatastoreMO dsMo, String vmName, String vmdkFileName, String excludeFolders) throws Exception { + if (vmName != null) { String path = getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, vmdkFileName); if (!dsMo.fileExists(path)) { @@ -80,7 +85,7 @@ public class VmwareStorageLayoutHelper { String path = getLegacyDatastorePathFromVmdkFileName(dsMo, vmdkFileName); if (!dsMo.fileExists(path)) { // Datastore file movement is not atomic operations, we need to sync and repair - path = dsMo.searchFileInSubFolders(vmdkFileName, false); + path = dsMo.searchFileInSubFolders(vmdkFileName, false, excludeFolders); // to save one call to vCenter, we won't check file existence for this round, so the caller // may still fail with exception, but if that's case, we will let it fail anyway @@ -90,6 +95,10 @@ public class VmwareStorageLayoutHelper { } public static String syncVolumeToVmDefaultFolder(DatacenterMO dcMo, String vmName, DatastoreMO ds, String vmdkName) throws Exception { + return syncVolumeToVmDefaultFolder(dcMo, vmName, ds, vmdkName, null); + } + + public static String syncVolumeToVmDefaultFolder(DatacenterMO dcMo, String vmName, DatastoreMO ds, String vmdkName, String excludeFolders) throws Exception { assert (ds != null); if (!ds.folderExists(String.format("[%s]", ds.getName()), vmName)) { @@ -109,7 +118,7 @@ public class VmwareStorageLayoutHelper { // be left over in its previous owner VM. We will do a fixup synchronization here by moving it to root // again. // - syncVolumeToRootFolder(dcMo, ds, vmdkName, vmName); + syncVolumeToRootFolder(dcMo, ds, vmdkName, vmName, excludeFolders); } if (ds.fileExists(vmdkFullCloneModeLegacyPair[1])) { @@ -134,7 +143,11 @@ public class VmwareStorageLayoutHelper { } public static void syncVolumeToRootFolder(DatacenterMO dcMo, DatastoreMO ds, String vmdkName, String vmName) throws Exception { - String fileDsFullPath = ds.searchFileInSubFolders(vmdkName + ".vmdk", false); + syncVolumeToRootFolder(dcMo, ds, vmdkName, null); + } + + public static void syncVolumeToRootFolder(DatacenterMO dcMo, DatastoreMO ds, String vmdkName, String vmName, String excludeFolders) throws Exception { + String fileDsFullPath = ds.searchFileInSubFolders(vmdkName + ".vmdk", false, excludeFolders); if (fileDsFullPath == null) return; @@ -259,13 +272,17 @@ public class VmwareStorageLayoutHelper { } public static void deleteVolumeVmdkFiles(DatastoreMO dsMo, String volumeName, DatacenterMO dcMo) throws Exception { + deleteVolumeVmdkFiles(dsMo, volumeName, dcMo, null); + } + + public static void deleteVolumeVmdkFiles(DatastoreMO dsMo, String volumeName, DatacenterMO dcMo, String excludeFolders) throws Exception { String fileName = volumeName + ".vmdk"; String fileFullPath = getLegacyDatastorePathFromVmdkFileName(dsMo, fileName); if (!dsMo.fileExists(fileFullPath)) - fileFullPath = dsMo.searchFileInSubFolders(fileName, false); + fileFullPath = dsMo.searchFileInSubFolders(fileName, false, excludeFolders); if (fileFullPath != null) { - dsMo.deleteFile(fileFullPath, dcMo.getMor(), true); + dsMo.deleteFile(fileFullPath, dcMo.getMor(), true, excludeFolders); } else { s_logger.warn("Unable to locate VMDK file: " + fileName); } @@ -273,9 +290,9 @@ public class VmwareStorageLayoutHelper { fileName = volumeName + "-flat.vmdk"; fileFullPath = getLegacyDatastorePathFromVmdkFileName(dsMo, fileName); if (!dsMo.fileExists(fileFullPath)) - fileFullPath = dsMo.searchFileInSubFolders(fileName, false); + fileFullPath = dsMo.searchFileInSubFolders(fileName, false, excludeFolders); if (fileFullPath != null) { - dsMo.deleteFile(fileFullPath, dcMo.getMor(), true); + dsMo.deleteFile(fileFullPath, dcMo.getMor(), true, excludeFolders); } else { s_logger.warn("Unable to locate VMDK file: " + fileName); } @@ -283,9 +300,9 @@ public class VmwareStorageLayoutHelper { fileName = volumeName + "-delta.vmdk"; fileFullPath = getLegacyDatastorePathFromVmdkFileName(dsMo, fileName); if (!dsMo.fileExists(fileFullPath)) - fileFullPath = dsMo.searchFileInSubFolders(fileName, false); + fileFullPath = dsMo.searchFileInSubFolders(fileName, false, excludeFolders); if (fileFullPath != null) { - dsMo.deleteFile(fileFullPath, dcMo.getMor(), true); + dsMo.deleteFile(fileFullPath, dcMo.getMor(), true, excludeFolders); } else { s_logger.warn("Unable to locate VMDK file: " + fileName); } diff --git a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java index 802657515fd..012556eb1ca 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java +++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java @@ -450,6 +450,7 @@ public class VmwareStorageProcessor implements StorageProcessor { VolumeObjectTO volume = (VolumeObjectTO)destData; DataStoreTO primaryStore = volume.getDataStore(); DataStoreTO srcStore = template.getDataStore(); + String searchExcludedFolders = cmd.getContextParam("searchexludefolders"); try { VmwareContext context = hostService.getServiceContext(null); @@ -481,7 +482,7 @@ public class VmwareStorageProcessor implements StorageProcessor { String volumeDatastorePath = vmdkFilePair[0]; synchronized (this) { s_logger.info("Delete file if exists in datastore to clear the way for creating the volume. file: " + volumeDatastorePath); - VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, vmdkName, dcMo); + VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, vmdkName, dcMo, searchExcludedFolders); vmMo.createDisk(volumeDatastorePath, (int)(volume.getSize() / (1024L * 1024L)), morDatastore, -1); vmMo.detachDisk(volumeDatastorePath, false); } @@ -527,14 +528,14 @@ public class VmwareStorageProcessor implements StorageProcessor { vmMo.destroy(); String srcFile = dsMo.getDatastorePath(vmdkName, true); - dsMo.deleteFile(srcFile, dcMo.getMor(), true); + dsMo.deleteFile(srcFile, dcMo.getMor(), true, searchExcludedFolders); } // restoreVM - move the new ROOT disk into corresponding VM folder VirtualMachineMO restoreVmMo = dcMo.findVm(volume.getVmName()); if (restoreVmMo != null) { String vmNameInVcenter = restoreVmMo.getName(); // VM folder name in datastore will be VM's name in vCenter. if (dsMo.folderExists(String.format("[%s]", dsMo.getName()), vmNameInVcenter)) { - VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmNameInVcenter, dsMo, vmdkFileBaseName); + VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmNameInVcenter, dsMo, vmdkFileBaseName, searchExcludedFolders); } } @@ -631,8 +632,8 @@ public class VmwareStorageProcessor implements StorageProcessor { } - private String getVolumePathInDatastore(DatastoreMO dsMo, String volumeFileName) throws Exception { - String datastoreVolumePath = dsMo.searchFileInSubFolders(volumeFileName, true); + private String getVolumePathInDatastore(DatastoreMO dsMo, String volumeFileName, String searchExcludedFolders) throws Exception { + String datastoreVolumePath = dsMo.searchFileInSubFolders(volumeFileName, true, searchExcludedFolders); assert (datastoreVolumePath != null) : "Virtual disk file missing from datastore."; return datastoreVolumePath; } @@ -642,6 +643,7 @@ public class VmwareStorageProcessor implements StorageProcessor { VirtualMachineMO workerVm = null; VirtualMachineMO vmMo = null; String exportName = UUID.randomUUID().toString().replace("-", ""); + String searchExcludedFolders = cmd.getContextParam("searchexludefolders"); try { ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, poolId); @@ -665,7 +667,7 @@ public class VmwareStorageProcessor implements StorageProcessor { } // attach volume to worker VM - String datastoreVolumePath = getVolumePathInDatastore(dsMo, volumePath + ".vmdk"); + String datastoreVolumePath = getVolumePathInDatastore(dsMo, volumePath + ".vmdk", searchExcludedFolders); workerVm.attachDisk(new String[] {datastoreVolumePath}, morDs); vmMo = workerVm; } @@ -690,6 +692,7 @@ public class VmwareStorageProcessor implements StorageProcessor { VolumeObjectTO srcVolume = (VolumeObjectTO)cmd.getSrcTO(); VolumeObjectTO destVolume = (VolumeObjectTO)cmd.getDestTO(); String vmName = srcVolume.getVmName(); + String searchExcludedFolders = cmd.getContextParam("searchexludefolders"); VmwareContext context = hostService.getServiceContext(cmd); try { @@ -1380,7 +1383,7 @@ public class VmwareStorageProcessor implements StorageProcessor { if (isManaged) { datastoreVolumePath = dsMo.getDatastorePath(dsMo.getName() + ".vmdk"); } else { - datastoreVolumePath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dsMo.getOwnerDatacenter().first(), vmName, dsMo, volumeTO.getPath()); + datastoreVolumePath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dsMo.getOwnerDatacenter().first(), vmName, dsMo, volumeTO.getPath(), VmwareManager.s_vmwareSearchExcludeFolder.value()); } } else { if (isManaged) { @@ -1415,7 +1418,7 @@ public class VmwareStorageProcessor implements StorageProcessor { if (isManaged) { handleDatastoreAndVmdkDetachManaged(diskUuid, iScsiName, storageHost, storagePort); } else { - VmwareStorageLayoutHelper.syncVolumeToRootFolder(dsMo.getOwnerDatacenter().first(), dsMo, volumeTO.getPath(), vmName); + VmwareStorageLayoutHelper.syncVolumeToRootFolder(dsMo.getOwnerDatacenter().first(), dsMo, volumeTO.getPath(), vmName, VmwareManager.s_vmwareSearchExcludeFolder.value()); } } @@ -1591,7 +1594,7 @@ public class VmwareStorageProcessor implements StorageProcessor { } catch (Exception e) { s_logger.error("Deleting file " + volumeDatastorePath + " due to error: " + e.getMessage()); - VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, volumeUuid.toString(), dcMo); + VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, volumeUuid.toString(), dcMo, VmwareManager.s_vmwareSearchExcludeFolder.value()); throw new CloudRuntimeException("Unable to create volume due to: " + e.getMessage()); } } @@ -1753,7 +1756,7 @@ public class VmwareStorageProcessor implements StorageProcessor { } } - VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, vol.getPath(), new DatacenterMO(context, morDc)); + VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, vol.getPath(), new DatacenterMO(context, morDc), VmwareManager.s_vmwareSearchExcludeFolder.value()); return new Answer(cmd, true, "Success"); } catch (Throwable e) { diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/mo/DatastoreMO.java b/vmware-base/src/com/cloud/hypervisor/vmware/mo/DatastoreMO.java index 290e1a0bdb6..1152ba5078a 100644 --- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/DatastoreMO.java +++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/DatastoreMO.java @@ -166,6 +166,10 @@ public class DatastoreMO extends BaseMO { } public boolean deleteFile(String path, ManagedObjectReference morDc, boolean testExistence) throws Exception { + return deleteFile(path, morDc, testExistence, null); + } + + public boolean deleteFile(String path, ManagedObjectReference morDc, boolean testExistence, String excludeFolders) throws Exception { String datastoreName = getName(); ManagedObjectReference morFileManager = _context.getServiceContent().getFileManager(); @@ -180,7 +184,7 @@ public class DatastoreMO extends BaseMO { try { if (testExistence && !fileExists(fullPath)) { - String searchResult = searchFileInSubFolders(file.getFileName(), true); + String searchResult = searchFileInSubFolders(file.getFileName(), true, excludeFolders); if (searchResult == null) { return true; } else { @@ -352,8 +356,13 @@ public class DatastoreMO extends BaseMO { } public String searchFileInSubFolders(String fileName, boolean caseInsensitive) throws Exception { + return searchFileInSubFolders(fileName,caseInsensitive,null); + } + + public String searchFileInSubFolders(String fileName, boolean caseInsensitive, String excludeFolders) throws Exception { String datastorePath = "[" + getName() + "]"; String rootDirectoryFilePath = String.format("%s %s", datastorePath, fileName); + String[] searchExcludedFolders = getSearchExcludedFolders(excludeFolders); if (fileExists(rootDirectoryFilePath)) { return rootDirectoryFilePath; } @@ -380,6 +389,9 @@ public class DatastoreMO extends BaseMO { if (parentFolderPath.endsWith("]")) absoluteFileName += " "; absoluteFileName += fi.getPath(); + if(isValidCloudStackFolderPath(parentFolderPath, searchExcludedFolders)) { + return absoluteFileName; + } break; } } @@ -387,6 +399,20 @@ public class DatastoreMO extends BaseMO { return absoluteFileName; } + private String[] getSearchExcludedFolders(String excludeFolders) { + return excludeFolders != null ? excludeFolders.replaceAll("\\s","").split(",") : new String[] {}; + } + + private boolean isValidCloudStackFolderPath(String dataStoreFolderPath, String[] searchExcludedFolders) throws Exception { + String dsFolder = dataStoreFolderPath.replaceFirst("\\[" + getName() + "\\]", "").trim(); + for( String excludedFolder : searchExcludedFolders) { + if (dsFolder.startsWith(excludedFolder)) { + return false; + } + } + return true; + } + public boolean isAccessibleToHost(String hostValue) throws Exception { boolean isAccessible = true; List hostMounts = getHostMounts(); diff --git a/vmware-base/test/com/cloud/hypervisor/vmware/mo/DatastoreMOTest.java b/vmware-base/test/com/cloud/hypervisor/vmware/mo/DatastoreMOTest.java new file mode 100644 index 00000000000..394d199ce50 --- /dev/null +++ b/vmware-base/test/com/cloud/hypervisor/vmware/mo/DatastoreMOTest.java @@ -0,0 +1,114 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package com.cloud.hypervisor.vmware.mo; + +import com.cloud.hypervisor.vmware.util.VmwareClient; +import com.cloud.hypervisor.vmware.util.VmwareContext; +import com.vmware.vim25.FileInfo; +import com.vmware.vim25.HostDatastoreBrowserSearchResults; +import com.vmware.vim25.ManagedObjectReference; +import com.vmware.vim25.VimPortType; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.util.ArrayList; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.when; + +/** + * Created by sudharma_jain on 6/13/17. + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest(DatastoreMO.class) +public class DatastoreMOTest { + @Mock + VmwareContext _context ; + @Mock + VmwareClient _client; + @Mock + ManagedObjectReference _mor; + @Mock + HostDatastoreBrowserMO browserMo; + @Mock + VimPortType vimPortType; + + DatastoreMO datastoreMO ; + String fileName = "ROOT-5.vmdk"; + + + @Before + public void setUp() throws Exception { + + datastoreMO = new DatastoreMO(_context, _mor); + PowerMockito.whenNew(HostDatastoreBrowserMO.class).withAnyArguments().thenReturn(browserMo); + when(_context.getVimClient()).thenReturn(_client); + when(_client.getDynamicProperty(any(ManagedObjectReference.class), eq("name"))).thenReturn("252d36c96cfb32f48ce7756ccb79ae37"); + + ArrayList results = new ArrayList<>(); + + HostDatastoreBrowserSearchResults r1 = new HostDatastoreBrowserSearchResults(); + FileInfo f1 = new FileInfo(); + f1.setPath(fileName); + r1.getFile().add(f1); + r1.setFolderPath("[252d36c96cfb32f48ce7756ccb79ae37] .snapshot/hourly.2017-02-23_1705/i-2-5-VM/"); + + HostDatastoreBrowserSearchResults r2 = new HostDatastoreBrowserSearchResults(); + FileInfo f2 = new FileInfo(); + f2.setPath(fileName); + r2.getFile().add(f2); + r2.setFolderPath("[252d36c96cfb32f48ce7756ccb79ae37] .snapshot/hourly.2017-02-23_1605/i-2-5-VM/"); + + HostDatastoreBrowserSearchResults r3 = new HostDatastoreBrowserSearchResults(); + FileInfo f3 = new FileInfo(); + f3.setPath(fileName); + r3.getFile().add(f3); + r3.setFolderPath("[252d36c96cfb32f48ce7756ccb79ae37] i-2-5-VM/"); + + results.add(r1); + results.add(r2); + results.add(r3); + + when(browserMo.searchDatastore(any(String.class), any(String.class), eq(true))).thenReturn(null); + when(browserMo.searchDatastoreSubFolders(any(String.class),any(String.class), any(Boolean.class) )).thenReturn(results); + } + + @After + public void tearDown() throws Exception { + + } + + @Test + public void testSearchFileInSubFolders() throws Exception { + assertEquals("Unexpected Behavior: search should exclude .snapshot folder", "[252d36c96cfb32f48ce7756ccb79ae37] i-2-5-VM/ROOT-5.vmdk", datastoreMO.searchFileInSubFolders(fileName, false, ".snapshot") ); + } + + @Test + public void testSearchFileInSubFoldersWithExcludeMultipleFolders() throws Exception { + assertEquals("Unexpected Behavior: search should exclude folders", datastoreMO.searchFileInSubFolders(fileName, false, "i-2-5-VM, .snapshot/hourly.2017-02-23_1705"), "[252d36c96cfb32f48ce7756ccb79ae37] .snapshot/hourly.2017-02-23_1605/i-2-5-VM/ROOT-5.vmdk" ); + } + +} \ No newline at end of file