server: try with all supported hypervisors (ordered, no duplications) when deploy a virtual router (#7877)

This commit is contained in:
Wei Zhou 2023-08-25 11:49:03 +02:00 committed by GitHub
parent 8dc5fdd067
commit b19db10ea6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 29 additions and 9 deletions

View File

@ -21,6 +21,7 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@ -35,6 +36,7 @@ import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.network.router.deployment.RouterDeploymentDefinition;
import org.apache.cloudstack.utils.CloudStackVersion;
import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
@ -42,6 +44,7 @@ import com.cloud.agent.api.Answer;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.manager.Commands;
import com.cloud.alert.AlertManager;
import com.cloud.capacity.CapacityManager;
import com.cloud.configuration.Config;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenter;
@ -167,6 +170,8 @@ public class NetworkHelperImpl implements NetworkHelper {
RouterHealthCheckResultDao _routerHealthCheckResultDao;
@Inject
Ipv6Service ipv6Service;
@Inject
CapacityManager capacityMgr;
protected final Map<HypervisorType, ConfigKey<String>> hypervisorsMap = new HashMap<>();
@ -502,12 +507,12 @@ public class NetworkHelperImpl implements NetworkHelper {
// failed both times, throw the exception up
final List<HypervisorType> hypervisors = getHypervisors(routerDeploymentDefinition);
int allocateRetry = 0;
int startRetry = 0;
DomainRouterVO router = null;
for (final Iterator<HypervisorType> iter = hypervisors.iterator(); iter.hasNext();) {
final HypervisorType hType = iter.next();
try {
checkIfZoneHasCapacity(routerDeploymentDefinition.getDest().getDataCenter(), hType, routerOffering);
final long id = _routerDao.getNextInSequence(Long.class, "id");
if (s_logger.isDebugEnabled()) {
s_logger.debug(String.format("Allocating the VR with id=%s in datacenter %s with the hypervisor type %s", id, routerDeploymentDefinition.getDest()
@ -547,14 +552,12 @@ public class NetworkHelperImpl implements NetworkHelper {
reallocateRouterNetworks(routerDeploymentDefinition, router, template, null);
router = _routerDao.findById(router.getId());
} catch (final InsufficientCapacityException ex) {
if (allocateRetry < 2 && iter.hasNext()) {
if (iter.hasNext()) {
s_logger.debug("Failed to allocate the VR with hypervisor type " + hType + ", retrying one more time");
continue;
} else {
throw ex;
}
} finally {
allocateRetry++;
}
if (startRouter) {
@ -562,7 +565,7 @@ public class NetworkHelperImpl implements NetworkHelper {
router = startVirtualRouter(router, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount(), routerDeploymentDefinition.getParams());
break;
} catch (final InsufficientCapacityException ex) {
if (startRetry < 2 && iter.hasNext()) {
if (iter.hasNext()) {
s_logger.debug("Failed to start the VR " + router + " with hypervisor type " + hType + ", " + "destroying it and recreating one more time");
// destroy the router
destroyRouter(router.getId(), _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM), User.UID_SYSTEM);
@ -570,8 +573,6 @@ public class NetworkHelperImpl implements NetworkHelper {
} else {
throw ex;
}
} finally {
startRetry++;
}
} else {
// return stopped router
@ -582,6 +583,25 @@ public class NetworkHelperImpl implements NetworkHelper {
return router;
}
private void checkIfZoneHasCapacity(final DataCenter zone, final HypervisorType hypervisorType, final ServiceOfferingVO routerOffering) throws InsufficientServerCapacityException {
List <HostVO> hosts = _hostDao.listByDataCenterIdAndHypervisorType(zone.getId(), hypervisorType);
if (CollectionUtils.isEmpty(hosts)) {
String msg = String.format("Zone %s has no %s host available which is enabled and in Up state", zone.getName(), hypervisorType);
s_logger.debug(msg);
throw new InsufficientServerCapacityException(msg, DataCenter.class, zone.getId());
}
for (HostVO host : hosts) {
Pair<Boolean, Boolean> cpuCapabilityAndCapacity = capacityMgr.checkIfHostHasCpuCapabilityAndCapacity(host, routerOffering, false);
if (cpuCapabilityAndCapacity.first() && cpuCapabilityAndCapacity.second()) {
s_logger.debug("Host " + host + " has enough capacity for the router");
return;
}
}
String msg = String.format("Zone %s has no %s host which has enough capacity", zone.getName(), hypervisorType);
s_logger.debug(msg);
throw new InsufficientServerCapacityException(msg, DataCenter.class, zone.getId());
}
protected void filterSupportedHypervisors(final List<HypervisorType> hypervisors) {
// For non vpc we keep them all assuming all types in the list are
// supported
@ -618,7 +638,7 @@ public class NetworkHelperImpl implements NetworkHelper {
throw new InsufficientServerCapacityException("Unable to create virtual router, there are no clusters in the zone." + getNoHypervisorsErrMsgDetails(),
DataCenter.class, dest.getDataCenter().getId());
}
return hypervisors;
return new ArrayList(new LinkedHashSet<>(hypervisors));
}
/*