Skip to content

Commit 343b065

Browse files
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.
1 parent 98d3231 commit 343b065

File tree

5 files changed

+146
-0
lines changed

5 files changed

+146
-0
lines changed

engine/schema/src/main/java/com/cloud/host/dao/HostDao.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ public interface HostDao extends GenericDao<HostVO, Long>, StateDao<Status, Stat
7575

7676
List<HostVO> findHypervisorHostInCluster(long clusterId);
7777

78+
HostVO findOldestExistentHypervisorHostInCluster(long clusterId);
79+
7880
List<HostVO> listAllUpAndEnabledNonHAHosts(Type type, Long clusterId, Long podId, long dcId, String haTag);
7981

8082
List<HostVO> findByDataCenterId(Long zoneId);

engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1168,6 +1168,23 @@ public List<HostVO> findHypervisorHostInCluster(long clusterId) {
11681168
return listBy(sc);
11691169
}
11701170

1171+
@Override
1172+
public HostVO findOldestExistentHypervisorHostInCluster(long clusterId) {
1173+
SearchCriteria<HostVO> sc = TypeClusterStatusSearch.create();
1174+
sc.setParameters("type", Host.Type.Routing);
1175+
sc.setParameters("cluster", clusterId);
1176+
sc.setParameters("status", Status.Up);
1177+
sc.setParameters("resourceState", ResourceState.Enabled);
1178+
Filter orderByFilter = new Filter(HostVO.class, "created", true, null, null);
1179+
1180+
List<HostVO> hosts = search(sc, orderByFilter, null, false);
1181+
if (hosts != null && hosts.size() > 0) {
1182+
return hosts.get(0);
1183+
}
1184+
1185+
return null;
1186+
}
1187+
11711188
@Override
11721189
public List<Long> listAllHosts(long zoneId) {
11731190
SearchCriteria<Long> sc = HostIdSearch.create();

plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import com.cloud.exception.OperationTimedoutException;
5050
import com.cloud.exception.ResourceInUseException;
5151
import com.cloud.host.Host;
52+
import com.cloud.host.HostVO;
5253
import com.cloud.host.Status;
5354
import com.cloud.host.dao.HostDao;
5455
import com.cloud.host.dao.HostDetailsDao;
@@ -100,6 +101,7 @@
100101
import com.cloud.utils.FileUtil;
101102
import com.cloud.utils.NumbersUtil;
102103
import com.cloud.utils.Pair;
104+
import com.cloud.utils.UriUtils;
103105
import com.cloud.utils.component.ManagerBase;
104106
import com.cloud.utils.concurrency.NamedThreadFactory;
105107
import com.cloud.utils.db.DB;
@@ -145,6 +147,7 @@
145147
import java.net.URI;
146148
import java.net.URISyntaxException;
147149
import java.net.URL;
150+
import java.net.URLDecoder;
148151
import java.rmi.RemoteException;
149152
import java.time.Duration;
150153
import java.time.Instant;
@@ -446,6 +449,29 @@ private void prepareHost(HostMO hostMo, String privateTrafficLabel) throws Excep
446449
}
447450
}
448451

