You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by GitBox <gi...@apache.org> on 2018/02/10 17:24:06 UTC

[GitHub] rhtyd closed pull request #2445: CLOUDSTACK-10218: fix for forced network update in a nuage network

rhtyd closed pull request #2445: CLOUDSTACK-10218: fix for forced network update in a nuage network
URL: https://github.com/apache/cloudstack/pull/2445
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/api/commands/AssociateNuageVspDomainTemplateCmd.java b/plugins/network-elements/nuage-vsp/src/com/cloud/api/commands/AssociateNuageVspDomainTemplateCmd.java
index 760916a5b10..9b36aaff735 100644
--- a/plugins/network-elements/nuage-vsp/src/com/cloud/api/commands/AssociateNuageVspDomainTemplateCmd.java
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/api/commands/AssociateNuageVspDomainTemplateCmd.java
@@ -89,10 +89,10 @@ public Long getVpcId() {
     @Override
     public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException {
         try {
-            boolean result =_nuageVspManager.associateNuageVspDomainTemplate(this);
+            _nuageVspManager.associateNuageVspDomainTemplate(this);
             SuccessResponse response = new SuccessResponse(getCommandName());
             response.setResponseName(getCommandName());
-            response.setSuccess(result);
+            response.setSuccess(true);
             this.setResponseObject(response);
         } catch (InvalidParameterValueException invalidParamExcp) {
             throw new ServerApiException(ApiErrorCode.PARAM_ERROR, invalidParamExcp.getMessage());
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/element/NuageVspElement.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/element/NuageVspElement.java
index abe7a71098b..d5496b0157a 100644
--- a/plugins/network-elements/nuage-vsp/src/com/cloud/network/element/NuageVspElement.java
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/element/NuageVspElement.java
@@ -90,7 +90,6 @@
 import com.cloud.network.dao.IPAddressVO;
 import com.cloud.network.dao.NetworkDao;
 import com.cloud.network.dao.NetworkServiceMapDao;
-import com.cloud.network.dao.NetworkVO;
 import com.cloud.network.dao.PhysicalNetworkDao;
 import com.cloud.network.dao.PhysicalNetworkVO;
 import com.cloud.network.manager.NuageVspManager;
@@ -276,14 +275,8 @@ public boolean implement(Network network, NetworkOffering offering, DeployDestin
             return false;
         }
 
-        if (!_nuageVspEntityBuilder.usesVirtualRouter(offering.getId())) {
-            // Update broadcast uri if VR is no longer used
-            NetworkVO networkToUpdate = _networkDao.findById(network.getId());
-            String broadcastUriStr = networkToUpdate.getUuid() + "/null";
-            networkToUpdate.setBroadcastUri(Networks.BroadcastDomainType.Vsp.toUri(broadcastUriStr));
-            _networkDao.update(network.getId(), networkToUpdate);
-        }
-
+        _nuageVspManager.updateBroadcastUri(network);
+        network = _networkDao.findById(network.getId());
         VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(network);
         List<VspAclRule> ingressFirewallRules = getFirewallRulesToApply(network, FirewallRule.TrafficType.Ingress);
         List<VspAclRule> egressFirewallRules = getFirewallRulesToApply(network, FirewallRule.TrafficType.Egress);
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/guru/NuageVspGuestNetworkGuru.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/guru/NuageVspGuestNetworkGuru.java
index 23a0efce739..b17840c194d 100644
--- a/plugins/network-elements/nuage-vsp/src/com/cloud/network/guru/NuageVspGuestNetworkGuru.java
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/guru/NuageVspGuestNetworkGuru.java
@@ -255,7 +255,7 @@ public Network implement(Network network, NetworkOffering offering, DeployDestin
             VpcDetailVO detail = _vpcDetailsDao.findDetail(network.getVpcId(), NuageVspManager.nuageDomainTemplateDetailName);
             if (detail != null && network.getNetworkACLId() != null) {
                 s_logger.error("Pre-configured DT are used in combination with ACL lists. Which is not supported.");
-                throw new IllegalArgumentException("CloudStack ACLs are not supported with Nuage Preconfigured Domain Template");
+                throw new IllegalArgumentException("CloudStack ACLs are not supported with Nuage Pre-configured Domain Template");
             }
 
             if(detail != null && !_nuageVspManager.checkIfDomainTemplateExist(network.getDomainId(),detail.getValue(),network.getDataCenterId(),null)){
@@ -302,7 +302,9 @@ public Network implement(Network network, NetworkOffering offering, DeployDestin
                 implemented.setCidr(network.getCidr());
             }
 
-            VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(implemented, true);
+            implemented.setBroadcastUri(_nuageVspManager.calculateBroadcastUri(implemented));
+            implemented.setBroadcastDomainType(Networks.BroadcastDomainType.Vsp);
+            VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(implemented);
 
             if (vspNetwork.isShared()) {
                 Boolean previousUnderlay= null;
@@ -321,11 +323,6 @@ public Network implement(Network network, NetworkOffering offering, DeployDestin
                 }
             }
 
-            String tenantId = context.getDomain().getName() + "-" + context.getAccount().getAccountId();
-            String broadcastUriStr = implemented.getUuid() + "/" + vspNetwork.getVirtualRouterIp();
-            implemented.setBroadcastUri(Networks.BroadcastDomainType.Vsp.toUri(broadcastUriStr));
-            implemented.setBroadcastDomainType(Networks.BroadcastDomainType.Vsp);
-
             boolean implementSucceeded = implement(network.getVpcId(), physicalNetworkId, vspNetwork, implemented, _nuageVspEntityBuilder.buildNetworkDhcpOption(network, offering));
 
             if (!implementSucceeded) {
@@ -340,6 +337,7 @@ public Network implement(Network network, NetworkOffering offering, DeployDestin
                 }
             }
 
+            String tenantId = context.getDomain().getName() + "-" + context.getAccount().getAccountId();
             s_logger.info("Implemented OK, network " + implemented.getUuid() + " in tenant " + tenantId + " linked to " + implemented.getBroadcastUri());
         } finally {
             _networkDao.releaseFromLockTable(network.getId());
@@ -430,7 +428,7 @@ private void saveNetworkDetail(long networkId, String key, String value) {
     public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException {
         if (vm.getType() != VirtualMachine.Type.DomainRouter && _nuageVspEntityBuilder.usesVirtualRouter(network.getNetworkOfferingId())) {
             VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(network);
-            if (nic != null && nic.getRequestedIPv4() != null && vspNetwork.getVirtualRouterIp().equals(nic.getRequestedIPv4())) {
+            if (nic != null && nic.getRequestedIPv4() != null && nic.getRequestedIPv4().equals(vspNetwork.getVirtualRouterIp())) {
                 DataCenter dc = _dcDao.findById(network.getDataCenterId());
                 s_logger.error("Unable to acquire requested Guest IP address " + nic.getRequestedIPv4() + " because it is reserved for the VR in network " + network);
                 throw new InsufficientVirtualNetworkCapacityException("Unable to acquire requested Guest IP address " + nic.getRequestedIPv4() + " because it is reserved " +
@@ -470,14 +468,13 @@ public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, D
             HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(network.getPhysicalNetworkId());
             VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(vm.getVirtualMachine().getDomainId(), network);
 
-            if (vm.getType() == VirtualMachine.Type.DomainRouter && vspNetwork.getVirtualRouterIp().equals("null")) {
-                //In case of upgrade network offering
-                vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(vm.getVirtualMachine().getDomainId(), network, null, true);
-                String broadcastUriStr = network.getUuid() + "/" + vspNetwork.getVirtualRouterIp();
-                NetworkVO updatedNetwork = _networkDao.createForUpdate(network.getId());
-                updatedNetwork.setBroadcastUri(Networks.BroadcastDomainType.Vsp.toUri(broadcastUriStr));
-                _networkDao.update(updatedNetwork.getId(), updatedNetwork);
+            boolean vrAddedToNuage = vm.getType() == VirtualMachine.Type.DomainRouter && vspNetwork.getVirtualRouterIp()
+                                                                                          .equals("null");
+            if (vrAddedToNuage) {
+                //In case a VR is added due to upgrade network offering - recalculate the broadcast uri before using it.
+                _nuageVspManager.updateBroadcastUri(network);
                 network = _networkDao.findById(network.getId());
+                vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(vm.getVirtualMachine().getDomainId(), network, null);
             }
 
             if (vspNetwork.isShared()) {
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManager.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManager.java
index 6f91dc34276..803063060f7 100644
--- a/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManager.java
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManager.java
@@ -19,6 +19,7 @@
 
 package com.cloud.network.manager;
 
+import java.net.URI;
 import java.util.List;
 
 import org.apache.cloudstack.framework.config.ConfigKey;
@@ -35,6 +36,7 @@
 import com.cloud.api.response.NuageVspDeviceResponse;
 import com.cloud.dc.Vlan;
 import com.cloud.api.response.NuageVspDomainTemplateResponse;
+import com.cloud.exception.InsufficientVirtualNetworkCapacityException;
 import com.cloud.host.HostVO;
 import com.cloud.network.Network;
 import com.cloud.network.NuageVspDeviceVO;
@@ -119,10 +121,9 @@
 
     /**
      * Associates a Nuage Vsp domain template with a
-     * @param cmd
-     * @return
+     * @param cmd Associate cmd which contains all the data
      */
-    boolean associateNuageVspDomainTemplate(AssociateNuageVspDomainTemplateCmd cmd);
+    void associateNuageVspDomainTemplate(AssociateNuageVspDomainTemplateCmd cmd);
 
     /**
      * Queries the VSD to check if the entity provided in the entityCmd exists on the VSD
@@ -134,26 +135,41 @@
 
     /**
      * Sets the preconfigured domain template for a given network
-     * @param network
-     * @param domainTemplateName
+     * @param network the network for which we want to set the domain template
+     * @param domainTemplateName the domain template name we want to use
      */
     void setPreConfiguredDomainTemplateName(Network network, String domainTemplateName);
 
     /**
      * Returns the current pre configured domain template for a given network
-     * @param network
-     * @return
+     * @param network the network for which we want the domain template name
+     * @return the domain template name
      */
     String getPreConfiguredDomainTemplateName(Network network);
 
     /**
      * Checks if a given domain template exists or not on the VSD.
-     * @param domainId
+     * @param domainId Id of the domain to search in.
      * @param domainTemplate The name of the domain template for which we need to query the VSD.
      * @param zoneId zoneId OR PhysicalNetworkId needs to be provided.
      * @param physicalNetworkId zoneId OR PhysicalNetworkId needs to be provided.
      * @return true if the domain template exists on the VSD else false if it does not exist on the VSD
      */
-    public boolean checkIfDomainTemplateExist(Long domainId, String domainTemplate, Long zoneId, Long physicalNetworkId);
+    boolean checkIfDomainTemplateExist(Long domainId, String domainTemplate, Long zoneId, Long physicalNetworkId);
+
+    /**
+     * calculates the new broadcast uri of a network and persists it in the database
+     * @param network the network for which you want to calculate the broadcast uri
+     * @throws InsufficientVirtualNetworkCapacityException in case there is no free ip that can be used as the VR ip.
+     */
+    void updateBroadcastUri(Network network) throws InsufficientVirtualNetworkCapacityException;
+
+    /**
+     * Calculates the broadcast uri based on the network and the offering of the given network
+     * @param network the network for which you want to calculate the broadcast uri
+     * @return the calculated broadcast uri
+     * @throws InsufficientVirtualNetworkCapacityException in case there is no free ip that can be used as the VR ip.
+     */
+    URI calculateBroadcastUri(Network network) throws InsufficientVirtualNetworkCapacityException;
 
 }
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManagerImpl.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManagerImpl.java
index 748de100c0c..0a3a966cb78 100644
--- a/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManagerImpl.java
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManagerImpl.java
@@ -35,6 +35,7 @@
 import net.nuage.vsp.acs.client.api.model.VspHost;
 import net.nuage.vsp.acs.client.common.NuageVspApiVersion;
 import net.nuage.vsp.acs.client.common.NuageVspConstants;
+import net.nuage.vsp.acs.client.common.model.Pair;
 import net.nuage.vsp.acs.client.exception.NuageVspException;
 import org.apache.cloudstack.api.ResponseGenerator;
 import org.apache.cloudstack.context.CallContext;
@@ -53,15 +54,19 @@
 import javax.annotation.Nonnull;
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
+import java.net.URI;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
+import java.util.TreeSet;
 import java.util.UUID;
 import java.util.stream.Collectors;
 
@@ -105,6 +110,7 @@
 import com.cloud.domain.Domain;
 import com.cloud.domain.DomainVO;
 import com.cloud.domain.dao.DomainDao;
+import com.cloud.exception.InsufficientVirtualNetworkCapacityException;
 import com.cloud.exception.InvalidParameterValueException;
 import com.cloud.host.DetailVO;
 import com.cloud.host.Host;
@@ -113,6 +119,7 @@
 import com.cloud.host.dao.HostDao;
 import com.cloud.host.dao.HostDetailsDao;
 import com.cloud.network.Network;
+import com.cloud.network.NetworkModel;
 import com.cloud.network.Networks;
 import com.cloud.network.NuageVspDeviceVO;
 import com.cloud.network.PhysicalNetwork;
@@ -154,6 +161,11 @@
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.utils.fsm.StateListener;
 import com.cloud.utils.fsm.StateMachine2;
+import com.cloud.utils.net.NetUtils;
+import com.cloud.vm.VMInstanceVO;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.dao.NicDao;
+import com.cloud.vm.dao.VMInstanceDao;
 
 import static com.cloud.agent.api.sync.SyncNuageVspCmsIdCommand.SyncType;
 
@@ -213,6 +225,12 @@
     ResponseGenerator _responseGenerator;
     @Inject
     MessageBus _messageBus;
+    @Inject
+    VMInstanceDao _vmInstanceDao;
+    @Inject
+    NicDao _nicDao;
+    @Inject
+    NetworkModel _networkModel;
 
     static {
         Set<Network.Provider> nuageVspProviders = ImmutableSet.of(Network.Provider.NuageVsp);
@@ -902,7 +920,7 @@ private Long getPhysicalNetworkBasedOnZone(Long zoneId){
     }
 
     @Override
-    public boolean associateNuageVspDomainTemplate(AssociateNuageVspDomainTemplateCmd cmd){
+    public void associateNuageVspDomainTemplate(AssociateNuageVspDomainTemplateCmd cmd){
         VpcVO vpc = _vpcDao.findById(cmd.getVpcId());
         Long physicalNetworkId;
         if (cmd.getPhysicalNetworkId() != null) {
@@ -923,7 +941,6 @@ public boolean associateNuageVspDomainTemplate(AssociateNuageVspDomainTemplateCm
             throw new InvalidParameterValueException("Could not find a Domain Template with name: " + cmd.getDomainTemplate());
         }
         setPreConfiguredDomainTemplateName(cmd.getVpcId(), cmd.getDomainTemplate());
-        return true;
     }
 
     @Override
@@ -939,6 +956,131 @@ public boolean checkIfDomainTemplateExist(Long domainId, String domainTemplate,
         return false;
     }
 
+    @Override
+    public void updateBroadcastUri(Network network) throws InsufficientVirtualNetworkCapacityException {
+        NetworkVO updatedNetwork = _networkDao.createForUpdate(network.getId());
+        URI broadcastUri = calculateBroadcastUri(network);
+        if (!broadcastUri.equals(network.getBroadcastUri())) {
+            updatedNetwork.setBroadcastUri(broadcastUri);
+            _networkDao.update(network.getId(), updatedNetwork);
+        }
+    }
+
+    @Override
+    public URI calculateBroadcastUri(Network network) throws InsufficientVirtualNetworkCapacityException {
+        String vrIp = calculateVirtualRouterIp(network);
+        return Networks.BroadcastDomainType.Vsp.toUri(network.getUuid() + "/" + vrIp);
+    }
+
+    private boolean usesVirtualRouter(long networkOfferingId) {
+        return _networkOfferingServiceMapDao.isProviderForNetworkOffering(networkOfferingId, Network.Provider.VirtualRouter) ||
+                _networkOfferingServiceMapDao.isProviderForNetworkOffering(networkOfferingId, Network.Provider.VPCVirtualRouter);
+    }
+
+    private String calculateVirtualRouterIp(Network network)
+            throws InsufficientVirtualNetworkCapacityException {
+        if (!usesVirtualRouter(network.getNetworkOfferingId())) {
+            return null;
+        }
+
+        List<Pair<String, String>> ipAddressRanges =
+                network.getGuestType() == Network.GuestType.Shared ? getSharedIpAddressRanges(network.getId()) : getIpAddressRanges(network);
+
+        //check if a vr might be present already or not? CLOUD-1216 - before we always picked .2
+        List<VMInstanceVO> vrs =_vmInstanceDao.listNonRemovedVmsByTypeAndNetwork(network.getId(), VirtualMachine.Type.DomainRouter);
+
+        for (VMInstanceVO vr : vrs) {
+            return _nicDao.listByVmIdAndNicIdAndNtwkId(vr.getId(), null, network.getId()).get(0).getIPv4Address();
+        }
+
+        ensureIpCapacity(network, ipAddressRanges);
+
+        if(network.getGuestType() == Network.GuestType.Shared) {
+            return ipAddressRanges.stream()
+                                  .sorted(Comparator.comparingLong(p -> NetUtils.ip2Long(p.getLeft())))
+                                  .findFirst()
+                                  .map(Pair::getLeft)
+                                  .orElseThrow(() -> new IllegalArgumentException("Shared network without ip ranges? How can this happen?"));
+        }
+
+        Network networkToCheck;
+        if (isMigratingNetwork(network)) {
+            networkToCheck = _networkDao.findById(network.getRelated());
+        } else {
+            networkToCheck = network;
+        }
+
+        Long freeIp = _networkModel.getAvailableIps(networkToCheck, null)
+                                   .stream()
+                                   .findFirst()
+                                   .orElseThrow(() -> new InsufficientVirtualNetworkCapacityException("There is no free ip available for the VirtualRouter.",
+                                                                                                      Network.class,
+                                                                                                      network.getId()));
+
+        return NetUtils.long2Ip(freeIp);
+    }
+
+    private List<Pair<String, String>> getSharedIpAddressRanges(long networkId) {
+        List<VlanVO> vlans = _vlanDao.listVlansByNetworkId(networkId);
+        List<Pair<String, String>> ipAddressRanges = Lists.newArrayList();
+        for (VlanVO vlan : vlans) {
+            Pair<String, String> ipAddressRange = NuageVspUtil.getIpAddressRange(vlan);
+            if (ipAddressRange != null) {
+                ipAddressRanges.add(ipAddressRange);
+            }
+        }
+        return ipAddressRanges;
+    }
+
+    private List<Pair<String, String>> getIpAddressRanges(Network network) {
+        List<Pair<String, String>> ipAddressRanges = Lists.newArrayList();
+        String subnet = NetUtils.getCidrSubNet(network.getCidr());
+        String netmask = NetUtils.getCidrNetmask(network.getCidr());
+        long cidrSize = NetUtils.getCidrSize(netmask);
+        Set<Long> allIPsInCidr = NetUtils.getAllIpsFromCidr(subnet, cidrSize, new HashSet<Long>());
+        if (allIPsInCidr == null || !(allIPsInCidr instanceof TreeSet)) {
+            throw new IllegalStateException("The IPs in CIDR for subnet " + subnet + " where null or returned in a non-ordered set.");
+        }
+
+        Iterator<Long> ipIterator = allIPsInCidr.iterator();
+        long ip =  ipIterator.next();
+        long gatewayIp = NetUtils.ip2Long(network.getGateway());
+        String lastIp = NetUtils.getIpRangeEndIpFromCidr(subnet, cidrSize);
+        if (gatewayIp == ip) {
+            ip = ipIterator.next();
+            ipAddressRanges.add(Pair.of(NetUtils.long2Ip(ip), lastIp));
+        } else if (!network.getGateway().equals(lastIp)) {
+            ipAddressRanges.add(Pair.of(NetUtils.long2Ip(ip), NetUtils.long2Ip(gatewayIp - 1)));
+            ipAddressRanges.add(Pair.of(NetUtils.long2Ip(gatewayIp + 1), lastIp));
+        } else {
+            ipAddressRanges.add(Pair.of(NetUtils.long2Ip(ip), NetUtils.long2Ip(gatewayIp - 1)));
+        }
+
+        return ipAddressRanges;
+    }
+
+    private void ensureIpCapacity(Network network, List<Pair<String, String>> ipAddressRanges) throws InsufficientVirtualNetworkCapacityException {
+        long ipCount = ipAddressRanges.stream()
+                                      .mapToLong(this::getIpCount)
+                                      .sum();
+
+        if (ipCount == 0) {
+            throw new InsufficientVirtualNetworkCapacityException("VSP allocates an IP for VirtualRouter." + " But no ip address ranges are specified", Network.class,
+                                                                  network.getId());
+        } else if (ipCount < 3) {
+            throw new InsufficientVirtualNetworkCapacityException("VSP allocates an IP for VirtualRouter." + " So, subnet should have atleast minimum 3 hosts", Network.class,
+                                                                  network.getId());
+        }
+    }
+
+    private boolean isMigratingNetwork(Network network) {
+        return network.getRelated() != network.getId();
+    }
+
+    private long getIpCount(Pair<String, String> ipAddressRange) {
+        return NetUtils.ip2Long(ipAddressRange.getRight()) - NetUtils.ip2Long(ipAddressRange.getLeft()) + 1;
+    }
+
     @Override
     public boolean entityExist(EntityExistsCommand cmd, Long physicalNetworkId){
         Long hostId = getNuageVspHostId(physicalNetworkId);
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/util/NuageVspEntityBuilder.java b/plugins/network-elements/nuage-vsp/src/com/cloud/util/NuageVspEntityBuilder.java
index cd986e5cbcb..5b1419f015b 100644
--- a/plugins/network-elements/nuage-vsp/src/com/cloud/util/NuageVspEntityBuilder.java
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/util/NuageVspEntityBuilder.java
@@ -19,13 +19,8 @@
 
 package com.cloud.util;
 
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
 import java.util.stream.Collectors;
 
 import javax.inject.Inject;
@@ -44,10 +39,8 @@
 import net.nuage.vsp.acs.client.common.model.Pair;
 
 import org.apache.commons.collections.MapUtils;
-import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Logger;
 
-import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 
@@ -60,7 +53,6 @@
 import com.cloud.domain.Domain;
 import com.cloud.domain.DomainVO;
 import com.cloud.domain.dao.DomainDao;
-import com.cloud.exception.InsufficientVirtualNetworkCapacityException;
 import com.cloud.network.Network;
 import com.cloud.network.NetworkModel;
 import com.cloud.network.dao.IPAddressDao;
@@ -79,7 +71,6 @@
 import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
 import com.cloud.user.AccountVO;
 import com.cloud.user.dao.AccountDao;
-import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.utils.net.NetUtils;
 import com.cloud.vm.NicProfile;
 import com.cloud.vm.NicVO;
@@ -157,30 +148,18 @@ public VspDomainCleanUp buildVspDomainCleanUp(Domain domain) {
     }
 
     public VspNetwork buildVspNetwork(Network network) {
-        return buildVspNetwork(network.getDomainId(), network, null, false);
-    }
-
-    public VspNetwork buildVspNetwork(Network network, boolean recalculateBroadcastUri) {
-        return buildVspNetwork(network.getDomainId(), network, null, recalculateBroadcastUri);
+        return buildVspNetwork(network.getDomainId(), network, null);
     }
 
     public VspNetwork buildVspNetwork(Network network, String vsdSubnetId) {
-        return buildVspNetwork(network.getDomainId(), network, vsdSubnetId, false);
+        return buildVspNetwork(network.getDomainId(), network, vsdSubnetId);
     }
 
     public VspNetwork buildVspNetwork(long domainId, Network network) {
-        return buildVspNetwork(domainId, network, null, false);
-    }
-
-    public VspNetwork buildVspNetwork(long domainId, Network network, boolean recalculateBroadcastUri) {
-        return buildVspNetwork(domainId, network, null, recalculateBroadcastUri);
+        return buildVspNetwork(domainId, network, null);
     }
 
     public VspNetwork buildVspNetwork(long domainId, Network network, String vsdSubnetId) {
-        return buildVspNetwork(domainId, network, vsdSubnetId, false);
-    }
-
-    public VspNetwork buildVspNetwork(long domainId, Network network, String vsdSubnetId, boolean recalculateBroadcastUri) {
         VspNetwork.Builder vspNetworkBuilder = new VspNetwork.Builder()
                 .id(network.getId())
                 .uuid(network.getUuid())
@@ -254,15 +233,8 @@ public VspNetwork buildVspNetwork(long domainId, Network network, String vsdSubn
         vspNetworkBuilder.domainTemplateName(preConfiguredDomainTemplateName);
 
         if (usesVirtualRouter(networkOffering.getId())) {
-            try {
-                List<Pair<String, String>> ipAddressRanges =
-                        networkOffering.getGuestType() == Network.GuestType.Shared ? getSharedIpAddressRanges(network.getId()) : getIpAddressRanges(network);
-                String virtualRouterIp = getVirtualRouterIP(network, ipAddressRanges, recalculateBroadcastUri);
+                String virtualRouterIp = getVirtualRouterIP(network);
                 vspNetworkBuilder.virtualRouterIp(virtualRouterIp);
-            } catch (InsufficientVirtualNetworkCapacityException ex) {
-                s_logger.error("There is an insufficient network capacity in network " + network.getId(), ex);
-                throw new CloudRuntimeException("There is an insufficient network capacity in network " + network.getId(), ex);
-            }
         }
 
         return vspNetworkBuilder.build();
@@ -298,128 +270,16 @@ public VspNetwork updateVspNetworkByPublicIp(VspNetwork vspNetwork, Network netw
     }
 
     private boolean isVlanContainingIp(Vlan vlan, long ip) {
-        Pair<String, String> ipAddressRange = getIpAddressRange(vlan);
+        Pair<String, String> ipAddressRange =  NuageVspUtil.getIpAddressRange(vlan);
         long startIp = NetUtils.ip2Long(ipAddressRange.getLeft());
         long endIp = NetUtils.ip2Long(ipAddressRange.getRight());
         return startIp <= ip && ip <= endIp;
     }
 
-    private List<Pair<String, String>> getSharedIpAddressRanges(long networkId) {
-        List<VlanVO> vlans = _vlanDao.listVlansByNetworkId(networkId);
-        List<Pair<String, String>> ipAddressRanges = Lists.newArrayList();
-        for (VlanVO vlan : vlans) {
-            Pair<String, String> ipAddressRange = getIpAddressRange(vlan);
-            if (ipAddressRange != null) {
-                ipAddressRanges.add(ipAddressRange);
-            }
-        }
-        return ipAddressRanges;
+    private String getVirtualRouterIP(Network network) {
+        return network.getBroadcastUri() != null ? network.getBroadcastUri().getPath().substring(1) : null;
     }
 
-    private List<Pair<String, String>> getIpAddressRanges(Network network) {
-        List<Pair<String, String>> ipAddressRanges = Lists.newArrayList();
-        String subnet = NetUtils.getCidrSubNet(network.getCidr());
-        String netmask = NetUtils.getCidrNetmask(network.getCidr());
-        long cidrSize = NetUtils.getCidrSize(netmask);
-        Set<Long> allIPsInCidr = NetUtils.getAllIpsFromCidr(subnet, cidrSize, new HashSet<Long>());
-        if (allIPsInCidr == null || !(allIPsInCidr instanceof TreeSet)) {
-            throw new IllegalStateException("The IPs in CIDR for subnet " + subnet + " where null or returned in a non-ordered set.");
-        }
-
-        Iterator<Long> ipIterator = allIPsInCidr.iterator();
-        long ip =  ipIterator.next();
-        long gatewayIp = NetUtils.ip2Long(network.getGateway());
-        String lastIp = NetUtils.getIpRangeEndIpFromCidr(subnet, cidrSize);
-        if (gatewayIp == ip) {
-            ip = ipIterator.next();
-            ipAddressRanges.add(Pair.of(NetUtils.long2Ip(ip), lastIp));
-        } else if (!network.getGateway().equals(lastIp)) {
-            ipAddressRanges.add(Pair.of(NetUtils.long2Ip(ip), NetUtils.long2Ip(gatewayIp - 1)));
-            ipAddressRanges.add(Pair.of(NetUtils.long2Ip(gatewayIp + 1), lastIp));
-        } else {
-            ipAddressRanges.add(Pair.of(NetUtils.long2Ip(ip), NetUtils.long2Ip(gatewayIp - 1)));
-        }
-
-        return ipAddressRanges;
-    }
-
-    public Pair<String, String> getIpAddressRange(Vlan vlan) {
-        boolean isIpv4 = StringUtils.isNotBlank(vlan.getIpRange());
-        String[] range = isIpv4 ? vlan.getIpRange().split("-") : vlan.getIp6Range().split("-");
-        if (range.length == 2) {
-            return Pair.of(range[0], range[1]);
-        }
-        return null;
-    }
-
-    private String getVirtualRouterIP(Network network, List<Pair<String, String>> ipAddressRanges, boolean recalculateBroadcastUri) throws InsufficientVirtualNetworkCapacityException {
-        //Add a check to see if a VR should be present in the offering or not?
-        if (!recalculateBroadcastUri && network.getBroadcastUri() != null) {
-            return network.getBroadcastUri().getPath().substring(1);
-        }
-        ensureIpCapacity(network, ipAddressRanges);
-
-        if(network.getGuestType() == Network.GuestType.Shared) {
-            return ipAddressRanges.stream()
-                                  .sorted(Comparator.comparingLong(p -> NetUtils.ip2Long(p.getLeft())))
-                                  .findFirst()
-                                  .map(Pair::getLeft)
-                                  .orElseThrow(() -> new IllegalArgumentException("Shared network without ip ranges? How can this happen?"));
-        }
-
-        Pair<String, String> lowestIpAddressRange = null;
-        long ipCount = 0;
-        if (ipAddressRanges.size() == 1) {
-            lowestIpAddressRange = Iterables.getOnlyElement(ipAddressRanges);
-            ipCount = NetUtils.ip2Long(lowestIpAddressRange.getRight()) - NetUtils.ip2Long(lowestIpAddressRange.getLeft()) + 1;
-        } else {
-            for (Pair<String, String> ipAddressRange : ipAddressRanges) {
-                if (lowestIpAddressRange == null || NetUtils.ip2Long(ipAddressRange.getLeft()) < NetUtils.ip2Long(lowestIpAddressRange.getLeft())) {
-                    lowestIpAddressRange = ipAddressRange;
-                }
-                ipCount += NetUtils.ip2Long(ipAddressRange.getRight()) - NetUtils.ip2Long(ipAddressRange.getLeft()) + 1;
-            }
-        }
-
-
-        Network networkToCheck;
-        if (isMigratingNetwork(network)) {
-            networkToCheck = _networkDao.findById(network.getRelated());
-        } else {
-            networkToCheck = network;
-        }
-
-        Long freeIp = _networkModel.getAvailableIps(networkToCheck, null)
-                                   .stream()
-                                   .findFirst()
-                                   .orElseThrow(() -> new InsufficientVirtualNetworkCapacityException("There is no free ip available for the VirtualRouter.",
-                                                                                                      Network.class,
-                                                                                                      network.getId()));
-
-        return NetUtils.long2Ip(freeIp);
-    }
-
-    private boolean isMigratingNetwork(Network network) {
-        return network.getRelated() != network.getId();
-    }
-
-    private void ensureIpCapacity(Network network, List<Pair<String, String>> ipAddressRanges) throws InsufficientVirtualNetworkCapacityException {
-        long ipCount = ipAddressRanges.stream()
-                                      .mapToLong(this::getIpCount)
-                                      .sum();
-
-        if (ipCount == 0) {
-            throw new InsufficientVirtualNetworkCapacityException("VSP allocates an IP for VirtualRouter." + " But no ip address ranges are specified", Network.class,
-                    network.getId());
-        } else if (ipCount < 3) {
-            throw new InsufficientVirtualNetworkCapacityException("VSP allocates an IP for VirtualRouter." + " So, subnet should have atleast minimum 3 hosts", Network.class,
-                    network.getId());
-        }
-    }
-
-    private long getIpCount(Pair<String, String> ipAddressRange) {
-        return NetUtils.ip2Long(ipAddressRange.getRight()) - NetUtils.ip2Long(ipAddressRange.getLeft()) + 1;
-    }
 
     public VspVm buildVspVm(VirtualMachine vm, Network network) {
         VspVm.Builder vspVmBuilder = new VspVm.Builder()
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/util/NuageVspUtil.java b/plugins/network-elements/nuage-vsp/src/com/cloud/util/NuageVspUtil.java
index 16d28b64aec..e5266d0ff15 100644
--- a/plugins/network-elements/nuage-vsp/src/com/cloud/util/NuageVspUtil.java
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/util/NuageVspUtil.java
@@ -24,6 +24,8 @@
 import com.cloud.dc.dao.VlanDetailsDao;
 import com.cloud.network.manager.NuageVspManager;
 import com.cloud.utils.StringUtils;
+
+import net.nuage.vsp.acs.client.common.model.Pair;
 import org.apache.commons.codec.binary.Base64;
 
 public class NuageVspUtil {
@@ -44,4 +46,13 @@ public static boolean isUnderlayEnabledForVlan(VlanDetailsDao vlanDetailsDao, Vl
         VlanDetailsVO nuageUnderlayDetail = vlanDetailsDao.findDetail(vlan.getId(), NuageVspManager.nuageUnderlayVlanIpRangeDetailKey);
         return nuageUnderlayDetail != null && nuageUnderlayDetail.getValue().equalsIgnoreCase(String.valueOf(true));
     }
+
+    public static Pair<String, String> getIpAddressRange(Vlan vlan) {
+        boolean isIpv4 = StringUtils.isNotBlank(vlan.getIpRange());
+        String[] range = isIpv4 ? vlan.getIpRange().split("-") : vlan.getIp6Range().split("-");
+        if (range.length == 2) {
+            return Pair.of(range[0], range[1]);
+        }
+        return null;
+    }
 }
diff --git a/plugins/network-elements/nuage-vsp/test/com/cloud/NuageTest.java b/plugins/network-elements/nuage-vsp/test/com/cloud/NuageTest.java
index ae383bfea0b..02497994570 100644
--- a/plugins/network-elements/nuage-vsp/test/com/cloud/NuageTest.java
+++ b/plugins/network-elements/nuage-vsp/test/com/cloud/NuageTest.java
@@ -92,9 +92,7 @@ public void setUp() throws Exception {
 
         VspNetwork vspNetwork = buildVspNetwork();
         when(_nuageVspEntityBuilder.buildVspNetwork(any(Network.class))).thenReturn(vspNetwork);
-        when(_nuageVspEntityBuilder.buildVspNetwork(any(Network.class), anyBoolean())).thenReturn(vspNetwork);
         when(_nuageVspEntityBuilder.buildVspNetwork(anyLong(), any(Network.class))).thenReturn(vspNetwork);
-        when(_nuageVspEntityBuilder.buildVspNetwork(anyLong(), any(Network.class), anyBoolean())).thenReturn(vspNetwork);
 
         when(_nuageVspEntityBuilder.buildVspVm(any(VirtualMachine.class), any(Network.class))).thenReturn(buildVspVm());
 
diff --git a/plugins/network-elements/nuage-vsp/test/com/cloud/network/element/NuageVspElementTest.java b/plugins/network-elements/nuage-vsp/test/com/cloud/network/element/NuageVspElementTest.java
index 46046fd9643..e48d9a46ced 100644
--- a/plugins/network-elements/nuage-vsp/test/com/cloud/network/element/NuageVspElementTest.java
+++ b/plugins/network-elements/nuage-vsp/test/com/cloud/network/element/NuageVspElementTest.java
@@ -26,6 +26,8 @@
 import java.util.Collections;
 import java.util.Set;
 
+import com.cloud.network.dao.NetworkDao;
+import com.cloud.network.dao.NetworkVO;
 import com.cloud.tags.dao.ResourceTagDao;
 import org.junit.Before;
 import org.junit.Test;
@@ -60,9 +62,7 @@
 import com.cloud.network.dao.FirewallRulesDao;
 import com.cloud.network.dao.IPAddressDao;
 import com.cloud.network.dao.IPAddressVO;
-import com.cloud.network.dao.NetworkDao;
 import com.cloud.network.dao.NetworkServiceMapDao;
-import com.cloud.network.dao.NetworkVO;
 import com.cloud.network.dao.NuageVspDao;
 import com.cloud.network.dao.PhysicalNetworkDao;
 import com.cloud.network.dao.PhysicalNetworkVO;
@@ -89,6 +89,7 @@
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.withSettings;
 
 public class NuageVspElementTest extends NuageTest {
 
@@ -119,6 +120,7 @@ public void setUp() throws Exception {
         _nuageVspElement._nuageVspEntityBuilder = _nuageVspEntityBuilder;
         _nuageVspElement._vpcDetailsDao = _vpcDetailsDao;
         _nuageVspElement._routerDao = _domainRouterDao;
+        _nuageVspElement._networkDao = _networkDao;
 
         when(_networkServiceMapDao.canProviderSupportServiceInNetwork(NETWORK_ID, Service.Connectivity, Provider.NuageVsp)).thenReturn(true);
         when(_networkServiceMapDao.canProviderSupportServiceInNetwork(NETWORK_ID, Service.SourceNat, Provider.NuageVsp)).thenReturn(true);
@@ -166,7 +168,7 @@ public void testCanHandle() {
 
     @Test
     public void testImplement() throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException, URISyntaxException {
-        final Network network = mock(Network.class);
+        final Network network = mock(NetworkVO.class, withSettings().extraInterfaces(Network.class));
         when(network.getBroadcastDomainType()).thenReturn(BroadcastDomainType.Vsp);
         when(network.getId()).thenReturn(NETWORK_ID);
         when(network.getVpcId()).thenReturn(null);
@@ -209,6 +211,7 @@ public void testImplement() throws ConcurrentOperationException, ResourceUnavail
         when(_firewallRulesDao.listByNetworkPurposeTrafficType(NETWORK_ID, FirewallRule.Purpose.Firewall, FirewallRule.TrafficType.Egress)).thenReturn(new ArrayList<FirewallRuleVO>());
         when(_ipAddressDao.listStaticNatPublicIps(NETWORK_ID)).thenReturn(new ArrayList<IPAddressVO>());
         when(_nuageVspManager.getDnsDetails(network.getDataCenterId())).thenReturn(new ArrayList<String>());
+        when(_networkDao.findById(network.getId())).thenReturn((NetworkVO)network);
 
         assertTrue(_nuageVspElement.implement(network, offering, deployDest, context));
     }
diff --git a/test/integration/plugins/nuagevsp/test_nuage_internal_dns.py b/test/integration/plugins/nuagevsp/test_nuage_internal_dns.py
index b0026d7c77c..0c2a6b611ed 100644
--- a/test/integration/plugins/nuagevsp/test_nuage_internal_dns.py
+++ b/test/integration/plugins/nuagevsp/test_nuage_internal_dns.py
@@ -947,3 +947,63 @@ def test_08_VPC_Network_Restarts_With_InternalDns(self):
                 self.debug("excepted value found in vm: " + item)
             else:
                 self.fail("excepted value not found in vm: " + item)
+
+    @attr(tags=["advanced", "nuagevsp"], required_hardware="true")
+    def test_09_update_network_offering_isolated_network(self):
+        """Test Update network offering for isolated Networks
+           with Nuage VSP SDN plugin
+        """
+        #    Create an Isolated Network with Nuage VSP Isolated Network
+        #    offering specifying Services which don't need a VR.
+        #    Update the network offering of this network to one that
+        #    needs a VR, check that a VR is spawn
+        #    After that update network to previous offering
+        #    Check that VR is destroyed and removed.
+
+        self.debug("+++Create an Isolated network with a network "
+                   "offering which has only services without VR")
+        cmd = updateZone.updateZoneCmd()
+        cmd.id = self.zone.id
+        cmd.domain = "isolated.com"
+        self.apiclient.updateZone(cmd)
+        self.debug("Creating and enabling Nuage Vsp Isolated Network "
+                   "offering which has only service without VR...")
+        network_offering = self.create_NetworkOffering(
+                self.test_data["nuagevsp"]
+                ["isolated_network_offering_without_vr"])
+        self.validate_NetworkOffering(network_offering, state="Enabled")
+
+        network_1 = self.create_Network(network_offering)
+        self.validate_Network(network_1, state="Allocated")
+
+        self.debug("+++Deploy VM in the created Isolated network "
+                   "with only services without VR")
+        vm_1 = self.create_VM(network_1)
+
+        # VSD verification
+        self.verify_vsd_network(self.domain.id, network_1)
+        self.verify_vsd_vm(vm_1)
+
+        with self.assertRaises(Exception):
+            self.get_Router(network_1)
+        self.debug("+++Verified no VR is spawned for this network ")
+
+        self.debug("+++ Upgrade offering of created Isolated network with "
+                   "a dns offering which spins a VR")
+        self.upgrade_Network(self.test_data["nuagevsp"][
+                            "isolated_network_offering"],
+                            network_1)
+        vr = self.get_Router(network_1)
+        self.check_Router_state(vr, state="Running")
+        # VSD verification
+        self.verify_vsd_network(self.domain.id, network_1)
+        self.verify_vsd_router(vr)
+
+        self.debug("+++ Upgrade offering of created Isolated network with "
+                   "an offering which removes the VR...")
+        self.upgrade_Network(self.test_data["nuagevsp"][
+                    "isolated_network_offering_without_vr"],
+                    network_1)
+        with self.assertRaises(Exception):
+            self.get_Router(network_1)
+        self.debug("+++Verified no VR is spawned for this network ")


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services