Refactor to include network creation as actual deployment Conflicts: server/src/org/cloud/network/router/deployment/RouterDeploymentDefinition.java server/src/org/cloud/network/router/deployment/RouterDeploymentDefinitionBuilder.java server/src/org/cloud/network/router/deployment/VpcRouterDeploymentDefinition.java server/test/org/cloud/network/router/deployment/VpcRouterDeploymentDefinitionTest.java
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/2da3ceda Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/2da3ceda Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/2da3ceda Branch: refs/heads/master Commit: 2da3ceda31f08404f309e0bf384ed809e00ae175 Parents: 00dc8a7 Author: Antonio Fornie <afor...@schubergphilis.com> Authored: Tue Aug 19 04:57:46 2014 -0500 Committer: wilderrodrigues <wrodrig...@schubergphilis.com> Committed: Tue Oct 14 15:02:12 2014 +0200 ---------------------------------------------------------------------- .../network/router/NetworkGeneralHelper.java | 862 ------------------- .../com/cloud/network/router/NetworkHelper.java | 87 ++ .../cloud/network/router/NetworkHelperImpl.java | 820 ++++++++++++++++++ .../VirtualNetworkApplianceManagerImpl.java | 2 +- .../cloud/network/router/VpcNetworkHelper.java | 15 + .../network/router/VpcNetworkHelperImpl.java | 210 +++++ .../VpcVirtualNetworkApplianceManagerImpl.java | 2 +- .../router/VpcVirtualNetworkHelperImpl.java | 121 --- .../com/cloud/network/rules/RuleApplier.java | 4 +- .../rules/VirtualNetworkApplianceFactory.java | 4 +- .../network/topology/BasicNetworkTopology.java | 4 +- .../network/topology/BasicNetworkVisitor.java | 4 +- .../deployment/RouterDeploymentDefinition.java | 8 +- .../RouterDeploymentDefinitionBuilder.java | 12 +- .../VpcRouterDeploymentDefinition.java | 61 +- .../RouterDeploymentDefinitionTestBase.java | 4 +- .../VpcRouterDeploymentDefinitionTest.java | 83 +- 17 files changed, 1223 insertions(+), 1080 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2da3ceda/server/src/com/cloud/network/router/NetworkGeneralHelper.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/router/NetworkGeneralHelper.java b/server/src/com/cloud/network/router/NetworkGeneralHelper.java deleted file mode 100644 index 9768de2..0000000 --- a/server/src/com/cloud/network/router/NetworkGeneralHelper.java +++ /dev/null @@ -1,862 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package com.cloud.network.router; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.TreeSet; - -import javax.inject.Inject; - -import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; -import org.apache.log4j.Logger; -import org.cloud.network.router.deployment.RouterDeploymentDefinition; -import org.cloud.network.router.deployment.VpcRouterDeploymentDefinition; - -import com.cloud.agent.AgentManager; -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.BumpUpPriorityCommand; -import com.cloud.agent.api.routing.NetworkElementCommand; -import com.cloud.agent.api.to.NicTO; -import com.cloud.agent.manager.Commands; -import com.cloud.alert.AlertManager; -import com.cloud.dc.ClusterVO; -import com.cloud.dc.DataCenter; -import com.cloud.dc.Pod; -import com.cloud.dc.dao.ClusterDao; -import com.cloud.dc.dao.VlanDao; -import com.cloud.deploy.DataCenterDeployment; -import com.cloud.deploy.DeployDestination; -import com.cloud.deploy.DeploymentPlan; -import com.cloud.deploy.DeploymentPlanner.ExcludeList; -import com.cloud.exception.AgentUnavailableException; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientAddressCapacityException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.InsufficientServerCapacityException; -import com.cloud.exception.OperationTimedoutException; -import com.cloud.exception.ResourceUnavailableException; -import com.cloud.exception.StorageUnavailableException; -import com.cloud.host.HostVO; -import com.cloud.host.Status; -import com.cloud.host.dao.HostDao; -import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.maint.Version; -import com.cloud.network.IpAddress; -import com.cloud.network.IpAddressManager; -import com.cloud.network.Network; -import com.cloud.network.NetworkModel; -import com.cloud.network.Networks.BroadcastDomainType; -import com.cloud.network.Networks.IsolationType; -import com.cloud.network.Networks.TrafficType; -import com.cloud.network.VirtualNetworkApplianceService; -import com.cloud.network.addr.PublicIp; -import com.cloud.network.dao.IPAddressDao; -import com.cloud.network.dao.IPAddressVO; -import com.cloud.network.dao.NetworkDao; -import com.cloud.network.dao.NetworkVO; -import com.cloud.network.dao.UserIpv6AddressDao; -import com.cloud.network.router.VirtualRouter.RedundantState; -import com.cloud.network.router.VirtualRouter.Role; -import com.cloud.network.vpc.PrivateGateway; -import com.cloud.network.vpc.VpcManager; -import com.cloud.network.vpn.Site2SiteVpnManager; -import com.cloud.offering.NetworkOffering; -import com.cloud.resource.ResourceManager; -import com.cloud.service.ServiceOfferingVO; -import com.cloud.service.dao.ServiceOfferingDao; -import com.cloud.storage.VMTemplateVO; -import com.cloud.storage.Volume; -import com.cloud.storage.VolumeVO; -import com.cloud.storage.dao.VMTemplateDao; -import com.cloud.storage.dao.VolumeDao; -import com.cloud.user.Account; -import com.cloud.user.AccountManager; -import com.cloud.user.User; -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.net.NetUtils; -import com.cloud.vm.DomainRouterVO; -import com.cloud.vm.Nic; -import com.cloud.vm.NicProfile; -import com.cloud.vm.NicVO; -import com.cloud.vm.VirtualMachine.State; -import com.cloud.vm.VirtualMachineManager; -import com.cloud.vm.VirtualMachineName; -import com.cloud.vm.VirtualMachineProfile.Param; -import com.cloud.vm.dao.DomainRouterDao; -import com.cloud.vm.dao.NicDao; - -public class NetworkGeneralHelper { - - private static final Logger s_logger = Logger.getLogger(NetworkGeneralHelper.class); - - @Inject - private NicDao _nicDao; - @Inject - private NetworkDao _networkDao; - @Inject - private DomainRouterDao _routerDao; - @Inject - private AgentManager _agentMgr; - @Inject - private AlertManager _alertMgr; - @Inject - private NetworkModel _networkModel; - @Inject - private VirtualMachineManager _itMgr; - @Inject - private AccountManager _accountMgr; - @Inject - private Site2SiteVpnManager _s2sVpnMgr; - @Inject - private HostDao _hostDao; - @Inject - private VolumeDao _volumeDao; - @Inject - private ServiceOfferingDao _serviceOfferingDao; - @Inject - private VMTemplateDao _templateDao; - @Inject - private ResourceManager _resourceMgr; - @Inject - private ClusterDao _clusterDao; - @Inject - private IPAddressDao _ipAddressDao; - @Inject - private IpAddressManager _ipAddrMgr; - @Inject - private UserIpv6AddressDao _ipv6Dao; - @Inject - private NetworkOrchestrationService _networkMgr; - @Inject - protected VpcVirtualNetworkHelperImpl _vpcHelper; - @Inject - protected VpcManager _vpcMgr; - @Inject - protected VlanDao _vlanDao; - - - public String getRouterControlIp(final long routerId) { - String routerControlIpAddress = null; - final List<NicVO> nics = _nicDao.listByVmId(routerId); - for (final NicVO n : nics) { - final NetworkVO nc = _networkDao.findById(n.getNetworkId()); - if (nc != null && nc.getTrafficType() == TrafficType.Control) { - routerControlIpAddress = n.getIp4Address(); - // router will have only one control ip - break; - } - } - - if (routerControlIpAddress == null) { - s_logger.warn("Unable to find router's control ip in its attached NICs!. routerId: " + routerId); - final DomainRouterVO router = _routerDao.findById(routerId); - return router.getPrivateIpAddress(); - } - - return routerControlIpAddress; - } - - public String getRouterIpInNetwork(final long networkId, final long instanceId) { - return _nicDao.getIpAddress(networkId, instanceId); - } - - - // @Override - public boolean sendCommandsToRouter(final VirtualRouter router, final Commands cmds) throws AgentUnavailableException { - if(!checkRouterVersion(router)){ - s_logger.debug("Router requires upgrade. Unable to send command to router:" + router.getId() + ", router template version : " + router.getTemplateVersion() - + ", minimal required version : " + VirtualNetworkApplianceService.MinVRVersion); - throw new CloudRuntimeException("Unable to send command. Upgrade in progress. Please contact administrator."); - } - Answer[] answers = null; - try { - answers = _agentMgr.send(router.getHostId(), cmds); - } catch (final OperationTimedoutException e) { - s_logger.warn("Timed Out", e); - throw new AgentUnavailableException("Unable to send commands to virtual router ", router.getHostId(), e); - } - - if (answers == null) { - return false; - } - - if (answers.length != cmds.size()) { - return false; - } - - // FIXME: Have to return state for individual command in the future - boolean result = true; - if (answers.length > 0) { - for (final Answer answer : answers) { - if (!answer.getResult()) { - result = false; - break; - } - } - } - return result; - } - - public void handleSingleWorkingRedundantRouter(final List<? extends VirtualRouter> connectedRouters, final List<? extends VirtualRouter> disconnectedRouters, final String reason) - throws ResourceUnavailableException { - if (connectedRouters.isEmpty() || disconnectedRouters.isEmpty()) { - return; - } - if (connectedRouters.size() != 1 || disconnectedRouters.size() != 1) { - s_logger.warn("How many redundant routers do we have?? "); - return; - } - if (!connectedRouters.get(0).getIsRedundantRouter()) { - throw new ResourceUnavailableException("Who is calling this with non-redundant router or non-domain router?", DataCenter.class, connectedRouters.get(0) - .getDataCenterId()); - } - if (!disconnectedRouters.get(0).getIsRedundantRouter()) { - throw new ResourceUnavailableException("Who is calling this with non-redundant router or non-domain router?", DataCenter.class, disconnectedRouters.get(0) - .getDataCenterId()); - } - - final DomainRouterVO connectedRouter = (DomainRouterVO)connectedRouters.get(0); - DomainRouterVO disconnectedRouter = (DomainRouterVO)disconnectedRouters.get(0); - - if (s_logger.isDebugEnabled()) { - s_logger.debug("About to stop the router " + disconnectedRouter.getInstanceName() + " due to: " + reason); - } - final String title = "Virtual router " + disconnectedRouter.getInstanceName() + " would be stopped after connecting back, due to " + reason; - final String context = - "Virtual router (name: " + disconnectedRouter.getInstanceName() + ", id: " + disconnectedRouter.getId() + - ") would be stopped after connecting back, due to: " + reason; - _alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_DOMAIN_ROUTER, disconnectedRouter.getDataCenterId(), disconnectedRouter.getPodIdToDeployIn(), title, - context); - disconnectedRouter.setStopPending(true); - disconnectedRouter = _routerDao.persist(disconnectedRouter); - - final int connRouterPR = getRealPriority(connectedRouter); - final int disconnRouterPR = getRealPriority(disconnectedRouter); - if (connRouterPR < disconnRouterPR) { - //connRouterPR < disconnRouterPR, they won't equal at anytime - if (!connectedRouter.getIsPriorityBumpUp()) { - final BumpUpPriorityCommand command = new BumpUpPriorityCommand(); - command.setAccessDetail(NetworkElementCommand.ROUTER_IP, getRouterControlIp(connectedRouter.getId())); - command.setAccessDetail(NetworkElementCommand.ROUTER_NAME, connectedRouter.getInstanceName()); - final Answer answer = _agentMgr.easySend(connectedRouter.getHostId(), command); - if (!answer.getResult()) { - s_logger.error("Failed to bump up " + connectedRouter.getInstanceName() + "'s priority! " + answer.getDetails()); - } - } else { - final String t = "Can't bump up virtual router " + connectedRouter.getInstanceName() + "'s priority due to it's already bumped up!"; - _alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_DOMAIN_ROUTER, connectedRouter.getDataCenterId(), connectedRouter.getPodIdToDeployIn(), t, t); - } - } - } - - public int getRealPriority(final DomainRouterVO router) { - int priority = router.getPriority(); - if (router.getIsPriorityBumpUp()) { - priority += VirtualNetworkApplianceManager.DEFAULT_DELTA; - } - return priority; - } - - // @Override - public NicTO getNicTO(final VirtualRouter router, final Long networkId, final String broadcastUri) { - NicProfile nicProfile = _networkModel.getNicProfile(router, networkId, broadcastUri); - - return _itMgr.toNicTO(nicProfile, router.getHypervisorType()); - } - - // @Override - public VirtualRouter destroyRouter(final long routerId, final Account caller, final Long callerUserId) throws ResourceUnavailableException, ConcurrentOperationException { - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Attempting to destroy router " + routerId); - } - - final DomainRouterVO router = _routerDao.findById(routerId); - if (router == null) { - return null; - } - - _accountMgr.checkAccess(caller, null, true, router); - - _itMgr.expunge(router.getUuid()); - _routerDao.remove(router.getId()); - return router; - } - - /** - * Checks if the router is at the required version. Compares MS version and router version. - * - * @param router - * @return - */ - // @Override - public boolean checkRouterVersion(final VirtualRouter router) { - if(!VirtualNetworkApplianceManagerImpl.routerVersionCheckEnabled.value()){ - //Router version check is disabled. - return true; - } - if(router.getTemplateVersion() == null){ - return false; - } - final String trimmedVersion = Version.trimRouterVersion(router.getTemplateVersion()); - return (Version.compare(trimmedVersion, VirtualNetworkApplianceService.MinVRVersion) >= 0); - } - - - protected DomainRouterVO start(DomainRouterVO router, final User user, final Account caller, final Map<Param, Object> params, final DeploymentPlan planToDeploy) - throws StorageUnavailableException, InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { - s_logger.debug("Starting router " + router); - try { - _itMgr.advanceStart(router.getUuid(), params, planToDeploy, null); - } catch (final OperationTimedoutException e) { - throw new ResourceUnavailableException("Starting router " + router + " failed! " + e.toString(), DataCenter.class, router.getDataCenterId()); - } - if (router.isStopPending()) { - s_logger.info("Clear the stop pending flag of router " + router.getHostName() + " after start router successfully!"); - router.setStopPending(false); - router = _routerDao.persist(router); - } - // We don't want the failure of VPN Connection affect the status of router, so we try to make connection - // only after router start successfully - final Long vpcId = router.getVpcId(); - if (vpcId != null) { - _s2sVpnMgr.reconnectDisconnectedVpnByVpc(vpcId); - } - return _routerDao.findById(router.getId()); - } - - protected DomainRouterVO waitRouter(final DomainRouterVO router) { - DomainRouterVO vm = _routerDao.findById(router.getId()); - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Router " + router.getInstanceName() + " is not fully up yet, we will wait"); - } - while (vm.getState() == State.Starting) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - } - - // reload to get the latest state info - vm = _routerDao.findById(router.getId()); - } - - if (vm.getState() == State.Running) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Router " + router.getInstanceName() + " is now fully up"); - } - - return router; - } - - s_logger.warn("Router " + router.getInstanceName() + " failed to start. current state: " + vm.getState()); - return null; - } - - - // @Override - public List<DomainRouterVO> startRouters(final RouterDeploymentDefinition routerDeploymentDefinition) - throws StorageUnavailableException, InsufficientCapacityException, - ConcurrentOperationException, ResourceUnavailableException { - - List<DomainRouterVO> runningRouters = new ArrayList<DomainRouterVO>(); - - for (DomainRouterVO router : routerDeploymentDefinition.getRouters()) { - boolean skip = false; - final State state = router.getState(); - if (router.getHostId() != null && state != State.Running) { - final HostVO host = _hostDao.findById(router.getHostId()); - if (host == null || host.getState() != Status.Up) { - skip = true; - } - } - if (!skip) { - if (state != State.Running) { - router = startVirtualRouter(router, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount(), - routerDeploymentDefinition.getParams()); - } - if (router != null) { - runningRouters.add(router); - } - } - } - return runningRouters; - } - - // @Override - public DomainRouterVO startVirtualRouter(final DomainRouterVO router, final User user, final Account caller, final Map<Param, Object> params) - throws StorageUnavailableException, InsufficientCapacityException, - ConcurrentOperationException, ResourceUnavailableException { - - if (router.getRole() != Role.VIRTUAL_ROUTER || !router.getIsRedundantRouter()) { - return start(router, user, caller, params, null); - } - - if (router.getState() == State.Running) { - s_logger.debug("Redundant router " + router.getInstanceName() + " is already running!"); - return router; - } - - // - // If another thread has already requested a VR start, there is a transition period for VR to transit from - // Starting to Running, there exist a race conditioning window here - // We will wait until VR is up or fail - if (router.getState() == State.Starting) { - return waitRouter(router); - } - - DataCenterDeployment plan = new DataCenterDeployment(0, null, null, null, null, null); - DomainRouterVO result = null; - assert router.getIsRedundantRouter(); - final List<Long> networkIds = _routerDao.getRouterNetworks(router.getId()); - //Not support VPC now - if (networkIds.size() > 1) { - throw new ResourceUnavailableException("Unable to support more than one guest network for redundant router now!", DataCenter.class, router.getDataCenterId()); - } - DomainRouterVO routerToBeAvoid = null; - if (networkIds.size() != 0) { - final List<DomainRouterVO> routerList = _routerDao.findByNetwork(networkIds.get(0)); - for (final DomainRouterVO rrouter : routerList) { - if (rrouter.getHostId() != null && rrouter.getIsRedundantRouter() && rrouter.getState() == State.Running) { - if (routerToBeAvoid != null) { - throw new ResourceUnavailableException("Try to start router " + router.getInstanceName() + "(" + router.getId() + ")" + - ", but there are already two redundant routers with IP " + router.getPublicIpAddress() + ", they are " + rrouter.getInstanceName() + "(" + - rrouter.getId() + ") and " + routerToBeAvoid.getInstanceName() + "(" + routerToBeAvoid.getId() + ")", DataCenter.class, - rrouter.getDataCenterId()); - } - routerToBeAvoid = rrouter; - } - } - } - if (routerToBeAvoid == null) { - return start(router, user, caller, params, null); - } - // We would try best to deploy the router to another place - final int retryIndex = 5; - final ExcludeList[] avoids = new ExcludeList[5]; - avoids[0] = new ExcludeList(); - avoids[0].addPod(routerToBeAvoid.getPodIdToDeployIn()); - avoids[1] = new ExcludeList(); - avoids[1].addCluster(_hostDao.findById(routerToBeAvoid.getHostId()).getClusterId()); - avoids[2] = new ExcludeList(); - final List<VolumeVO> volumes = _volumeDao.findByInstanceAndType(routerToBeAvoid.getId(), Volume.Type.ROOT); - if (volumes != null && volumes.size() != 0) { - avoids[2].addPool(volumes.get(0).getPoolId()); - } - avoids[2].addHost(routerToBeAvoid.getHostId()); - avoids[3] = new ExcludeList(); - avoids[3].addHost(routerToBeAvoid.getHostId()); - avoids[4] = new ExcludeList(); - - for (int i = 0; i < retryIndex; i++) { - if (s_logger.isTraceEnabled()) { - s_logger.trace("Try to deploy redundant virtual router:" + router.getHostName() + ", for " + i + " time"); - } - plan.setAvoids(avoids[i]); - try { - result = start(router, user, caller, params, plan); - } catch (final InsufficientServerCapacityException ex) { - result = null; - } - if (result != null) { - break; - } - } - return result; - } - - - // @Override - public DomainRouterVO deployRouter(final RouterDeploymentDefinition routerDeploymentDefinition, - final LinkedHashMap<Network, List<? extends NicProfile>> networks, - final boolean startRouter, final List<HypervisorType> supportedHypervisors) - throws InsufficientAddressCapacityException, - InsufficientServerCapacityException, InsufficientCapacityException, - StorageUnavailableException, ResourceUnavailableException { - - final ServiceOfferingVO routerOffering = _serviceOfferingDao.findById(routerDeploymentDefinition.getOfferingId()); - final DeployDestination dest = routerDeploymentDefinition.getDest(); - final Account owner = routerDeploymentDefinition.getOwner(); - - // Router is the network element, we don't know the hypervisor type yet. - // Try to allocate the domR twice using diff hypervisors, and when failed both times, throw the exception up - final List<HypervisorType> hypervisors = getHypervisors(routerDeploymentDefinition, supportedHypervisors); - - int allocateRetry = 0; - int startRetry = 0; - DomainRouterVO router = null; - for (final Iterator<HypervisorType> iter = hypervisors.iterator(); iter.hasNext();) { - final HypervisorType hType = iter.next(); - try { - final long id = _routerDao.getNextInSequence(Long.class, "id"); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Allocating the VR i=" + id + " in datacenter " + dest.getDataCenter() + "with the hypervisor type " + hType); - } - - String templateName = null; - switch (hType) { - case XenServer: - templateName = VirtualNetworkApplianceManager.RouterTemplateXen.valueIn(dest.getDataCenter().getId()); - break; - case KVM: - templateName = VirtualNetworkApplianceManager.RouterTemplateKvm.valueIn(dest.getDataCenter().getId()); - break; - case VMware: - templateName = VirtualNetworkApplianceManager.RouterTemplateVmware.valueIn(dest.getDataCenter().getId()); - break; - case Hyperv: - templateName = VirtualNetworkApplianceManager.RouterTemplateHyperV.valueIn(dest.getDataCenter().getId()); - break; - case LXC: - templateName = VirtualNetworkApplianceManager.RouterTemplateLxc.valueIn(dest.getDataCenter().getId()); - break; - default: - break; - } - final VMTemplateVO template = _templateDao.findRoutingTemplate(hType, templateName); - - if (template == null) { - s_logger.debug(hType + " won't support system vm, skip it"); - continue; - } - - boolean offerHA = routerOffering.getOfferHA(); - /* We don't provide HA to redundant router VMs, admin should own it all, and redundant router themselves are HA */ - if (routerDeploymentDefinition.isRedundant()) { - offerHA = false; - } - - // routerDeploymentDefinition.getVpc().getId() ==> do not use VPC because it is not a VPC offering. - Long vpcId = routerDeploymentDefinition.getVpc() != null ? routerDeploymentDefinition.getVpc().getId() : null; - - router = new DomainRouterVO(id, routerOffering.getId(), routerDeploymentDefinition.getVirtualProvider().getId(), - VirtualMachineName.getRouterName(id, VirtualNwStatus.instance), template.getId(), template.getHypervisorType(), - template.getGuestOSId(), owner.getDomainId(), owner.getId(), routerDeploymentDefinition.isRedundant(), 0, - false, RedundantState.UNKNOWN, offerHA, false, vpcId); - - router.setDynamicallyScalable(template.isDynamicallyScalable()); - router.setRole(Role.VIRTUAL_ROUTER); - router = _routerDao.persist(router); - _itMgr.allocate(router.getInstanceName(), template, routerOffering, networks, routerDeploymentDefinition.getPlan(), null); - router = _routerDao.findById(router.getId()); - } catch (final InsufficientCapacityException ex) { - if (allocateRetry < 2 && 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) { - try { - router = startVirtualRouter(router, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount(), routerDeploymentDefinition.getParams()); - break; - } catch (final InsufficientCapacityException ex) { - if (startRetry < 2 && 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); - continue; - } else { - throw ex; - } - } finally { - startRetry++; - } - } else { - //return stopped router - return router; - } - } - - return router; - } - - protected List<HypervisorType> getHypervisors(final RouterDeploymentDefinition routerDeploymentDefinition, final List<HypervisorType> supportedHypervisors) - throws InsufficientServerCapacityException { - final DeployDestination dest = routerDeploymentDefinition.getDest(); - List<HypervisorType> hypervisors = new ArrayList<HypervisorType>(); - - if (dest.getCluster() != null) { - if (dest.getCluster().getHypervisorType() == HypervisorType.Ovm) { - hypervisors.add(getClusterToStartDomainRouterForOvm(dest.getCluster().getPodId())); - } else { - hypervisors.add(dest.getCluster().getHypervisorType()); - } - } else { - final HypervisorType defaults = _resourceMgr.getDefaultHypervisor(dest.getDataCenter().getId()); - if (defaults != HypervisorType.None) { - hypervisors.add(defaults); - } else { - //if there is no default hypervisor, get it from the cluster - hypervisors = _resourceMgr.getSupportedHypervisorTypes(dest.getDataCenter().getId(), true, routerDeploymentDefinition.getPlan().getPodId()); - } - } - - //keep only elements defined in supported hypervisors - final StringBuilder hTypesStr = new StringBuilder(); - if (supportedHypervisors != null && !supportedHypervisors.isEmpty()) { - hypervisors.retainAll(supportedHypervisors); - for (final HypervisorType hType : supportedHypervisors) { - hTypesStr.append(hType).append(" "); - } - } - - if (hypervisors.isEmpty()) { - final String errMsg = (hTypesStr.capacity() > 0) ? "supporting hypervisors " + hTypesStr.toString() : ""; - if (routerDeploymentDefinition.getPodId() != null) { - throw new InsufficientServerCapacityException("Unable to create virtual router, " + "there are no clusters in the pod " + errMsg, Pod.class, - routerDeploymentDefinition.getPodId()); - } - throw new InsufficientServerCapacityException("Unable to create virtual router, " + "there are no clusters in the zone " + errMsg, DataCenter.class, - dest.getDataCenter().getId()); - } - return hypervisors; - } - - /* - * Ovm won't support any system. So we have to choose a partner cluster in the same pod to start domain router for us - */ - protected HypervisorType getClusterToStartDomainRouterForOvm(final long podId) { - final List<ClusterVO> clusters = _clusterDao.listByPodId(podId); - for (final ClusterVO cv : clusters) { - if (cv.getHypervisorType() == HypervisorType.Ovm || cv.getHypervisorType() == HypervisorType.BareMetal) { - continue; - } - - final List<HostVO> hosts = _resourceMgr.listAllHostsInCluster(cv.getId()); - if (hosts == null || hosts.isEmpty()) { - continue; - } - - for (final HostVO h : hosts) { - if (h.getState() == Status.Up) { - s_logger.debug("Pick up host that has hypervisor type " + h.getHypervisorType() + " in cluster " + cv.getId() + " to start domain router for OVM"); - return h.getHypervisorType(); - } - } - } - - final String errMsg = - new StringBuilder("Cannot find an available cluster in Pod ") - .append(podId) - .append(" to start domain router for Ovm. \n Ovm won't support any system vm including domain router, ") - .append("please make sure you have a cluster with hypervisor type of any of xenserver/KVM/Vmware in the same pod") - .append(" with Ovm cluster. And there is at least one host in UP status in that cluster.") - .toString(); - throw new CloudRuntimeException(errMsg); - } - - - public LinkedHashMap<Network, List<? extends NicProfile>> createRouterNetworks( - final RouterDeploymentDefinition routerDeploymentDefinition) - throws ConcurrentOperationException, InsufficientAddressCapacityException { - - //Form networks - LinkedHashMap<Network, List<? extends NicProfile>> networks = new LinkedHashMap<Network, List<? extends NicProfile>>(3); - //1) Guest network - boolean hasGuestNetwork = false; - if (routerDeploymentDefinition.getGuestNetwork() != null) { - s_logger.debug("Adding nic for Virtual Router in Guest network " + routerDeploymentDefinition.getGuestNetwork()); - String defaultNetworkStartIp = null, defaultNetworkStartIpv6 = null; - if (!routerDeploymentDefinition.isPublicNetwork()) { - final Nic placeholder = _networkModel.getPlaceholderNicForRouter(routerDeploymentDefinition.getGuestNetwork(), routerDeploymentDefinition.getPodId()); - if (routerDeploymentDefinition.getGuestNetwork().getCidr() != null) { - if (placeholder != null && placeholder.getIp4Address() != null) { - s_logger.debug("Requesting ipv4 address " + placeholder.getIp4Address() + " stored in placeholder nic for the network " + routerDeploymentDefinition.getGuestNetwork()); - defaultNetworkStartIp = placeholder.getIp4Address(); - } else { - final String startIp = _networkModel.getStartIpAddress(routerDeploymentDefinition.getGuestNetwork().getId()); - if (startIp != null && _ipAddressDao.findByIpAndSourceNetworkId(routerDeploymentDefinition.getGuestNetwork().getId(), startIp).getAllocatedTime() == null) { - defaultNetworkStartIp = startIp; - } else if (s_logger.isDebugEnabled()) { - s_logger.debug("First ipv4 " + startIp + " in network id=" + routerDeploymentDefinition.getGuestNetwork().getId() + - " is already allocated, can't use it for domain router; will get random ip address from the range"); - } - } - } - - if (routerDeploymentDefinition.getGuestNetwork().getIp6Cidr() != null) { - if (placeholder != null && placeholder.getIp6Address() != null) { - s_logger.debug("Requesting ipv6 address " + placeholder.getIp6Address() + " stored in placeholder nic for the network " + routerDeploymentDefinition.getGuestNetwork()); - defaultNetworkStartIpv6 = placeholder.getIp6Address(); - } else { - final String startIpv6 = _networkModel.getStartIpv6Address(routerDeploymentDefinition.getGuestNetwork().getId()); - if (startIpv6 != null && _ipv6Dao.findByNetworkIdAndIp(routerDeploymentDefinition.getGuestNetwork().getId(), startIpv6) == null) { - defaultNetworkStartIpv6 = startIpv6; - } else if (s_logger.isDebugEnabled()) { - s_logger.debug("First ipv6 " + startIpv6 + " in network id=" + routerDeploymentDefinition.getGuestNetwork().getId() + - " is already allocated, can't use it for domain router; will get random ipv6 address from the range"); - } - } - } - } - - final NicProfile gatewayNic = new NicProfile(defaultNetworkStartIp, defaultNetworkStartIpv6); - if (routerDeploymentDefinition.isPublicNetwork()) { - if (routerDeploymentDefinition.isRedundant()) { - gatewayNic.setIp4Address(_ipAddrMgr.acquireGuestIpAddress(routerDeploymentDefinition.getGuestNetwork(), null)); - } else { - gatewayNic.setIp4Address(routerDeploymentDefinition.getGuestNetwork().getGateway()); - } - gatewayNic.setBroadcastUri(routerDeploymentDefinition.getGuestNetwork().getBroadcastUri()); - gatewayNic.setBroadcastType(routerDeploymentDefinition.getGuestNetwork().getBroadcastDomainType()); - gatewayNic.setIsolationUri(routerDeploymentDefinition.getGuestNetwork().getBroadcastUri()); - gatewayNic.setMode(routerDeploymentDefinition.getGuestNetwork().getMode()); - final String gatewayCidr = routerDeploymentDefinition.getGuestNetwork().getCidr(); - gatewayNic.setNetmask(NetUtils.getCidrNetmask(gatewayCidr)); - } else { - gatewayNic.setDefaultNic(true); - } - - networks.put(routerDeploymentDefinition.getGuestNetwork(), new ArrayList<NicProfile>(Arrays.asList(gatewayNic))); - hasGuestNetwork = true; - } - - //2) Control network - s_logger.debug("Adding nic for Virtual Router in Control network "); - List<? extends NetworkOffering> offerings = _networkModel.getSystemAccountNetworkOfferings(NetworkOffering.SystemControlNetwork); - NetworkOffering controlOffering = offerings.get(0); - Network controlConfig = _networkMgr.setupNetwork(VirtualNwStatus.account, controlOffering, routerDeploymentDefinition.getPlan(), - null, null, false).get(0); - networks.put(controlConfig, new ArrayList<NicProfile>()); - //3) Public network - if (routerDeploymentDefinition.isPublicNetwork()) { - s_logger.debug("Adding nic for Virtual Router in Public network "); - //if source nat service is supported by the network, get the source nat ip address - final NicProfile defaultNic = new NicProfile(); - defaultNic.setDefaultNic(true); - final PublicIp sourceNatIp = routerDeploymentDefinition.getSourceNatIP(); - defaultNic.setIp4Address(sourceNatIp.getAddress().addr()); - defaultNic.setGateway(sourceNatIp.getGateway()); - defaultNic.setNetmask(sourceNatIp.getNetmask()); - defaultNic.setMacAddress(sourceNatIp.getMacAddress()); - // get broadcast from public network - final Network pubNet = _networkDao.findById(sourceNatIp.getNetworkId()); - if (pubNet.getBroadcastDomainType() == BroadcastDomainType.Vxlan) { - defaultNic.setBroadcastType(BroadcastDomainType.Vxlan); - defaultNic.setBroadcastUri(BroadcastDomainType.Vxlan.toUri(sourceNatIp.getVlanTag())); - defaultNic.setIsolationUri(BroadcastDomainType.Vxlan.toUri(sourceNatIp.getVlanTag())); - } else { - defaultNic.setBroadcastType(BroadcastDomainType.Vlan); - defaultNic.setBroadcastUri(BroadcastDomainType.Vlan.toUri(sourceNatIp.getVlanTag())); - defaultNic.setIsolationUri(IsolationType.Vlan.toUri(sourceNatIp.getVlanTag())); - } - if (hasGuestNetwork) { - defaultNic.setDeviceId(2); - } - final NetworkOffering publicOffering = _networkModel.getSystemAccountNetworkOfferings(NetworkOffering.SystemPublicNetwork).get(0); - final List<? extends Network> publicNetworks = _networkMgr.setupNetwork(VirtualNwStatus.account, publicOffering, - routerDeploymentDefinition.getPlan(), null, null, false); - final String publicIp = defaultNic.getIp4Address(); - // We want to use the identical MAC address for RvR on public interface if possible - final NicVO peerNic = _nicDao.findByIp4AddressAndNetworkId(publicIp, publicNetworks.get(0).getId()); - if (peerNic != null) { - s_logger.info("Use same MAC as previous RvR, the MAC is " + peerNic.getMacAddress()); - defaultNic.setMacAddress(peerNic.getMacAddress()); - } - networks.put(publicNetworks.get(0), new ArrayList<NicProfile>(Arrays.asList(defaultNic))); - } - - return networks; - } - - public LinkedHashMap<Network, List<? extends NicProfile>> createVpcRouterNetworks( - final VpcRouterDeploymentDefinition vpcRouterDeploymentDefinition) - throws ConcurrentOperationException, InsufficientAddressCapacityException { - - final TreeSet<String> publicVlans = new TreeSet<String>(); - publicVlans.add(vpcRouterDeploymentDefinition.getSourceNatIP().getVlanTag()); - - //1) allocate nic for control and source nat public ip - final LinkedHashMap<Network, List<? extends NicProfile>> networks = - createRouterNetworks(vpcRouterDeploymentDefinition); - - - final Long vpcId = vpcRouterDeploymentDefinition.getVpc().getId(); - //2) allocate nic for private gateways if needed - final List<PrivateGateway> privateGateways = _vpcMgr.getVpcPrivateGateways(vpcId); - if (privateGateways != null && !privateGateways.isEmpty()) { - for (PrivateGateway privateGateway : privateGateways) { - NicProfile privateNic = _vpcHelper.createPrivateNicProfileForGateway(privateGateway); - Network privateNetwork = _networkModel.getNetwork(privateGateway.getNetworkId()); - networks.put(privateNetwork, new ArrayList<NicProfile>(Arrays.asList(privateNic))); - } - } - - //3) allocate nic for guest gateway if needed - List<? extends Network> guestNetworks = _vpcMgr.getVpcNetworks(vpcId); - for (Network guestNetwork : guestNetworks) { - if (_networkModel.isPrivateGateway(guestNetwork.getId())) { - continue; - } - if (guestNetwork.getState() == Network.State.Implemented || guestNetwork.getState() == Network.State.Setup) { - NicProfile guestNic = _vpcHelper.createGuestNicProfileForVpcRouter(guestNetwork); - networks.put(guestNetwork, new ArrayList<NicProfile>(Arrays.asList(guestNic))); - } - } - - //4) allocate nic for additional public network(s) - final List<IPAddressVO> ips = _ipAddressDao.listByAssociatedVpc(vpcId, false); - final List<NicProfile> publicNics = new ArrayList<NicProfile>(); - Network publicNetwork = null; - for (IPAddressVO ip : ips) { - PublicIp publicIp = PublicIp.createFromAddrAndVlan(ip, _vlanDao.findById(ip.getVlanId())); - if ((ip.getState() == IpAddress.State.Allocated || ip.getState() == IpAddress.State.Allocating) && _vpcMgr.isIpAllocatedToVpc(ip) && - !publicVlans.contains(publicIp.getVlanTag())) { - s_logger.debug("Allocating nic for router in vlan " + publicIp.getVlanTag()); - NicProfile publicNic = new NicProfile(); - publicNic.setDefaultNic(false); - publicNic.setIp4Address(publicIp.getAddress().addr()); - publicNic.setGateway(publicIp.getGateway()); - publicNic.setNetmask(publicIp.getNetmask()); - publicNic.setMacAddress(publicIp.getMacAddress()); - publicNic.setBroadcastType(BroadcastDomainType.Vlan); - publicNic.setBroadcastUri(BroadcastDomainType.Vlan.toUri(publicIp.getVlanTag())); - publicNic.setIsolationUri(IsolationType.Vlan.toUri(publicIp.getVlanTag())); - NetworkOffering publicOffering = _networkModel.getSystemAccountNetworkOfferings(NetworkOffering.SystemPublicNetwork).get(0); - if (publicNetwork == null) { - List<? extends Network> publicNetworks = _networkMgr.setupNetwork(VirtualNwStatus.account, - publicOffering, vpcRouterDeploymentDefinition.getPlan(), null, null, false); - publicNetwork = publicNetworks.get(0); - } - publicNics.add(publicNic); - publicVlans.add(publicIp.getVlanTag()); - } - } - if (publicNetwork != null) { - if (networks.get(publicNetwork) != null) { - List<NicProfile> publicNicProfiles = (List<NicProfile>)networks.get(publicNetwork); - publicNicProfiles.addAll(publicNics); - networks.put(publicNetwork, publicNicProfiles); - } else { - networks.put(publicNetwork, publicNics); - } - } - - return networks; - } - -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2da3ceda/server/src/com/cloud/network/router/NetworkHelper.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/router/NetworkHelper.java b/server/src/com/cloud/network/router/NetworkHelper.java new file mode 100644 index 0000000..8bc76ea --- /dev/null +++ b/server/src/com/cloud/network/router/NetworkHelper.java @@ -0,0 +1,87 @@ +package com.cloud.network.router; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.cloud.network.router.deployment.RouterDeploymentDefinition; + +import com.cloud.agent.api.to.NicTO; +import com.cloud.agent.manager.Commands; +import com.cloud.exception.AgentUnavailableException; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientAddressCapacityException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InsufficientServerCapacityException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.exception.StorageUnavailableException; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.network.Network; +import com.cloud.user.Account; +import com.cloud.user.User; +import com.cloud.vm.DomainRouterVO; +import com.cloud.vm.NicProfile; +import com.cloud.vm.VirtualMachineProfile.Param; + +public interface NetworkHelper { + + public abstract String getRouterControlIp(long routerId); + + public abstract String getRouterIpInNetwork(long networkId, long instanceId); + + // @Override + public abstract boolean sendCommandsToRouter(VirtualRouter router, + Commands cmds) throws AgentUnavailableException; + + public abstract void handleSingleWorkingRedundantRouter( + List<? extends VirtualRouter> connectedRouters, + List<? extends VirtualRouter> disconnectedRouters, String reason) + throws ResourceUnavailableException; + + public abstract int getRealPriority(DomainRouterVO router); + + // @Override + public abstract NicTO getNicTO(VirtualRouter router, Long networkId, + String broadcastUri); + + // @Override + public abstract VirtualRouter destroyRouter(long routerId, Account caller, + Long callerUserId) throws ResourceUnavailableException, + ConcurrentOperationException; + + /** + * Checks if the router is at the required version. Compares MS version and router version. + * + * @param router + * @return + */ + // @Override + public abstract boolean checkRouterVersion(VirtualRouter router); + + // @Override + public abstract List<DomainRouterVO> startRouters( + RouterDeploymentDefinition routerDeploymentDefinition) + throws StorageUnavailableException, InsufficientCapacityException, + ConcurrentOperationException, ResourceUnavailableException; + + // @Override + public abstract DomainRouterVO startVirtualRouter(DomainRouterVO router, + User user, Account caller, Map<Param, Object> params) + throws StorageUnavailableException, InsufficientCapacityException, + ConcurrentOperationException, ResourceUnavailableException; + + // @Override + public abstract DomainRouterVO deployRouter( + RouterDeploymentDefinition routerDeploymentDefinition, + LinkedHashMap<Network, List<? extends NicProfile>> networks, + boolean startRouter, List<HypervisorType> supportedHypervisors) + throws InsufficientAddressCapacityException, + InsufficientServerCapacityException, InsufficientCapacityException, + StorageUnavailableException, ResourceUnavailableException; + + public abstract LinkedHashMap<Network, List<? extends NicProfile>> createRouterNetworks( + RouterDeploymentDefinition routerDeploymentDefinition) + throws ConcurrentOperationException, + InsufficientAddressCapacityException; + +} \ No newline at end of file