452+
private HostMO getOldestExistentHostInCluster(Long clusterId, VmwareContext serviceContext) throws Exception {
453+
HostVO host = hostDao.findOldestExistentHypervisorHostInCluster(clusterId);
454+
if (host == null) {
455+
return null;
456+
}
457+
458+
ManagedObjectReference morSrcHost = HypervisorHostHelper.getHypervisorHostMorFromGuid(host.getGuid());
459+
if (morSrcHost == null) {
460+
Map<String, String> clusterDetails = clusterDetailsDao.findDetails(clusterId);
461+
if (clusterDetails.get("url") == null) {
462+
return null;
463+
}
464+
465+
URI uriForHost = new URI(UriUtils.encodeURIComponent(clusterDetails.get("url") + "/" + host.getName()));
466+
morSrcHost = serviceContext.getHostMorByPath(URLDecoder.decode(uriForHost.getPath(), "UTF-8"));
467+
if (morSrcHost == null) {
468+
return null;
469+
}
470+
}
471+
472+
return new HostMO(serviceContext, morSrcHost);
473+
}
474+
449475
@Override
450476
public List<ManagedObjectReference> addHostToPodCluster(VmwareContext serviceContext, long dcId, Long podId, Long clusterId, String hostInventoryPath)
451477
throws Exception {
@@ -498,6 +524,11 @@ public List<ManagedObjectReference> addHostToPodCluster(VmwareContext serviceCon
498524
// For ESX host, we need to enable host firewall to allow VNC access
499525
HostMO hostMo = new HostMO(serviceContext, mor);
500526
prepareHost(hostMo, privateTrafficLabel);
527+
HostMO olderHostMo = getOldestExistentHostInCluster(clusterId, serviceContext);
528+
if (olderHostMo != null) {
529+
hostMo.copyPortGroupsFromHost(olderHostMo);
530+
}
531+
501532
returnedHostList.add(mor);
502533
return returnedHostList;
503534
} else {

vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import com.vmware.vim25.HostNetworkTrafficShapingPolicy;
5252
import com.vmware.vim25.HostOpaqueNetworkInfo;
5353
import com.vmware.vim25.HostPortGroup;
54+
import com.vmware.vim25.HostPortGroupPort;
5455
import com.vmware.vim25.HostPortGroupSpec;
5556
import com.vmware.vim25.HostRuntimeInfo;
5657
import com.vmware.vim25.HostSystemConnectionState;
@@ -130,6 +131,43 @@ public HostPortGroupSpec getHostPortGroupSpec(String portGroupName) throws Excep
130131
return null;
131132
}
132133

134+
public List<HostPortGroupSpec> getHostPortGroupSpecs() throws Exception {
135+
HostNetworkInfo hostNetInfo = getHostNetworkInfo();
136+
if (hostNetInfo == null) {
137+
return null;
138+
}
139+
140+
List<HostPortGroup> portGroups = hostNetInfo.getPortgroup();
141+
if (CollectionUtils.isEmpty(portGroups)) {
142+
return null;
143+
}
144+
145+
List<HostPortGroupSpec> portGroupSpecs = new ArrayList<HostPortGroupSpec>();
146+
for (HostPortGroup portGroup : portGroups) {
147+
if (!isVMKernelPort(portGroup)) {
148+
portGroupSpecs.add(portGroup.getSpec());
149+
}
150+
}
151+
152+
return portGroupSpecs;
153+
}
154+
155+
private boolean isVMKernelPort(HostPortGroup portGroup) {
156+
assert (portGroup != null);
157+
List<HostPortGroupPort> ports = portGroup.getPort();
158+
if (CollectionUtils.isEmpty(ports)) {
159+
return false;
160+
}
161+
162+
for (HostPortGroupPort port : ports) {
163+
if (port.getType().equalsIgnoreCase("host")) {
164+
return true;
165+
}
166+
}
167+
168+
return false;
169+
}
170+
133171
@Override
134172
public String getHyperHostName() throws Exception {
135173
return getName();
@@ -1156,6 +1194,41 @@ public String getNetworkName(String netMorVal) throws Exception {
11561194
return networkName;
11571195
}
11581196

1197+
public void createPortGroup(HostPortGroupSpec spec) throws Exception {
1198+
if (spec == null) {
1199+
return;
1200+
}
1201+
1202+
synchronized (_mor.getValue().intern()) {
1203+
HostNetworkSystemMO hostNetMo = getHostNetworkSystemMO();
1204+
if (hostNetMo == null) {
1205+
return;
1206+
}
1207+
1208+
ManagedObjectReference morNetwork = getNetworkMor(spec.getName());
1209+
if (morNetwork == null) {
1210+
hostNetMo.addPortGroup(spec);
1211+
}
1212+
}
1213+
}
1214+
1215+
public void copyPortGroupsFromHost(HostMO srcHost) throws Exception {
1216+
if (srcHost == null) {
1217+
return;
1218+
}
1219+
1220+
List<HostPortGroupSpec> portGroupSpecs = srcHost.getHostPortGroupSpecs();
1221+
if (CollectionUtils.isEmpty(portGroupSpecs)) {
1222+
s_logger.debug("No port groups in the host: " + srcHost.getName());
1223+
return;
1224+
}
1225+
1226+
for (HostPortGroupSpec spec : portGroupSpecs) {
1227+
s_logger.debug("Creating port group: " + spec.getName() + " in the host: " + getName());
1228+
createPortGroup(spec);
1229+
}
1230+
}
1231+
11591232
public void createPortGroup(HostVirtualSwitch vSwitch, String portGroupName, Integer vlanId,
11601233
HostNetworkSecurityPolicy secPolicy, HostNetworkTrafficShapingPolicy shapingPolicy, long timeOutMs)
11611234
throws Exception {

vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2187,6 +2187,29 @@ public static String getOVFParamValue(VirtualMachineConfigSpec config) {
21872187
return paramVal;
21882188
}
21892189

2190+
public static ManagedObjectReference getHypervisorHostMorFromGuid(String guid) {
2191+
if (guid == null) {
2192+
return null;
2193+
}
2194+
2195+
String[] tokens = guid.split("@");
2196+
if (tokens == null || tokens.length != 2) {
2197+
s_logger.error("Invalid content in host guid");
2198+
return null;
2199+
}
2200+
2201+
String[] hostTokens = tokens[0].split(":");
2202+
if (hostTokens == null || hostTokens.length != 2) {
2203+
s_logger.error("Invalid content in host guid");
2204+
return null;
2205+
}
2206+
2207+
ManagedObjectReference morHyperHost = new ManagedObjectReference();
2208+
morHyperHost.setType(hostTokens[0]);
2209+
morHyperHost.setValue(hostTokens[1]);
2210+
2211+
return morHyperHost;
2212+
}
21902213

21912214
public static String getScsiController(Pair<String, String> controllerInfo, String recommendedController) {
21922215
String rootDiskController = controllerInfo.first();

0 commit comments

Comments
 (0)