From d0dac137874b2ebed02a5e8d6e034fb3de9651e2 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 --- .../src/com/cloud/configuration/Config.java | 1 - .../src/com/cloud/network/NetworkManager.java | 6 + .../com/cloud/network/NetworkManagerImpl.java | 5 + .../VirtualNetworkApplianceManagerImpl.java | 181 +++++++++--------- ...VpcVirtualNetworkApplianceManagerImpl.java | 2 +- 5 files changed, 103 insertions(+), 92 deletions(-) diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index d5306c2561b..9766505a8d4 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -22,7 +22,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 90de281f8ab..c0cbbebbcdd 100755 --- a/server/src/com/cloud/network/NetworkManager.java +++ b/server/src/com/cloud/network/NetworkManager.java @@ -470,4 +470,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 ffe3eee17f8..771f701aa01 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -7350,5 +7350,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 d850ad3b75d..9253a22ff47 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -1344,57 +1344,49 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian protected List findOrDeployVirtualRouterInGuestNetwork(Network guestNetwork, DeployDestination dest, Account owner, 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 { + 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); @@ -1430,21 +1422,23 @@ 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); + null, networks, false); - _routerDao.addRouterToGuestNetwork(router, network); + _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); } } } @@ -1453,7 +1447,7 @@ 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, + Long vpcId, List> networks, boolean startRouter) throws ConcurrentOperationException, InsufficientAddressCapacityException, InsufficientServerCapacityException, InsufficientCapacityException, StorageUnavailableException, ResourceUnavailableException { @@ -1466,31 +1460,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian // 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()); - } + List supportedHypervisors = getSupportedHypervisors(dest, plan); int allocateRetry = 0; int startRetry = 0; @@ -1523,7 +1493,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; @@ -1532,27 +1502,58 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian 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 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 { @@ -2414,7 +2415,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian 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 + // 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 3839157a35a..0cdaa45a57d 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; }