Skip to content

Commit c533665

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 e8de07a commit c533665

File tree

5 files changed

+150
-0
lines changed

5 files changed

+150
-0
lines changed

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: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import com.vmware.vim25.HostNetworkTrafficShapingPolicy;
4949
import com.vmware.vim25.HostOpaqueNetworkInfo;
5050
import com.vmware.vim25.HostPortGroup;
51+
import com.vmware.vim25.HostPortGroupPort;
5152
import com.vmware.vim25.HostPortGroupSpec;
5253
import com.vmware.vim25.HostRuntimeInfo;
5354
import com.vmware.vim25.HostSystemConnectionState;
@@ -127,6 +128,43 @@ public HostPortGroupSpec getHostPortGroupSpec(String portGroupName) throws Excep
127128
return null;
128129
}
129130

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

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,6 +1571,30 @@ public void action(Long param) {
15711571
}
15721572
}
15731573

1574+
public static ManagedObjectReference getHypervisorHostMorFromGuid(String guid) {
1575+
if (guid == null) {
1576+
return null;
1577+
}
1578+
1579+
String[] tokens = guid.split("@");
1580+
if (tokens == null || tokens.length != 2) {
1581+
s_logger.error("Invalid content in host guid");
1582+
return null;
1583+
}
1584+
1585+
String[] hostTokens = tokens[0].split(":");
1586+
if (hostTokens == null || hostTokens.length != 2) {
1587+
s_logger.error("Invalid content in host guid");
1588+
return null;
1589+
}
1590+
1591+
ManagedObjectReference morHyperHost = new ManagedObjectReference();
1592+
morHyperHost.setType(hostTokens[0]);
1593+
morHyperHost.setValue(hostTokens[1]);
1594+
1595+
return morHyperHost;
1596+
}
1597+
15741598
public static String getScsiController(Pair<String, String> controllerInfo, String recommendedController) {
15751599
String rootDiskController = controllerInfo.first();
15761600
String dataDiskController = controllerInfo.second();

0 commit comments

Comments
 (0)