Skip to content

Commit 16d78f7

Browse files
Suresh Kumar AnapartiSuresh Kumar Anaparti
authored andcommitted
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 f231c8c commit 16d78f7

5 files changed

Lines changed: 151 additions & 0 deletions

File tree

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

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

7373
List<HostVO> findHypervisorHostInCluster(long clusterId);
7474

75+
HostVO findOldestExistentHypervisorHostInCluster(long clusterId);
76+
7577
/**
7678
* @param type
7779
* @param clusterId

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

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

1125+
@Override
1126+
public HostVO findOldestExistentHypervisorHostInCluster(long clusterId) {
1127+
SearchCriteria<HostVO> sc = TypeClusterStatusSearch.create();
1128+
sc.setParameters("type", Host.Type.Routing);
1129+
sc.setParameters("cluster", clusterId);
1130+
sc.setParameters("status", Status.Up);
1131+
sc.setParameters("resourceState", ResourceState.Enabled);
1132+
Filter orderByFilter = new Filter(HostVO.class, "created", true, null, null);
1133+
1134+
List<HostVO> hosts = search(sc, orderByFilter, null, false);
1135+
if (hosts != null && hosts.size() > 0) {
1136+
return hosts.get(0);
1137+
}
1138+
1139+
return null;
1140+
}
1141+
11251142
@Override
11261143
public List<Long> listAllHosts(long zoneId) {
11271144
SearchCriteria<Long> sc = HostIdSearch.create();

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.net.URI;
2222
import java.net.URISyntaxException;
2323
import java.net.URL;
24+
import java.net.URLDecoder;
2425
import java.rmi.RemoteException;
2526
import java.util.ArrayList;
2627
import java.util.HashMap;
@@ -71,6 +72,8 @@
7172
import com.cloud.exception.DiscoveryException;
7273
import com.cloud.exception.InvalidParameterValueException;
7374
import com.cloud.exception.ResourceInUseException;
75+
import com.cloud.host.dao.HostDao;
76+
import com.cloud.host.HostVO;
7477
import com.cloud.host.Host;
7578
import com.cloud.host.Status;
7679
import com.cloud.hypervisor.Hypervisor.HypervisorType;
@@ -121,6 +124,7 @@
121124
import com.cloud.utils.exception.CloudRuntimeException;
122125
import com.cloud.utils.script.Script;
123126
import com.cloud.utils.ssh.SshHelper;
127+
import com.cloud.utils.UriUtils;
124128
import com.cloud.vm.DomainRouterVO;
125129

126130
public class VmwareManagerImpl extends ManagerBase implements VmwareManager, VmwareStorageMount, Listener, VmwareDatacenterService {
@@ -139,6 +143,8 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
139143
@Inject
140144
private NetworkModel _netMgr;
141145
@Inject
146+
private HostDao _hostDao;
147+
@Inject
142148
private ClusterDao _clusterDao;
143149
@Inject
144150
private ClusterDetailsDao _clusterDetailsDao;
@@ -377,6 +383,29 @@ private void prepareHost(HostMO hostMo, String privateTrafficLabel) throws Excep
377383
}
378384
}
379385

386+
private HostMO getOldestExistentHostInCluster(Long clusterId, VmwareContext serviceContext) throws Exception {
387+
HostVO host = _hostDao.findOldestExistentHypervisorHostInCluster(clusterId);
388+
if (host == null) {
389+
return null;
390+
}
391+
392+
ManagedObjectReference morSrcHost = HypervisorHostHelper.getHypervisorHostMorFromGuid(host.getGuid());
393+
if (morSrcHost == null) {
394+
Map<String, String> clusterDetails = _clusterDetailsDao.findDetails(clusterId);
395+
if (clusterDetails.get("url") == null) {
396+
return null;
397+
}
398+
399+
URI uriForHost = new URI(UriUtils.encodeURIComponent(clusterDetails.get("url") + "/" + host.getName()));
400+
morSrcHost = serviceContext.getHostMorByPath(URLDecoder.decode(uriForHost.getPath(), "UTF-8"));
401+
if (morSrcHost == null) {
402+
return null;
403+
}
404+
}
405+
406+
return new HostMO(serviceContext, morSrcHost);
407+
}
408+
380409
@Override
381410
public List<ManagedObjectReference> addHostToPodCluster(VmwareContext serviceContext, long dcId, Long podId, Long clusterId, String hostInventoryPath)
382411
throws Exception {
@@ -429,6 +458,11 @@ public List<ManagedObjectReference> addHostToPodCluster(VmwareContext serviceCon
429458
// For ESX host, we need to enable host firewall to allow VNC access
430459
HostMO hostMo = new HostMO(serviceContext, mor);
431460
prepareHost(hostMo, privateTrafficLabel);
461+
HostMO olderHostMo = getOldestExistentHostInCluster(clusterId, serviceContext);
462+
if (olderHostMo != null) {
463+
hostMo.copyPortGroupsFromHost(olderHostMo);
464+
}
465+
432466
returnedHostList.add(mor);
433467
return returnedHostList;
434468
} else {

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

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.util.regex.Pattern;
2525

2626
import org.apache.log4j.Logger;
27+
import org.apache.commons.collections.CollectionUtils;
2728

2829
import com.google.gson.Gson;
2930
import com.vmware.vim25.AboutInfo;
@@ -48,6 +49,7 @@
4849
import com.vmware.vim25.HostNetworkTrafficShapingPolicy;
4950
import com.vmware.vim25.HostOpaqueNetworkInfo;
5051
import com.vmware.vim25.HostPortGroup;
52+
import com.vmware.vim25.HostPortGroupPort;
5153
import com.vmware.vim25.HostPortGroupSpec;
5254
import com.vmware.vim25.HostRuntimeInfo;
5355
import com.vmware.vim25.HostSystemConnectionState;
@@ -127,6 +129,43 @@ public HostPortGroupSpec getHostPortGroupSpec(String portGroupName) throws Excep
127129
return null;
128130
}
129131

132+
public List<HostPortGroupSpec> getHostPortGroupSpecs() throws Exception {
133+
HostNetworkInfo hostNetInfo = getHostNetworkInfo();
134+
if (hostNetInfo == null) {
135+
return null;
136+
}
137+
138+
List<HostPortGroup> portGroups = hostNetInfo.getPortgroup();
139+
if (CollectionUtils.isEmpty(portGroups)) {
140+
return null;
141+
}
142+
143+
List<HostPortGroupSpec> portGroupSpecs = new ArrayList<HostPortGroupSpec>();
144+
for (HostPortGroup portGroup : portGroups) {
145+
if (!isVMKernelPort(portGroup)) {
146+
portGroupSpecs.add(portGroup.getSpec());
147+
}
148+
}
149+
150+
return portGroupSpecs;
151+
}
152+
153+
private boolean isVMKernelPort(HostPortGroup portGroup) {
154+
assert (portGroup != null);
155+
List<HostPortGroupPort> ports = portGroup.getPort();
156+
if (CollectionUtils.isEmpty(ports)) {
157+
return false;
158+
}
159+
160+
for (HostPortGroupPort port : ports) {
161+
if (port.getType().equalsIgnoreCase("host")) {
162+
return true;
163+
}
164+
}
165+
166+
return false;
167+
}
168+
130169
@Override
131170
public String getHyperHostName() throws Exception {
132171
return getName();
@@ -1110,4 +1149,39 @@ public String getNetworkName(String netMorVal) throws Exception {
11101149
}
11111150
return networkName;
11121151
}
1152+
1153+
public void createPortGroup(HostPortGroupSpec spec) throws Exception {
1154+
if (spec == null) {
1155+
return;
1156+
}
1157+
1158+
synchronized (_mor.getValue().intern()) {
1159+
HostNetworkSystemMO hostNetMo = getHostNetworkSystemMO();
1160+
if (hostNetMo == null) {
1161+
return;
1162+
}
1163+
1164+
ManagedObjectReference morNetwork = getNetworkMor(spec.getName());
1165+
if (morNetwork == null) {
1166+
hostNetMo.addPortGroup(spec);
1167+
}
1168+
}
1169+
}
1170+
1171+
public void copyPortGroupsFromHost(HostMO srcHost) throws Exception {
1172+
if (srcHost == null) {
1173+
return;
1174+
}
1175+
1176+
List<HostPortGroupSpec> portGroupSpecs = srcHost.getHostPortGroupSpecs();
1177+
if (CollectionUtils.isEmpty(portGroupSpecs)) {
1178+
s_logger.debug("No port groups in the host: " + srcHost.getName());
1179+
return;
1180+
}
1181+
1182+
for (HostPortGroupSpec spec : portGroupSpecs) {
1183+
s_logger.debug("Creating port group: " + spec.getName() + " in the host: " + getName());
1184+
createPortGroup(spec);
1185+
}
1186+
}
11131187
}

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,6 +1584,30 @@ public void action(Long param) {
15841584
}
15851585
}
15861586

1587+
public static ManagedObjectReference getHypervisorHostMorFromGuid(String guid) {
1588+
if (guid == null) {
1589+
return null;
1590+
}
1591+
1592+
String[] tokens = guid.split("@");
1593+
if (tokens == null || tokens.length != 2) {
1594+
s_logger.error("Invalid content in host guid");
1595+
return null;
1596+
}
1597+
1598+
String[] hostTokens = tokens[0].split(":");
1599+
if (hostTokens == null || hostTokens.length != 2) {
1600+
s_logger.error("Invalid content in host guid");
1601+
return null;
1602+
}
1603+
1604+
ManagedObjectReference morHyperHost = new ManagedObjectReference();
1605+
morHyperHost.setType(hostTokens[0]);
1606+
morHyperHost.setValue(hostTokens[1]);
1607+
1608+
return morHyperHost;
1609+
}
1610+
15871611
public static String getScsiController(Pair<String, String> controllerInfo, String recommendedController) {
15881612
String rootDiskController = controllerInfo.first();
15891613
String dataDiskController = controllerInfo.second();

0 commit comments

Comments
 (0)