From 8bc7ae695d621b67e1e5d1916a1852cad1f4dda0 Mon Sep 17 00:00:00 2001 From: Koushik Das Date: Thu, 31 Jul 2014 11:51:58 +0530 Subject: [PATCH] CLOUDSTACK-7182: NPE while trying to deploy VMs in parallel in isolated network - Check to see if network is implemented changed from 'state == Implementing||Implemented' to 'state == Implemented'. The earlier check was a hack to prevent the issue described below. - At the time of implementing network (using implementNetwork() method), if the VR needs to be deployed then it follows the same path of regular VM deployment. This leads to a nested call to implementNetwork() while preparing VR nics. This flow creates issues in dealing with network state transitions. The original call puts network in "Implementing" state and then the nested call again tries to put it into same state resulting in issues. In order to avoid it, implementNetwork() call for VR is replaced with below code. --- .../orchestration/NetworkOrchestrator.java | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index cdca839fc30..ca0b86d0e16 100755 --- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -928,7 +928,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra boolean isNetworkImplemented(NetworkVO network) { Network.State state = network.getState(); - if (state == Network.State.Implemented || state == Network.State.Implementing) { + if (state == Network.State.Implemented) { return true; } else if (state == Network.State.Setup) { DataCenterVO zone = _dcDao.findById(network.getDataCenterId()); @@ -939,6 +939,24 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra return false; } + Pair implementNetwork(long networkId, DeployDestination dest, ReservationContext context, boolean isRouter) throws ConcurrentOperationException, + ResourceUnavailableException, InsufficientCapacityException { + Pair implemented = null; + if (!isRouter) { + implemented = implementNetwork(networkId, dest, context); + } else { + // At the time of implementing network (using implementNetwork() method), if the VR needs to be deployed then + // it follows the same path of regular VM deployment. This leads to a nested call to implementNetwork() while + // preparing VR nics. This flow creates issues in dealing with network state transitions. The original call + // puts network in "Implementing" state and then the nested call again tries to put it into same state resulting + // in issues. In order to avoid it, implementNetwork() call for VR is replaced with below code. + NetworkVO network = _networksDao.findById(networkId); + NetworkGuru guru = AdapterBase.getAdapterByName(networkGurus, network.getGuruName()); + implemented = new Pair(guru, network); + } + return implemented; + } + @Override @DB public Pair implementNetwork(long networkId, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, @@ -1280,7 +1298,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra }); for (NicVO nic : nics) { - Pair implemented = implementNetwork(nic.getNetworkId(), dest, context); + Pair implemented = implementNetwork(nic.getNetworkId(), dest, context, vmProfile.getVirtualMachine().getType() == Type.DomainRouter); if (implemented == null || implemented.first() == null) { s_logger.warn("Failed to implement network id=" + nic.getNetworkId() + " as a part of preparing nic id=" + nic.getId()); throw new CloudRuntimeException("Failed to implement network id=" + nic.getNetworkId() + " as a part preparing nic id=" + nic.getId()); @@ -3082,9 +3100,10 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra //2) prepare nic if (prepare) { - Pair implemented = implementNetwork(nic.getNetworkId(), dest, context); - if (implemented == null) { - throw new CloudRuntimeException("Failed to prepare the nic as a part of creating nic " + nic + " for vm "+ vm + " due to network " + network + " implement failure"); + Pair implemented = implementNetwork(nic.getNetworkId(), dest, context, vmProfile.getVirtualMachine().getType() == Type.DomainRouter); + if (implemented == null || implemented.first() == null) { + s_logger.warn("Failed to implement network id=" + nic.getNetworkId() + " as a part of preparing nic id=" + nic.getId()); + throw new CloudRuntimeException("Failed to implement network id=" + nic.getNetworkId() + " as a part preparing nic id=" + nic.getId()); } nic = prepareNic(vmProfile, dest, context, nic.getId(), implemented.second()); s_logger.debug("Nic is prepared successfully for vm " + vm + " in network " + network);