This is an automated email from the ASF dual-hosted git repository.

nvazquez pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/main by this push:
     new 7f4f3f7  [VMware DRS] Adding new host to DRS cluster does not 
participate in load balancing. (#1257)
7f4f3f7 is described below

commit 7f4f3f7f1afbf0b61bc45351044c4b1dd91180d5
Author: sureshanaparti <[email protected]>
AuthorDate: Fri Aug 27 22:52:47 2021 +0530

    [VMware DRS] Adding new host to DRS cluster does not participate in load 
balancing. (#1257)
    
    * CLOUDSTACK-9175: [VMware DRS] Adding new host to DRS cluster does not 
participate in load balancing.
    
    Summary: When a new host is added to a cluster, Cloudstack doesn't create 
all the port groups (created by cloudstack earlier in other hosts) present in 
the cluster. Since the new host doesn't have all the necessary networking port 
groups of cloudstack, it is not eligible to participate in DRS load balancing 
or HA.
    
    Solution: When adding a host to the cluster in Cloudstack, use VMware API 
to find the list of unique port groups on a previously added host (older host 
in the cluster) if exists and then create them on the new host.
    
    * Added few checks for cluster details
---
 .../src/main/java/com/cloud/host/dao/HostDao.java  |  2 +
 .../main/java/com/cloud/host/dao/HostDaoImpl.java  | 17 +++++
 .../vmware/manager/VmwareManagerImpl.java          | 33 ++++++++++
 .../com/cloud/hypervisor/vmware/mo/HostMO.java     | 73 ++++++++++++++++++++++
 .../hypervisor/vmware/mo/HypervisorHostHelper.java | 23 +++++++
 5 files changed, 148 insertions(+)

diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java 
b/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java
index 12207da..1ea65e2 100644
--- a/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java
+++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java
@@ -75,6 +75,8 @@ public interface HostDao extends GenericDao<HostVO, Long>, 
StateDao<Status, Stat
 
     List<HostVO> findHypervisorHostInCluster(long clusterId);
 
+    HostVO findOldestExistentHypervisorHostInCluster(long clusterId);
+
     List<HostVO> listAllUpAndEnabledNonHAHosts(Type type, Long clusterId, Long 
podId, long dcId, String haTag);
 
     List<HostVO> findByDataCenterId(Long zoneId);
diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java 
b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java
index 58248ad..7c2e109 100644
--- a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java
+++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java
@@ -1169,6 +1169,23 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, 
Long> implements HostDao
     }
 
     @Override
+    public HostVO findOldestExistentHypervisorHostInCluster(long clusterId) {
+        SearchCriteria<HostVO> sc = TypeClusterStatusSearch.create();
+        sc.setParameters("type", Host.Type.Routing);
+        sc.setParameters("cluster", clusterId);
+        sc.setParameters("status", Status.Up);
+        sc.setParameters("resourceState", ResourceState.Enabled);
+        Filter orderByFilter = new Filter(HostVO.class, "created", true, null, 
null);
+
+        List<HostVO> hosts = search(sc, orderByFilter, null, false);
+        if (hosts != null && hosts.size() > 0) {
+            return hosts.get(0);
+        }
+
+        return null;
+    }
+
+    @Override
     public List<Long> listAllHosts(long zoneId) {
         SearchCriteria<Long> sc = HostIdSearch.create();
         sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
diff --git 
a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
 
b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
index f3b6dcb..04c6bc3 100644
--- 
a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
+++ 
b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
@@ -49,6 +49,7 @@ import com.cloud.exception.InvalidParameterValueException;
 import com.cloud.exception.OperationTimedoutException;
 import com.cloud.exception.ResourceInUseException;
 import com.cloud.host.Host;
+import com.cloud.host.HostVO;
 import com.cloud.host.Status;
 import com.cloud.host.dao.HostDao;
 import com.cloud.host.dao.HostDetailsDao;
@@ -100,6 +101,7 @@ import com.cloud.template.TemplateManager;
 import com.cloud.utils.FileUtil;
 import com.cloud.utils.NumbersUtil;
 import com.cloud.utils.Pair;
+import com.cloud.utils.UriUtils;
 import com.cloud.utils.component.ManagerBase;
 import com.cloud.utils.concurrency.NamedThreadFactory;
 import com.cloud.utils.db.DB;
@@ -136,6 +138,8 @@ import 
org.apache.cloudstack.storage.command.CheckDataStoreStoragePolicyComplain
 import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
 import org.apache.cloudstack.utils.identity.ManagementServerNode;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Logger;
 
 import javax.inject.Inject;
@@ -145,6 +149,7 @@ import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
+import java.net.URLDecoder;
 import java.rmi.RemoteException;
 import java.time.Duration;
 import java.time.Instant;
@@ -446,6 +451,29 @@ public class VmwareManagerImpl extends ManagerBase 
implements VmwareManager, Vmw
         }
     }
 
