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