Repository: cloudstack Updated Branches: refs/heads/master e4a8bbcdf -> 771d05238
Splitting Vpc and NonVpc deployment into phases & testing it Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/8852153d Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/8852153d Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/8852153d Branch: refs/heads/master Commit: 8852153d0cc3876a1cdddd7eeed8d662ee408ff2 Parents: 325026d Author: Antonio Fornie <afor...@schubergphilis.com> Authored: Thu Jul 17 07:48:20 2014 -0500 Committer: wilderrodrigues <wrodrig...@schubergphilis.com> Committed: Tue Oct 14 15:01:14 2014 +0200 ---------------------------------------------------------------------- .../deployment/RouterDeploymentDefinition.java | 168 ++++++++++++++++++- .../VpcRouterDeploymentDefinition.java | 68 +++++++- 2 files changed, 232 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8852153d/server/src/org/cloud/network/router/deployment/RouterDeploymentDefinition.java ---------------------------------------------------------------------- diff --git a/server/src/org/cloud/network/router/deployment/RouterDeploymentDefinition.java b/server/src/org/cloud/network/router/deployment/RouterDeploymentDefinition.java index df9d49b..01fc774 100644 --- a/server/src/org/cloud/network/router/deployment/RouterDeploymentDefinition.java +++ b/server/src/org/cloud/network/router/deployment/RouterDeploymentDefinition.java @@ -116,8 +116,7 @@ public class RouterDeploymentDefinition { protected DeploymentPlan plan; protected List<DomainRouterVO> routers = new ArrayList<>(); protected ServiceOfferingVO offering; - - + protected Long tableLockId; protected RouterDeploymentDefinition(final Network guestNetwork, final DeployDestination dest, @@ -220,6 +219,171 @@ public class RouterDeploymentDefinition { protected void findOrDeployVirtualRouter() throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { + try { + this.lock(); + this.checkPreconditions(); + // dest has pod=null, for Basic Zone findOrDeployVRs for all Pods + final List<DeployDestination> destinations = findDestinations(); + + for (final DeployDestination destination : destinations) { + this.dest = destination; + this.planDeploymentRouters(); + this.generateDeploymentPlan(); + this.proceedEffectiveDeployment(); + } + } finally { + this.unlock(); + } + } + + protected void lock() { + final Network lock = networkDao.acquireInLockTable(guestNetwork.getId(), NetworkOrchestrationService.NetworkLockTimeout.value()); + if (lock == null) { + throw new ConcurrentOperationException("Unable to lock network " + guestNetwork.getId()); + } + this.tableLockId = lock.getId(); + } + + protected void unlock() { + if (this.tableLockId != null) { + networkDao.releaseFromLockTable(this.tableLockId); + if (logger.isDebugEnabled()) { + logger.debug("Lock is released for network id " + this.tableLockId + + " as a part of router startup in " + dest); + } + } + } + + protected void checkPreconditions() throws ResourceUnavailableException { + if (guestNetwork.getState() != Network.State.Implemented && + guestNetwork.getState() != Network.State.Setup && + guestNetwork.getState() != Network.State.Implementing) { + throw new ResourceUnavailableException("Network is not yet fully implemented: " + guestNetwork, + Network.class, this.guestNetwork.getId()); + } + + if (guestNetwork.getTrafficType() != TrafficType.Guest) { + throw new ResourceUnavailableException("Network is not type Guest as expected: " + guestNetwork, + Network.class, this.guestNetwork.getId()); + } + } + + protected List<DeployDestination> findDestinations() { + // dest has pod=null, for Basic Zone findOrDeployVRs for all Pods + final List<DeployDestination> destinations = new ArrayList<DeployDestination>(); + + // for basic zone, if 'dest' has pod set to null then this is network restart scenario otherwise it is a vm deployment scenario + if (this.isBasic() && dest.getPod() == null) { + // Find all pods in the data center with running or starting user vms + final long dcId = dest.getDataCenter().getId(); + final List<HostPodVO> pods = listByDataCenterIdVMTypeAndStates(dcId, VirtualMachine.Type.User, VirtualMachine.State.Starting, VirtualMachine.State.Running); + + // Loop through all the pods skip those with running or starting VRs + for (final HostPodVO pod : pods) { + // Get list of VRs in starting or running state + final long podId = pod.getId(); + final List<DomainRouterVO> virtualRouters = routerDao.listByPodIdAndStates(podId, VirtualMachine.State.Starting, VirtualMachine.State.Running); + + assert (virtualRouters.size() <= 1) : "Pod can have utmost one VR in Basic Zone, please check!"; + + // Add virtualRouters to the routers, this avoids the situation when + // all routers are skipped and VirtualRouterElement throws exception + this.routers.addAll(virtualRouters); + + // If List size is one, we already have a starting or running VR, skip deployment + if (virtualRouters.size() == 1) { + logger.debug("Skipping VR deployment: Found a running or starting VR in Pod " + pod.getName() + " id=" + podId); + continue; + } + // Add new DeployDestination for this pod + destinations.add(new DeployDestination(dest.getDataCenter(), pod, null, null)); + } + } else { + // Else, just add the supplied dest + destinations.add(dest); + } + return destinations; + } + + protected void proceedEffectiveDeployment() + throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { + // 2) Figure out required routers count + int routerCount = 1; + if (this.isRedundant) { + routerCount = 2; + //Check current redundant routers, if possible(all routers are stopped), reset the priority + if (this.routers.size() != 0) { + checkAndResetPriorityOfRedundantRouter(this.routers); + } + } + + // If old network is redundant but new is single router, then routers.size() = 2 but routerCount = 1 + if (this.routers.size() >= routerCount) { + return; + } + + if (this.routers.size() >= 5) { + logger.error("Too much redundant routers!"); + } + + // Check if providers are supported in the physical networks + final Type type = Type.VirtualRouter; + final Long physicalNetworkId = networkModel.getPhysicalNetworkId(guestNetwork); + final PhysicalNetworkServiceProvider provider = physicalProviderDao.findByServiceProvider(physicalNetworkId, type.toString()); + if (provider == null) { + throw new CloudRuntimeException("Cannot find service provider " + type.toString() + " in physical network " + physicalNetworkId); + } + final VirtualRouterProvider vrProvider = vrProviderDao.findByNspIdAndType(provider.getId(), type); + if (vrProvider == null) { + throw new CloudRuntimeException("Cannot find virtual router provider " + type.toString() + " as service provider " + provider.getId()); + } + + if (networkModel.isNetworkSystem(guestNetwork) || guestNetwork.getGuestType() == Network.GuestType.Shared) { + this.owner = accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM); + } + + // Check if public network has to be set on VR + boolean publicNetwork = false; + if (networkModel.isProviderSupportServiceInNetwork(guestNetwork.getId(), Service.SourceNat, Provider.VirtualRouter)) { + publicNetwork = true; + } + if (this.isRedundant && !publicNetwork) { + logger.error("Didn't support redundant virtual router without public network!"); + this.routers = null; + return; + } + + Long offeringId = networkOfferingDao.findById(guestNetwork.getNetworkOfferingId()).getServiceOfferingId(); + if (offeringId == null) { + offeringId = getOfferingId(); + } + + PublicIp sourceNatIp = null; + if (publicNetwork) { + sourceNatIp = ipAddrMgr.assignSourceNatIpAddressToGuestNetwork( + this.owner, guestNetwork); + } + + // 3) deploy virtual router(s) + final int count = routerCount - this.routers.size(); + for (int i = 0; i < count; i++) { + LinkedHashMap<Network, List<? extends NicProfile>> networks = + createRouterNetworks(new Pair<Boolean, PublicIp>( + publicNetwork, sourceNatIp)); + //don't start the router as we are holding the network lock that needs to be released at the end of router allocation + DomainRouterVO router = nwHelper.deployRouter(this, vrProvider, offeringId, networks, false, null); + + if (router != null) { + routerDao.addRouterToGuestNetwork(router, guestNetwork); + this.routers.add(router); + } + } + } + + @DB + protected void findOrDeployVirtualRouterOLD() + throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { + final Network lock = networkDao.acquireInLockTable(guestNetwork.getId(), NetworkOrchestrationService.NetworkLockTimeout.value()); if (lock == null) { throw new ConcurrentOperationException("Unable to lock network " + guestNetwork.getId()); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8852153d/server/src/org/cloud/network/router/deployment/VpcRouterDeploymentDefinition.java ---------------------------------------------------------------------- diff --git a/server/src/org/cloud/network/router/deployment/VpcRouterDeploymentDefinition.java b/server/src/org/cloud/network/router/deployment/VpcRouterDeploymentDefinition.java index 6111754..ef2367f 100644 --- a/server/src/org/cloud/network/router/deployment/VpcRouterDeploymentDefinition.java +++ b/server/src/org/cloud/network/router/deployment/VpcRouterDeploymentDefinition.java @@ -75,8 +75,72 @@ public class VpcRouterDeploymentDefinition extends RouterDeploymentDefinition { } @Override + protected void lock() { + Vpc vpcLock = vpcDao.acquireInLockTable(vpc.getId()); + if (vpcLock == null) { + throw new ConcurrentOperationException("Unable to lock vpc " + vpc.getId()); + } + this.tableLockId = vpcLock.getId(); + } + + @Override + protected void unlock() { + if (this.tableLockId != null) { + vpcDao.releaseFromLockTable(this.tableLockId); + if (logger.isDebugEnabled()) { + logger.debug("Lock is released for vpc id " + this.tableLockId + + " as a part of router startup in " + dest); + } + } + } + + @Override + protected void checkPreconditions() { + // No preconditions for Vpc + } + + @Override + protected List<DeployDestination> findDestinations() { + final List<DeployDestination> destinations = new ArrayList<>(); + destinations.add(this.dest); + return destinations; + } + + @Override + protected void proceedEffectiveDeployment() + throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { + //2) Return routers if exist, otherwise... + if (this.routers.size() < 1) { + Long offeringId = vpcOffDao.findById(vpc.getVpcOfferingId()).getServiceOfferingId(); + if (offeringId == null) { + offeringId = offering.getId(); + } + //3) Deploy Virtual Router + List<? extends PhysicalNetwork> pNtwks = pNtwkDao.listByZone(vpc.getZoneId()); + + VirtualRouterProvider vpcVrProvider = null; + + for (PhysicalNetwork pNtwk : pNtwks) { + PhysicalNetworkServiceProvider provider = physicalProviderDao.findByServiceProvider(pNtwk.getId(), Type.VPCVirtualRouter.toString()); + if (provider == null) { + throw new CloudRuntimeException("Cannot find service provider " + Type.VPCVirtualRouter.toString() + " in physical network " + pNtwk.getId()); + } + vpcVrProvider = vrProviderDao.findByNspIdAndType(provider.getId(), Type.VPCVirtualRouter); + if (vpcVrProvider != null) { + break; + } + } + + PublicIp sourceNatIp = vpcMgr.assignSourceNatIpAddressToVpc(this.owner, vpc); + + DomainRouterVO router = deployVpcRouter(vpcVrProvider, offeringId, sourceNatIp); + this.routers.add(router); + } + } + + @Override @DB - protected void findOrDeployVirtualRouter() + protected void findOrDeployVirtualRouterOLD() throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { logger.debug("Deploying Virtual Router in VPC " + vpc); @@ -87,7 +151,7 @@ public class VpcRouterDeploymentDefinition extends RouterDeploymentDefinition { } //1) Find out the list of routers and generate deployment plan - planDeploymentRouters(); + this.planDeploymentRouters(); this.generateDeploymentPlan(); //2) Return routers if exist, otherwise...