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();