Skip to content

Commit b19db10

Browse files
server: try with all supported hypervisors (ordered, no duplications) when deploy a virtual router (#7877)
1 parent 8dc5fdd commit b19db10

File tree

1 file changed

+29
-9
lines changed

1 file changed

+29
-9
lines changed

server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.HashMap;
2222
import java.util.Iterator;
2323
import java.util.LinkedHashMap;
24+
import java.util.LinkedHashSet;
2425
import java.util.List;
2526
import java.util.Map;
2627

@@ -35,13 +36,15 @@
3536
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
3637
import org.apache.cloudstack.network.router.deployment.RouterDeploymentDefinition;
3738
import org.apache.cloudstack.utils.CloudStackVersion;
39+
import org.apache.commons.collections.CollectionUtils;
3840
import org.apache.log4j.Logger;
3941

4042
import com.cloud.agent.AgentManager;
4143
import com.cloud.agent.api.Answer;
4244
import com.cloud.agent.api.to.NicTO;
4345
import com.cloud.agent.manager.Commands;
4446
import com.cloud.alert.AlertManager;
47+
import com.cloud.capacity.CapacityManager;
4548
import com.cloud.configuration.Config;
4649
import com.cloud.dc.ClusterVO;
4750
import com.cloud.dc.DataCenter;
@@ -167,6 +170,8 @@ public class NetworkHelperImpl implements NetworkHelper {
167170
RouterHealthCheckResultDao _routerHealthCheckResultDao;
168171
@Inject
169172
Ipv6Service ipv6Service;
173+
@Inject
174+
CapacityManager capacityMgr;
170175

171176
protected final Map<HypervisorType, ConfigKey<String>> hypervisorsMap = new HashMap<>();
172177

@@ -502,12 +507,12 @@ public DomainRouterVO deployRouter(final RouterDeploymentDefinition routerDeploy
502507
// failed both times, throw the exception up
503508
final List<HypervisorType> hypervisors = getHypervisors(routerDeploymentDefinition);
504509

505-
int allocateRetry = 0;
506-
int startRetry = 0;
507510
DomainRouterVO router = null;
508511
for (final Iterator<HypervisorType> iter = hypervisors.iterator(); iter.hasNext();) {
509512
final HypervisorType hType = iter.next();
510513
try {
514+
checkIfZoneHasCapacity(routerDeploymentDefinition.getDest().getDataCenter(), hType, routerOffering);
515+
511516
final long id = _routerDao.getNextInSequence(Long.class, "id");
512517
if (s_logger.isDebugEnabled()) {
513518
s_logger.debug(String.format("Allocating the VR with id=%s in datacenter %s with the hypervisor type %s", id, routerDeploymentDefinition.getDest()
@@ -547,31 +552,27 @@ public DomainRouterVO deployRouter(final RouterDeploymentDefinition routerDeploy
547552
reallocateRouterNetworks(routerDeploymentDefinition, router, template, null);
548553
router = _routerDao.findById(router.getId());
549554
} catch (final InsufficientCapacityException ex) {
550-
if (allocateRetry < 2 && iter.hasNext()) {
555+
if (iter.hasNext()) {
551556
s_logger.debug("Failed to allocate the VR with hypervisor type " + hType + ", retrying one more time");
552557
continue;
553558
} else {
554559
throw ex;
555560
}
556-
} finally {
557-
allocateRetry++;
558561
}
559562

560563
if (startRouter) {
561564
try {
562565
router = startVirtualRouter(router, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount(), routerDeploymentDefinition.getParams());
563566
break;
564567
} catch (final InsufficientCapacityException ex) {
565-
if (startRetry < 2 && iter.hasNext()) {
568+
if (iter.hasNext()) {
566569
s_logger.debug("Failed to start the VR " + router + " with hypervisor type " + hType + ", " + "destroying it and recreating one more time");
567570
// destroy the router
568571
destroyRouter(router.getId(), _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM), User.UID_SYSTEM);
569572
continue;
570573
} else {
571574
throw ex;
572575
}
573-
} finally {
574-
startRetry++;
575576
}
576577
} else {
577578
// return stopped router
@@ -582,6 +583,25 @@ public DomainRouterVO deployRouter(final RouterDeploymentDefinition routerDeploy
582583
return router;
583584
}
584585

586+
private void checkIfZoneHasCapacity(final DataCenter zone, final HypervisorType hypervisorType, final ServiceOfferingVO routerOffering) throws InsufficientServerCapacityException {
587+
List <HostVO> hosts = _hostDao.listByDataCenterIdAndHypervisorType(zone.getId(), hypervisorType);
588+
if (CollectionUtils.isEmpty(hosts)) {
589+
String msg = String.format("Zone %s has no %s host available which is enabled and in Up state", zone.getName(), hypervisorType);
590+
s_logger.debug(msg);
591+
throw new InsufficientServerCapacityException(msg, DataCenter.class, zone.getId());
592+
}
593+
for (HostVO host : hosts) {
594+
Pair<Boolean, Boolean> cpuCapabilityAndCapacity = capacityMgr.checkIfHostHasCpuCapabilityAndCapacity(host, routerOffering, false);
595+
if (cpuCapabilityAndCapacity.first() && cpuCapabilityAndCapacity.second()) {
596+
s_logger.debug("Host " + host + " has enough capacity for the router");
597+
return;
598+
}
599+
}
600+
String msg = String.format("Zone %s has no %s host which has enough capacity", zone.getName(), hypervisorType);
601+
s_logger.debug(msg);
602+
throw new InsufficientServerCapacityException(msg, DataCenter.class, zone.getId());
603+
}
604+
585605
protected void filterSupportedHypervisors(final List<HypervisorType> hypervisors) {
586606
// For non vpc we keep them all assuming all types in the list are
587607
// supported
@@ -618,7 +638,7 @@ protected List<HypervisorType> getHypervisors(final RouterDeploymentDefinition r
618638
throw new InsufficientServerCapacityException("Unable to create virtual router, there are no clusters in the zone." + getNoHypervisorsErrMsgDetails(),
619639
DataCenter.class, dest.getDataCenter().getId());
620640
}
621-
return hypervisors;
641+
return new ArrayList(new LinkedHashSet<>(hypervisors));
622642
}
623643

624644
/*

0 commit comments

Comments
 (0)