From aa62144d6ae669a13a44c37edae3106204105dea Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Thu, 17 Aug 2023 15:04:11 +0200 Subject: [PATCH 1/3] server: try with all supported hypervisors (ordered, no duplicatios) when deploy a virtual router --- .../java/com/cloud/network/router/NetworkHelperImpl.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java b/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java index 934336066ccf..8e3fe50660f6 100644 --- a/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java +++ b/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java @@ -21,6 +21,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -502,7 +503,6 @@ public DomainRouterVO deployRouter(final RouterDeploymentDefinition routerDeploy // failed both times, throw the exception up final List hypervisors = getHypervisors(routerDeploymentDefinition); - int allocateRetry = 0; int startRetry = 0; DomainRouterVO router = null; for (final Iterator iter = hypervisors.iterator(); iter.hasNext();) { @@ -547,14 +547,12 @@ public DomainRouterVO deployRouter(final RouterDeploymentDefinition routerDeploy 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) { @@ -618,7 +616,7 @@ protected List getHypervisors(final RouterDeploymentDefinition r 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)); } /* From d317225c398a3f5f827576778139911b08d40a6b Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Tue, 22 Aug 2023 16:38:45 +0200 Subject: [PATCH 2/3] PR7877: fix startRouter exceptions --- .../java/com/cloud/network/router/NetworkHelperImpl.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java b/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java index 8e3fe50660f6..60c7ba988879 100644 --- a/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java +++ b/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java @@ -503,7 +503,6 @@ public DomainRouterVO deployRouter(final RouterDeploymentDefinition routerDeploy // failed both times, throw the exception up final List hypervisors = getHypervisors(routerDeploymentDefinition); - int startRetry = 0; DomainRouterVO router = null; for (final Iterator iter = hypervisors.iterator(); iter.hasNext();) { final HypervisorType hType = iter.next(); @@ -560,7 +559,7 @@ public DomainRouterVO deployRouter(final RouterDeploymentDefinition routerDeploy 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); @@ -568,8 +567,6 @@ public DomainRouterVO deployRouter(final RouterDeploymentDefinition routerDeploy } else { throw ex; } - } finally { - startRetry++; } } else { // return stopped router From d00b96cdd7f1a160d0a5fbfd057a4fcda1c999e3 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Wed, 23 Aug 2023 13:12:58 +0200 Subject: [PATCH 3/3] PR7877: check if zone has enough capacity in VR deployment (not start) --- .../network/router/NetworkHelperImpl.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java b/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java index 60c7ba988879..56860499ae02 100644 --- a/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java +++ b/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java @@ -36,6 +36,7 @@ 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; @@ -43,6 +44,7 @@ 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; @@ -168,6 +170,8 @@ public class NetworkHelperImpl implements NetworkHelper { RouterHealthCheckResultDao _routerHealthCheckResultDao; @Inject Ipv6Service ipv6Service; + @Inject + CapacityManager capacityMgr; protected final Map> hypervisorsMap = new HashMap<>(); @@ -507,6 +511,8 @@ public DomainRouterVO deployRouter(final RouterDeploymentDefinition routerDeploy for (final Iterator 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() @@ -577,6 +583,25 @@ public DomainRouterVO deployRouter(final RouterDeploymentDefinition routerDeploy return router; } + private void checkIfZoneHasCapacity(final DataCenter zone, final HypervisorType hypervisorType, final ServiceOfferingVO routerOffering) throws InsufficientServerCapacityException { + List 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 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 hypervisors) { // For non vpc we keep them all assuming all types in the list are // supported