mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-02 11:52:28 +01:00
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:
parent
7d0ad98c93
commit
2bf5c99bc6
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
}
|
||||
|
||||
@ -7329,4 +7329,10 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
|
||||
return nic;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getNetworkLockTimeout() {
|
||||
return _networkLockTimeout;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user