From 3883e74df4a35a134255771ea67014bfc20eca99 Mon Sep 17 00:00:00 2001 From: cloudops Date: Thu, 29 Apr 2021 20:34:58 -0400 Subject: [PATCH 1/4] draft fix to enable creation of vms with solidfire root volumes on vmware67 --- .../motion/StorageSystemDataMotionStrategy.java | 8 +++++--- .../resource/VmwareStorageProcessor.java | 3 ++- .../cloud/hypervisor/vmware/mo/DatastoreMO.java | 17 +++++++++-------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java index b48ae6d22dc0..743639d3ce2b 100644 --- a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java +++ b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java @@ -1413,10 +1413,12 @@ else if (volumeInfo.getFormat() == ImageFormat.OVA) { verifyCopyCmdAnswer(copyCmdAnswer, templateInfo); + // Seems like vmware 6.5 and above does not automatically remount the datastore after rescanning the storage. + // Not sure if this is needed. // If using VMware, have the host rescan its software HBA if dynamic discovery is in use. - if (HypervisorType.VMware.equals(templateInfo.getHypervisorType())) { - disconnectHostFromVolume(hostVO, volumeInfo.getPoolId(), volumeInfo.get_iScsiName()); - } + //if (HypervisorType.VMware.equals(templateInfo.getHypervisorType())) { + // disconnectHostFromVolume(hostVO, volumeInfo.getPoolId(), volumeInfo.get_iScsiName()); + //} } else { VolumeObjectTO newVolume = new VolumeObjectTO(); diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java index d2f7fc88a3b9..5fa572bc04f4 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java @@ -283,7 +283,8 @@ public ResignatureAnswer resignature(ResignatureCommand cmd) { } } - removeVmfsDatastore(cmd, hyperHost, datastoreName, storageHost, storagePortNumber, trimIqn(iScsiName), lstHosts); + //vmware 6.7 does not automatically mount datastores after rescanning once removed + //removeVmfsDatastore(cmd, hyperHost, datastoreName, storageHost, storagePortNumber, trimIqn(iScsiName), lstHosts); if (!foundExtent) { throw new CloudRuntimeException("Unable to locate the applicable extent"); diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DatastoreMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DatastoreMO.java index a76e7d94346d..94841c551003 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DatastoreMO.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DatastoreMO.java @@ -316,14 +316,15 @@ public boolean fileExists(String fileFullPath) throws Exception { DatastoreFile dirFile = new DatastoreFile(file.getDatastoreName(), file.getDir()); HostDatastoreBrowserMO browserMo = getHostDatastoreBrowserMO(); - - s_logger.info("Search file " + file.getFileName() + " on " + dirFile.getPath()); - HostDatastoreBrowserSearchResults results = browserMo.searchDatastore(dirFile.getPath(), file.getFileName(), true); - if (results != null) { - List info = results.getFile(); - if (info != null && info.size() > 0) { - s_logger.info("File " + fileFullPath + " exists on datastore"); - return true; + if(folderExists(String.format("[%s]", file.getDatastoreName()), file.getDir())){ + s_logger.info("Search file " + file.getFileName() + " on " + dirFile.getPath()); + HostDatastoreBrowserSearchResults results = browserMo.searchDatastore(dirFile.getPath(), file.getFileName(), true); + if (results != null) { + List info = results.getFile(); + if (info != null && info.size() > 0) { + s_logger.info("File " + fileFullPath + " exists on datastore"); + return true; + } } } From ff281cb63405aeee7acd7493ac9c92a2f21ecd7c Mon Sep 17 00:00:00 2001 From: cloudops Date: Fri, 30 Apr 2021 01:22:34 -0400 Subject: [PATCH 2/4] create fcd folder to maintain compatibility --- .../storage/resource/VmwareStorageLayoutHelper.java | 7 ++++++- .../com/cloud/hypervisor/vmware/mo/DatastoreMO.java | 11 +++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageLayoutHelper.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageLayoutHelper.java index 1cb57c37813d..a29ab9255f82 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageLayoutHelper.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageLayoutHelper.java @@ -168,12 +168,17 @@ public static String syncVolumeToVmDefaultFolder(DatacenterMO dcMo, String vmNam 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)) { s_logger.info("VM folder does not exist on target datastore, we will create one. vm: " + vmName + ", datastore: " + ds.getName()); - ds.makeDirectory(String.format("[%s] %s", ds.getName(), vmName), dcMo.getMor()); } + if (!ds.folderExists(String.format("[%s]", ds.getName()), "fcd")) { + s_logger.info("fcd folder does not exist on target datastore, we will create one. vm: " + vmName + ", datastore: " + ds.getName()); + ds.makeDirectory(String.format("[%s] %s", ds.getName(), "fcd"), dcMo.getMor()); + } + String[] vmdkLinkedCloneModeLegacyPair = getVmdkFilePairDatastorePath(ds, vmName, vmdkName, VmwareStorageLayoutType.CLOUDSTACK_LEGACY, true); String[] vmdkFullCloneModeLegacyPair = getVmdkFilePairDatastorePath(ds, vmName, vmdkName, VmwareStorageLayoutType.CLOUDSTACK_LEGACY, false); diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DatastoreMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DatastoreMO.java index 94841c551003..fc567e88db43 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DatastoreMO.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DatastoreMO.java @@ -314,9 +314,12 @@ public String[] listDirContent(String path) throws Exception { public boolean fileExists(String fileFullPath) throws Exception { DatastoreFile file = new DatastoreFile(fileFullPath); DatastoreFile dirFile = new DatastoreFile(file.getDatastoreName(), file.getDir()); - - HostDatastoreBrowserMO browserMo = getHostDatastoreBrowserMO(); - if(folderExists(String.format("[%s]", file.getDatastoreName()), file.getDir())){ + Boolean folderExists = true; + if(file.getDir() != ""){ + folderExists = folderExists(String.format("[%s]", file.getDatastoreName()), file.getDir()); + } + if(folderExists){ + HostDatastoreBrowserMO browserMo = getHostDatastoreBrowserMO(); s_logger.info("Search file " + file.getFileName() + " on " + dirFile.getPath()); HostDatastoreBrowserSearchResults results = browserMo.searchDatastore(dirFile.getPath(), file.getFileName(), true); if (results != null) { @@ -365,7 +368,7 @@ public long fileDiskSize(String fileFullPath) throws Exception { public boolean folderExists(String folderParentDatastorePath, String folderName) throws Exception { HostDatastoreBrowserMO browserMo = getHostDatastoreBrowserMO(); - + s_logger.info("Search folder " + folderName + " on " + folderParentDatastorePath); HostDatastoreBrowserSearchResults results = browserMo.searchDatastore(folderParentDatastorePath, folderName, true); if (results != null) { List info = results.getFile(); From e0b0edb9005c470ee394f11ddd363627c496b17e Mon Sep 17 00:00:00 2001 From: Pierre-Luc Dion Date: Tue, 11 May 2021 15:21:06 -0400 Subject: [PATCH 3/4] Update vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DatastoreMO.java Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com> --- .../main/java/com/cloud/hypervisor/vmware/mo/DatastoreMO.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DatastoreMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DatastoreMO.java index fc567e88db43..41a8ae93f90c 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DatastoreMO.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DatastoreMO.java @@ -318,7 +318,7 @@ public boolean fileExists(String fileFullPath) throws Exception { if(file.getDir() != ""){ folderExists = folderExists(String.format("[%s]", file.getDatastoreName()), file.getDir()); } - if(folderExists){ + if (folderExists){ HostDatastoreBrowserMO browserMo = getHostDatastoreBrowserMO(); s_logger.info("Search file " + file.getFileName() + " on " + dirFile.getPath()); HostDatastoreBrowserSearchResults results = browserMo.searchDatastore(dirFile.getPath(), file.getFileName(), true); From 96aa862d6388b36e997472b46e5298af85650b07 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 8 Jul 2022 13:14:13 +0530 Subject: [PATCH 4/4] refactor, address comments Signed-off-by: Abhishek Kumar --- engine/storage/datamotion/pom.xml | 6 ++++ .../StorageSystemDataMotionStrategy.java | 28 +++++++++++++------ .../resource/VmwareStorageLayoutHelper.java | 6 ++-- .../resource/VmwareStorageProcessor.java | 6 ++-- .../hypervisor/vmware/mo/DatastoreMO.java | 7 +++-- .../vmware/mo/HypervisorHostHelper.java | 16 +++++++++++ 6 files changed, 52 insertions(+), 17 deletions(-) diff --git a/engine/storage/datamotion/pom.xml b/engine/storage/datamotion/pom.xml index c0a70af6abdc..9249c50e39e1 100644 --- a/engine/storage/datamotion/pom.xml +++ b/engine/storage/datamotion/pom.xml @@ -45,5 +45,11 @@ ${project.version} runtime + + org.apache.maven + maven-artifact + 3.8.2 + compile + diff --git a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java index 743639d3ce2b..6745e9a44ef7 100644 --- a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java +++ b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java @@ -19,15 +19,18 @@ package org.apache.cloudstack.storage.motion; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; import java.util.UUID; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import javax.inject.Inject; @@ -68,9 +71,11 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; import org.apache.cloudstack.storage.to.VolumeObjectTO; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; +import org.apache.maven.artifact.versioning.ComparableVersion; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; @@ -133,10 +138,6 @@ import com.cloud.vm.VirtualMachineManager; import com.cloud.vm.dao.VMInstanceDao; import com.google.common.base.Preconditions; -import java.util.Arrays; -import java.util.HashSet; -import java.util.stream.Collectors; -import org.apache.commons.collections.CollectionUtils; public class StorageSystemDataMotionStrategy implements DataMotionStrategy { private static final Logger LOGGER = Logger.getLogger(StorageSystemDataMotionStrategy.class); @@ -187,6 +188,14 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy { @Inject VMTemplatePoolDao templatePoolDao; + private boolean isVMwareHostWithVersionOrHigher(Host host, String requiredVersion) { + if (!HypervisorType.VMware.equals(host.getHypervisorType()) || StringUtils.isBlank(requiredVersion)) { + return false; + } + ComparableVersion version = new ComparableVersion(host.getHypervisorVersion()); + return version.compareTo(new ComparableVersion(requiredVersion)) >= 0; + } + @Override public StrategyPriority canHandle(DataObject srcData, DataObject destData) { if (srcData instanceof SnapshotInfo) { @@ -1413,12 +1422,10 @@ else if (volumeInfo.getFormat() == ImageFormat.OVA) { verifyCopyCmdAnswer(copyCmdAnswer, templateInfo); - // Seems like vmware 6.5 and above does not automatically remount the datastore after rescanning the storage. - // Not sure if this is needed. // If using VMware, have the host rescan its software HBA if dynamic discovery is in use. - //if (HypervisorType.VMware.equals(templateInfo.getHypervisorType())) { - // disconnectHostFromVolume(hostVO, volumeInfo.getPoolId(), volumeInfo.get_iScsiName()); - //} + if (HypervisorType.VMware.equals(templateInfo.getHypervisorType())) { + disconnectHostFromVolume(hostVO, volumeInfo.getPoolId(), volumeInfo.get_iScsiName()); + } } else { VolumeObjectTO newVolume = new VolumeObjectTO(); @@ -2135,6 +2142,9 @@ protected String connectHostToVolume(Host host, long storagePoolId, String iqn) } private void disconnectHostFromVolume(Host host, long storagePoolId, String iqn) { + if (isVMwareHostWithVersionOrHigher(host, "6.5")) { + return; + } ModifyTargetsCommand modifyTargetsCommand = getModifyTargetsCommand(storagePoolId, iqn, false); sendModifyTargetsCommand(modifyTargetsCommand, host.getId()); diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageLayoutHelper.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageLayoutHelper.java index a29ab9255f82..455bf3a73a39 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageLayoutHelper.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageLayoutHelper.java @@ -174,9 +174,9 @@ public static String syncVolumeToVmDefaultFolder(DatacenterMO dcMo, String vmNam ds.makeDirectory(String.format("[%s] %s", ds.getName(), vmName), dcMo.getMor()); } - if (!ds.folderExists(String.format("[%s]", ds.getName()), "fcd")) { - s_logger.info("fcd folder does not exist on target datastore, we will create one. vm: " + vmName + ", datastore: " + ds.getName()); - ds.makeDirectory(String.format("[%s] %s", ds.getName(), "fcd"), dcMo.getMor()); + if (!ds.folderExists(String.format("[%s]", ds.getName()), HypervisorHostHelper.VSPHERE_DATASTORE_BASE_FOLDER)) { + s_logger.info(String.format("%s folder does not exist on target datastore, we will create one. vm: %s, datastore: %s", HypervisorHostHelper.VSPHERE_DATASTORE_BASE_FOLDER, vmName, ds.getName())); + ds.makeDirectory(String.format("[%s] %s", ds.getName(), HypervisorHostHelper.VSPHERE_DATASTORE_BASE_FOLDER), dcMo.getMor()); } String[] vmdkLinkedCloneModeLegacyPair = getVmdkFilePairDatastorePath(ds, vmName, vmdkName, VmwareStorageLayoutType.CLOUDSTACK_LEGACY, true); diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java index 5fa572bc04f4..f574c8bf6a51 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java @@ -283,8 +283,7 @@ public ResignatureAnswer resignature(ResignatureCommand cmd) { } } - //vmware 6.7 does not automatically mount datastores after rescanning once removed - //removeVmfsDatastore(cmd, hyperHost, datastoreName, storageHost, storagePortNumber, trimIqn(iScsiName), lstHosts); + removeVmfsDatastore(cmd, hyperHost, datastoreName, storageHost, storagePortNumber, trimIqn(iScsiName), lstHosts); if (!foundExtent) { throw new CloudRuntimeException("Unable to locate the applicable extent"); @@ -3118,6 +3117,9 @@ private void removeVmfsDatastore(Command cmd, VmwareHypervisorHost hyperHost, St private void removeVmfsDatastore(Command cmd, VmwareHypervisorHost hyperHost, String datastoreName, String storageIpAddress, int storagePortNumber, String iqn, List> lstHosts) throws Exception { + if (HypervisorHostHelper.isHostVersionEqualOrHigher(hyperHost, "6.5")) { + return; + } VmwareContext context = hostService.getServiceContext(cmd); unmountVmfsDatastore(context, hyperHost, datastoreName, lstHosts); diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DatastoreMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DatastoreMO.java index 41a8ae93f90c..33554e098eee 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DatastoreMO.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DatastoreMO.java @@ -21,6 +21,8 @@ import java.util.ArrayList; import java.util.List; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import com.cloud.exception.CloudException; @@ -315,7 +317,7 @@ public boolean fileExists(String fileFullPath) throws Exception { DatastoreFile file = new DatastoreFile(fileFullPath); DatastoreFile dirFile = new DatastoreFile(file.getDatastoreName(), file.getDir()); Boolean folderExists = true; - if(file.getDir() != ""){ + if(StringUtils.isNotBlank(file.getDir())){ folderExists = folderExists(String.format("[%s]", file.getDatastoreName()), file.getDir()); } if (folderExists){ @@ -323,8 +325,7 @@ public boolean fileExists(String fileFullPath) throws Exception { s_logger.info("Search file " + file.getFileName() + " on " + dirFile.getPath()); HostDatastoreBrowserSearchResults results = browserMo.searchDatastore(dirFile.getPath(), file.getFileName(), true); if (results != null) { - List info = results.getFile(); - if (info != null && info.size() > 0) { + if (CollectionUtils.isNotEmpty(results.getFile())) { s_logger.info("File " + fileFullPath + " exists on datastore"); return true; } diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java index 9f950024f13f..38d3c3ce93f3 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java @@ -2339,4 +2339,20 @@ public static String getMinimumHostHardwareVersion(VmwareHypervisorHost host1, V } return hardwareVersion; } + + public static boolean isHostVersionEqualOrHigher(VmwareHypervisorHost host, String requiredVersion) { + if (StringUtils.isBlank(requiredVersion)) { + return false; + } + HostMO hostMo = new HostMO(host.getContext(), host.getMor()); + String hostApiVersion = ""; + try { + hostApiVersion = hostMo.getHostAboutInfo().getApiVersion(); + } catch (Exception ignored) {} + if (StringUtils.isBlank(hostApiVersion)) { + return false; + } + ComparableVersion version = new ComparableVersion(hostApiVersion); + return version.compareTo(new ComparableVersion(requiredVersion)) >= 0; + } }