You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by bh...@apache.org on 2016/12/07 18:36:49 UTC

[10/13] git commit: updated refs/heads/master to 0e057ad

CLOUDSTACK-9403: Support for shared networks in Nuage VSP plugin

BUG-ID: CLOUDSTACK-9403
Co-Authored-By: Prashanth Manthena <pr...@nuagenetworks.net>
Co-Authored-By: Rahul Singal <ra...@nuagenetworks.net>
Co-Authored-By: Sigert Goeminne <si...@nuagenetworks.net>
Co-Authored-By: Nick Livens <ni...@nuagenetworks.net>


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/4c91c9c5
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/4c91c9c5
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/4c91c9c5

Branch: refs/heads/master
Commit: 4c91c9c519d5269a4661b2c9fad4925d9222d311
Parents: 70c79ad
Author: Frank Maximus <fr...@nuagenetworks.net>
Authored: Tue Nov 29 14:28:10 2016 +0100
Committer: Prashanth Manthena <Pr...@alcatel-lucent.com>
Committed: Wed Dec 7 10:03:28 2016 +0100

----------------------------------------------------------------------
 api/src/com/cloud/network/Network.java          |    5 +-
 api/src/com/cloud/network/NetworkModel.java     |    2 +
 api/src/com/cloud/offering/NetworkOffering.java |    2 +
 .../org/apache/cloudstack/api/ApiConstants.java |    1 +
 .../api/response/NetworkOfferingResponse.java   |    8 +
 client/pom.xml                                  |   20 +-
 engine/schema/src/com/cloud/dc/dao/VlanDao.java |    2 +
 .../src/com/cloud/dc/dao/VlanDaoImpl.java       |   12 +-
 .../com/cloud/offerings/NetworkOfferingVO.java  |   11 +-
 plugins/network-elements/nuage-vsp/pom.xml      |    4 +-
 .../agent/api/manager/CleanUpDomainCommand.java |   72 +
 .../agent/api/manager/EntityExistsCommand.java  |   30 +-
 .../manager/UpdateNuageVspDeviceCommand.java    |   70 +
 .../agent/api/sync/SyncNuageVspCmsIdAnswer.java |    8 +
 .../cloud/network/element/NuageVspElement.java  |  181 +-
 .../network/guru/NuageVspGuestNetworkGuru.java  |  165 +-
 .../cloud/network/manager/NuageVspManager.java  |    3 +-
 .../network/manager/NuageVspManagerImpl.java    |  403 ++-
 .../resource/NuageVspRequestWrapper.java        |   78 +
 .../network/resource/NuageVspResource.java      |  626 +----
 .../resource/NuageVspResourceConfiguration.java |  359 +++
 .../NuageVspApiSupportCommandWrapper.java       |   41 +
 .../NuageVspApplyAclRulesCommandWrapper.java    |   42 +
 .../NuageVspApplyStaticNatCommandWrapper.java   |   42 +
 .../NuageVspCleanupDomainCommandWrapper.java    |   41 +
 .../wrapper/NuageVspCommandWrapper.java         |   52 +
 ...eVspDeallocateVmInterfaceCommandWrapper.java |   42 +
 .../NuageVspEntityExistsCommandWrapper.java     |   55 +
 .../NuageVspGetApiDefaultsCommandWrapper.java   |   43 +
 ...geVspGuruImplementNetworkCommandWrapper.java |   42 +
 .../NuageVspGuruTrashNetworkCommandWrapper.java |   42 +
 .../NuageVspImplementNetworkCommandWrapper.java |   43 +
 .../wrapper/NuageVspMaintainCommandWrapper.java |   35 +
 .../wrapper/NuageVspReadyCommandWrapper.java    |   35 +
 ...uageVspReserveVmInterfaceCommandWrapper.java |   42 +
 .../NuageVspShutdownNetworkCommandWrapper.java  |   42 +
 .../NuageVspShutdownVpcCommandWrapper.java      |   42 +
 .../NuageVspSyncCmsIdCommandWrapper.java        |   62 +
 .../NuageVspSyncDomainCommandWrapper.java       |   41 +
 ...NuageVspUpdateDhcpOptionsCommandWrapper.java |   42 +
 .../UpdateNuageVspDeviceCommandWrapper.java     |   46 +
 .../com/cloud/util/NuageVspEntityBuilder.java   |  160 +-
 .../vsp/acs/NuageVspPluginClientLoader.java     |   86 -
 .../nuage-vsp/test/com/cloud/NuageTest.java     |    6 +-
 .../test/com/cloud/agent/api/CommandsTest.java  |   39 +
 .../network/element/NuageVspElementTest.java    |   36 +-
 .../guru/NuageVspGuestNetworkGuruTest.java      |   41 +-
 .../network/resource/NuageVspResourceTest.java  |   84 +-
 .../cloud/util/NuageVspEntityBuilderTest.java   |   87 +-
 server/src/com/cloud/api/ApiResponseHelper.java |    1 +
 .../configuration/ConfigurationManagerImpl.java |  192 +-
 .../src/com/cloud/network/NetworkModelImpl.java |   28 +-
 .../cloud/server/ConfigurationServerImpl.java   |    2 +-
 server/src/com/cloud/user/DomainManager.java    |    1 +
 .../src/com/cloud/user/DomainManagerImpl.java   |    7 +-
 .../configuration/ConfigurationManagerTest.java |   70 +
 .../cloud/network/CreatePrivateNetworkTest.java |    2 +-
 .../com/cloud/network/MockNetworkModelImpl.java |    5 +
 .../com/cloud/network/NetworkModelTest.java     |   58 +
 .../com/cloud/vpc/MockNetworkModelImpl.java     |    9 +-
 setup/db/db/schema-4910to41000.sql              |    4 +-
 .../plugins/nuagevsp/nuageTestCase.py           |  191 +-
 ...t_nuage_non_public_sharednetwork_ip_range.py |  654 +++++
 .../nuagevsp/test_nuage_password_reset.py       |  252 +-
 .../test_nuage_public_sharednetwork_ip_range.py |  823 ++++++
 .../test_nuage_public_sharednetwork_userdata.py |  948 +++++++
 .../nuagevsp/test_nuage_publicsharednetwork.py  | 2575 ++++++++++++++++++
 .../test_nuage_sharednetwork_deployVM.py        | 2573 +++++++++++++++++
 .../test_nuage_sharednetwork_vpc_vm_monitor.py  |  704 +++++
 .../plugins/nuagevsp/test_nuage_source_nat.py   |   22 +-
 .../nuagevsp/test_nuage_vpc_internal_lb.py      |  257 +-
 .../plugins/nuagevsp/test_nuage_vpc_network.py  |    9 +-
 .../plugins/nuagevsp/test_nuage_vsp.py          |  206 +-
 tools/marvin/marvin/config/test_data.py         |   94 +
 tools/marvin/marvin/lib/base.py                 |    2 +-
 ui/l10n/en.js                                   |    1 +
 ui/scripts/configuration.js                     |   48 +-
 77 files changed, 11746 insertions(+), 1465 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4c91c9c5/api/src/com/cloud/network/Network.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java
