From 2bf5c99bc6f18c751944181e687429ce4e7e4686 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Mon, 20 Aug 2012 15:21:30 -0700 Subject: [PATCH] CS-15304: VR deployment - release the lock for the network once the router entry is allocated (2.2.x behavior) as opposed to releasing it when the router start is completed Reviewed-by: Frank Zhang Conflicts: server/src/com/cloud/network/NetworkManagerImpl.java server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java --- .../src/com/cloud/configuration/Config.java | 1 - .../src/com/cloud/network/NetworkManager.java | 6 + .../com/cloud/network/NetworkManagerImpl.java | 6 + .../VirtualNetworkApplianceManagerImpl.java | 199 +++++++++--------- ...VpcVirtualNetworkApplianceManagerImpl.java | 2 +- 5 files changed, 114 insertions(+), 100 deletions(-) diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index 9fea7fbd5d0..ebcd07002e6 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -26,7 +26,6 @@ import com.cloud.ha.HighAvailabilityManager; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.NetworkManager; import com.cloud.network.router.VpcVirtualNetworkApplianceManager; -import com.cloud.network.vpn.Site2SiteVpnManager; import com.cloud.server.ManagementServer; import com.cloud.storage.StorageManager; import com.cloud.storage.allocator.StoragePoolAllocator; diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java index 1f803af6a50..74e9d885eb6 100755 --- a/server/src/com/cloud/network/NetworkManager.java +++ b/server/src/com/cloud/network/NetworkManager.java @@ -476,4 +476,10 @@ public interface NetworkManager extends NetworkService { */ PublicIp assignDedicateIpAddress(Account owner, Long guestNtwkId, Long vpcId, long dcId, boolean isSourceNat) throws ConcurrentOperationException, InsufficientAddressCapacityException; + + /** + * @return + */ + int getNetworkLockTimeout(); + } diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 30620d8746b..01feba21471 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -7329,4 +7329,10 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag return nic; } + + @Override + public int getNetworkLockTimeout() { + return _networkLockTimeout; + } + } diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 8c8b9274c5d..730ce28053a 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -1266,58 +1266,50 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian boolean isRedundant, Map params) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { - 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 - boolean isPodBased = (dest.getDataCenter().getNetworkType() == NetworkType.Basic || - _networkMgr.areServicesSupportedInNetwork(guestNetwork.getId(), Service.SecurityGroup)) - && guestNetwork.getTrafficType() == TrafficType.Guest; - - Pair> planAndRouters = getDeploymentPlanAndRouters(isPodBased, dest, guestNetwork.getId()); - DeploymentPlan plan = planAndRouters.first(); - List routers = planAndRouters.second(); - - //2) Figure out required routers count - int routerCount = 1; - if (isRedundant) { - routerCount = 2; - } - - /* If it is the single router network, then keep it untouched */ - for (DomainRouterVO router : routers) { - if (!router.getIsRedundantRouter() || isPodBased) { - routerCount = 1; - break; - } - } - - /* If old network is redundant but new is single router, then routers.size() = 2 but routerCount = 1 */ - if (routers.size() >= routerCount) { - return routers; - } - - if (routers.size() >= 5) { - s_logger.error("Too much redundant routers!"); - } - - Network network = _networkDao.acquireInLockTable(guestNetwork.getId()); - if (network == null) { + List routers = new ArrayList(); + Network lock = _networkDao.acquireInLockTable(guestNetwork.getId(), _networkMgr.getNetworkLockTimeout()); + if (lock == null) { throw new ConcurrentOperationException("Unable to lock network " + guestNetwork.getId()); } if (s_logger.isDebugEnabled()) { - s_logger.debug("Lock is acquired for network id " + network.getId() + " as a part of router startup in " + dest); + s_logger.debug("Lock is acquired for network id " + lock.getId() + " as a part of router startup in " + dest); } - + try { - //Check if providers are supported in the physical networks + + 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 + boolean isPodBased = (dest.getDataCenter().getNetworkType() == NetworkType.Basic || + _networkMgr.areServicesSupportedInNetwork(guestNetwork.getId(), Service.SecurityGroup)) + && guestNetwork.getTrafficType() == TrafficType.Guest; + + Pair> planAndRouters = getDeploymentPlanAndRouters(isPodBased, dest, guestNetwork.getId()); + routers = planAndRouters.second(); + + // 2) Figure out required routers count + int routerCount = 1; + if (isRedundant) { + routerCount = 2; + } + + /* If old network is redundant but new is single router, then routers.size() = 2 but routerCount = 1 */ + if (routers.size() >= routerCount) { + return routers; + } + + if (routers.size() >= 5) { + s_logger.error("Too much redundant routers!"); + } + + // Check if providers are supported in the physical networks VirtualRouterProviderType type = VirtualRouterProviderType.VirtualRouter; - Long physicalNetworkId = _networkMgr.getPhysicalNetworkId(network); + Long physicalNetworkId = _networkMgr.getPhysicalNetworkId(guestNetwork); PhysicalNetworkServiceProvider provider = _physicalProviderDao.findByServiceProvider(physicalNetworkId, type.toString()); if (provider == null) { throw new CloudRuntimeException("Cannot find service provider " + type.toString() + " in physical network " + physicalNetworkId); @@ -1353,21 +1345,22 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian //3) deploy virtual router(s) int count = routerCount - routers.size(); + DeploymentPlan plan = planAndRouters.first(); for (int i = 0; i < count; i++) { List> networks = createRouterNetworks(owner, isRedundant, plan, guestNetwork, 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 = deployRouter(owner, dest, plan, params, isRedundant, vrProvider, offeringId, - null, networks); - - _routerDao.addRouterToGuestNetwork(router, network); - + null, networks, false); + + _routerDao.addRouterToGuestNetwork(router, guestNetwork); routers.add(router); } } finally { - if (network != null) { - _networkDao.releaseFromLockTable(network.getId()); + if (lock != null) { + _networkDao.releaseFromLockTable(lock.getId()); if (s_logger.isDebugEnabled()) { - s_logger.debug("Lock is released for network id " + network.getId() + " as a part of router startup in " + dest); + s_logger.debug("Lock is released for network id " + lock.getId() + " as a part of router startup in " + dest); } } } @@ -1376,8 +1369,8 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian protected DomainRouterVO deployRouter(Account owner, DeployDestination dest, DeploymentPlan plan, Map params, boolean isRedundant, VirtualRouterProvider vrProvider, long svcOffId, - Long vpcId, List> networks) throws ConcurrentOperationException, - InsufficientAddressCapacityException, InsufficientServerCapacityException, InsufficientCapacityException, + Long vpcId, List> networks, boolean startRouter) throws ConcurrentOperationException, + InsufficientAddressCapacityException, InsufficientServerCapacityException, InsufficientCapacityException, StorageUnavailableException, ResourceUnavailableException { long id = _routerDao.getNextInSequence(Long.class, "id"); @@ -1388,33 +1381,9 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian ServiceOfferingVO routerOffering = _serviceOfferingDao.findById(svcOffId); // Router is the network element, we don't know the hypervisor type yet. - //Try to allocate the domR twice using diff hypervisors, and when failed both times, throw the exception up - List supportedHypervisors = new ArrayList(); - HypervisorType defaults = _resourceMgr.getDefaultHypervisor(dest.getDataCenter().getId()); - if (defaults != HypervisorType.None) { - supportedHypervisors.add(defaults); - } - - if (dest.getCluster() != null) { - if (dest.getCluster().getHypervisorType() == HypervisorType.Ovm) { - supportedHypervisors.add(getClusterToStartDomainRouterForOvm(dest.getCluster().getPodId())); - } else { - supportedHypervisors.add(dest.getCluster().getHypervisorType()); - } - } else { - supportedHypervisors = _resourceMgr.getSupportedHypervisorTypes(dest.getDataCenter().getId(), true, - plan.getPodId()); - } - - if (supportedHypervisors.isEmpty()) { - if (plan.getPodId() != null) { - throw new InsufficientServerCapacityException("Unable to create virtual router, " + - "there are no clusters in the pod ", Pod.class, plan.getPodId()); - } - throw new InsufficientServerCapacityException("Unable to create virtual router, " + - "there are no clusters in the zone ", DataCenter.class, dest.getDataCenter().getId()); - } - + // Try to allocate the domR twice using diff hypervisors, and when failed both times, throw the exception up + List supportedHypervisors = getSupportedHypervisors(dest, plan); + int allocateRetry = 0; int startRetry = 0; DomainRouterVO router = null; @@ -1443,7 +1412,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian router = _itMgr.allocate(router, template, routerOffering, networks, plan, null, owner); } catch (InsufficientCapacityException ex) { if (allocateRetry < 2 && iter.hasNext()) { - s_logger.debug("Failed to allocate the domR with hypervisor type " + hType + ", retrying one more time"); + s_logger.debug("Failed to allocate the VR with hypervisor type " + hType + ", retrying one more time"); continue; } else { throw ex; @@ -1451,29 +1420,62 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian } finally { allocateRetry++; } - - try { - router = startVirtualRouter(router, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount(), params); - break; - } catch (InsufficientCapacityException ex) { - if (startRetry < 2 && iter.hasNext()) { - s_logger.debug("Failed to start the domR " + router + " with hypervisor type " + hType + ", " + - "destroying it and recreating one more time"); - //destroy the router - destroyRouter(router.getId()); - continue; - } else { - throw ex; + + + if (startRouter) { + try { + router = startVirtualRouter(router, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount(), params); + break; + } catch (InsufficientCapacityException ex) { + if (startRetry < 2 && iter.hasNext()) { + s_logger.debug("Failed to start the VR " + router + " with hypervisor type " + hType + ", " + + "destroying it and recreating one more time"); + // destroy the router + destroyRouter(router.getId()); + continue; + } else { + throw ex; + } + } finally { + startRetry++; } - } finally { - startRetry++; } } return router; } - protected List> createRouterNetworks(Account owner, boolean isRedundant, + + protected List getSupportedHypervisors(DeployDestination dest, DeploymentPlan plan) throws InsufficientServerCapacityException { + List supportedHypervisors = new ArrayList(); + HypervisorType defaults = _resourceMgr.getDefaultHypervisor(dest.getDataCenter().getId()); + if (defaults != HypervisorType.None) { + supportedHypervisors.add(defaults); + } + + if (dest.getCluster() != null) { + if (dest.getCluster().getHypervisorType() == HypervisorType.Ovm) { + supportedHypervisors.add(getClusterToStartDomainRouterForOvm(dest.getCluster().getPodId())); + } else { + supportedHypervisors.add(dest.getCluster().getHypervisorType()); + } + } else { + supportedHypervisors = _resourceMgr.getSupportedHypervisorTypes(dest.getDataCenter().getId(), true, + plan.getPodId()); + } + + if (supportedHypervisors.isEmpty()) { + if (plan.getPodId() != null) { + throw new InsufficientServerCapacityException("Unable to create virtual router, " + + "there are no clusters in the pod ", Pod.class, plan.getPodId()); + } + throw new InsufficientServerCapacityException("Unable to create virtual router, " + + "there are no clusters in the zone ", DataCenter.class, dest.getDataCenter().getId()); + } + return supportedHypervisors; + } + + protected List> createRouterNetworks(Account owner, boolean isRedundant, DeploymentPlan plan, Network guestNetwork, Pair publicNetwork) throws ConcurrentOperationException, InsufficientAddressCapacityException { @@ -2340,7 +2342,8 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian ConcurrentOperationException, ResourceUnavailableException { s_logger.debug("Starting router " + router); if (_itMgr.start(router, params, user, caller, planToDeploy) != null) { - // We don't want the failure of VPN Connection affect the status of router, so we try to make connection only after router start successfully + // We don't want the failure of VPN Connection affect the status of router, so we try to make connection + // only after router start successfully Long vpcId = router.getVpcId(); if (vpcId != null) { _s2sVpnMgr.reconnectDisconnectedVpnByVpc(vpcId); diff --git a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java index 4f3e02e8705..a9155613244 100644 --- a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java @@ -318,7 +318,7 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian List> networks = createVpcRouterNetworks(owner, isRedundant, plan, new Pair(true, sourceNatIp), vpcId); DomainRouterVO router = - super.deployRouter(owner, dest, plan, params, isRedundant, vrProvider, svcOffId, vpcId, networks); + super.deployRouter(owner, dest, plan, params, isRedundant, vrProvider, svcOffId, vpcId, networks, true); return router; }