From d0467731dee7dbd7de2581502127133ca7f91e96 Mon Sep 17 00:00:00 2001 From: Antonio Fornie Date: Sun, 27 Jul 2014 12:08:57 -0500 Subject: [PATCH] More refactoring and testing in the same classes Conflicts: server/src/org/cloud/network/router/deployment/RouterDeploymentDefinitionBuilder.java --- .../network/router/NetworkGeneralHelper.java | 179 +---- .../VirtualNetworkApplianceManagerImpl.java | 2 +- .../RouterDeploymentDefinition.java | 419 ++++------- .../RouterDeploymentDefinitionBuilder.java | 75 +- .../VpcRouterDeploymentDefinition.java | 94 ++- .../RouterDeploymentDefinitionTest.java | 700 +++++++++++++++++- 6 files changed, 930 insertions(+), 539 deletions(-) diff --git a/server/src/com/cloud/network/router/NetworkGeneralHelper.java b/server/src/com/cloud/network/router/NetworkGeneralHelper.java index 28ff08f1c1a..dd90bef7254 100644 --- a/server/src/com/cloud/network/router/NetworkGeneralHelper.java +++ b/server/src/com/cloud/network/router/NetworkGeneralHelper.java @@ -17,7 +17,6 @@ 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; @@ -57,12 +56,8 @@ import com.cloud.maint.Version; 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.VirtualRouterProvider; -import com.cloud.network.addr.PublicIp; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; @@ -70,7 +65,6 @@ import com.cloud.network.dao.UserIpv6AddressDao; import com.cloud.network.router.VirtualRouter.RedundantState; import com.cloud.network.router.VirtualRouter.Role; 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; @@ -82,11 +76,8 @@ 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.Pair; 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; @@ -413,14 +404,13 @@ public class NetworkGeneralHelper { // @Override public DomainRouterVO deployRouter(final RouterDeploymentDefinition routerDeploymentDefinition, - final VirtualRouterProvider vrProvider, final long svcOffId, final LinkedHashMap> networks, final boolean startRouter, final List supportedHypervisors) throws InsufficientAddressCapacityException, InsufficientServerCapacityException, InsufficientCapacityException, StorageUnavailableException, ResourceUnavailableException { - final ServiceOfferingVO routerOffering = serviceOfferingDao.findById(svcOffId); + final ServiceOfferingVO routerOffering = serviceOfferingDao.findById(routerDeploymentDefinition.getOfferingId()); final DeployDestination dest = routerDeploymentDefinition.getDest(); final Account owner = routerDeploymentDefinition.getOwner(); @@ -475,7 +465,7 @@ public class NetworkGeneralHelper { // 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(), vrProvider.getId(), + 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); @@ -596,169 +586,4 @@ public class NetworkGeneralHelper { throw new CloudRuntimeException(errMsg); } - - // @Override - public LinkedHashMap> createRouterNetworks( - final RouterDeploymentDefinition routerDeploymentDefinition, - final Network guestNetwork, final Pair publicNetwork) - throws ConcurrentOperationException, - InsufficientAddressCapacityException { - - boolean setupPublicNetwork = false; - if (publicNetwork != null) { - setupPublicNetwork = publicNetwork.first(); - } - - // Form networks - LinkedHashMap> networks = new LinkedHashMap>( - 3); - // 1) Guest network - boolean hasGuestNetwork = false; - if (guestNetwork != null) { - s_logger.debug("Adding nic for Virtual Router in Guest network " - + guestNetwork); - String defaultNetworkStartIp = null, defaultNetworkStartIpv6 = null; - if (!setupPublicNetwork) { - final Nic placeholder = networkModel - .getPlaceholderNicForRouter(guestNetwork, - routerDeploymentDefinition.getPodId()); - if (guestNetwork.getCidr() != null) { - if (placeholder != null - && placeholder.getIp4Address() != null) { - s_logger.debug("Requesting ipv4 address " - + placeholder.getIp4Address() - + " stored in placeholder nic for the network " - + guestNetwork); - defaultNetworkStartIp = placeholder.getIp4Address(); - } else { - final String startIp = networkModel - .getStartIpAddress(guestNetwork.getId()); - if (startIp != null - && ipAddressDao.findByIpAndSourceNetworkId( - guestNetwork.getId(), startIp) - .getAllocatedTime() == null) { - defaultNetworkStartIp = startIp; - } else if (s_logger.isDebugEnabled()) { - s_logger.debug("First ipv4 " - + startIp - + " in network id=" - + guestNetwork.getId() - + " is already allocated, can't use it for domain router; will get random ip address from the range"); - } - } - } - - if (guestNetwork.getIp6Cidr() != null) { - if (placeholder != null - && placeholder.getIp6Address() != null) { - s_logger.debug("Requesting ipv6 address " - + placeholder.getIp6Address() - + " stored in placeholder nic for the network " - + guestNetwork); - defaultNetworkStartIpv6 = placeholder.getIp6Address(); - } else { - final String startIpv6 = networkModel - .getStartIpv6Address(guestNetwork.getId()); - if (startIpv6 != null - && ipv6Dao.findByNetworkIdAndIp( - guestNetwork.getId(), startIpv6) == null) { - defaultNetworkStartIpv6 = startIpv6; - } else if (s_logger.isDebugEnabled()) { - s_logger.debug("First ipv6 " - + startIpv6 - + " in network id=" - + guestNetwork.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 (setupPublicNetwork) { - if (routerDeploymentDefinition.isRedundant()) { - gatewayNic.setIp4Address(ipAddrMgr.acquireGuestIpAddress( - guestNetwork, null)); - } else { - gatewayNic.setIp4Address(guestNetwork.getGateway()); - } - gatewayNic.setBroadcastUri(guestNetwork.getBroadcastUri()); - gatewayNic.setBroadcastType(guestNetwork - .getBroadcastDomainType()); - gatewayNic.setIsolationUri(guestNetwork.getBroadcastUri()); - gatewayNic.setMode(guestNetwork.getMode()); - final String gatewayCidr = guestNetwork.getCidr(); - gatewayNic.setNetmask(NetUtils.getCidrNetmask(gatewayCidr)); - } else { - gatewayNic.setDefaultNic(true); - } - - networks.put(guestNetwork, - new ArrayList(Arrays.asList(gatewayNic))); - hasGuestNetwork = true; - } - - // 2) Control network - s_logger.debug("Adding nic for Virtual Router in Control network "); - List 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()); - // 3) Public network - if (setupPublicNetwork) { - final PublicIp sourceNatIp = publicNetwork.second(); - 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); - 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 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( - Arrays.asList(defaultNic))); - } - - return networks; - } - } \ No newline at end of file diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index ce00b884b54..e95a079b7c0 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -662,7 +662,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V useLocalStorage, true, null, true, VirtualMachine.Type.DomainRouter, true); offering.setUniqueName(ServiceOffering.routerDefaultOffUniqueName); offering = _serviceOfferingDao.persistSystemServiceOffering(offering); - routerDeploymentManagerBuilder.setOffering(offering); + routerDeploymentManagerBuilder.setOfferingId(offering.getId()); // this can sometimes happen, if DB is manually or programmatically // manipulated diff --git a/server/src/org/cloud/network/router/deployment/RouterDeploymentDefinition.java b/server/src/org/cloud/network/router/deployment/RouterDeploymentDefinition.java index a5e3ec7279a..f93ce3cef5d 100644 --- a/server/src/org/cloud/network/router/deployment/RouterDeploymentDefinition.java +++ b/server/src/org/cloud/network/router/deployment/RouterDeploymentDefinition.java @@ -62,10 +62,8 @@ import com.cloud.network.router.VpcVirtualNetworkHelperImpl; import com.cloud.network.vpc.Vpc; import com.cloud.offering.NetworkOffering; import com.cloud.offerings.dao.NetworkOfferingDao; -import com.cloud.service.ServiceOfferingVO; import com.cloud.user.Account; import com.cloud.user.AccountManager; -import com.cloud.utils.Pair; import com.cloud.utils.db.DB; import com.cloud.utils.db.JoinBuilder; import com.cloud.utils.db.SearchBuilder; @@ -100,6 +98,7 @@ public class RouterDeploymentDefinition { protected NicDao nicDao; protected UserIpv6AddressDao ipv6Dao; protected IPAddressDao ipAddressDao; + protected VirtualRouterProvider vrProvider; @Inject @@ -115,9 +114,10 @@ public class RouterDeploymentDefinition { protected boolean isRedundant; protected DeploymentPlan plan; protected List routers = new ArrayList<>(); - protected ServiceOfferingVO offering; + protected Long offeringId; protected Long tableLockId; - + protected boolean publicNetwork; + protected PublicIp sourceNatIp; protected RouterDeploymentDefinition(final Network guestNetwork, final DeployDestination dest, final Account owner, final Map params, final boolean isRedundant) { @@ -129,9 +129,10 @@ public class RouterDeploymentDefinition { this.isRedundant = isRedundant; } - protected void setOffering(ServiceOfferingVO offering) { - this.offering = offering; + public Long getOfferingId() { + return this.offeringId; } + public Vpc getVpc() { return null; } @@ -166,12 +167,12 @@ public class RouterDeploymentDefinition { return routers; } - public boolean isBasic() { - return this.dest.getDataCenter().getNetworkType() == NetworkType.Basic; + public VirtualRouterProvider getVirtualProvider() { + return this.vrProvider; } - public Long getOfferingId() { - return offering == null ? null : offering.getId(); + public boolean isBasic() { + return this.dest.getDataCenter().getNetworkType() == NetworkType.Basic; } protected void generateDeploymentPlan() { @@ -190,7 +191,7 @@ public class RouterDeploymentDefinition { throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { - findOrDeployVirtualRouter(); + this.findOrDeployVirtualRouter(); return nwHelper.startRouters(this); } @@ -288,225 +289,120 @@ public class RouterDeploymentDefinition { return destinations; } - protected void executeDeployment() - 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); - } + protected int getNumberOfRoutersToDeploy() { + // TODO Are we sure this makes sense? Somebody said 5 was too many? + if (this.routers.size() >= 5) { + logger.error("Too many redundant routers!"); } // If old network is redundant but new is single router, then routers.size() = 2 but routerCount = 1 - if (this.routers.size() >= routerCount) { - return; + int routersExpected = 1; + if (this.isRedundant) { + routersExpected = 2; } + return routersExpected < this.routers.size() ? + 0 : routersExpected - this.routers.size(); + } - if (this.routers.size() >= 5) { - logger.error("Too much redundant routers!"); + /** + * Executes preparation and deployment of the routers. After this method ends, {@link this#routers} + * should have all of the deployed routers ready for start, and no more. + * + * @throws ConcurrentOperationException + * @throws InsufficientCapacityException + * @throws ResourceUnavailableException + */ + protected void executeDeployment() + throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { + + //Check current redundant routers, if possible(all routers are stopped), reset the priority + // TODO Why shouldn't we call this method also for VPC + setupPriorityOfRedundantRouter(); + + if (this.getNumberOfRoutersToDeploy() > 0) { + 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 + this.publicNetwork = networkModel.isProviderSupportServiceInNetwork( + guestNetwork.getId(), Service.SourceNat, Provider.VirtualRouter); + + if (this.isRedundant && !this.publicNetwork) { + // TODO Shouldn't be this throw an exception instead of log error and empty list of routers + logger.error("Didn't support redundant virtual router without public network!"); + this.routers = new ArrayList<>(); + } else { + this.findVirtualProvider(); + this.findOfferingId(); + this.findSourceNatIP(); + this.deployAllVirtualRouters(); + } } + } + protected void findSourceNatIP() throws InsufficientAddressCapacityException, ConcurrentOperationException { + this.sourceNatIp = null; + if (this.publicNetwork) { + this.sourceNatIp = this.ipAddrMgr.assignSourceNatIpAddressToGuestNetwork( + this.owner,this.guestNetwork); + } + } + + protected void findOfferingId() { + Long networkOfferingId = networkOfferingDao.findById(guestNetwork.getNetworkOfferingId()).getServiceOfferingId(); + if (networkOfferingId != null) { + this.offeringId = networkOfferingId; + } + } + + protected void findVirtualProvider() { // 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()); + 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()); + throw new CloudRuntimeException( + String.format("Cannot find service provider %s in physical network %s", + type.toString(), physicalNetworkId)); } - if (networkModel.isNetworkSystem(guestNetwork) || guestNetwork.getGuestType() == Network.GuestType.Shared) { - this.owner = accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM); + this.vrProvider = vrProviderDao.findByNspIdAndType(provider.getId(), type); + if (this.vrProvider == null) { + throw new CloudRuntimeException( + String.format("Cannot find virtual router provider %s as service provider %s", + type.toString(), provider.getId())); } + } - // 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; - } + protected void deployAllVirtualRouters() + throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { - 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++) { + int routersToDeploy = this.getNumberOfRoutersToDeploy(); + for(int i = 0; i < routersToDeploy; i++) { LinkedHashMap> networks = - createRouterNetworks(new Pair( - publicNetwork, sourceNatIp)); + createRouterNetworks(); //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); + DomainRouterVO router = nwHelper.deployRouter(this, networks, false, null); if (router != null) { - routerDao.addRouterToGuestNetwork(router, guestNetwork); + this.routerDao.addRouterToGuestNetwork(router, this.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()); - } - - if (logger.isDebugEnabled()) { - logger.debug("Lock is acquired for network id " + lock.getId() + " as a part of router startup in " + dest); - } - - try { - - assert guestNetwork.getState() == Network.State.Implemented || guestNetwork.getState() == Network.State.Setup || - guestNetwork.getState() == Network.State.Implementing : "Network is not yet fully implemented: " + guestNetwork; - assert guestNetwork.getTrafficType() == TrafficType.Guest; - - // 1) Get deployment plan and find out the list of routers - - // dest has pod=null, for Basic Zone findOrDeployVRs for all Pods - final List destinations = new ArrayList(); - - // 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 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 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); - } - - // Except for Basic Zone, the for loop will iterate only once - for (final DeployDestination destination : destinations) { - this.dest = destination; - planDeploymentRouters(); - this.generateDeploymentPlan(); - - // 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> networks = - createRouterNetworks(new Pair( - 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); - } - } - } - } finally { - if (lock != null) { - networkDao.releaseFromLockTable(lock.getId()); - if (logger.isDebugEnabled()) { - logger.debug("Lock is released for network id " + lock.getId() + " as a part of router startup in " + dest); - } - } - } - } - - + /** + * Lists all pods given a Data Center Id, a {@link VirtualMachine.Type} and a list of + * {@link VirtualMachine.State} + * + * @param id + * @param type + * @param states + * @return + */ protected List listByDataCenterIdVMTypeAndStates(final long id, final VirtualMachine.Type type, final VirtualMachine.State... states) { final SearchBuilder vmInstanceSearch = vmDao.createSearchBuilder(); vmInstanceSearch.and("type", vmInstanceSearch.entity().getType(), SearchCriteria.Op.EQ); @@ -535,69 +431,75 @@ public class RouterDeploymentDefinition { } } - private void checkAndResetPriorityOfRedundantRouter(final List routers) { - boolean allStopped = true; - for (final DomainRouterVO router : routers) { + /** + * Routers need reset if at least one of the routers is not redundant or stopped. + * + * @return + */ + protected boolean routersNeedReset() { + boolean needReset = true; + for (final DomainRouterVO router : this.routers) { if (!router.getIsRedundantRouter() || router.getState() != VirtualMachine.State.Stopped) { - allStopped = false; + needReset = false; break; } } - if (!allStopped) { - return; - } - for (final DomainRouterVO router : routers) { - // getUpdatedPriority() would update the value later - router.setPriority(0); - router.setIsPriorityBumpUp(false); - routerDao.update(router.getId(), router); - } + return needReset; } - protected LinkedHashMap> createRouterNetworks( - final Pair publicNetwork) - throws ConcurrentOperationException, InsufficientAddressCapacityException { - final Network guestNetwork = this.guestNetwork; - boolean setupPublicNetwork = false; - if (publicNetwork != null) { - setupPublicNetwork = publicNetwork.first(); - } + /** + * Only for redundant deployment and if any routers needed reset, we shall reset all + * routers priorities + */ + protected void setupPriorityOfRedundantRouter() { + if (this.isRedundant && this.routersNeedReset()) { + for (final DomainRouterVO router : this.routers) { + // getUpdatedPriority() would update the value later + router.setPriority(0); + router.setIsPriorityBumpUp(false); + routerDao.update(router.getId(), router); + } + } + } + + protected LinkedHashMap> createRouterNetworks() + throws ConcurrentOperationException, InsufficientAddressCapacityException { //Form networks LinkedHashMap> networks = new LinkedHashMap>(3); //1) Guest network boolean hasGuestNetwork = false; - if (guestNetwork != null) { - logger.debug("Adding nic for Virtual Router in Guest network " + guestNetwork); + if (this.guestNetwork != null) { + logger.debug("Adding nic for Virtual Router in Guest network " + this.guestNetwork); String defaultNetworkStartIp = null, defaultNetworkStartIpv6 = null; - if (!setupPublicNetwork) { - final Nic placeholder = networkModel.getPlaceholderNicForRouter(guestNetwork, this.getPodId()); - if (guestNetwork.getCidr() != null) { + if (!this.publicNetwork) { + final Nic placeholder = networkModel.getPlaceholderNicForRouter(this.guestNetwork, this.getPodId()); + if (this.guestNetwork.getCidr() != null) { if (placeholder != null && placeholder.getIp4Address() != null) { - logger.debug("Requesting ipv4 address " + placeholder.getIp4Address() + " stored in placeholder nic for the network " + guestNetwork); + logger.debug("Requesting ipv4 address " + placeholder.getIp4Address() + " stored in placeholder nic for the network " + this.guestNetwork); defaultNetworkStartIp = placeholder.getIp4Address(); } else { - final String startIp = networkModel.getStartIpAddress(guestNetwork.getId()); - if (startIp != null && ipAddressDao.findByIpAndSourceNetworkId(guestNetwork.getId(), startIp).getAllocatedTime() == null) { + final String startIp = networkModel.getStartIpAddress(this.guestNetwork.getId()); + if (startIp != null && ipAddressDao.findByIpAndSourceNetworkId(this.guestNetwork.getId(), startIp).getAllocatedTime() == null) { defaultNetworkStartIp = startIp; } else if (logger.isDebugEnabled()) { - logger.debug("First ipv4 " + startIp + " in network id=" + guestNetwork.getId() + + logger.debug("First ipv4 " + startIp + " in network id=" + this.guestNetwork.getId() + " is already allocated, can't use it for domain router; will get random ip address from the range"); } } } - if (guestNetwork.getIp6Cidr() != null) { + if (this.guestNetwork.getIp6Cidr() != null) { if (placeholder != null && placeholder.getIp6Address() != null) { - logger.debug("Requesting ipv6 address " + placeholder.getIp6Address() + " stored in placeholder nic for the network " + guestNetwork); + logger.debug("Requesting ipv6 address " + placeholder.getIp6Address() + " stored in placeholder nic for the network " + this.guestNetwork); defaultNetworkStartIpv6 = placeholder.getIp6Address(); } else { - final String startIpv6 = networkModel.getStartIpv6Address(guestNetwork.getId()); - if (startIpv6 != null && ipv6Dao.findByNetworkIdAndIp(guestNetwork.getId(), startIpv6) == null) { + final String startIpv6 = networkModel.getStartIpv6Address(this.guestNetwork.getId()); + if (startIpv6 != null && ipv6Dao.findByNetworkIdAndIp(this.guestNetwork.getId(), startIpv6) == null) { defaultNetworkStartIpv6 = startIpv6; } else if (logger.isDebugEnabled()) { - logger.debug("First ipv6 " + startIpv6 + " in network id=" + guestNetwork.getId() + + logger.debug("First ipv6 " + startIpv6 + " in network id=" + this.guestNetwork.getId() + " is already allocated, can't use it for domain router; will get random ipv6 address from the range"); } } @@ -605,23 +507,23 @@ public class RouterDeploymentDefinition { } final NicProfile gatewayNic = new NicProfile(defaultNetworkStartIp, defaultNetworkStartIpv6); - if (setupPublicNetwork) { + if (this.publicNetwork) { if (this.isRedundant) { - gatewayNic.setIp4Address(ipAddrMgr.acquireGuestIpAddress(guestNetwork, null)); + gatewayNic.setIp4Address(ipAddrMgr.acquireGuestIpAddress(this.guestNetwork, null)); } else { - gatewayNic.setIp4Address(guestNetwork.getGateway()); + gatewayNic.setIp4Address(this.guestNetwork.getGateway()); } - gatewayNic.setBroadcastUri(guestNetwork.getBroadcastUri()); - gatewayNic.setBroadcastType(guestNetwork.getBroadcastDomainType()); - gatewayNic.setIsolationUri(guestNetwork.getBroadcastUri()); - gatewayNic.setMode(guestNetwork.getMode()); - final String gatewayCidr = guestNetwork.getCidr(); + gatewayNic.setBroadcastUri(this.guestNetwork.getBroadcastUri()); + gatewayNic.setBroadcastType(this.guestNetwork.getBroadcastDomainType()); + gatewayNic.setIsolationUri(this.guestNetwork.getBroadcastUri()); + gatewayNic.setMode(this.guestNetwork.getMode()); + final String gatewayCidr = this.guestNetwork.getCidr(); gatewayNic.setNetmask(NetUtils.getCidrNetmask(gatewayCidr)); } else { gatewayNic.setDefaultNic(true); } - networks.put(guestNetwork, new ArrayList(Arrays.asList(gatewayNic))); + networks.put(this.guestNetwork, new ArrayList(Arrays.asList(gatewayNic))); hasGuestNetwork = true; } @@ -633,26 +535,25 @@ public class RouterDeploymentDefinition { null, null, false).get(0); networks.put(controlConfig, new ArrayList()); //3) Public network - if (setupPublicNetwork) { - final PublicIp sourceNatIp = publicNetwork.second(); + if (publicNetwork) { 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); - defaultNic.setIp4Address(sourceNatIp.getAddress().addr()); - defaultNic.setGateway(sourceNatIp.getGateway()); - defaultNic.setNetmask(sourceNatIp.getNetmask()); - defaultNic.setMacAddress(sourceNatIp.getMacAddress()); + defaultNic.setIp4Address(this.sourceNatIp.getAddress().addr()); + defaultNic.setGateway(this.sourceNatIp.getGateway()); + defaultNic.setNetmask(this.sourceNatIp.getNetmask()); + defaultNic.setMacAddress(this.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())); + defaultNic.setBroadcastUri(BroadcastDomainType.Vxlan.toUri(this.sourceNatIp.getVlanTag())); + defaultNic.setIsolationUri(BroadcastDomainType.Vxlan.toUri(this.sourceNatIp.getVlanTag())); } else { defaultNic.setBroadcastType(BroadcastDomainType.Vlan); - defaultNic.setBroadcastUri(BroadcastDomainType.Vlan.toUri(sourceNatIp.getVlanTag())); - defaultNic.setIsolationUri(IsolationType.Vlan.toUri(sourceNatIp.getVlanTag())); + defaultNic.setBroadcastUri(BroadcastDomainType.Vlan.toUri(this.sourceNatIp.getVlanTag())); + defaultNic.setIsolationUri(IsolationType.Vlan.toUri(this.sourceNatIp.getVlanTag())); } if (hasGuestNetwork) { defaultNic.setDeviceId(2); diff --git a/server/src/org/cloud/network/router/deployment/RouterDeploymentDefinitionBuilder.java b/server/src/org/cloud/network/router/deployment/RouterDeploymentDefinitionBuilder.java index a5662b527c8..c9f2f6acc67 100644 --- a/server/src/org/cloud/network/router/deployment/RouterDeploymentDefinitionBuilder.java +++ b/server/src/org/cloud/network/router/deployment/RouterDeploymentDefinitionBuilder.java @@ -20,12 +20,13 @@ import com.cloud.network.dao.PhysicalNetworkDao; import com.cloud.network.dao.PhysicalNetworkServiceProviderDao; import com.cloud.network.dao.UserIpv6AddressDao; import com.cloud.network.dao.VirtualRouterProviderDao; +import com.cloud.network.router.NetworkGeneralHelper; +import com.cloud.network.router.VpcVirtualNetworkHelperImpl; import com.cloud.network.vpc.Vpc; import com.cloud.network.vpc.VpcManager; import com.cloud.network.vpc.dao.VpcDao; import com.cloud.network.vpc.dao.VpcOfferingDao; import com.cloud.offerings.dao.NetworkOfferingDao; -import com.cloud.service.ServiceOfferingVO; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.vm.DomainRouterVO; @@ -39,7 +40,7 @@ public class RouterDeploymentDefinitionBuilder { @Inject protected NetworkDao networkDao; @Inject - private DomainRouterDao routerDao = null; + private final DomainRouterDao routerDao = null; @Inject private PhysicalNetworkServiceProviderDao physicalProviderDao; @Inject @@ -75,53 +76,55 @@ public class RouterDeploymentDefinitionBuilder { @Inject private VlanDao vlanDao; - protected ServiceOfferingVO offering; + @Inject + protected NetworkGeneralHelper nwHelper; + @Inject + protected VpcVirtualNetworkHelperImpl vpcHelper; - public void setOffering(ServiceOfferingVO offering) { - this.offering = offering; + protected Long offeringId; + + public void setOfferingId(final Long offeringId) { + this.offeringId = offeringId; } public IntermediateStateBuilder create() { return new IntermediateStateBuilder(this); } - protected RouterDeploymentDefinition injectDependencies( - final RouterDeploymentDefinition routerDeploymentDefinition) { + protected RouterDeploymentDefinition injectDependencies(final RouterDeploymentDefinition routerDeploymentDefinition) { - routerDeploymentDefinition.networkDao = this.networkDao; - routerDeploymentDefinition.routerDao = this.routerDao; - routerDeploymentDefinition.physicalProviderDao = this.physicalProviderDao; - routerDeploymentDefinition.networkModel = this.networkModel; - routerDeploymentDefinition.vrProviderDao = this.vrProviderDao; - routerDeploymentDefinition.networkOfferingDao = this.networkOfferingDao; - routerDeploymentDefinition.ipAddrMgr = this.ipAddrMgr; - routerDeploymentDefinition.vmDao = this.vmDao; - routerDeploymentDefinition.podDao = this.podDao; - routerDeploymentDefinition.accountMgr = this.accountMgr; - routerDeploymentDefinition.networkMgr = this.networkMgr; - routerDeploymentDefinition.nicDao = this.nicDao; - routerDeploymentDefinition.ipv6Dao = this.ipv6Dao; - routerDeploymentDefinition.ipAddressDao = this.ipAddressDao; - routerDeploymentDefinition.offering = this.offering; + routerDeploymentDefinition.networkDao = networkDao; + routerDeploymentDefinition.routerDao = routerDao; + routerDeploymentDefinition.physicalProviderDao = physicalProviderDao; + routerDeploymentDefinition.networkModel = networkModel; + routerDeploymentDefinition.vrProviderDao = vrProviderDao; + routerDeploymentDefinition.networkOfferingDao = networkOfferingDao; + routerDeploymentDefinition.ipAddrMgr = ipAddrMgr; + routerDeploymentDefinition.vmDao = vmDao; + routerDeploymentDefinition.podDao = podDao; + routerDeploymentDefinition.accountMgr = accountMgr; + routerDeploymentDefinition.networkMgr = networkMgr; + routerDeploymentDefinition.nicDao = nicDao; + routerDeploymentDefinition.ipv6Dao = ipv6Dao; + routerDeploymentDefinition.ipAddressDao = ipAddressDao; + routerDeploymentDefinition.offeringId = offeringId; if (routerDeploymentDefinition instanceof VpcRouterDeploymentDefinition) { - this.injectVpcDependencies((VpcRouterDeploymentDefinition) routerDeploymentDefinition); + injectVpcDependencies((VpcRouterDeploymentDefinition) routerDeploymentDefinition); } return routerDeploymentDefinition; } - protected void injectVpcDependencies( - final VpcRouterDeploymentDefinition routerDeploymentDefinition) { + protected void injectVpcDependencies(final VpcRouterDeploymentDefinition routerDeploymentDefinition) { - routerDeploymentDefinition.vpcDao = this.vpcDao; - routerDeploymentDefinition.vpcOffDao = this.vpcOffDao; - routerDeploymentDefinition.pNtwkDao = this.pNtwkDao; - routerDeploymentDefinition.vpcMgr = this.vpcMgr; - routerDeploymentDefinition.vlanDao = this.vlanDao; + routerDeploymentDefinition.vpcDao = vpcDao; + routerDeploymentDefinition.vpcOffDao = vpcOffDao; + routerDeploymentDefinition.pNtwkDao = pNtwkDao; + routerDeploymentDefinition.vpcMgr = vpcMgr; + routerDeploymentDefinition.vlanDao = vlanDao; } - public class IntermediateStateBuilder { RouterDeploymentDefinitionBuilder builder; @@ -134,16 +137,16 @@ public class RouterDeploymentDefinitionBuilder { protected boolean isRedundant; protected List routers = new ArrayList<>(); - protected IntermediateStateBuilder(RouterDeploymentDefinitionBuilder builder) { + protected IntermediateStateBuilder(final RouterDeploymentDefinitionBuilder builder) { this.builder = builder; } public IntermediateStateBuilder makeRedundant() { - this.isRedundant = true; + isRedundant = true; return this; } - public IntermediateStateBuilder setRedundant(boolean isRedundant) { + public IntermediateStateBuilder setRedundant(final boolean isRedundant) { this.isRedundant = isRedundant; return this; } @@ -154,7 +157,7 @@ public class RouterDeploymentDefinitionBuilder { } public IntermediateStateBuilder setGuestNetwork(final Network nw) { - this.guestNetwork = nw; + guestNetwork = nw; return this; } @@ -175,7 +178,7 @@ public class RouterDeploymentDefinitionBuilder { public RouterDeploymentDefinition build() { RouterDeploymentDefinition routerDeploymentDefinition = null; - if (this.vpc != null) { + if (vpc != null) { routerDeploymentDefinition = new VpcRouterDeploymentDefinition(vpc, dest, owner, params, isRedundant); } else { routerDeploymentDefinition = new RouterDeploymentDefinition(guestNetwork, dest, owner, params, isRedundant); diff --git a/server/src/org/cloud/network/router/deployment/VpcRouterDeploymentDefinition.java b/server/src/org/cloud/network/router/deployment/VpcRouterDeploymentDefinition.java index f6a99a18af0..eb080113216 100644 --- a/server/src/org/cloud/network/router/deployment/VpcRouterDeploymentDefinition.java +++ b/server/src/org/cloud/network/router/deployment/VpcRouterDeploymentDefinition.java @@ -24,7 +24,6 @@ import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.IsolationType; import com.cloud.network.PhysicalNetwork; import com.cloud.network.PhysicalNetworkServiceProvider; -import com.cloud.network.VirtualRouterProvider; import com.cloud.network.VirtualRouterProvider.Type; import com.cloud.network.addr.PublicIp; import com.cloud.network.dao.IPAddressVO; @@ -37,7 +36,6 @@ import com.cloud.network.vpc.dao.VpcDao; import com.cloud.network.vpc.dao.VpcOfferingDao; import com.cloud.offering.NetworkOffering; import com.cloud.user.Account; -import com.cloud.utils.Pair; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.DomainRouterVO; import com.cloud.vm.NicProfile; @@ -105,64 +103,86 @@ public class VpcRouterDeploymentDefinition extends RouterDeploymentDefinition { return destinations; } + @Override + protected int getNumberOfRoutersToDeploy() { + // TODO Should we make our changes here in order to enable Redundant Router for VPC? + return 1 - this.routers.size(); + } + + /** + * @see RouterDeploymentDefinition#executeDeployment() + */ @Override protected void executeDeployment() 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(); - } + if (getNumberOfRoutersToDeploy() > 0) { + this.findVirtualProvider(); + this.findOfferingId(); + this.findSourceNatIP(); + //3) Deploy Virtual Router - List 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); + DomainRouterVO router = deployVpcRouter(sourceNatIp); this.routers.add(router); } } - protected DomainRouterVO deployVpcRouter(final VirtualRouterProvider vrProvider, - final long svcOffId, final PublicIp sourceNatIp) throws ConcurrentOperationException, InsufficientAddressCapacityException, + @Override + protected void findSourceNatIP() throws InsufficientAddressCapacityException, ConcurrentOperationException { + this.sourceNatIp = vpcMgr.assignSourceNatIpAddressToVpc(this.owner, vpc); + } + + @Override + protected void findVirtualProvider() { + List pNtwks = pNtwkDao.listByZone(vpc.getZoneId()); + + this.vrProvider = 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()); + } + this.vrProvider = vrProviderDao.findByNspIdAndType(provider.getId(), Type.VPCVirtualRouter); + if (this.vrProvider != null) { + break; + } + } + } + + @Override + protected void findOfferingId() { + Long vpcOfferingId = vpcOffDao.findById(vpc.getVpcOfferingId()).getServiceOfferingId(); + if (vpcOfferingId != null) { + this.offeringId = vpcOfferingId; + } + } + + protected DomainRouterVO deployVpcRouter(final PublicIp sourceNatIp) + throws ConcurrentOperationException, InsufficientAddressCapacityException, InsufficientServerCapacityException, InsufficientCapacityException, StorageUnavailableException, ResourceUnavailableException { - LinkedHashMap> networks = createVpcRouterNetworks( - new Pair(true, sourceNatIp), this.vpc.getId()); + LinkedHashMap> networks = createRouterNetworks(); DomainRouterVO router = - nwHelper.deployRouter(this, vrProvider, svcOffId, networks, true, vpcMgr.getSupportedVpcHypervisors()); + nwHelper.deployRouter(this, networks, true, vpcMgr.getSupportedVpcHypervisors()); return router; } - protected LinkedHashMap> createVpcRouterNetworks( - final Pair sourceNatIp, final long vpcId) + @Override + protected LinkedHashMap> createRouterNetworks() throws ConcurrentOperationException, InsufficientAddressCapacityException { TreeSet publicVlans = new TreeSet(); - publicVlans.add(sourceNatIp.second().getVlanTag()); + publicVlans.add(this.sourceNatIp.getVlanTag()); //1) allocate nic for control and source nat public ip - LinkedHashMap> networks = nwHelper.createRouterNetworks(this, null, sourceNatIp); + LinkedHashMap> networks = super.createRouterNetworks(); //2) allocate nic for private gateways if needed - List privateGateways = vpcMgr.getVpcPrivateGateways(vpcId); + List privateGateways = vpcMgr.getVpcPrivateGateways(this.vpc.getId()); if (privateGateways != null && !privateGateways.isEmpty()) { for (PrivateGateway privateGateway : privateGateways) { NicProfile privateNic = vpcHelper.createPrivateNicProfileForGateway(privateGateway); @@ -172,7 +192,7 @@ public class VpcRouterDeploymentDefinition extends RouterDeploymentDefinition { } //3) allocate nic for guest gateway if needed - List guestNetworks = vpcMgr.getVpcNetworks(vpcId); + List guestNetworks = vpcMgr.getVpcNetworks(this.vpc.getId()); for (Network guestNetwork : guestNetworks) { if (networkModel.isPrivateGateway(guestNetwork.getId())) { continue; @@ -184,7 +204,7 @@ public class VpcRouterDeploymentDefinition extends RouterDeploymentDefinition { } //4) allocate nic for additional public network(s) - List ips = ipAddressDao.listByAssociatedVpc(vpcId, false); + List ips = ipAddressDao.listByAssociatedVpc(this.vpc.getId(), false); List publicNics = new ArrayList(); Network publicNetwork = null; for (IPAddressVO ip : ips) { diff --git a/server/test/org/cloud/network/router/deployment/RouterDeploymentDefinitionTest.java b/server/test/org/cloud/network/router/deployment/RouterDeploymentDefinitionTest.java index 6941e9ac96f..10d4b42b69e 100644 --- a/server/test/org/cloud/network/router/deployment/RouterDeploymentDefinitionTest.java +++ b/server/test/org/cloud/network/router/deployment/RouterDeploymentDefinitionTest.java @@ -1,9 +1,19 @@ package org.cloud.network.router.deployment; import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertNull; +import static junit.framework.Assert.assertTrue; +import static junit.framework.Assert.fail; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.anyObject; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -14,7 +24,6 @@ import java.util.List; import java.util.Map; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -27,29 +36,59 @@ import com.cloud.dc.DataCenter; import com.cloud.dc.DataCenter.NetworkType; import com.cloud.dc.HostPodVO; import com.cloud.dc.Pod; +import com.cloud.dc.dao.HostPodDao; import com.cloud.deploy.DeployDestination; +import com.cloud.deploy.DeploymentPlan; import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientAddressCapacityException; +import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.IpAddressManager; import com.cloud.network.Network; +import com.cloud.network.Network.Provider; +import com.cloud.network.Network.Service; +import com.cloud.network.NetworkModel; import com.cloud.network.Networks.TrafficType; +import com.cloud.network.VirtualRouterProvider.Type; +import com.cloud.network.addr.PublicIp; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; +import com.cloud.network.dao.PhysicalNetworkServiceProviderDao; +import com.cloud.network.dao.PhysicalNetworkServiceProviderVO; +import com.cloud.network.dao.VirtualRouterProviderDao; +import com.cloud.network.element.VirtualRouterProviderVO; +import com.cloud.network.router.NetworkGeneralHelper; +import com.cloud.network.router.VirtualRouter.Role; +import com.cloud.offerings.NetworkOfferingVO; +import com.cloud.offerings.dao.NetworkOfferingDao; +import com.cloud.service.ServiceOfferingVO; import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.DomainRouterVO; +import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile.Param; import com.cloud.vm.dao.DomainRouterDao; +import com.cloud.vm.dao.VMInstanceDao; @RunWith(MockitoJUnitRunner.class) public class RouterDeploymentDefinitionTest { + private static final long OFFERING_ID = 16L; + private static final String NUMBER_OF_ROUTERS_TO_DEPLOY_IS_NOT_THE_EXPECTED = "Number of routers to deploy is not the expected"; private static final String ONLY_THE_PROVIDED_AS_DEFAULT_DESTINATION_WAS_EXPECTED = "Only the provided as default destination was expected"; protected static final Long DATA_CENTER_ID = 100l; + protected static final Long NW_ID = 102l; protected static final Long POD_ID1 = 111l; protected static final Long POD_ID2 = 112l; protected static final Long POD_ID3 = 113l; - protected static final Long NW_ID = 102l; + protected static final Long ROUTER1_ID = 121l; + protected static final Long ROUTER2_ID = 122l; + private static final long PROVIDER_ID = 131L; + private static final long PHYSICAL_NW_ID = 141L; // General delegates (Daos, Mgrs...) @Mock @@ -69,11 +108,32 @@ public class RouterDeploymentDefinitionTest { @Mock protected HostPodVO mockHostPodVO3; @Mock - protected NetworkVO mockNwLock; + protected NetworkVO mockNw; + @Mock + NetworkOfferingVO mockNwOfferingVO; @Mock protected Account mockOwner; @Mock protected DomainRouterDao mockRouterDao; + @Mock + protected NetworkGeneralHelper mockNetworkGeneralHelper; + @Mock + protected VMInstanceDao mockVmDao; + @Mock + protected HostPodDao mockPodDao; + @Mock + protected VirtualRouterProviderDao mockVrProviderDao; + @Mock + protected PhysicalNetworkServiceProviderDao physicalProviderDao; + @Mock + protected NetworkModel mockNetworkModel; + @Mock + protected IpAddressManager mockIpAddrMgr; + @Mock + protected NetworkOfferingDao mockNetworkOfferingDao; + @Mock + protected AccountManager mockAccountMgr; + protected List mockPods = new ArrayList<>(); protected Map params = new HashMap<>(); @@ -92,26 +152,72 @@ public class RouterDeploymentDefinitionTest { when(this.mockHostPodVO1.getId()).thenReturn(POD_ID1); when(this.mockHostPodVO2.getId()).thenReturn(POD_ID2); when(this.mockHostPodVO3.getId()).thenReturn(POD_ID3); - when(this.mockNwLock.getId()).thenReturn(NW_ID); + when(this.mockNw.getId()).thenReturn(NW_ID); this.deployment = this.builder.create() - .setGuestNetwork(this.mockNwLock) + .setGuestNetwork(this.mockNw) .setDeployDestination(this.mockDestination) + .setAccountOwner(this.mockOwner) .build(); } + @Test + public void testRedundancyProperty() { + // Set and confirm is redundant + RouterDeploymentDefinition deployment1 = this.builder.create() + .setGuestNetwork(this.mockNw) + .setDeployDestination(this.mockDestination) + .makeRedundant() + .build(); + assertTrue("The builder ignored \".makeRedundant()\"", deployment1.isRedundant()); + RouterDeploymentDefinition deployment2 = this.builder.create() + .setGuestNetwork(this.mockNw) + .setDeployDestination(this.mockDestination) + .setRedundant(true) + .build(); + assertTrue("The builder ignored \".setRedundant(true)\"", deployment2.isRedundant()); + } + + @Test + public void testConstructionFieldsAndFlags() { + // Vpc type + assertFalse(this.deployment.isVpcRouter()); + // Offering null + this.deployment.offeringId = null; + assertNull(this.deployment.getOfferingId()); + // Offering null + ServiceOfferingVO offeringVO = mock(ServiceOfferingVO.class); + this.deployment.offeringId = OFFERING_ID; + assertEquals(OFFERING_ID, this.deployment.getOfferingId().longValue()); + // Routers + assertNotNull(this.deployment.getRouters()); + // Guest network + assertNotNull(this.deployment.getGuestNetwork()); + // Deploy Destination + assertNotNull(this.deployment.getDest()); + // Account owner + assertNotNull(this.deployment.getOwner()); + // Deployment plan + this.deployment.plan = mock(DeploymentPlan.class); + assertNotNull(this.deployment.getPlan()); + // Redundant : by default is not + assertFalse(this.deployment.isRedundant()); + this.deployment.isRedundant = true; + assertTrue(this.deployment.isRedundant()); + } + @Test public void testLock() { // Prepare when(this.mockNwDao.acquireInLockTable(NW_ID, NetworkOrchestrationService.NetworkLockTimeout.value())) - .thenReturn(mockNwLock); + .thenReturn(mockNw); // Execute this.deployment.lock(); // Assert verify(this.mockNwDao, times(1)).acquireInLockTable(NW_ID, 600); - Assert.assertNotNull(this.deployment.tableLockId); + assertNotNull(this.deployment.tableLockId); } @Test(expected = ConcurrentOperationException.class) @@ -125,7 +231,7 @@ public class RouterDeploymentDefinitionTest { // Assert verify(this.mockNwDao, times(1)).acquireInLockTable(NW_ID, 600); - Assert.assertNotNull(this.deployment.tableLockId); + assertNotNull(this.deployment.tableLockId); } @Test @@ -176,8 +282,8 @@ public class RouterDeploymentDefinitionTest { @Test public void testGenerateDeploymentPlanBasic() { // Prepare - when(this.mockDestination.getPod()).thenReturn(mockPod); - when(mockDataCenter.getNetworkType()).thenReturn(NetworkType.Basic); + when(this.mockDestination.getPod()).thenReturn(this.mockPod); + when(this.mockDataCenter.getNetworkType()).thenReturn(NetworkType.Basic); // Execute this.deployment.generateDeploymentPlan(); @@ -260,9 +366,9 @@ public class RouterDeploymentDefinitionTest { List destinations = this.deployment.findDestinations(); // Assert - Assert.assertEquals(ONLY_THE_PROVIDED_AS_DEFAULT_DESTINATION_WAS_EXPECTED, + assertEquals(ONLY_THE_PROVIDED_AS_DEFAULT_DESTINATION_WAS_EXPECTED, 1, destinations.size()); - Assert.assertEquals(ONLY_THE_PROVIDED_AS_DEFAULT_DESTINATION_WAS_EXPECTED, + assertEquals(ONLY_THE_PROVIDED_AS_DEFAULT_DESTINATION_WAS_EXPECTED, this.mockDestination, destinations.get(0)); } @@ -276,9 +382,9 @@ public class RouterDeploymentDefinitionTest { List destinations = this.deployment.findDestinations(); // Assert - Assert.assertEquals(ONLY_THE_PROVIDED_AS_DEFAULT_DESTINATION_WAS_EXPECTED, + assertEquals(ONLY_THE_PROVIDED_AS_DEFAULT_DESTINATION_WAS_EXPECTED, 1, destinations.size()); - Assert.assertEquals(ONLY_THE_PROVIDED_AS_DEFAULT_DESTINATION_WAS_EXPECTED, + assertEquals(ONLY_THE_PROVIDED_AS_DEFAULT_DESTINATION_WAS_EXPECTED, this.mockDestination, destinations.get(0)); } @@ -292,7 +398,7 @@ public class RouterDeploymentDefinitionTest { this.mockPods.add(this.mockHostPodVO1); this.mockPods.add(this.mockHostPodVO2); this.mockPods.add(this.mockHostPodVO3); - RouterDeploymentDefinition deployment = Mockito.spy(this.deployment); + RouterDeploymentDefinition deployment = spy(this.deployment); doReturn(mockPods).when(deployment).listByDataCenterIdVMTypeAndStates( DATA_CENTER_ID, VirtualMachine.Type.User, VirtualMachine.State.Starting, VirtualMachine.State.Running); @@ -318,41 +424,577 @@ public class RouterDeploymentDefinitionTest { List destinations = deployment.findDestinations(); // Assert that 2 were added (for the 1st and 3rd - Assert.assertEquals("", + assertEquals("", 2, destinations.size()); - Assert.assertEquals("", + assertEquals("", this.mockDataCenter, destinations.get(0).getDataCenter()); - Assert.assertEquals("", + assertEquals("", this.mockHostPodVO1, destinations.get(0).getPod()); - Assert.assertEquals("", + assertEquals("", this.mockDataCenter, destinations.get(1).getDataCenter()); - Assert.assertEquals("", + assertEquals("", this.mockHostPodVO3, destinations.get(1).getPod()); } + @Test(expected = CloudRuntimeException.class) + public void testFindDestinationsMoreThan1PodPerBasicZone() { + // Prepare + when(this.mockDataCenter.getNetworkType()).thenReturn(NetworkType.Basic); + when(this.mockDestination.getPod()).thenReturn(null); + + // Stub local method listByDataCenterIdVMTypeAndStates + this.mockPods.add(this.mockHostPodVO1); + this.mockPods.add(this.mockHostPodVO2); + // Deployment under test is a Mockito spy + RouterDeploymentDefinition deploymentUT = Mockito.spy(this.deployment); + doReturn(mockPods).when(deploymentUT).listByDataCenterIdVMTypeAndStates( + DATA_CENTER_ID, VirtualMachine.Type.User, + VirtualMachine.State.Starting, VirtualMachine.State.Running); + + // Leave this one empty to force adding add destination for this pod + List virtualRouters1 = new ArrayList<>(); + when(this.mockRouterDao.listByPodIdAndStates(POD_ID1, + VirtualMachine.State.Starting, VirtualMachine.State.Running)).thenReturn(virtualRouters1); + + // This list is not empty, so it will not add any for this pod, and continue with next pod + List virtualRouters2 = new ArrayList<>(); + DomainRouterVO domainRouterVO1 = mock(DomainRouterVO.class); + DomainRouterVO domainRouterVO2 = mock(DomainRouterVO.class); + virtualRouters2.add(domainRouterVO1); + virtualRouters2.add(domainRouterVO2); + when(this.mockRouterDao.listByPodIdAndStates(POD_ID2, + VirtualMachine.State.Starting, VirtualMachine.State.Running)).thenReturn(virtualRouters2); + + // Execute + deploymentUT.findDestinations(); + + // Assert by expected exception + } + + @Test + public void testPlanDeploymentRoutersBasic() { + // Prepare + when(this.mockDataCenter.getNetworkType()).thenReturn(NetworkType.Basic); + when(this.mockDestination.getPod()).thenReturn(this.mockPod); + + // Execute + this.deployment.planDeploymentRouters(); + + // Assert + verify(this.mockRouterDao, times(1)).listByNetworkAndPodAndRole(this.mockNw.getId(), + POD_ID1, Role.VIRTUAL_ROUTER); + } + + @Test + public void testPlanDeploymentRoutersNonBasic() { + // Prepare + when(mockDataCenter.getNetworkType()).thenReturn(NetworkType.Advanced); + when(this.mockDestination.getPod()).thenReturn(this.mockPod); + + // Execute + this.deployment.planDeploymentRouters(); + + // Assert + verify(this.mockRouterDao, times(1)).listByNetworkAndRole( + this.mockNw.getId(), Role.VIRTUAL_ROUTER); + } + @Test public void testListByDataCenterIdVMTypeAndStates() { - // TODO Implement this test + // Prepare + VMInstanceVO vmInstanceVO = mock(VMInstanceVO.class); + final SearchBuilder vmInstanceSearch = mock(SearchBuilder.class); + when(this.mockVmDao.createSearchBuilder()).thenReturn(vmInstanceSearch); + when(vmInstanceSearch.entity()).thenReturn(vmInstanceVO); + when(vmInstanceVO.getType()).thenReturn(VirtualMachine.Type.Instance); + when(vmInstanceVO.getState()).thenReturn(VirtualMachine.State.Stopped); + when(vmInstanceVO.getPodIdToDeployIn()).thenReturn(POD_ID1); + + final SearchBuilder podIdSearch = mock(SearchBuilder.class); + when(this.mockPodDao.createSearchBuilder()).thenReturn(podIdSearch); + final SearchCriteria sc = mock(SearchCriteria.class); + HostPodVO hostPodVO = mock(HostPodVO.class); + when(podIdSearch.entity()).thenReturn(hostPodVO); + when(hostPodVO.getId()).thenReturn(POD_ID1); + when(hostPodVO.getDataCenterId()).thenReturn(DATA_CENTER_ID); + when(podIdSearch.create()).thenReturn(sc); + + final List expectedPods = mock(List.class); + when(this.mockPodDao.search(sc, null)).thenReturn(expectedPods); + + // Execute + final List pods = this.deployment.listByDataCenterIdVMTypeAndStates(DATA_CENTER_ID, + VirtualMachine.Type.User, + VirtualMachine.State.Starting, + VirtualMachine.State.Running); + + // Assert + assertNotNull(pods); + assertEquals(expectedPods, pods); + verify(sc, times(1)).setParameters("dc", DATA_CENTER_ID); + verify(sc, times(1)).setJoinParameters("vmInstanceSearch", "type", VirtualMachine.Type.User); + verify(sc, times(1)).setJoinParameters("vmInstanceSearch", "states", + VirtualMachine.State.Starting, VirtualMachine.State.Running); + verify(this.mockPodDao, times(1)).search(sc, null); } @Test - public void testFindOrDeployVirtualRouter() { - // TODO Implement this test + public void testFindOrDeployVirtualRouter() throws ConcurrentOperationException, + InsufficientCapacityException, ResourceUnavailableException { + // Prepare + RouterDeploymentDefinition deploymentUT = spy(this.deployment); + doNothing().when(deploymentUT).findOrDeployVirtualRouter(); + + // Execute + deploymentUT.deployVirtualRouter(); + + // Assert + verify(this.mockNetworkGeneralHelper, times(1)).startRouters(deploymentUT); + } + + @Test(expected = ConcurrentOperationException.class) + public void testDeployVirtualRouter() throws ConcurrentOperationException, + InsufficientCapacityException, ResourceUnavailableException { + + // Prepare + List mockDestinations = new ArrayList<>(); + mockDestinations.add(mock(DeployDestination.class)); + mockDestinations.add(mock(DeployDestination.class)); + + RouterDeploymentDefinition deploymentUT = spy(this.deployment); + doNothing().when(deploymentUT).lock(); + doNothing().when(deploymentUT).checkPreconditions(); + doReturn(mockDestinations).when(deploymentUT).findDestinations(); + doNothing().when(deploymentUT).planDeploymentRouters(); + doNothing().when(deploymentUT).generateDeploymentPlan(); + // Let's test that if the last step fails in the last iteration it unlocks the table + ConcurrentOperationException exception = + new ConcurrentOperationException(null); + doNothing().doThrow(exception).when(deploymentUT).executeDeployment(); + doNothing().when(deploymentUT).unlock(); + + // Execute + try { + deploymentUT.findOrDeployVirtualRouter(); + } catch (ConcurrentOperationException e) { + throw e; + } finally { + // Assert + verify(deploymentUT, times(1)).lock(); + verify(deploymentUT, times(1)).checkPreconditions(); + verify(deploymentUT, times(1)).findDestinations(); + verify(deploymentUT, times(2)).planDeploymentRouters(); + verify(deploymentUT, times(2)).generateDeploymentPlan(); + verify(deploymentUT, times(2)).executeDeployment(); + verify(deploymentUT, times(1)).unlock(); + } + + fail(); + } + + /** + * If any router is NOT redundant, then it shouldn't update routers + */ + @Test + public void testSetupPriorityOfRedundantRouterWithNonRedundantRouters() { + // Prepare + this.deployment.routers = new ArrayList<>(); + final DomainRouterVO routerVO1 = mock(DomainRouterVO.class); + this.deployment.routers.add(routerVO1); + when(routerVO1.getIsRedundantRouter()).thenReturn(true); + when(routerVO1.getState()).thenReturn(VirtualMachine.State.Stopped); + final DomainRouterVO routerVO2 = mock(DomainRouterVO.class); + this.deployment.routers.add(routerVO2); + when(routerVO2.getIsRedundantRouter()).thenReturn(false); + when(routerVO2.getState()).thenReturn(VirtualMachine.State.Stopped); + // If this deployment is not redundant nothing will be executed + this.deployment.isRedundant = true; + + // Execute + this.deployment.setupPriorityOfRedundantRouter(); + + // Assert + verify(routerVO1, times(0)).setPriority(anyInt()); + verify(routerVO1, times(0)).setIsPriorityBumpUp(anyBoolean()); + verify(this.mockRouterDao, times(0)).update(anyLong(), (DomainRouterVO) anyObject()); + } + + /** + * If any router is NOT Stopped, then it shouldn't update routers + */ + @Test + public void testSetupPriorityOfRedundantRouterWithRunningRouters() { + // Prepare + this.deployment.routers = new ArrayList<>(); + final DomainRouterVO routerVO1 = mock(DomainRouterVO.class); + this.deployment.routers.add(routerVO1); + when(routerVO1.getIsRedundantRouter()).thenReturn(true); + when(routerVO1.getState()).thenReturn(VirtualMachine.State.Stopped); + final DomainRouterVO routerVO2 = mock(DomainRouterVO.class); + this.deployment.routers.add(routerVO2); + when(routerVO2.getIsRedundantRouter()).thenReturn(true); + when(routerVO2.getState()).thenReturn(VirtualMachine.State.Running); + // If this deployment is not redundant nothing will be executed + this.deployment.isRedundant = true; + + // Execute + this.deployment.setupPriorityOfRedundantRouter(); + + // Assert + verify(routerVO1, times(0)).setPriority(anyInt()); + verify(routerVO1, times(0)).setIsPriorityBumpUp(anyBoolean()); + verify(this.mockRouterDao, times(0)).update(anyLong(), (DomainRouterVO) anyObject()); + } + + /** + * Given all routers are redundant and Stopped, then it should update ALL routers + */ + @Test + public void testSetupPriorityOfRedundantRouter() { + // Prepare + this.deployment.routers = new ArrayList<>(); + final DomainRouterVO routerVO1 = mock(DomainRouterVO.class); + this.deployment.routers.add(routerVO1); + when(routerVO1.getId()).thenReturn(ROUTER1_ID); + when(routerVO1.getIsRedundantRouter()).thenReturn(true); + when(routerVO1.getState()).thenReturn(VirtualMachine.State.Stopped); + final DomainRouterVO routerVO2 = mock(DomainRouterVO.class); + this.deployment.routers.add(routerVO2); + when(routerVO2.getId()).thenReturn(ROUTER2_ID); + when(routerVO2.getIsRedundantRouter()).thenReturn(true); + when(routerVO2.getState()).thenReturn(VirtualMachine.State.Stopped); + // If this deployment is not redundant nothing will be executed + this.deployment.isRedundant = true; + + // Execute + this.deployment.setupPriorityOfRedundantRouter(); + + // Assert + verify(routerVO1, times(1)).setPriority(0); + verify(routerVO1, times(1)).setIsPriorityBumpUp(false); + verify(this.mockRouterDao, times(1)).update(ROUTER1_ID, routerVO1); + verify(routerVO2, times(1)).setPriority(0); + verify(routerVO2, times(1)).setIsPriorityBumpUp(false); + verify(this.mockRouterDao, times(1)).update(ROUTER2_ID, routerVO2); + } + + /** + * If this is not a redundant deployment, then we shouldn't reset priorities + */ + @Test + public void testSetupPriorityOfRedundantRouterWithNonRedundantDeployment() { + // Prepare + this.deployment.routers = new ArrayList<>(); + final DomainRouterVO routerVO1 = mock(DomainRouterVO.class); + this.deployment.routers.add(routerVO1); + when(routerVO1.getIsRedundantRouter()).thenReturn(true); + when(routerVO1.getState()).thenReturn(VirtualMachine.State.Stopped); + final DomainRouterVO routerVO2 = mock(DomainRouterVO.class); + this.deployment.routers.add(routerVO2); + when(routerVO2.getIsRedundantRouter()).thenReturn(true); + when(routerVO2.getState()).thenReturn(VirtualMachine.State.Stopped); + + // Execute + this.deployment.setupPriorityOfRedundantRouter(); + + // Assert + verify(routerVO1, times(0)).setPriority(anyInt()); + verify(routerVO1, times(0)).setIsPriorityBumpUp(anyBoolean()); + verify(this.mockRouterDao, times(0)).update(anyLong(), (DomainRouterVO) anyObject()); } @Test - public void testDeployVirtualRouter() { - // TODO Implement this test + public void testGetNumberOfRoutersToDeploy() { + // Prepare + this.deployment.routers = new ArrayList<>(); // Empty list + + // Execute and assert + assertEquals(NUMBER_OF_ROUTERS_TO_DEPLOY_IS_NOT_THE_EXPECTED, + 1, this.deployment.getNumberOfRoutersToDeploy()); + + // Execute and assert, just the same but for redundant deployment + this.deployment.isRedundant = true; + assertEquals(NUMBER_OF_ROUTERS_TO_DEPLOY_IS_NOT_THE_EXPECTED, + 2, this.deployment.getNumberOfRoutersToDeploy()); + + // Just the same, instead of an empty list, a 1 items list + this.deployment.routers.add(mock(DomainRouterVO.class)); + this.deployment.isRedundant = false; + assertEquals(NUMBER_OF_ROUTERS_TO_DEPLOY_IS_NOT_THE_EXPECTED, + 0, this.deployment.getNumberOfRoutersToDeploy()); + + this.deployment.isRedundant = true; + assertEquals(NUMBER_OF_ROUTERS_TO_DEPLOY_IS_NOT_THE_EXPECTED, + 1, this.deployment.getNumberOfRoutersToDeploy()); } @Test - public void testExecuteDeployment() { - // TODO Implement this test + public void testFindVirtualProvider() { + // Prepare + when(this.mockNetworkModel.getPhysicalNetworkId(this.deployment.guestNetwork)).thenReturn(PHYSICAL_NW_ID); + Type type = Type.VirtualRouter; + PhysicalNetworkServiceProviderVO physicalNwSrvProvider = mock(PhysicalNetworkServiceProviderVO.class); + when(this.physicalProviderDao.findByServiceProvider(PHYSICAL_NW_ID, type.toString())) + .thenReturn(physicalNwSrvProvider); + when(physicalNwSrvProvider.getId()).thenReturn(PROVIDER_ID); + + VirtualRouterProviderVO vrProvider = mock(VirtualRouterProviderVO.class); + when(this.mockVrProviderDao.findByNspIdAndType(PROVIDER_ID, type)) + .thenReturn(vrProvider); + + // Execute + this.deployment.findVirtualProvider(); + + // Assert + assertEquals("Didn't find and set the VirtualRouterProvider as expected", + vrProvider, this.deployment.getVirtualProvider()); + } + + @Test(expected = CloudRuntimeException.class) + public void testFindVirtualProviderWithNullPhyNwSrvProvider() { + // Prepare + when(this.mockNetworkModel.getPhysicalNetworkId(this.deployment.guestNetwork)).thenReturn(PHYSICAL_NW_ID); + Type type = Type.VirtualRouter; + when(this.physicalProviderDao.findByServiceProvider(PHYSICAL_NW_ID, type.toString())) + .thenReturn(null); + + // Execute + this.deployment.findVirtualProvider(); + } + + @Test(expected = CloudRuntimeException.class) + public void testFindVirtualProviderWithNullVrProvider() { + // Prepare + when(this.mockNetworkModel.getPhysicalNetworkId(this.deployment.guestNetwork)).thenReturn(PHYSICAL_NW_ID); + Type type = Type.VirtualRouter; + PhysicalNetworkServiceProviderVO physicalNwSrvProvider = mock(PhysicalNetworkServiceProviderVO.class); + when(this.physicalProviderDao.findByServiceProvider(PHYSICAL_NW_ID, type.toString())) + .thenReturn(physicalNwSrvProvider); + when(physicalNwSrvProvider.getId()).thenReturn(PROVIDER_ID); + + when(this.mockVrProviderDao.findByNspIdAndType(PROVIDER_ID, type)) + .thenReturn(null); + + // Execute + this.deployment.findVirtualProvider(); } @Test - public void testPlanDeploymentRouters() { - // TODO Implement this test + public void testFindSourceNatIPPublicNw() throws InsufficientAddressCapacityException, ConcurrentOperationException { + // Prepare + PublicIp sourceNatIp = mock(PublicIp.class); + when(this.mockIpAddrMgr.assignSourceNatIpAddressToGuestNetwork( + this.mockOwner, this.mockNw)).thenReturn(sourceNatIp); + this.deployment.publicNetwork = true; + + // It should be null until this method finds it + assertNull(this.deployment.sourceNatIp); + // Execute + this.deployment.findSourceNatIP(); + + // Assert + assertEquals("SourceNatIP was not correctly found and set", sourceNatIp, this.deployment.sourceNatIp); + } + + @Test + public void testFindSourceNatIPNonPublicNw() throws InsufficientAddressCapacityException, ConcurrentOperationException { + // Prepare + PublicIp sourceNatIp = mock(PublicIp.class); + when(this.mockIpAddrMgr.assignSourceNatIpAddressToGuestNetwork( + this.mockOwner, this.mockNw)).thenReturn(sourceNatIp); + this.deployment.publicNetwork = false; + + // It should be null until this method finds it + assertNull(this.deployment.sourceNatIp); + // Execute + this.deployment.findSourceNatIP(); + + // Assert + assertEquals("SourceNatIP should remain null given a non public network", + null, this.deployment.sourceNatIp); + } + + @Test + public void testFindOfferingIdReceivingNewOne() { + // Prepare + this.deployment.offeringId = 1L; + when(this.mockNw.getNetworkOfferingId()).thenReturn(OFFERING_ID); + when(this.mockNetworkOfferingDao.findById(OFFERING_ID)).thenReturn(this.mockNwOfferingVO); + when(this.mockNwOfferingVO.getServiceOfferingId()).thenReturn(OFFERING_ID); + + // Execute + this.deployment.findOfferingId(); + + // Assert + assertEquals("Given that no Offering was found, the previous Offering Id should be kept", + OFFERING_ID, this.deployment.offeringId.longValue()); + } + + @Test + public void testFindOfferingIdReceivingKeepingPrevious() { + // Prepare + this.deployment.offeringId = 1L; + when(this.mockNw.getNetworkOfferingId()).thenReturn(OFFERING_ID); + when(this.mockNetworkOfferingDao.findById(OFFERING_ID)).thenReturn(this.mockNwOfferingVO); + when(this.mockNwOfferingVO.getServiceOfferingId()).thenReturn(null); + + // Execute + this.deployment.findOfferingId(); + + // Assert + assertEquals("Found Offering Id didn't replace previous one", + 1L, this.deployment.offeringId.longValue()); + } + + @Test + public void testDeployAllVirtualRouters() + throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { + + // Prepare + this.deployment.routers = new ArrayList<>(); + this.deployment.isRedundant = true; + //this.deployment.routers.add(routerVO1); + RouterDeploymentDefinition deploymentUT = Mockito.spy(this.deployment); + doReturn(2).when(deploymentUT).getNumberOfRoutersToDeploy(); + doReturn(null).when(deploymentUT).createRouterNetworks(); + + final DomainRouterVO routerVO1 = mock(DomainRouterVO.class); + final DomainRouterVO routerVO2 = mock(DomainRouterVO.class); + when(this.mockNetworkGeneralHelper.deployRouter(deploymentUT, null, false, null)) + .thenReturn(routerVO1).thenReturn(routerVO2); + + // Execute + deploymentUT.deployAllVirtualRouters(); + + // Assert + verify(this.mockRouterDao, times(1)).addRouterToGuestNetwork(routerVO1, this.mockNw); + verify(this.mockRouterDao, times(1)).addRouterToGuestNetwork(routerVO2, this.mockNw); + assertEquals("First router to deploy was not added to list of available routers", + routerVO1, this.deployment.routers.get(0)); + assertEquals("Second router to deploy was not added to list of available routers", + routerVO2, this.deployment.routers.get(1)); + } + + @Test + public void testExecuteDeploymentPublicNw() + throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { + // Prepare + this.deployment.isRedundant = true; + RouterDeploymentDefinition deploymentUT = Mockito.spy(this.deployment); + doNothing().when(deploymentUT).setupPriorityOfRedundantRouter(); + doReturn(2).when(deploymentUT).getNumberOfRoutersToDeploy(); + doNothing().when(deploymentUT).findVirtualProvider(); + doNothing().when(deploymentUT).findOfferingId(); + doNothing().when(deploymentUT).findSourceNatIP(); + doNothing().when(deploymentUT).deployAllVirtualRouters(); + + when(this.mockNetworkModel.isNetworkSystem(this.mockNw)).thenReturn(true); + Account newAccountOwner = mock(Account.class); + when(this.mockAccountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM)).thenReturn(newAccountOwner); + + when(this.mockNetworkModel.isProviderSupportServiceInNetwork( + NW_ID, Service.SourceNat, Provider.VirtualRouter)).thenReturn(true); + + // Execute + deploymentUT.executeDeployment(); + + // Assert + assertEquals("New account owner not properly set", newAccountOwner, deploymentUT.owner); + verify(deploymentUT, times(1)).findVirtualProvider(); + verify(deploymentUT, times(1)).findOfferingId(); + verify(deploymentUT, times(1)).findSourceNatIP(); + verify(deploymentUT, times(1)).deployAllVirtualRouters(); + } + + @Test + public void testExecuteDeploymentNonRedundant() + throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { + // Prepare + this.deployment.isRedundant = false; + RouterDeploymentDefinition deploymentUT = Mockito.spy(this.deployment); + doNothing().when(deploymentUT).setupPriorityOfRedundantRouter(); + doReturn(2).when(deploymentUT).getNumberOfRoutersToDeploy(); + doNothing().when(deploymentUT).findVirtualProvider(); + doNothing().when(deploymentUT).findOfferingId(); + doNothing().when(deploymentUT).findSourceNatIP(); + doNothing().when(deploymentUT).deployAllVirtualRouters(); + + when(this.mockNetworkModel.isNetworkSystem(this.mockNw)).thenReturn(true); + Account newAccountOwner = mock(Account.class); + when(this.mockAccountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM)).thenReturn(newAccountOwner); + + when(this.mockNetworkModel.isProviderSupportServiceInNetwork( + NW_ID, Service.SourceNat, Provider.VirtualRouter)).thenReturn(true); + + // Execute + deploymentUT.executeDeployment(); + + // Assert + assertEquals("New account owner not properly set", newAccountOwner, deploymentUT.owner); + verify(deploymentUT, times(1)).findVirtualProvider(); + verify(deploymentUT, times(1)).findOfferingId(); + verify(deploymentUT, times(1)).findSourceNatIP(); + verify(deploymentUT, times(1)).deployAllVirtualRouters(); + } + + @Test + public void testExecuteDeploymentRedundantNonPublicNw() + throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { + // Prepare + this.deployment.isRedundant = true; + RouterDeploymentDefinition deploymentUT = Mockito.spy(this.deployment); + doNothing().when(deploymentUT).setupPriorityOfRedundantRouter(); + doReturn(2).when(deploymentUT).getNumberOfRoutersToDeploy(); + doNothing().when(deploymentUT).findVirtualProvider(); + doNothing().when(deploymentUT).findOfferingId(); + doNothing().when(deploymentUT).findSourceNatIP(); + doNothing().when(deploymentUT).deployAllVirtualRouters(); + + when(this.mockNetworkModel.isNetworkSystem(this.mockNw)).thenReturn(true); + Account newAccountOwner = mock(Account.class); + when(this.mockAccountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM)).thenReturn(newAccountOwner); + + when(this.mockNetworkModel.isProviderSupportServiceInNetwork( + NW_ID, Service.SourceNat, Provider.VirtualRouter)).thenReturn(false); + + // Execute + deploymentUT.executeDeployment(); + + // Assert + assertEquals("New account owner not properly set", newAccountOwner, deploymentUT.owner); + assertEquals("Since is redundant deployment in non public nw there should be 0 routers to start", + 0, this.deployment.routers.size()); + verify(this.mockNetworkModel, times(1)).isNetworkSystem(this.mockNw); + verify(deploymentUT, times(0)).findVirtualProvider(); + verify(deploymentUT, times(0)).findOfferingId(); + verify(deploymentUT, times(0)).findSourceNatIP(); + verify(deploymentUT, times(0)).deployAllVirtualRouters(); + } + + @Test + public void testExecuteDeploymentNoRoutersToDeploy() + throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { + // Prepare + this.deployment.isRedundant = true; + this.deployment.publicNetwork = false; + RouterDeploymentDefinition deploymentUT = Mockito.spy(this.deployment); + doNothing().when(deploymentUT).setupPriorityOfRedundantRouter(); + doReturn(0).when(deploymentUT).getNumberOfRoutersToDeploy(); + doNothing().when(deploymentUT).findVirtualProvider(); + doNothing().when(deploymentUT).findOfferingId(); + doNothing().when(deploymentUT).findSourceNatIP(); + doNothing().when(deploymentUT).deployAllVirtualRouters(); + + // Execute + deploymentUT.executeDeployment(); + + // Assert + assertEquals("New account owner not properly set", this.mockOwner, deploymentUT.owner); + verify(this.mockNetworkModel, times(0)).isNetworkSystem((Network)anyObject()); + verify(deploymentUT, times(0)).findVirtualProvider(); + verify(deploymentUT, times(0)).findOfferingId(); + verify(deploymentUT, times(0)).findSourceNatIP(); + verify(deploymentUT, times(0)).deployAllVirtualRouters(); } @Test