index 81447d6..122ce70 100644
--- a/api/src/com/cloud/network/Network.java
+++ b/api/src/com/cloud/network/Network.java
@@ -60,7 +60,8 @@ public interface Network extends ControlledEntity, StateObject<Network.State>, I
         public static final Service PortForwarding = new Service("PortForwarding");
         public static final Service SecurityGroup = new Service("SecurityGroup");
         public static final Service NetworkACL = new Service("NetworkACL", Capability.SupportedProtocols);
-        public static final Service Connectivity = new Service("Connectivity", Capability.DistributedRouter, Capability.RegionLevelVpc, Capability.StretchedL2Subnet);
+        public static final Service Connectivity = new Service("Connectivity", Capability.DistributedRouter, Capability.RegionLevelVpc, Capability.StretchedL2Subnet,
+                Capability.NoVlan, Capability.PublicAccess);
 
         private final String name;
         private final Capability[] caps;
@@ -215,6 +216,8 @@ public interface Network extends ControlledEntity, StateObject<Network.State>, I
         public static final Capability DistributedRouter = new Capability("DistributedRouter");
         public static final Capability StretchedL2Subnet = new Capability("StretchedL2Subnet");
         public static final Capability RegionLevelVpc = new Capability("RegionLevelVpc");
+        public static final Capability NoVlan = new Capability("NoVlan");
+        public static final Capability PublicAccess = new Capability("PublicAccess");
 
         private final String name;
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4c91c9c5/api/src/com/cloud/network/NetworkModel.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/NetworkModel.java b/api/src/com/cloud/network/NetworkModel.java
index 780f97d..02746d0 100644
--- a/api/src/com/cloud/network/NetworkModel.java
+++ b/api/src/com/cloud/network/NetworkModel.java
@@ -154,6 +154,8 @@ public interface NetworkModel {
 
     boolean checkIpForService(IpAddress ip, Service service, Long networkId);
 
+    boolean providerSupportsCapability(Set<Provider> providers, Service service, Capability cap);
+
     void checkCapabilityForProvider(Set<Provider> providers, Service service, Capability cap, String capValue);
 
     Provider getDefaultUniqueProviderForService(String serviceName);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4c91c9c5/api/src/com/cloud/offering/NetworkOffering.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/offering/NetworkOffering.java b/api/src/com/cloud/offering/NetworkOffering.java
index f1ef69c..5eab98a 100644
--- a/api/src/com/cloud/offering/NetworkOffering.java
+++ b/api/src/com/cloud/offering/NetworkOffering.java
@@ -131,4 +131,6 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity,
     boolean isKeepAliveEnabled();
 
     boolean getSupportsStrechedL2();
+
+    boolean getSupportsPublicAccess();
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4c91c9c5/api/src/org/apache/cloudstack/api/ApiConstants.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java
index ad68658..00e9d38 100644
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -639,6 +639,7 @@ public class ApiConstants {
     public static final String READ_ONLY = "readonly";
     public static final String SUPPORTS_REGION_LEVEL_VPC = "supportsregionLevelvpc";
     public static final String SUPPORTS_STRECHED_L2_SUBNET = "supportsstrechedl2subnet";
+    public static final String SUPPORTS_PUBLIC_ACCESS = "supportspublicaccess";
     public static final String REGION_LEVEL_VPC = "regionlevelvpc";
     public static final String STRECHED_L2_SUBNET = "strechedl2subnet";
     public static final String NETWORK_SPANNED_ZONES = "zonesnetworkspans";

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4c91c9c5/api/src/org/apache/cloudstack/api/response/NetworkOfferingResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/NetworkOfferingResponse.java b/api/src/org/apache/cloudstack/api/response/NetworkOfferingResponse.java
index 775c9a8..93cbb12 100644
--- a/api/src/org/apache/cloudstack/api/response/NetworkOfferingResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/NetworkOfferingResponse.java
@@ -120,6 +120,10 @@ public class NetworkOfferingResponse extends BaseResponse {
     @Param(description = "true if network offering supports network that span multiple zones", since = "4.4")
     private Boolean supportsStrechedL2Subnet;
 
+    @SerializedName(ApiConstants.SUPPORTS_PUBLIC_ACCESS)
+    @Param(description = "true if network offering supports public access for guest networks", since = "4.10.0")
+    private Boolean supportsPublicAccess;
+
     public void setId(String id) {
         this.id = id;
     }
@@ -207,4 +211,8 @@ public class NetworkOfferingResponse extends BaseResponse {
     public void setSupportsStrechedL2Subnet(Boolean supportsStrechedL2Subnet) {
         this.supportsStrechedL2Subnet = supportsStrechedL2Subnet;
     }
+
+    public void setSupportsPublicAccess(Boolean supportsPublicAccess) {
+        this.supportsPublicAccess = supportsPublicAccess;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4c91c9c5/client/pom.xml
----------------------------------------------------------------------
diff --git a/client/pom.xml b/client/pom.xml
index 3954795..3595aaa 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -168,6 +168,11 @@
     </dependency>
     <dependency>
       <groupId>org.apache.cloudstack</groupId>
+      <artifactId>cloud-plugin-network-vsp</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.cloudstack</groupId>
       <artifactId>cloud-plugin-hypervisor-xenserver</artifactId>
       <version>${project.version}</version>
     </dependency>
@@ -991,21 +996,6 @@
       </dependencies>
     </profile>
     <profile>
-      <id>nuagevsp</id>
-      <activation>
-        <property>
-          <name>noredist</name>
-        </property>
-      </activation>
-      <dependencies>
-        <dependency>
-          <groupId>org.apache.cloudstack</groupId>
-          <artifactId>cloud-plugin-network-vsp</artifactId>
-          <version>${project.version}</version>
-        </dependency>
-      </dependencies>
-    </profile>
-    <profile>
       <id>srx</id>
       <activation>
         <property>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4c91c9c5/engine/schema/src/com/cloud/dc/dao/VlanDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/dc/dao/VlanDao.java b/engine/schema/src/com/cloud/dc/dao/VlanDao.java
index 485593e..e92a5cc 100644
--- a/engine/schema/src/com/cloud/dc/dao/VlanDao.java
+++ b/engine/schema/src/com/cloud/dc/dao/VlanDao.java
@@ -49,6 +49,8 @@ public interface VlanDao extends GenericDao<VlanVO, Long> {
 
     List<VlanVO> listVlansByNetworkId(long networkId);
 
+    List<VlanVO> listVlansByNetworkIdIncludingRemoved(long networkId);
+
     List<VlanVO> listVlansByPhysicalNetworkId(long physicalNetworkId);
 
     List<VlanVO> listZoneWideNonDedicatedVlans(long zoneId);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4c91c9c5/engine/schema/src/com/cloud/dc/dao/VlanDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/dc/dao/VlanDaoImpl.java b/engine/schema/src/com/cloud/dc/dao/VlanDaoImpl.java
index eabfbaa..0c59148 100644
--- a/engine/schema/src/com/cloud/dc/dao/VlanDaoImpl.java
+++ b/engine/schema/src/com/cloud/dc/dao/VlanDaoImpl.java
@@ -105,7 +105,7 @@ public class VlanDaoImpl extends GenericDaoBase<VlanVO, Long> implements VlanDao
         ZoneTypeSearch.done();
 
         NetworkVlanSearch = createSearchBuilder();
-        NetworkVlanSearch.and("networkOfferingId", NetworkVlanSearch.entity().getNetworkId(), SearchCriteria.Op.EQ);
+        NetworkVlanSearch.and("networkId", NetworkVlanSearch.entity().getNetworkId(), SearchCriteria.Op.EQ);
         NetworkVlanSearch.done();
 
         PhysicalNetworkVlanSearch = createSearchBuilder();
@@ -330,12 +330,18 @@ public class VlanDaoImpl extends GenericDaoBase<VlanVO, Long> implements VlanDao
     }
 
     @Override
-    public List<VlanVO> listVlansByNetworkId(long networkOfferingId) {
+    public List<VlanVO> listVlansByNetworkId(long networkId) {
         SearchCriteria<VlanVO> sc = NetworkVlanSearch.create();
-        sc.setParameters("networkOfferingId", networkOfferingId);
+        sc.setParameters("networkId", networkId);
         return listBy(sc);
     }
 
+    @Override public List<VlanVO> listVlansByNetworkIdIncludingRemoved(long networkId) {
+        SearchCriteria<VlanVO> sc = NetworkVlanSearch.create();
+        sc.setParameters("networkId", networkId);
+        return listIncludingRemovedBy(sc);
+    }
+
     @Override
     public List<VlanVO> listVlansByNetworkIdAndGateway(long networkid, String gateway) {
         SearchCriteria<VlanVO> sc = VlanGatewaysearch.create();

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4c91c9c5/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java b/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java
index c3d849d..4325287 100644
--- a/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java
+++ b/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java
@@ -142,6 +142,9 @@ public class NetworkOfferingVO implements NetworkOffering {
     @Column(name="supports_streched_l2")
     boolean supportsStrechedL2 = false;
 
+    @Column(name="supports_public_access")
+    boolean supportsPublicAccess = false;
+
     @Override
     public String getDisplayText() {
         return displayText;
@@ -334,7 +337,7 @@ public class NetworkOfferingVO implements NetworkOffering {
     public NetworkOfferingVO(String name, String displayText, TrafficType trafficType, boolean systemOnly, boolean specifyVlan, Integer rateMbps,
             Integer multicastRateMbps, boolean isDefault, Availability availability, String tags, Network.GuestType guestType, boolean conserveMode, boolean dedicatedLb,
             boolean sharedSourceNat, boolean redundantRouter, boolean elasticIp, boolean elasticLb, boolean specifyIpRanges, boolean inline, boolean isPersistent,
-            boolean associatePublicIP, boolean publicLb, boolean internalLb, boolean egressdefaultpolicy, boolean supportsStrechedL2) {
+            boolean associatePublicIP, boolean publicLb, boolean internalLb, boolean egressdefaultpolicy, boolean supportsStrechedL2, boolean supportsPublicAccess) {
         this(name,
             displayText,
             trafficType,
@@ -360,6 +363,7 @@ public class NetworkOfferingVO implements NetworkOffering {
         this.eipAssociatePublicIp = associatePublicIP;
         this.egressdefaultpolicy = egressdefaultpolicy;
         this.supportsStrechedL2 = supportsStrechedL2;
+        this.supportsPublicAccess = supportsPublicAccess;
     }
 
     public NetworkOfferingVO() {
@@ -495,4 +499,9 @@ public class NetworkOfferingVO implements NetworkOffering {
     public boolean getSupportsStrechedL2() {
         return supportsStrechedL2;
     }
+
+    @Override
+    public boolean getSupportsPublicAccess() {
+        return supportsPublicAccess;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4c91c9c5/plugins/network-elements/nuage-vsp/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/network-elements/nuage-vsp/pom.xml b/plugins/network-elements/nuage-vsp/pom.xml
index d26a3aa..78468dd 100644
--- a/plugins/network-elements/nuage-vsp/pom.xml
+++ b/plugins/network-elements/nuage-vsp/pom.xml
@@ -36,9 +36,9 @@
   </repositories>
   <dependencies>
     <dependency>
-      <groupId>net.nuage.vsp</groupId>
+      <groupId>net.nuagenetworks.vsp</groupId>
       <artifactId>nuage-vsp-acs-client</artifactId>
-      <version>3.2.8.1</version>
+      <version>1.0.0</version>
     </dependency>
   </dependencies>
   <build>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4c91c9c5/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/manager/CleanUpDomainCommand.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/manager/CleanUpDomainCommand.java b/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/manager/CleanUpDomainCommand.java
new file mode 100644
index 0000000..2229b61
--- /dev/null
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/manager/CleanUpDomainCommand.java
@@ -0,0 +1,72 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package com.cloud.agent.api.manager;
+
+import com.cloud.agent.api.Command;
+
+import com.google.common.base.Preconditions;
+import net.nuage.vsp.acs.client.api.model.VspDomainCleanUp;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+
+import java.util.Objects;
+
+public class CleanUpDomainCommand extends Command {
+
+    private final VspDomainCleanUp _domainCleanUp;
+
+    public CleanUpDomainCommand(VspDomainCleanUp domainCleanUp) {
+        super();
+        Preconditions.checkNotNull(domainCleanUp);
+        this._domainCleanUp = domainCleanUp;
+    }
+
+    public VspDomainCleanUp getDomainCleanUp() {
+        return _domainCleanUp;
+    }
+
+    @Override
+    public boolean executeInSequence() {
+        return false;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+
+        if (!(o instanceof CleanUpDomainCommand)) {
+            return false;
+        }
+
+        CleanUpDomainCommand that = (CleanUpDomainCommand) o;
+
+        return super.equals(that)
+                && Objects.equals(_domainCleanUp, that._domainCleanUp);
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder()
+                .appendSuper(super.hashCode())
+                .append(_domainCleanUp)
+                .toHashCode();
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4c91c9c5/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/manager/EntityExistsCommand.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/manager/EntityExistsCommand.java b/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/manager/EntityExistsCommand.java
index 64f3768..8e8fd81 100644
--- a/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/manager/EntityExistsCommand.java
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/manager/EntityExistsCommand.java
@@ -19,6 +19,10 @@
 
 package com.cloud.agent.api.manager;
 
+import org.apache.commons.lang.builder.HashCodeBuilder;
+
+import java.util.Objects;
+
 import com.cloud.agent.api.Command;
 
 public class EntityExistsCommand<T> extends Command {
@@ -55,23 +59,27 @@ public class EntityExistsCommand<T> extends Command {
 
     @Override
     public boolean equals(Object o) {
-        if (this == o) return true;
-        if (!(o instanceof EntityExistsCommand)) return false;
-        if (!super.equals(o)) return false;
+        if (this == o) {
+            return true;
+        }
 
-        EntityExistsCommand that = (EntityExistsCommand) o;
+        if (!(o instanceof EntityExistsCommand)) {
+            return false;
+        }
 
-        if (getType() != null ? !getType().equals(that.getType()) : that.getType() != null) return false;
-        if (_uuid != null ? !_uuid.equals(that._uuid) : that._uuid != null) return false;
+        EntityExistsCommand that = (EntityExistsCommand) o;
 
-        return true;
+        return super.equals(that)
+                && Objects.equals(getType(), that.getType())
+                && Objects.equals(_uuid, that._uuid);
     }
 
     @Override
     public int hashCode() {
-        int result = super.hashCode();
-        result = 31 * result + (getType() != null ? getType().hashCode() : 0);
-        result = 31 * result + (_uuid != null ? _uuid.hashCode() : 0);
-        return result;
+        return new HashCodeBuilder()
+                .appendSuper(super.hashCode())
+                .append(getType())
+                .append(_uuid)
+                .toHashCode();
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4c91c9c5/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/manager/UpdateNuageVspDeviceCommand.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/manager/UpdateNuageVspDeviceCommand.java b/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/manager/UpdateNuageVspDeviceCommand.java
new file mode 100644
index 0000000..d94ff70
--- /dev/null
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/manager/UpdateNuageVspDeviceCommand.java
@@ -0,0 +1,70 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package com.cloud.agent.api.manager;
+
+import org.apache.commons.lang.builder.HashCodeBuilder;
+
+import java.util.Objects;
+
+import com.cloud.agent.api.Command;
+import com.cloud.network.resource.NuageVspResourceConfiguration;
+
+public class UpdateNuageVspDeviceCommand extends Command {
+
+    private final NuageVspResourceConfiguration configuration;
+
+    public UpdateNuageVspDeviceCommand(NuageVspResourceConfiguration configuration) {
+        super();
+        this.configuration = configuration;
+    }
+
+    public NuageVspResourceConfiguration getConfiguration() {
+        return configuration;
+    }
+
+    @Override
+    public boolean executeInSequence() {
+        return false;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+
+        if (!(o instanceof UpdateNuageVspDeviceCommand)) {
+            return false;
+        }
+
+        UpdateNuageVspDeviceCommand that = (UpdateNuageVspDeviceCommand) o;
+
+        return super.equals(that)
+                && Objects.equals(configuration, that.configuration);
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder()
+                .appendSuper(super.hashCode())
+                .append(configuration)
+                .toHashCode();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4c91c9c5/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/sync/SyncNuageVspCmsIdAnswer.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/sync/SyncNuageVspCmsIdAnswer.java b/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/sync/SyncNuageVspCmsIdAnswer.java
index 289796f..98730fe 100644
--- a/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/sync/SyncNuageVspCmsIdAnswer.java
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/sync/SyncNuageVspCmsIdAnswer.java
@@ -24,6 +24,7 @@ import java.util.Objects;
 import org.apache.commons.lang.builder.HashCodeBuilder;
 
 import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
 
 public class SyncNuageVspCmsIdAnswer extends Answer {
 
@@ -38,6 +39,13 @@ public class SyncNuageVspCmsIdAnswer extends Answer {
         this._syncType = syncType;
     }
 
+    public SyncNuageVspCmsIdAnswer(Command command, Exception e, SyncNuageVspCmsIdCommand.SyncType syncType) {
+        super(command, e);
+        this._nuageVspCmsId = null;
+        this._success = false;
+        this._syncType = syncType;
+    }
+
     public boolean getSuccess() {
         return _success;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4c91c9c5/plugins/network-elements/nuage-vsp/src/com/cloud/network/element/NuageVspElement.java
----------------------------------------------------------------------
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 d0b9ed9..f2c1305 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
@@ -20,30 +20,37 @@
 package com.cloud.network.element;
 
 import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+
 import javax.annotation.Nullable;
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
-import org.apache.commons.collections.CollectionUtils;
-import org.apache.log4j.Logger;
-import com.google.common.base.Function;
-import com.google.common.collect.Lists;
-
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
 import net.nuage.vsp.acs.client.api.model.VspAclRule;
 import net.nuage.vsp.acs.client.api.model.VspDhcpDomainOption;
 import net.nuage.vsp.acs.client.api.model.VspNetwork;
 import net.nuage.vsp.acs.client.api.model.VspStaticNat;
 
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.log4j.Logger;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
 import org.apache.cloudstack.api.InternalIdentity;
 import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
 import org.apache.cloudstack.network.ExternalNetworkDeviceManager;
 import org.apache.cloudstack.network.topology.NetworkTopologyContext;
 import org.apache.cloudstack.resourcedetail.VpcDetailVO;
 import org.apache.cloudstack.resourcedetail.dao.VpcDetailsDao;
+
 import com.cloud.agent.AgentManager;
 import com.cloud.agent.api.Answer;
 import com.cloud.agent.api.StartupCommand;
@@ -64,6 +71,7 @@ import com.cloud.domain.dao.DomainDao;
 import com.cloud.exception.ConcurrentOperationException;
 import com.cloud.exception.InsufficientCapacityException;
 import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.exception.UnsupportedServiceException;
 import com.cloud.host.Host;
 import com.cloud.host.HostVO;
 import com.cloud.host.dao.HostDao;
@@ -111,6 +119,7 @@ import com.cloud.resource.ServerResource;
 import com.cloud.resource.UnableDeleteHostException;
 import com.cloud.util.NuageVspEntityBuilder;
 import com.cloud.util.NuageVspUtil;
+import com.cloud.utils.Pair;
 import com.cloud.utils.component.AdapterBase;
 import com.cloud.utils.net.NetUtils;
 import com.cloud.vm.DomainRouterVO;
@@ -128,6 +137,26 @@ public class NuageVspElement extends AdapterBase implements ConnectivityProvider
 
     private static final Map<Service, Map<Capability, String>> capabilities = setCapabilities();
 
+    private static final Set<Service> REQUIRED_SERVICES = ImmutableSet.of(
+            Service.Connectivity,
+            Service.Dhcp
+    );
+    private static final Set<Service> NUAGE_ONLY_SERVICES = ImmutableSet.of(
+            Service.SourceNat,
+            Service.StaticNat,
+            Service.Gateway
+    );
+    private static final Set<Service> UNSUPPORTED_SERVICES = ImmutableSet.of(
+            Service.Vpn,
+            Service.Dns,
+            Service.PortForwarding,
+            Service.SecurityGroup
+    );
+    private static final Set<Pair<Service, Service>> ANY_REQUIRED_SERVICES = ImmutableSet.of(
+            new Pair<>(Service.SourceNat, Service.StaticNat)
+    );
+
+
     public static final ExternalNetworkDeviceManager.NetworkDevice NuageVspDevice = new ExternalNetworkDeviceManager.NetworkDevice("NuageVsp", Provider.NuageVsp.getName());
 
     @Inject
@@ -190,7 +219,6 @@ public class NuageVspElement extends AdapterBase implements ConnectivityProvider
     @Inject
     VpcVirtualNetworkApplianceManager _routerMgr;
 
-
     @Override
     public boolean applyIps(Network network, List<? extends PublicIpAddress> ipAddress, Set<Service> service) throws ResourceUnavailableException {
         return false;
@@ -202,45 +230,32 @@ public class NuageVspElement extends AdapterBase implements ConnectivityProvider
     }
 
     private static Map<Service, Map<Capability, String>> setCapabilities() {
-        Map<Service, Map<Capability, String>> capabilities = new HashMap<Service, Map<Capability, String>>();
-
-        // L2 Support : SDN provisioning
-        capabilities.put(Service.Connectivity, null);
-
-        // L3 Support : Generic
-        capabilities.put(Service.Gateway, null);
-
-        // Security Group
-        capabilities.put(Service.SecurityGroup, null);
-
-        // L3 Support : SourceNat
-        Map<Capability, String> sourceNatCapabilities = new HashMap<Capability, String>();
-        sourceNatCapabilities.put(Capability.SupportedSourceNatTypes, "perzone");
-        sourceNatCapabilities.put(Capability.RedundantRouter, "false");
-        capabilities.put(Service.SourceNat, sourceNatCapabilities);
-
-        // L3 support : StaticNat
-        capabilities.put(Service.StaticNat, null);
-
-        // Set capabilities for Firewall service
-        Map<Capability, String> firewallCapabilities = new HashMap<Capability, String>();
-        firewallCapabilities.put(Capability.TrafficStatistics, "per public ip");
-        firewallCapabilities.put(Capability.SupportedProtocols, "tcp,udp,icmp");
-        firewallCapabilities.put(Capability.SupportedEgressProtocols, "tcp,udp,icmp, all");
-        firewallCapabilities.put(Capability.SupportedTrafficDirection, "ingress, egress");
-        firewallCapabilities.put(Capability.MultipleIps, "true");
-        capabilities.put(Service.Firewall, firewallCapabilities);
-
-        // L3 Support : DHCP
-        Map<Capability, String> dhcpCapabilities = new HashMap<Capability, String>();
-        capabilities.put(Service.Dhcp, dhcpCapabilities);
-
-        //add network ACL capability
-        Map<Network.Capability, String> networkACLCapabilities = new HashMap<Network.Capability, String>();
-        networkACLCapabilities.put(Network.Capability.SupportedProtocols, "tcp,udp,icmp");
-        capabilities.put(Network.Service.NetworkACL, networkACLCapabilities);
-
-        return capabilities;
+        return ImmutableMap.<Service, Map<Capability, String>>builder()
+            .put(Service.Connectivity, ImmutableMap.of(
+                    Capability.NoVlan, "",
+                    Capability.PublicAccess, ""
+            ))
+            .put(Service.Gateway, ImmutableMap.<Capability, String>of())
+            .put(Service.SourceNat, ImmutableMap.of(
+                    Capability.SupportedSourceNatTypes, "perzone",
+                    Capability.RedundantRouter, "false"
+            ))
+            .put(Service.StaticNat, ImmutableMap.<Capability, String>of())
+            .put(Service.SecurityGroup, ImmutableMap.<Capability, String>of())
+            .put(Service.Firewall, ImmutableMap.of(
+                    Capability.TrafficStatistics, "per public ip",
+                    Capability.SupportedProtocols, "tcp,udp,icmp",
+                    Capability.SupportedEgressProtocols, "tcp,udp,icmp, all",
+                    Capability.SupportedTrafficDirection, "ingress, egress",
+                    Capability.MultipleIps, "true"
+            ))
+            .put(Service.Dhcp, ImmutableMap.of(
+                    Capability.DhcpAccrossMultipleSubnets, "true"
+            ))
+            .put(Service.NetworkACL, ImmutableMap.of(
+                    Capability.SupportedProtocols, "tcp,udp,icmp"
+            ))
+            .build();
     }
 
     @Override
@@ -266,7 +281,7 @@ public class NuageVspElement extends AdapterBase implements ConnectivityProvider
             return applyACLRulesForVpc(network, offering);
         }
 
-        if (!canHandle(network, Service.Connectivity)) {
+        if (!canHandle(network, offering, Service.Connectivity)) {
             return false;
         }
 
@@ -276,7 +291,7 @@ public class NuageVspElement extends AdapterBase implements ConnectivityProvider
         }
 
 
-        VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(network, true);
+        VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(network);
         List<VspAclRule> ingressFirewallRules = getFirewallRulesToApply(network, FirewallRule.TrafficType.Ingress);
         List<VspAclRule> egressFirewallRules = getFirewallRulesToApply(network, FirewallRule.TrafficType.Egress);
 
@@ -356,7 +371,7 @@ public class NuageVspElement extends AdapterBase implements ConnectivityProvider
             // The network is restarted, possibly the domain name is changed, update the dhcpOptions as soon as possible
             NetworkOfferingVO networkOfferingVO = _ntwkOfferingDao.findById(network.getNetworkOfferingId());
             VspDhcpDomainOption vspDhcpOptions = _nuageVspEntityBuilder.buildNetworkDhcpOption(network, networkOfferingVO);
-            VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(network, false);
+            VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(network);
             HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(network.getPhysicalNetworkId());
             ShutDownVspCommand cmd = new ShutDownVspCommand(vspNetwork, vspDhcpOptions);
             Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd);
@@ -387,41 +402,40 @@ public class NuageVspElement extends AdapterBase implements ConnectivityProvider
 
     @Override
     public boolean destroy(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
-        if (!canHandle(network, Service.Connectivity)) {
-            return false;
-        }
-
-        return true;
+        return canHandle(network, Service.Connectivity);
     }
 
     @Override
     public boolean verifyServicesCombination(Set<Service> services) {
-        // This element can only function in a NuageVsp based
-        // SDN network, so Connectivity needs to be present here
-        if (!services.contains(Service.Connectivity)) {
-            s_logger.warn("Unable to support services combination without Connectivity service provided by Nuage VSP.");
-            return false;
+        Preconditions.checkNotNull(services);
+        final Sets.SetView<Service> missingServices = Sets.difference(REQUIRED_SERVICES, services);
+        final Sets.SetView<Service> unsupportedServices = Sets.intersection(UNSUPPORTED_SERVICES, services);
+        final Sets.SetView<Service> wantedServices = Sets.intersection(NUAGE_ONLY_SERVICES, new HashSet<>());
+
+        if (!missingServices.isEmpty()) {
+            throw new UnsupportedServiceException("Provider " + Provider.NuageVsp + " requires services: " + missingServices);
         }
 
-        if (!services.contains(Service.SourceNat)) {
-            s_logger.warn("Unable to support services combination without SourceNat service provided by Nuage VSP.");
+        if (!unsupportedServices.isEmpty()) {
+            // NuageVsp doesn't implement any of these services.
+            // So if these services are requested, we can't handle it.
+            s_logger.debug("Unable to support services combination. The services " + unsupportedServices + " are not supported by Nuage VSP.");
             return false;
         }
 
-        if (services.contains(Service.Vpn) || services.contains(Service.Dns) || services.contains(Service.Lb) || services.contains(Service.PortForwarding)
-                || services.contains(Service.SecurityGroup)) {
-            // NuageVsp doesn't implement any of these services, and we don't
-            // want anyone else to do it for us. So if these services
-            // exist, we can't handle it.
-            s_logger.warn("Unable to support services combination. The services list contains service(s) not supported by Nuage VSP.");
-            return false;
+        if (!wantedServices.isEmpty()) {
+            throw new UnsupportedServiceException("Provider " + Provider.NuageVsp + " does not support services to be implemented by another provider: " + wantedServices);
         }
 
         return true;
     }
 
     protected boolean canHandle(Network network, Service service) {
+        NetworkOffering networkOffering = _ntwkOfferingDao.findById(network.getNetworkOfferingId());
+        return canHandle(network, networkOffering, service);
+    }
 
+    protected boolean canHandle(Network network, NetworkOffering networkOffering, Service service) {
         if (network.getBroadcastDomainType() != Networks.BroadcastDomainType.Vsp) {
             return false;
         }
@@ -442,28 +456,35 @@ public class NuageVspElement extends AdapterBase implements ConnectivityProvider
             }
         }
 
-        if (service != Service.Connectivity && !_ntwkSrvcDao.canProviderSupportServiceInNetwork(network.getId(), Service.Connectivity, getProvider())) {
+        if (service != Service.Connectivity
+                && !_ntwkSrvcDao.canProviderSupportServiceInNetwork(network.getId(), Service.Connectivity, getProvider())) {
             if (s_logger.isDebugEnabled()) {
                 s_logger.debug("NuageVsp can't handle networks which use a network offering without NuageVsp as Connectivity provider");
             }
             return false;
         }
 
-        if (service != Service.SourceNat && !_ntwkSrvcDao.canProviderSupportServiceInNetwork(network.getId(), Service.SourceNat, getProvider())) {
+        if (service != Service.SourceNat
+                && networkOffering.getGuestType() == Network.GuestType.Isolated
+                && !_ntwkSrvcDao.canProviderSupportServiceInNetwork(network.getId(), Service.SourceNat, getProvider())) {
             if (s_logger.isDebugEnabled()) {
                 s_logger.debug("NuageVsp can't handle networks which use a network offering without NuageVsp as SourceNat provider");
             }
             return false;
         }
 
-        if (network.getVpcId() != null) {
-            NetworkOffering networkOffering = _ntwkOfferingDao.findById(network.getNetworkOfferingId());
-            if (!networkOffering.getIsPersistent()) {
-                if (s_logger.isDebugEnabled()) {
-                    s_logger.debug("NuageVsp can't handle VPC tiers which use a network offering which are not persistent");
-                }
-                return false;
+        if (networkOffering.getSpecifyVlan()) {
+            if (s_logger.isDebugEnabled()) {
+                s_logger.debug("NuageVsp doesn't support VLAN values for networks");
             }
+            return false;
+        }
+
+        if (network.getVpcId() != null && !networkOffering.getIsPersistent()) {
+            if (s_logger.isDebugEnabled()) {
+                s_logger.debug("NuageVsp can't handle VPC tiers which use a network offering which are not persistent");
+            }
+            return false;
         }
 
         return true;
@@ -484,7 +505,7 @@ public class NuageVspElement extends AdapterBase implements ConnectivityProvider
     private boolean isDnsSupportedByVR(Network network) {
         return (_networkModel.areServicesSupportedInNetwork(network.getId(), Service.Dns) &&
                 ( _networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.Dns,  Provider.VirtualRouter) ||
-                        _networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.Dns,  Provider.VPCVirtualRouter)));
+                  _networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.Dns,  Provider.VPCVirtualRouter)));
     }
 
     @Override
@@ -506,7 +527,7 @@ public class NuageVspElement extends AdapterBase implements ConnectivityProvider
             vspStaticNatDetails.add(vspStaticNat);
         }
 
-        VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(config, false);
+        VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(config);
         HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(config.getPhysicalNetworkId());
         ApplyStaticNatVspCommand cmd = new ApplyStaticNatVspCommand(vspNetwork, vspStaticNatDetails);
         Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd);
@@ -566,7 +587,7 @@ public class NuageVspElement extends AdapterBase implements ConnectivityProvider
 
     protected boolean applyACLRules(final Network network, List<? extends InternalIdentity> rules, boolean isNetworkAcl, boolean networkReset)
             throws ResourceUnavailableException {
-        VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(network, false);
+        VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(network);
         List<VspAclRule> vspAclRules = Lists.transform(rules, new Function<InternalIdentity, VspAclRule>() {
             @Nullable
             @Override

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4c91c9c5/plugins/network-elements/nuage-vsp/src/com/cloud/network/guru/NuageVspGuestNetworkGuru.java
----------------------------------------------------------------------
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 6bdd9e4..80f6aab 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
@@ -21,10 +21,14 @@ package com.cloud.network.guru;
 
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import javax.inject.Inject;
 
+import com.google.common.collect.FluentIterable;
+import net.nuage.vsp.acs.client.api.model.VspDhcpDomainOption;
 import net.nuage.vsp.acs.client.api.model.VspDhcpVMOption;
+import net.nuage.vsp.acs.client.api.model.VspDomain;
 import net.nuage.vsp.acs.client.api.model.VspNetwork;
 import net.nuage.vsp.acs.client.api.model.VspNic;
 import net.nuage.vsp.acs.client.api.model.VspStaticNat;
@@ -33,6 +37,8 @@ import net.nuage.vsp.acs.client.api.model.VspVm;
 import org.apache.log4j.Logger;
 
 import com.google.common.base.Strings;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.LinkedListMultimap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 
@@ -56,6 +62,7 @@ import com.cloud.domain.dao.DomainDao;
 import com.cloud.exception.ConcurrentOperationException;
 import com.cloud.exception.InsufficientAddressCapacityException;
 import com.cloud.exception.InsufficientVirtualNetworkCapacityException;
+import com.cloud.exception.UnsupportedServiceException;
 import com.cloud.host.HostVO;
 import com.cloud.host.dao.HostDao;
 import com.cloud.network.Network;
@@ -82,10 +89,12 @@ import com.cloud.user.dao.AccountDao;
 import com.cloud.util.NuageVspEntityBuilder;
 import com.cloud.utils.StringUtils;
 import com.cloud.utils.db.DB;
+import com.cloud.utils.net.Ip;
 import com.cloud.vm.Nic;
 import com.cloud.vm.NicProfile;
 import com.cloud.vm.NicVO;
 import com.cloud.vm.ReservationContext;
+import com.cloud.vm.VMInstanceVO;
 import com.cloud.vm.VirtualMachine;
 import com.cloud.vm.VirtualMachineProfile;
 import com.cloud.vm.dao.VMInstanceDao;
@@ -157,7 +166,7 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
 
         NetworkVO implemented = null;
         try {
-            if (network.getState() != State.Implementing) {
+            if (offering.getGuestType() == GuestType.Isolated && network.getState() != State.Implementing) {
                 throw new IllegalStateException("Network " + networkId + " is not in expected state Implementing, but is in state " + network.getState());
             }
 
@@ -170,6 +179,9 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
                 throw new InsufficientVirtualNetworkCapacityException(errorMessage, Account.class, network.getAccountId());
             }
 
+            //We don't support a shared network with UserData and multiple IP ranges at the same time.
+            checkMultipleSubnetsCombinedWithUseData(network);
+
             long dcId = dest.getDataCenter().getId();
             //Get physical network id
             Long physicalNetworkId = network.getPhysicalNetworkId();
@@ -190,21 +202,13 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
                 implemented.setCidr(network.getCidr());
             }
 
-            VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(implemented, true);
+            VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(implemented);
             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);
 
-            HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(physicalNetworkId);
-            ImplementNetworkVspCommand cmd = new ImplementNetworkVspCommand(vspNetwork, _nuageVspEntityBuilder.buildNetworkDhcpOption(network, offering));
-            Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd);
-
-            if (answer == null || !answer.getResult()) {
-                s_logger.error("ImplementNetworkVspCommand for network " + network.getUuid() + " failed on Nuage VSD " + nuageVspHost.getDetail("hostname"));
-                if ((null != answer) && (null != answer.getDetails())) {
-                    s_logger.error(answer.getDetails());
-                }
+            if (!implement(physicalNetworkId, vspNetwork, _nuageVspEntityBuilder.buildNetworkDhcpOption(network, offering))) {
                 return null;
             }
 
@@ -225,8 +229,31 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
         return implemented;
     }
 
+    private boolean implement(long physicalNetworkId, VspNetwork vspNetwork, VspDhcpDomainOption vspDhcpDomainOption) {
+        HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(physicalNetworkId);
+        ImplementNetworkVspCommand cmd = new ImplementNetworkVspCommand(vspNetwork, vspDhcpDomainOption);
+        Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd);
+        if (answer == null || !answer.getResult()) {
+            s_logger.error("ImplementNetworkVspCommand for network " + vspNetwork.getUuid() + " failed on Nuage VSD " + nuageVspHost.getDetail("hostname"));
+            if ((null != answer) && (null != answer.getDetails())) {
+                s_logger.error(answer.getDetails());
+            }
+            return false;
+        }
+        return true;
+    }
+
     @Override
     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())) {
+                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 " +
+                        "for the VR in network " + network, DataCenter.class,dc.getId());
+            }
+        }
 
         return super.allocate(network, nic, vm);
     }
@@ -240,6 +267,9 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
         }
 
         try {
+            //We don't support a shared network with UserData and multiple IP ranges at the same time.
+            checkMultipleSubnetsCombinedWithUseData(network);
+
             if (s_logger.isDebugEnabled()) {
                 s_logger.debug("Handling reserve() call back to with Create a new VM or add an interface to existing VM in network " + network.getName());
             }
@@ -255,7 +285,32 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
             }
 
             HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(network.getPhysicalNetworkId());
-            VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(network, false);
+            VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(vm.getVirtualMachine().getDomainId(), network);
+
+            if (vspNetwork.isShared()) {
+                vspNetwork = _nuageVspEntityBuilder.updateVspNetworkByPublicIp(vspNetwork, network, nic.getIPv4Address());
+
+                if (VirtualMachine.Type.DomainRouter.equals(vm.getType()) && !nic.getIPv4Address().equals(vspNetwork.getVirtualRouterIp())) {
+                    if(s_logger.isDebugEnabled()) {
+                        s_logger.debug("VR got spawned with a different IP, releasing the previously allocated public IP " + nic.getIPv4Address());
+                    }
+                    IPAddressVO oldIpAddress = _ipAddressDao.findByIpAndSourceNetworkId(network.getId(), nic.getIPv4Address());
+                    _ipAddressDao.unassignIpAddress(oldIpAddress.getId());
+                    _ipAddressDao.mark(network.getDataCenterId(), new Ip(vspNetwork.getVirtualRouterIp()));
+                } else if (VirtualMachine.Type.User.equals(vm.getType()) && nic.getIPv4Address().equals(vspNetwork.getVirtualRouterIp())) {
+                    s_logger.error("Deploying a user VM with the same IP as the VR is not allowed.");
+                    throw new InsufficientVirtualNetworkCapacityException("Deploying a user VM with the same IP " + nic.getIPv4Address() + " as the VR is not allowed.",
+                            Network.class, network.getId());
+                }
+
+                // Make sure the shared network is present
+                NetworkOffering offering = _ntwkOfferingDao.findById(network.getNetworkOfferingId());
+                if (!implement(network.getPhysicalNetworkId(), vspNetwork, _nuageVspEntityBuilder.buildNetworkDhcpOption(network, offering))) {
+                    s_logger.error("Failed to implement shared network " + network.getUuid() + " under domain " + context.getDomain().getUuid());
+                    throw new InsufficientVirtualNetworkCapacityException("Failed to implement shared network " + network.getUuid() + " under domain " +
+                            context.getDomain().getUuid(), Network.class, network.getId());
+                }
+            }
 
             // Set flags for dhcp options
             boolean networkHasDns = networkHasDns(network);
@@ -275,7 +330,6 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
             //that we create in VSP
             NicVO nicFromDb = _nicDao.findById(nic.getId());
             IPAddressVO staticNatIp = _ipAddressDao.findByVmIdAndNetworkId(network.getId(), vm.getId());
-
             VspVm vspVm = _nuageVspEntityBuilder.buildVspVm(vm.getVirtualMachine(), network);
             VspNic vspNic = _nuageVspEntityBuilder.buildVspNic(nicFromDb.getUuid(), nic);
             VspStaticNat vspStaticNat = null;
@@ -317,20 +371,30 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
         if(s_logger.isDebugEnabled()) {
             s_logger.debug(String.format("DomainRouter is added to an existing network: %s in state: %s", network.getName(), network.getState()));
         }
-        List<VspDhcpVMOption> dhcpOptions = Lists.newLinkedList();
-        for (NicVO userNic :_nicDao.listByNetworkId(network.getId())) {
-            if (userNic.getVmType() != VirtualMachine.Type.DomainRouter) {
-                boolean defaultHasDns = getDefaultHasDns(networkHasDnsCache, userNic);
-                dhcpOptions.add(_nuageVspEntityBuilder.buildVmDhcpOption(userNic, defaultHasDns, networkHasDns));
+
+        List<NicVO> userNics = _nicDao.listByNetworkId(network.getId());
+        LinkedListMultimap<Long, VspDhcpVMOption> dhcpOptionsPerDomain = LinkedListMultimap.create();
+
+        for (NicVO userNic : userNics) {
+            if (userNic.getVmType() == VirtualMachine.Type.DomainRouter) {
+                continue;
             }
+
+            VMInstanceVO userVm  = _vmInstanceDao.findById(userNic.getInstanceId());
+            boolean defaultHasDns = getDefaultHasDns(networkHasDnsCache, userNic);
+            VspDhcpVMOption dhcpOption = _nuageVspEntityBuilder.buildVmDhcpOption(userNic, defaultHasDns, networkHasDns);
+            dhcpOptionsPerDomain.put(userVm.getDomainId(), dhcpOption);
         }
 
-        if (!dhcpOptions.isEmpty()) {
-            UpdateDhcpOptionVspCommand cmd = new UpdateDhcpOptionVspCommand(dhcpOptions, vspNetwork);
+        for (Long domainId : dhcpOptionsPerDomain.keySet()) {
+            VspDomain vspDomain = _nuageVspEntityBuilder.buildVspDomain(_domainDao.findById(domainId));
+            VspNetwork vspNetworkForDomain = new VspNetwork.Builder().fromObject(vspNetwork).domain(vspDomain).build();
+            List<VspDhcpVMOption> dhcpOptions = dhcpOptionsPerDomain.get(domainId);
+            UpdateDhcpOptionVspCommand cmd = new UpdateDhcpOptionVspCommand(dhcpOptions, vspNetworkForDomain);
             Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd);
 
             if (answer == null || !answer.getResult()) {
-                s_logger.error("UpdateDhcpOptionVspCommand failed at \"reserve\" for network " + vspNetwork.getName());
+                s_logger.error("UpdateDhcpOptionVspCommand failed at \"reserve\" for network " + vspNetwork.getName() + " under domain " + vspNetwork.getVspDomain().getName());
                 if ((null != answer) && (null != answer.getDetails())) {
                     s_logger.error(answer.getDetails());
                 }
@@ -339,34 +403,65 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
         }
     }
 
+    private void checkMultipleSubnetsCombinedWithUseData(Network network) {
+        if (_ntwkOfferingSrvcDao.listServicesForNetworkOffering(network.getNetworkOfferingId()).contains(Network.Service.UserData.getName())) {
+            List<VlanVO> vlanVOs = _vlanDao.listVlansByNetworkId(network.getId());
+            if (vlanVOs.size() > 1) {
+                VlanVO vlanVoItem = vlanVOs.get(0);
+                for (VlanVO VlanVoItem2 : FluentIterable.from(vlanVOs).skip(1)) {
+                    if (!vlanVoItem.equals(VlanVoItem2)
+                            && !VlanVoItem2.getVlanGateway().equals(vlanVoItem.getVlanGateway())) {
+                        s_logger.error("NuageVsp provider does not support multiple subnets in combination with user data. Network: " + network + ", vlans: " + vlanVOs);
+                        throw new UnsupportedServiceException("NuageVsp provider does not support multiple subnets in combination with user data.");
+                    }
+                }
+            }
+        }
+    }
+
     @Override
     protected boolean canHandle(NetworkOffering offering, final NetworkType networkType, final PhysicalNetwork physicalNetwork) {
-        if (networkType == NetworkType.Advanced && isMyTrafficType(offering.getTrafficType()) && (offering.getGuestType() == Network.GuestType.Isolated || offering.getGuestType() == Network.GuestType.Shared)
-                && isMyIsolationMethod(physicalNetwork) && hasRequiredServices(offering)) {
+        if (networkType == NetworkType.Advanced
+                && isMyTrafficType(offering.getTrafficType())
+                && isMyIsolationMethod(physicalNetwork)
+                && (offering.getGuestType() == Network.GuestType.Isolated || offering.getGuestType() == Network.GuestType.Shared)
+                && hasRequiredServices(offering)) {
             if (_configMgr.isOfferingForVpc(offering) && !offering.getIsPersistent()) {
                 if (s_logger.isDebugEnabled()) {
                     s_logger.debug("NuageVsp can't handle VPC tiers which use a network offering which are not persistent");
                 }
                 return false;
+            } else if (offering.getGuestType() == GuestType.Shared) {
+                List<String> supportedSharedNetworkServices = Lists.newArrayList(Network.Service.Connectivity.getName(), Network.Service.Dhcp.getName(), Network.Service.UserData.getName());
+                List<String> offeringServices = _ntwkOfferingSrvcDao.listServicesForNetworkOffering(offering.getId());
+                if (!supportedSharedNetworkServices.containsAll(offeringServices)) {
+                    if (s_logger.isDebugEnabled()) {
+                        s_logger.debug("We only support " + Iterables.toString(supportedSharedNetworkServices) + " services for shared networks");
+                    }
+                    return false;
+                }
             }
             return true;
         } else {
             if (s_logger.isTraceEnabled()) {
-                s_logger.trace("We only take care of Guest networks of type   " + GuestType.Isolated + " in zone of type " + NetworkType.Advanced);
+                s_logger.trace("We only take care of networks in zone of type " + NetworkType.Advanced + " without VLAN");
             }
             return false;
         }
     }
 
     private boolean hasRequiredServices(NetworkOffering networkOffering) {
-        if (!_ntwkOfferingSrvcDao.canProviderSupportServiceInNetworkOffering(networkOffering.getId(), Network.Service.Connectivity, Network.Provider.NuageVsp)) {
+        final Map<Network.Service, Set<Network.Provider>> serviceProviderMap = _networkModel.getNetworkOfferingServiceProvidersMap(networkOffering.getId());
+
+        if (!serviceProviderMap.get(Network.Service.Connectivity).contains(Network.Provider.NuageVsp)) {
             if (s_logger.isDebugEnabled()) {
                 s_logger.debug("NuageVsp can't handle networks which use a network offering without NuageVsp as Connectivity provider");
             }
             return false;
         }
 
-        if (!_ntwkOfferingSrvcDao.canProviderSupportServiceInNetworkOffering(networkOffering.getId(), Network.Service.SourceNat, Network.Provider.NuageVsp)) {
+        if (networkOffering.getGuestType() == GuestType.Isolated
+                && !serviceProviderMap.get(Network.Service.SourceNat).contains(Network.Provider.NuageVsp)) {
             if (s_logger.isDebugEnabled()) {
                 s_logger.debug("NuageVsp can't handle networks which use a network offering without NuageVsp as SourceNat provider");
             }
@@ -391,7 +486,7 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
 
             NicVO nicFromDb = _nicDao.findById(nic.getId());
 
-            VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(network, false);
+            VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(vm.getVirtualMachine().getDomainId(), network);
             VspVm vspVm = _nuageVspEntityBuilder.buildVspVm(vm.getVirtualMachine(), network);
             VspNic vspNic = _nuageVspEntityBuilder.buildVspNic(nicFromDb.getUuid(), nic);
             HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(network.getPhysicalNetworkId());
@@ -404,6 +499,14 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
                     s_logger.error(answer.getDetails());
                 }
             }
+
+            // In case of shared network, when a User VM is spawned with the same IP as the VR, and it gets cleaned up, make sure we do not release the public IP
+            // because it is still allocated for the VR.
+            if (vspNetwork.isShared() && VirtualMachine.Type.User.equals(vm.getType()) && nic.getIPv4Address().equals(vspNetwork.getVirtualRouterIp())) {
+                nic.deallocate();
+            } else {
+                super.deallocate(network, nic, vm);
+            }
         } finally {
             if (network != null && lockedNetwork) {
                 _networkDao.releaseFromLockTable(network.getId());
@@ -412,8 +515,6 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
                 }
             }
         }
-
-        super.deallocate(network, nic, vm);
     }
 
     private boolean lockNetworkForUserVm(Network network, VirtualMachineProfile vm) {
@@ -445,7 +546,7 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
             if (s_logger.isDebugEnabled()) {
                 s_logger.debug("Handling trash() call back to delete the network " + network.getName() + " with uuid " + network.getUuid() + " from VSP");
             }
-            VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(network, false);
+            VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(network);
             HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(network.getPhysicalNetworkId());
             TrashNetworkVspCommand cmd = new TrashNetworkVspCommand(vspNetwork);
             Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd);
@@ -489,9 +590,7 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
 
     private Long getDefaultNetwork(long vmId) {
         NicVO defaultNic = _nicDao.findDefaultNicForVM(vmId);
-        if (defaultNic != null)  {
-            return defaultNic.getNetworkId();
-        }
+        if (defaultNic != null) return defaultNic.getNetworkId();
         return  null;
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4c91c9c5/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManager.java
----------------------------------------------------------------------
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 e5c9871..9f46012 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
@@ -27,7 +27,6 @@ import com.cloud.api.response.NuageVlanIpRangeResponse;
 import com.cloud.api.response.NuageVspDeviceResponse;
 import com.cloud.dc.Vlan;
 import com.cloud.host.HostVO;
-import com.cloud.network.Network;
 import com.cloud.network.NuageVspDeviceVO;
 import com.cloud.utils.component.PluggableService;
 import org.apache.cloudstack.framework.config.ConfigKey;
@@ -84,7 +83,7 @@ public interface NuageVspManager extends PluggableService {
 
     List<NuageVspDeviceVO> listNuageVspDevices(ListNuageVspDevicesCmd cmd);
 
-    List<String> getDnsDetails(Network network);
+    List<String> getDnsDetails(long dataCenterId);
 
     List<String> getGatewaySystemIds();