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
This commit is contained in:
Alena Prokharchyk 2012-08-20 15:21:30 -07:00
parent 7d0ad98c93
commit 2bf5c99bc6
5 changed files with 114 additions and 100 deletions

View File

@ -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;

View File

@ -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();
}

View File

@ -7329,4 +7329,10 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
return nic;
}
@Override
public int getNetworkLockTimeout() {
return _networkLockTimeout;
}
}

View File

@ -1266,36 +1266,38 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
boolean isRedundant, Map<Param, Object> params) throws ConcurrentOperationException,
InsufficientCapacityException, ResourceUnavailableException {
List<DomainRouterVO> routers = new ArrayList<DomainRouterVO>();
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 " + 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
// 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<DeploymentPlan, List<DomainRouterVO>> planAndRouters = getDeploymentPlanAndRouters(isPodBased, dest, guestNetwork.getId());
DeploymentPlan plan = planAndRouters.first();
List<DomainRouterVO> routers = planAndRouters.second();
routers = planAndRouters.second();
//2) Figure out required routers count
// 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;
@ -1305,19 +1307,9 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
s_logger.error("Too much redundant routers!");
}
Network network = _networkDao.acquireInLockTable(guestNetwork.getId());
if (network == 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);
}
try {
//Check if providers are supported in the physical networks
// 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<Pair<NetworkVO, NicProfile>> networks = createRouterNetworks(owner, isRedundant, plan, guestNetwork,
new Pair<Boolean, PublicIp>(publicNetwork, sourceNatIp));
//don't start the router as we are holding the network lock that needs to be released at the end of router allocation
DomainRouterVO router = 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,7 +1369,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
protected DomainRouterVO deployRouter(Account owner, DeployDestination dest, DeploymentPlan plan, Map<Param, Object> params,
boolean isRedundant, VirtualRouterProvider vrProvider, long svcOffId,
Long vpcId, List<Pair<NetworkVO, NicProfile>> networks) throws ConcurrentOperationException,
Long vpcId, List<Pair<NetworkVO, NicProfile>> networks, boolean startRouter) throws ConcurrentOperationException,
InsufficientAddressCapacityException, InsufficientServerCapacityException, InsufficientCapacityException,
StorageUnavailableException, ResourceUnavailableException {
@ -1388,32 +1381,8 @@ 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<HypervisorType> supportedHypervisors = new ArrayList<HypervisorType>();
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<HypervisorType> supportedHypervisors = getSupportedHypervisors(dest, plan);
int allocateRetry = 0;
int startRetry = 0;
@ -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;
@ -1452,14 +1421,16 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
allocateRetry++;
}
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 domR " + router + " with hypervisor type " + hType + ", " +
s_logger.debug("Failed to start the VR " + router + " with hypervisor type " + hType + ", " +
"destroying it and recreating one more time");
//destroy the router
// destroy the router
destroyRouter(router.getId());
continue;
} else {
@ -1469,10 +1440,41 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
startRetry++;
}
}
}
return router;
}
protected List<HypervisorType> getSupportedHypervisors(DeployDestination dest, DeploymentPlan plan) throws InsufficientServerCapacityException {
List<HypervisorType> supportedHypervisors = new ArrayList<HypervisorType>();
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<Pair<NetworkVO, NicProfile>> createRouterNetworks(Account owner, boolean isRedundant,
DeploymentPlan plan, Network guestNetwork, Pair<Boolean, PublicIp> 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);

View File

@ -318,7 +318,7 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian
List<Pair<NetworkVO, NicProfile>> networks = createVpcRouterNetworks(owner, isRedundant, plan, new Pair<Boolean, PublicIp>(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;
}