+    private HostMO getOldestExistentHostInCluster(Long clusterId, 
VmwareContext serviceContext) throws Exception {
+        HostVO host = 
hostDao.findOldestExistentHypervisorHostInCluster(clusterId);
+        if (host == null) {
+            return null;
+        }
+
+        ManagedObjectReference morSrcHost = 
HypervisorHostHelper.getHypervisorHostMorFromGuid(host.getGuid());
+        if (morSrcHost == null) {
+            Map<String, String> clusterDetails = 
clusterDetailsDao.findDetails(clusterId);
+            if (MapUtils.isEmpty(clusterDetails) || 
StringUtils.isBlank(clusterDetails.get("url"))) {
+                return null;
+            }
+
+            URI uriForHost = new 
URI(UriUtils.encodeURIComponent(clusterDetails.get("url") + "/" + 
host.getName()));
+            morSrcHost = 
serviceContext.getHostMorByPath(URLDecoder.decode(uriForHost.getPath(), 
"UTF-8"));
+            if (morSrcHost == null) {
+                return null;
+            }
+        }
+
+        return new HostMO(serviceContext, morSrcHost);
+    }
+
     @Override
     public List<ManagedObjectReference> addHostToPodCluster(VmwareContext 
serviceContext, long dcId, Long podId, Long clusterId, String hostInventoryPath)
             throws Exception {
@@ -498,6 +526,11 @@ public class VmwareManagerImpl extends ManagerBase 
implements VmwareManager, Vmw
                 // For ESX host, we need to enable host firewall to allow VNC 
access
                 HostMO hostMo = new HostMO(serviceContext, mor);
                 prepareHost(hostMo, privateTrafficLabel);
+                HostMO olderHostMo = getOldestExistentHostInCluster(clusterId, 
serviceContext);
+                if (olderHostMo != null) {
+                    hostMo.copyPortGroupsFromHost(olderHostMo);
+                }
+
                 returnedHostList.add(mor);
                 return returnedHostList;
             } else {
diff --git 
a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java 
b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java
index ab3f109..a2435b1 100644
--- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java
+++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java
@@ -51,6 +51,7 @@ import com.vmware.vim25.HostNetworkSecurityPolicy;
 import com.vmware.vim25.HostNetworkTrafficShapingPolicy;
 import com.vmware.vim25.HostOpaqueNetworkInfo;
 import com.vmware.vim25.HostPortGroup;
+import com.vmware.vim25.HostPortGroupPort;
 import com.vmware.vim25.HostPortGroupSpec;
 import com.vmware.vim25.HostRuntimeInfo;
 import com.vmware.vim25.HostSystemConnectionState;
@@ -130,6 +131,43 @@ public class HostMO extends BaseMO implements 
VmwareHypervisorHost {
         return null;
     }
 
+    public List<HostPortGroupSpec> getHostPortGroupSpecs() throws Exception {
+        HostNetworkInfo hostNetInfo = getHostNetworkInfo();
+        if (hostNetInfo == null) {
+            return null;
+        }
+
+        List<HostPortGroup> portGroups = hostNetInfo.getPortgroup();
+        if (CollectionUtils.isEmpty(portGroups)) {
+            return null;
+        }
+
+        List<HostPortGroupSpec> portGroupSpecs = new 
ArrayList<HostPortGroupSpec>();
+        for (HostPortGroup portGroup : portGroups) {
+            if (!isVMKernelPort(portGroup)) {
+                portGroupSpecs.add(portGroup.getSpec());
+            }
+        }
+
+        return portGroupSpecs;
+    }
+
+    private boolean isVMKernelPort(HostPortGroup portGroup) {
+        assert (portGroup != null);
+        List<HostPortGroupPort> ports = portGroup.getPort();
+        if (CollectionUtils.isEmpty(ports)) {
+            return false;
+        }
+
+        for (HostPortGroupPort port : ports) {
+            if (port.getType().equalsIgnoreCase("host")) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
     @Override
     public String getHyperHostName() throws Exception {
         return getName();
@@ -1156,6 +1194,41 @@ public class HostMO extends BaseMO implements 
VmwareHypervisorHost {
         return networkName;
     }
 
+    public void createPortGroup(HostPortGroupSpec spec) throws Exception {
+        if (spec == null) {
+            return;
+        }
+
+        synchronized (_mor.getValue().intern()) {
+            HostNetworkSystemMO hostNetMo = getHostNetworkSystemMO();
+            if (hostNetMo == null) {
+                return;
+            }
+
+            ManagedObjectReference morNetwork = getNetworkMor(spec.getName());
+            if (morNetwork == null) {
+                hostNetMo.addPortGroup(spec);
+            }
+        }
+    }
+
+    public void copyPortGroupsFromHost(HostMO srcHost) throws Exception {
+        if (srcHost == null) {
+            return;
+        }
+
+        List<HostPortGroupSpec> portGroupSpecs = 
srcHost.getHostPortGroupSpecs();
+        if (CollectionUtils.isEmpty(portGroupSpecs)) {
+            s_logger.debug("No port groups in the host: " + srcHost.getName());
+            return;
+        }
+
+        for (HostPortGroupSpec spec : portGroupSpecs) {
+            s_logger.debug("Creating port group: " + spec.getName() + " in the 
host: " + getName());
+            createPortGroup(spec);
+        }
+    }
+
     public void createPortGroup(HostVirtualSwitch vSwitch, String 
portGroupName, Integer vlanId,
             HostNetworkSecurityPolicy secPolicy, 
HostNetworkTrafficShapingPolicy shapingPolicy, long timeOutMs)
             throws Exception {
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 df85886..090e769 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
@@ -2187,6 +2187,29 @@ public class HypervisorHostHelper {
        return paramVal;
    }
 
+    public static ManagedObjectReference getHypervisorHostMorFromGuid(String 
guid) {
+        if (guid == null) {
+            return null;
+        }
+
+        String[] tokens = guid.split("@");
+        if (tokens == null || tokens.length != 2) {
+            s_logger.error("Invalid content in host guid");
+            return null;
+        }
+
+        String[] hostTokens = tokens[0].split(":");
+        if (hostTokens == null || hostTokens.length != 2) {
+            s_logger.error("Invalid content in host guid");
+            return null;
+        }
+
+        ManagedObjectReference morHyperHost = new ManagedObjectReference();
+        morHyperHost.setType(hostTokens[0]);
+        morHyperHost.setValue(hostTokens[1]);
+
+        return morHyperHost;
+    }
 
     public static String getScsiController(Pair<String, String> 
controllerInfo, String recommendedController) {
         String rootDiskController = controllerInfo.first();

Reply via email to