This is an automated email from the ASF dual-hosted git repository.
bhaisaab pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/master by this push:
new 3f69c83 CLOUDSTACK-9956: File search on the vmware datastore may
select wrong file if there are multiple files with same name (#2153)
3f69c83 is described below
commit 3f69c83f96f927f4a84b2d4b29bce168caf0530d
Author: SudharmaJain <[email protected]>
AuthorDate: Tue Sep 19 15:12:17 2017 +0530
CLOUDSTACK-9956: File search on the vmware datastore may select wrong file
if there are multiple files with same name (#2153)
If there are multiple files with the same name on vmware datastore, search
operation may select any one file during volume related operations. This
involves volume attach/detach, volume download, volume snapshot etc.
While using NetApp as the backup solution. This has .snapshot folder on the
datastore and sometimes files from this folder gets selected during volume
operations and the operation fails. Because of wrong selection of file
following exception can be observed while volume deletion.
2017-02-23 19:39:05,750 ERROR [c.c.s.r.VmwareStorageProcessor]
(DirectAgent-304:ctx-a1dbf5d8 ac.local) delete volume failed due to Exception:
java.lang.RuntimeException
Message: Cannot delete file [4cbcd46d44c53f5c8244c0aad26a97e1]
.snapshot/hourly.2017-02-23_1605/r-97-VM/ROOT-97.vmdk
To fix this behavior I have added a global configuration by name
vmware.search.exclude.folders which can be comma separated list of folder paths.
I have also added a unit test to test the new method.
---
.../src/com/cloud/hypervisor/guru/VMwareGuru.java | 1 +
.../hypervisor/vmware/manager/VmwareManager.java | 3 +
.../vmware/manager/VmwareManagerImpl.java | 2 +-
.../vmware/manager/VmwareStorageManagerImpl.java | 11 +-
.../hypervisor/vmware/resource/VmwareResource.java | 14 +--
.../resource/VmwareStorageLayoutHelper.java | 35 +++++--
.../storage/resource/VmwareStorageProcessor.java | 23 +++--
.../cloud/hypervisor/vmware/mo/DatastoreMO.java | 28 ++++-
.../hypervisor/vmware/mo/DatastoreMOTest.java | 114 +++++++++++++++++++++
9 files changed, 199 insertions(+), 32 deletions(-)
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 7b6accf..d8076fd 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, Long>(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 65963eb..4a4d2ea 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<Boolean> s_vmwareCleanOldWorderVMs = new
ConfigKey<Boolean>("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<String> s_vmwareSearchExcludeFolder = new
ConfigKey<String>("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 c003b44..53e3239 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 3158ad4..00298ce 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 b8a3495..ccb5d0f 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 4096333..fc79a4b 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 8026575..012556e 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 290e1a0..1152ba5 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<DatastoreHostMount> 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 0000000..394d199
--- /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<HostDatastoreBrowserSearchResults> 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
--
To stop receiving notification emails like this one, please contact
['"[email protected]" <[email protected]>'].