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 2017/12/28 09:25:21 UTC

[GitHub] rhtyd closed pull request #2360: [CLOUDSTACK-10189] Adding nuage VSD managed network support to CloudStack.

rhtyd closed pull request #2360: [CLOUDSTACK-10189] Adding nuage VSD managed network support to CloudStack.
URL: https://github.com/apache/cloudstack/pull/2360
 
 
   

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/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java
index 95833d86b63..8b402bcefd1 100644
--- a/api/src/com/cloud/network/Network.java
+++ b/api/src/com/cloud/network/Network.java
@@ -390,4 +390,6 @@ public void setIp6Address(String ip6Address) {
     void setNetworkACLId(Long networkACLId);
 
     boolean isStrechedL2Network();
+
+    String getExternalId();
 }
diff --git a/api/src/com/cloud/network/NetworkProfile.java b/api/src/com/cloud/network/NetworkProfile.java
index ab033edaa53..127750aa2ef 100644
--- a/api/src/com/cloud/network/NetworkProfile.java
+++ b/api/src/com/cloud/network/NetworkProfile.java
@@ -57,6 +57,7 @@
     private Long networkAclId;
     private final String guruName;
     private boolean strechedL2Subnet;
+    private String externalId;
 
     public NetworkProfile(Network network) {
         id = network.getId();
@@ -91,6 +92,7 @@ public NetworkProfile(Network network) {
         guruName = network.getGuruName();
         strechedL2Subnet = network.isStrechedL2Network();
         isRedundant = network.isRedundant();
+        externalId = network.getExternalId();
     }
 
     public String getDns1() {
@@ -300,4 +302,9 @@ public boolean isStrechedL2Network() {
         return false;
     }
 
+    @Override
+    public String getExternalId() {
+        return externalId;
+    }
+
 }
diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java
index 55e8c285e6b..24099c418d5 100644
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -654,6 +654,7 @@
     public static final String IAM_ALLOW_DENY = "permission";
     public static final String ENTITY_TYPE = "entitytype";
     public static final String ENTITY_ID = "entityid";
+    public static final String EXTERNAL_ID = "externalid";
     public static final String ACCESS_TYPE = "accesstype";
 
     public static final String RESOURCE_DETAILS = "resourcedetails";
@@ -706,6 +707,7 @@
     public static final String HAS_ANNOTATION = "hasannotation";
     public static final String LAST_ANNOTATED = "lastannotated";
 
+
     public enum HostDetails {
         all, capacity, events, stats, min;
     }
diff --git a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java
index 17312614808..befef999bfd 100644
--- a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java
@@ -16,7 +16,6 @@
 // under the License.
 package org.apache.cloudstack.api.command.user.network;
 
-import com.cloud.utils.net.NetUtils;
 import org.apache.log4j.Logger;
 
 import org.apache.cloudstack.acl.RoleType;
@@ -44,6 +43,7 @@
 import com.cloud.network.Network;
 import com.cloud.network.Network.GuestType;
 import com.cloud.offering.NetworkOffering;
+import com.cloud.utils.net.NetUtils;
 
 @APICommand(name = "createNetwork", description = "Creates a network", responseObject = NetworkResponse.class, responseView = ResponseView.Restricted, entityType = {Network.class},
         requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
@@ -134,6 +134,9 @@
     @Parameter(name = ApiConstants.IP6_CIDR, type = CommandType.STRING, description = "the CIDR of IPv6 network, must be at least /64")
     private String ip6Cidr;
 
+    @Parameter(name = ApiConstants.EXTERNAL_ID, type = CommandType.STRING, description = "ID of the network in an external system.")
+    private String externalId;
+
     @Parameter(name = ApiConstants.DISPLAY_NETWORK,
                type = CommandType.BOOLEAN,
  description = "an optional field, whether to the display the network to the end user or not.", authorized = {RoleType.Admin})
@@ -209,6 +212,10 @@ public Boolean getDisplayNetwork() {
         return displayNetwork;
     }
 
+    public String getExternalId() {
+        return externalId;
+    }
+
     @Override
     public boolean isDisplay() {
         if(displayNetwork == null)
diff --git a/api/src/org/apache/cloudstack/api/response/NetworkResponse.java b/api/src/org/apache/cloudstack/api/response/NetworkResponse.java
index 40c90729cd6..f54b063ad41 100644
--- a/api/src/org/apache/cloudstack/api/response/NetworkResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/NetworkResponse.java
@@ -225,6 +225,10 @@
     @Param(description = "If a network is enabled for 'streched l2 subnet' then represents zones on which network currently spans", since = "4.4")
     private Set<String> networkSpannedZones;
 
+    @SerializedName(ApiConstants.EXTERNAL_ID)
+    @Param(description = "The external id of the network", since = "4.11")
+    private String externalId;
+
     public Boolean getDisplayNetwork() {
         return displayNetwork;
     }
@@ -429,4 +433,8 @@ public void setStrechedL2Subnet(Boolean strechedL2Subnet) {
     public void setNetworkSpannedZones(Set<String> networkSpannedZones) {
         this.networkSpannedZones = networkSpannedZones;
     }
+
+    public void setExternalId(String externalId) {
+        this.externalId = externalId;
+    }
 }
diff --git a/engine/api/src/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java b/engine/api/src/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java
index 86a8fe91a36..67471d0d3e4 100644
--- a/engine/api/src/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java
+++ b/engine/api/src/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java
@@ -169,7 +169,7 @@ void prepare(VirtualMachineProfile profile, DeployDestination dest, ReservationC
 
     Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway, String cidr, String vlanId, boolean bypassVlanOverlapCheck, String networkDomain, Account owner,
                                Long domainId, PhysicalNetwork physicalNetwork, long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, String ip6Gateway, String ip6Cidr,
-                               Boolean displayNetworkEnabled, String isolatedPvlan) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException;
+                               Boolean displayNetworkEnabled, String isolatedPvlan, String externalId) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException;
 
     UserDataServiceProvider getPasswordResetProvider(Network network);
 
diff --git a/engine/components-api/src/com/cloud/network/vpc/VpcManager.java b/engine/components-api/src/com/cloud/network/vpc/VpcManager.java
index 28ad0524a2a..db4221f9e3e 100644
--- a/engine/components-api/src/com/cloud/network/vpc/VpcManager.java
+++ b/engine/components-api/src/com/cloud/network/vpc/VpcManager.java
@@ -109,7 +109,7 @@
     Network
         createVpcGuestNetwork(long ntwkOffId, String name, String displayText, String gateway, String cidr, String vlanId, String networkDomain, Account owner,
             Long domainId, PhysicalNetwork pNtwk, long zoneId, ACLType aclType, Boolean subdomainAccess, long vpcId, Long aclId, Account caller,
-            Boolean displayNetworkEnabled)
+            Boolean displayNetworkEnabled, String externalId)
 
             throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException;
 
diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
index d5b02440bb7..9afd642f7ae 100644
--- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
+++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
@@ -38,7 +38,8 @@
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
-import com.cloud.vm.NicExtraDhcpOptionVO;
+import org.apache.log4j.Logger;
+
 import org.apache.cloudstack.acl.ControlledEntity.ACLType;
 import org.apache.cloudstack.context.CallContext;
 import org.apache.cloudstack.engine.cloud.entity.api.db.VMNetworkMapVO;
@@ -53,7 +54,7 @@
 import org.apache.cloudstack.framework.messagebus.PublishScope;
 import org.apache.cloudstack.managed.context.ManagedContextRunnable;
 import org.apache.cloudstack.region.PortableIpDao;
-import org.apache.log4j.Logger;
+
 
 import com.cloud.agent.AgentManager;
 import com.cloud.agent.Listener;
@@ -204,6 +205,7 @@
 import com.cloud.utils.net.Dhcp;
 import com.cloud.vm.Nic;
 import com.cloud.vm.Nic.ReservationStrategy;
+import com.cloud.vm.NicExtraDhcpOptionVO;
 import com.cloud.vm.NicIpAlias;
 import com.cloud.vm.NicProfile;
 import com.cloud.vm.NicVO;
@@ -700,7 +702,7 @@ protected NetworkOrchestrator() {
                     public void doInTransactionWithoutResult(final TransactionStatus status) {
                         final NetworkVO vo = new NetworkVO(id, network, offering.getId(), guru.getName(), owner.getDomainId(), owner.getId(), relatedFile, name, displayText, predefined
                                 .getNetworkDomain(), offering.getGuestType(), plan.getDataCenterId(), plan.getPhysicalNetworkId(), aclType, offering.getSpecifyIpRanges(),
-                                vpcId, offering.getRedundantRouter());
+                                vpcId, offering.getRedundantRouter(), predefined.getExternalId());
                         vo.setDisplayNetwork(isDisplayNetworkEnabled == null ? true : isDisplayNetworkEnabled);
                         vo.setStrechedL2Network(offering.getSupportsStrechedL2());
                         final NetworkVO networkPersisted = _networksDao.persist(vo, vo.getGuestType() == Network.GuestType.Isolated,
@@ -2083,7 +2085,7 @@ public void expungeNics(final VirtualMachineProfile vm) {
     public Network createGuestNetwork(final long networkOfferingId, final String name, final String displayText, final String gateway, final String cidr, String vlanId,
                                       boolean bypassVlanOverlapCheck, String networkDomain, final Account owner, final Long domainId, final PhysicalNetwork pNtwk,
                                       final long zoneId, final ACLType aclType, Boolean subdomainAccess, final Long vpcId, final String ip6Gateway, final String ip6Cidr,
-                                      final Boolean isDisplayNetworkEnabled, final String isolatedPvlan) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException {
+                                      final Boolean isDisplayNetworkEnabled, final String isolatedPvlan, String externalId) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException {
 
         final NetworkOfferingVO ntwkOff = _networkOfferingDao.findById(networkOfferingId);
         // this method supports only guest network creation
@@ -2333,14 +2335,17 @@ public Network doInTransaction(final TransactionStatus status) {
                     userNetwork.setIp6Gateway(ip6Gateway);
                 }
 
+                if (externalId != null) {
+                    userNetwork.setExternalId(externalId);
+                }
+
                 if (vlanIdFinal != null) {
                     if (isolatedPvlan == null) {
                         URI uri = null;
                         if (UuidUtils.validateUUID(vlanIdFinal)){
                             //Logical router's UUID provided as VLAN_ID
                             userNetwork.setVlanIdAsUUID(vlanIdFinal); //Set transient field
-                        }
-                        else {
+                        } else {
                             uri = BroadcastDomainType.fromString(vlanIdFinal);
                         }
                         userNetwork.setBroadcastUri(uri);
diff --git a/engine/schema/resources/META-INF/db/schema-41000to41100.sql b/engine/schema/resources/META-INF/db/schema-41000to41100.sql
index 3dbe5c3e564..19c903927ca 100644
--- a/engine/schema/resources/META-INF/db/schema-41000to41100.sql
+++ b/engine/schema/resources/META-INF/db/schema-41000to41100.sql
@@ -496,3 +496,6 @@ UPDATE `cloud`.`monitoring_services` SET pidfile="/var/run/apache2/apache2.pid"
 -- Use 'Other Linux 64-bit' as guest os for the default systemvmtemplate for VMware
 -- This fixes a memory allocation issue to systemvms on VMware/ESXi
 UPDATE `cloud`.`vm_template` SET guest_os_id=99 WHERE id=8;
+
+-- Network External Ids
+ALTER TABLE `cloud`.`networks` ADD `external_id` varchar(255);
diff --git a/engine/schema/src/com/cloud/network/dao/NetworkVO.java b/engine/schema/src/com/cloud/network/dao/NetworkVO.java
index f8717880773..320256b90c0 100644
--- a/engine/schema/src/com/cloud/network/dao/NetworkVO.java
+++ b/engine/schema/src/com/cloud/network/dao/NetworkVO.java
@@ -172,6 +172,9 @@
     @Column(name = "streched_l2")
     boolean strechedL2Network = false;
 
+    @Column(name = "external_id")
+    String externalId;
+
     @Transient
     transient String vlanIdAsUUID;
 
@@ -216,7 +219,7 @@ public NetworkVO(TrafficType trafficType, Mode mode, BroadcastDomainType broadca
     }
 
     public NetworkVO(long id, Network that, long offeringId, String guruName, long domainId, long accountId, long related, String name, String displayText,
-            String networkDomain, GuestType guestType, long dcId, Long physicalNetworkId, ACLType aclType, boolean specifyIpRanges, Long vpcId, final boolean isRedundant) {
+            String networkDomain, GuestType guestType, long dcId, Long physicalNetworkId, ACLType aclType, boolean specifyIpRanges, Long vpcId, final boolean isRedundant, String externalId) {
         this(id,
             that.getTrafficType(),
             that.getMode(),
@@ -248,6 +251,7 @@ public NetworkVO(long id, Network that, long offeringId, String guruName, long d
         uuid = UUID.randomUUID().toString();
         ip6Gateway = that.getIp6Gateway();
         ip6Cidr = that.getIp6Cidr();
+        this.externalId = externalId;
     }
 
     /**
@@ -638,4 +642,12 @@ public void setStrechedL2Network(boolean strechedL2Network) {
     public void setVpcId(Long vpcId) {
         this.vpcId = vpcId;
     }
+
+    public String getExternalId() {
+        return externalId;
+    }
+
+    public void setExternalId(String externalId) {
+        this.externalId = externalId;
+    }
 }
diff --git a/plugins/network-elements/nuage-vsp/pom.xml b/plugins/network-elements/nuage-vsp/pom.xml
index bea8cb924a0..7e0b1ef89cd 100644
--- a/plugins/network-elements/nuage-vsp/pom.xml
+++ b/plugins/network-elements/nuage-vsp/pom.xml
@@ -35,7 +35,7 @@
     </repository>
   </repositories>
   <properties>
-      <nuage.vsp.client.version>1.0.6</nuage.vsp.client.version>
+      <nuage.vsp.client.version>1.0.7</nuage.vsp.client.version>
   </properties>
   <dependencies>
     <dependency>
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/element/ShutDownVpcVspCommand.java b/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/element/ShutDownVpcVspCommand.java
index 77b22bc2af3..6c98238c944 100644
--- a/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/element/ShutDownVpcVspCommand.java
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/element/ShutDownVpcVspCommand.java
@@ -20,11 +20,15 @@
 package com.cloud.agent.api.element;
 
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 
 import org.apache.commons.lang.builder.HashCodeBuilder;
 
 import com.cloud.agent.api.Command;
+import com.cloud.network.manager.NuageVspManager;
+
+import net.nuage.vsp.acs.client.api.model.NetworkRelatedVsdIds;
 
 public class ShutDownVpcVspCommand extends Command {
 
@@ -32,13 +36,19 @@
     private final String _vpcUuid;
     private final String _domainTemplateName;
     private final List<String> _domainRouterUuids;
+    private final NetworkRelatedVsdIds _relatedVsdIds;
 
-    public ShutDownVpcVspCommand(String domainUuid, String vpcUuid, String domainTemplateName, List<String> domainRouterUuids) {
+    public ShutDownVpcVspCommand(String domainUuid, String vpcUuid, String domainTemplateName, List<String> domainRouterUuids, Map<String, String> details) {
         super();
         this._domainUuid = domainUuid;
         this._vpcUuid = vpcUuid;
         this._domainTemplateName = domainTemplateName;
         this._domainRouterUuids = domainRouterUuids;
+        this._relatedVsdIds = new NetworkRelatedVsdIds.Builder()
+                .vsdDomainId(details.get(NuageVspManager.NETWORK_METADATA_VSD_DOMAIN_ID))
+                .vsdZoneId(details.get(NuageVspManager.NETWORK_METADATA_VSD_ZONE_ID))
+                .withVsdManaged(details.get(NuageVspManager.NETWORK_METADATA_VSD_MANAGED) != null && details.get(NuageVspManager.NETWORK_METADATA_VSD_MANAGED).equals("true"))
+                .build();
     }
 
     public String getDomainUuid() {
@@ -57,6 +67,10 @@ public String getDomainTemplateName() {
         return _domainRouterUuids;
     }
 
+    public NetworkRelatedVsdIds getRelatedVsdIds() {
+        return _relatedVsdIds;
+    }
+
     @Override
     public boolean executeInSequence() {
         return false;
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/guru/ImplementNetworkVspCommand.java b/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/guru/ImplementNetworkVspCommand.java
index 5dc4ba7a5da..2f2d5fd98a2 100644
--- a/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/guru/ImplementNetworkVspCommand.java
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/guru/ImplementNetworkVspCommand.java
@@ -33,11 +33,13 @@
 
     private final VspNetwork _network;
     private final VspDhcpDomainOption _dhcpOption;
+    private final boolean _isVsdManaged;
 
-    public ImplementNetworkVspCommand(VspNetwork network, VspDhcpDomainOption dhcpOption) {
+    public ImplementNetworkVspCommand(VspNetwork network, VspDhcpDomainOption dhcpOption, boolean isVsdManaged) {
         super();
         this._network = network;
         this._dhcpOption = dhcpOption;
+        this._isVsdManaged = isVsdManaged;
     }
 
     public VspNetwork getNetwork() {
@@ -85,4 +87,8 @@ public String toDetailString() {
                 .append("dhcpOption", _dhcpOption)
                 .toString();
     }
+
+    public boolean isVsdManaged() {
+        return _isVsdManaged;
+    }
 }
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/manager/ImplementNetworkVspAnswer.java b/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/manager/ImplementNetworkVspAnswer.java
index 03ab183d7b5..8cfb715743c 100644
--- a/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/manager/ImplementNetworkVspAnswer.java
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/manager/ImplementNetworkVspAnswer.java
@@ -20,6 +20,7 @@
 package com.cloud.agent.api.manager;
 
 import net.nuage.vsp.acs.client.api.model.NetworkRelatedVsdIds;
+import net.nuage.vsp.acs.client.api.model.VspNetwork;
 
 import com.cloud.agent.api.Answer;
 import com.cloud.agent.api.guru.ImplementNetworkVspCommand;
@@ -30,8 +31,11 @@
 public class ImplementNetworkVspAnswer extends Answer {
     private NetworkRelatedVsdIds networkRelatedVsdIds;
 
-    public ImplementNetworkVspAnswer(ImplementNetworkVspCommand command, NetworkRelatedVsdIds networkRelatedVsdIds) {
+    private VspNetwork vspNetwork;
+
+    public ImplementNetworkVspAnswer(ImplementNetworkVspCommand command, VspNetwork vspNetwork, NetworkRelatedVsdIds networkRelatedVsdIds) {
         super(command);
+        this.vspNetwork = vspNetwork;
         this.networkRelatedVsdIds = networkRelatedVsdIds;
     }
 
@@ -42,4 +46,8 @@ public ImplementNetworkVspAnswer(ImplementNetworkVspCommand command, Exception e
     public NetworkRelatedVsdIds getNetworkRelatedVsdIds() {
         return networkRelatedVsdIds;
     }
+
+    public VspNetwork getVspNetwork() {
+        return vspNetwork;
+    }
 }
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 e91901a2c8e..26fdaac5e14 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
@@ -507,7 +507,6 @@ public boolean setExtraDhcpOptions(Network network, long nicId, Map<Integer, Str
         return true;
     }
 
-
     @Override
     public boolean applyStaticNats(Network config, List<? extends StaticNat> rules) throws ResourceUnavailableException {
         List<VspStaticNat> vspStaticNatDetails = new ArrayList<VspStaticNat>();
@@ -687,6 +686,8 @@ public String apply(@Nullable DomainRouterVO input) {
                 preConfiguredDomainTemplateName = _configDao.getValue(NuageVspManager.NuageVspVpcDomainTemplateName.key());
             }
 
+            Map<String, String> vpcDetails = _vpcDetailsDao.listDetailsKeyPairs(vpc.getId(), false);
+
             cleanUpVpcCaching(vpc.getId());
             //related to migration caching
             List<? extends ResourceTag> vpcResourceDetails = _resourceTagDao.listByResourceUuid(vpc.getUuid());
@@ -698,7 +699,7 @@ public String apply(@Nullable DomainRouterVO input) {
                                   .ifPresent(this::cleanUpVpcCaching);
             }
 
-            ShutDownVpcVspCommand cmd = new ShutDownVpcVspCommand(vpcDomain.getUuid(), vpc.getUuid(), preConfiguredDomainTemplateName, domainRouterUuids);
+            ShutDownVpcVspCommand cmd = new ShutDownVpcVspCommand(vpcDomain.getUuid(), vpc.getUuid(), preConfiguredDomainTemplateName, domainRouterUuids, vpcDetails);
             Answer answer =  _agentMgr.easySend(nuageVspHost.getId(), cmd);
             if (answer == null || !answer.getResult()) {
                 s_logger.error("ShutDownVpcVspCommand for VPC " + vpc.getUuid() + " failed on Nuage VSD " + nuageVspHost.getDetail("hostname"));
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 f43e350d4dc..a36bc0a07d0 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
@@ -58,7 +58,9 @@
 import com.cloud.configuration.ConfigurationManager;
 import com.cloud.dc.DataCenter;
 import com.cloud.dc.DataCenter.NetworkType;
+import com.cloud.dc.DataCenterDetailVO;
 import com.cloud.dc.VlanVO;
+import com.cloud.dc.dao.DataCenterDetailsDao;
 import com.cloud.deploy.DeployDestination;
 import com.cloud.deploy.DeploymentPlan;
 import com.cloud.domain.dao.DomainDao;
@@ -67,7 +69,6 @@
 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;
 import com.cloud.network.Network.GuestType;
 import com.cloud.network.Network.State;
@@ -76,13 +77,10 @@
 import com.cloud.network.PhysicalNetwork;
 import com.cloud.network.PhysicalNetwork.IsolationMethod;
 import com.cloud.network.dao.IPAddressVO;
-import com.cloud.network.dao.NetworkDetailVO;
 import com.cloud.network.dao.NetworkDetailsDao;
 import com.cloud.network.dao.NetworkVO;
-import com.cloud.network.dao.NuageVspDao;
 import com.cloud.network.dao.PhysicalNetworkVO;
 import com.cloud.network.manager.NuageVspManager;
-import com.cloud.network.vpc.dao.VpcDao;
 import com.cloud.offering.NetworkOffering;
 import com.cloud.offerings.dao.NetworkOfferingDao;
 import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
@@ -92,6 +90,7 @@
 import com.cloud.util.NuageVspEntityBuilder;
 import com.cloud.utils.StringUtils;
 import com.cloud.utils.db.DB;
+import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.utils.net.Ip;
 import com.cloud.vm.Nic;
 import com.cloud.vm.NicProfile;
@@ -102,7 +101,7 @@
 import com.cloud.vm.VirtualMachineProfile;
 import com.cloud.vm.dao.VMInstanceDao;
 
-public class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
+public class NuageVspGuestNetworkGuru extends GuestNetworkGuru implements NetworkGuruAdditionalFunctions {
     public static final Logger s_logger = Logger.getLogger(NuageVspGuestNetworkGuru.class);
 
     @Inject
@@ -114,12 +113,6 @@
     @Inject
     AccountDao _accountDao;
     @Inject
-    NuageVspDao _nuageVspDao;
-    @Inject
-    HostDao _hostDao;
-    @Inject
-    VpcDao _vpcDao;
-    @Inject
     VMInstanceDao _vmInstanceDao;
     @Inject
     AgentManager _agentMgr;
@@ -135,6 +128,8 @@
     VpcDetailsDao _vpcDetailsDao;
     @Inject
     NetworkOrchestrationService _networkOrchestrationService;
+    @Inject
+    DataCenterDetailsDao _dcDetailsDao;
 
     public NuageVspGuestNetworkGuru() {
         super();
@@ -158,10 +153,90 @@ public Network design(NetworkOffering offering, DeploymentPlan plan, Network use
         }
 
         networkObject.setBroadcastDomainType(Networks.BroadcastDomainType.Vsp);
+
+        if (userSpecified instanceof NetworkVO && userSpecified.getExternalId() != null) {
+            if (owner.getType() < Account.ACCOUNT_TYPE_ADMIN) {
+                throw new IllegalArgumentException("vsdManaged networks are only useable by admins.");
+            }
+
+            if (!isUniqueReference(plan.getDataCenterId(), userSpecified.getExternalId())) {
+                s_logger.debug("Refusing to design network. VsdManaged network object already present in zone.");
+                return null;
+            }
+        }
+
         return networkObject;
     }
 
+    private boolean isUniqueReference(long dataCenterId, String vsdSubnetId) {
+        DataCenterDetailVO detail = _dcDetailsDao.findDetail(dataCenterId, vsdSubnetId);
+        return detail == null;
+    }
+
+    private boolean isVsdManagedVpc(long vpcId) {
+        //Check if it's a vpc and if the vpc is already vsdManaged OR if it has 0 tiers
+        Map<String, String> vpcDetails = _vpcDetailsDao.listDetailsKeyPairs(vpcId, false);
+        return vpcDetails.get(NuageVspManager.NETWORK_METADATA_VSD_MANAGED) != null && vpcDetails.get(NuageVspManager.NETWORK_METADATA_VSD_MANAGED).equals("true");
+    }
+
     /** In case an externalId is specified, we get called here, and store the id the same way as cached data */
+    @Override
+    public void finalizeNetworkDesign(long networkId, String vlanIdAsUUID) {
+        NetworkVO designedNetwork = _networkDao.findById(networkId);
+        String externalId = designedNetwork.getExternalId();
+        boolean isVpc = designedNetwork.getVpcId() != null;
+
+        if (isVpc && _networkDao.listByVpc(designedNetwork.getVpcId()).size() > 1) {
+            boolean isVsdManagedVpc = isVsdManagedVpc(designedNetwork.getVpcId());
+            if (isVsdManagedVpc && externalId == null) {
+                throw new CloudRuntimeException("Refusing to design network. Network is vsdManaged but is part of a non vsd managed vpc.");
+            } else if (!isVsdManagedVpc && externalId != null) {
+                throw new CloudRuntimeException("Refusing to design network. Network is not vsdManaged but is part of a vsd managed vpc.");
+            }
+        }
+
+        if (externalId == null) {
+            return;
+        }
+
+        VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(designedNetwork, externalId);
+        HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(designedNetwork.getPhysicalNetworkId());
+
+        ImplementNetworkVspCommand cmd = new ImplementNetworkVspCommand(vspNetwork, null, true);
+        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());
+            }
+            throw new CloudRuntimeException("ImplementNetworkVspCommand for network " + vspNetwork.getUuid() + " failed on Nuage VSD " + nuageVspHost.getDetail("hostname"));
+        }
+
+        //check if the network does not violate the uuid cidr
+        ImplementNetworkVspAnswer implementAnswer = (ImplementNetworkVspAnswer) answer;
+        VspNetwork updatedVspNetwork = implementAnswer.getVspNetwork();
+        NetworkVO forUpdate = _networkDao.createForUpdate(networkId);
+
+        if (isVpc && (!designedNetwork.getCidr().equals(updatedVspNetwork.getCidr()) || !designedNetwork.getGateway().equals(updatedVspNetwork.getGateway()))) {
+         throw new CloudRuntimeException("Tier network does not match the VsdManaged subnet cidr or gateway.");
+        } else {
+            forUpdate.setCidr(updatedVspNetwork.getCidr());
+            forUpdate.setGateway(updatedVspNetwork.getGateway());
+        }
+
+        saveNetworkAndVpcDetails(vspNetwork, implementAnswer.getNetworkRelatedVsdIds(), designedNetwork.getVpcId());
+        saveNetworkDetail(networkId, NuageVspManager.NETWORK_METADATA_VSD_SUBNET_ID, externalId);
+        saveNetworkDetail(networkId, NuageVspManager.NETWORK_METADATA_VSD_MANAGED, "true");
+
+        forUpdate.setState(State.Allocated);
+        _networkDao.update(networkId, forUpdate);
+    }
+
+    @Override
+    public Map<String, ? extends Object> listAdditionalNicParams(String nicUuid) {
+        return null;
+    }
+
     @Override
     public Network implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapacityException {
         long networkId = network.getId();
@@ -213,7 +288,7 @@ public Network implement(Network network, NetworkOffering offering, DeployDestin
 
             implemented = new NetworkVO(network.getId(), network, network.getNetworkOfferingId(), network.getGuruName(), network.getDomainId(), network.getAccountId(),
                     network.getRelated(), network.getName(), network.getDisplayText(), network.getNetworkDomain(), network.getGuestType(), network.getDataCenterId(),
-                    physicalNetworkId, network.getAclType(), network.getSpecifyIpRanges(), network.getVpcId(), offering.getRedundantRouter());
+                    physicalNetworkId, network.getAclType(), network.getSpecifyIpRanges(), network.getVpcId(), offering.getRedundantRouter(), network.getExternalId());
             implemented.setUuid(network.getUuid());
             implemented.setState(State.Allocated);
             if (network.getGateway() != null) {
@@ -229,7 +304,7 @@ public Network implement(Network network, NetworkOffering offering, DeployDestin
             implemented.setBroadcastUri(Networks.BroadcastDomainType.Vsp.toUri(broadcastUriStr));
             implemented.setBroadcastDomainType(Networks.BroadcastDomainType.Vsp);
 
-            boolean implementSucceeded = implement(network.getVpcId(), physicalNetworkId, vspNetwork, _nuageVspEntityBuilder.buildNetworkDhcpOption(network, offering));
+            boolean implementSucceeded = implement(network.getVpcId(), physicalNetworkId, vspNetwork, implemented, _nuageVspEntityBuilder.buildNetworkDhcpOption(network, offering));
 
             if (!implementSucceeded) {
                 return null;
@@ -237,11 +312,9 @@ public Network implement(Network network, NetworkOffering offering, DeployDestin
 
             if (StringUtils.isNotBlank(vspNetwork.getDomainTemplateName())) {
                 if (network.getVpcId() != null) {
-                    VpcDetailVO vpcDetail = new VpcDetailVO(network.getVpcId(), NuageVspManager.nuageDomainTemplateDetailName, vspNetwork.getDomainTemplateName(), false);
-                    _vpcDetailsDao.persist(vpcDetail);
+                    saveVpcDetail(network.getVpcId(), NuageVspManager.nuageDomainTemplateDetailName, vspNetwork.getDomainTemplateName());
                 } else {
-                    NetworkDetailVO networkDetail = new NetworkDetailVO(implemented.getId(), NuageVspManager.nuageDomainTemplateDetailName, vspNetwork.getDomainTemplateName(), false);
-                    _networkDetailsDao.persist(networkDetail);
+                    saveNetworkDetail(implemented.getId(), NuageVspManager.nuageDomainTemplateDetailName, vspNetwork.getDomainTemplateName());
                 }
             }
 
@@ -252,10 +325,19 @@ public Network implement(Network network, NetworkOffering offering, DeployDestin
         return implemented;
     }
 
-    private boolean implement(Long vpcId, long physicalNetworkId, VspNetwork vspNetwork, VspDhcpDomainOption vspDhcpDomainOption) {
+    private boolean implement(Long vpcId, long physicalNetworkId, VspNetwork vspNetwork, NetworkVO implemented, VspDhcpDomainOption vspDhcpDomainOption) {
         HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(physicalNetworkId);
-        ImplementNetworkVspCommand cmd = new ImplementNetworkVspCommand(vspNetwork, vspDhcpDomainOption);
-        ImplementNetworkVspAnswer answer = (ImplementNetworkVspAnswer) _agentMgr.easySend(nuageVspHost.getId(), cmd);
+        final boolean isVsdManaged = vspNetwork.getNetworkRelatedVsdIds()
+                                          .getVsdSubnetId()
+                                          .isPresent();
+        if (isVsdManaged) {
+            //Implement cmd was already send in design step.
+            _dcDetailsDao.persist(implemented.getDataCenterId(), vspNetwork.getNetworkRelatedVsdIds().getVsdSubnetId().orElseThrow(() -> new CloudRuntimeException("Managed but no subnetId. How can this happen?")), implemented.getUuid());
+            return true;
+        }
+
+        ImplementNetworkVspCommand cmd = new ImplementNetworkVspCommand(vspNetwork, vspDhcpDomainOption, false);
+        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())) {
@@ -263,7 +345,9 @@ private boolean implement(Long vpcId, long physicalNetworkId, VspNetwork vspNetw
             }
             return false;
         }
-        saveNetworkAndVpcDetails(vspNetwork, answer.getNetworkRelatedVsdIds(), vpcId);
+
+        ImplementNetworkVspAnswer implementAnswer = (ImplementNetworkVspAnswer) answer;
+        saveNetworkAndVpcDetails(vspNetwork, implementAnswer.getNetworkRelatedVsdIds(), vpcId);
         return true;
     }
 
@@ -274,23 +358,31 @@ private void saveNetworkAndVpcDetails(VspNetwork vspNetwork, NetworkRelatedVsdId
             long networkId = vspNetwork.getId();
 
             for (Map.Entry<String, String> networkDetail : networkDetails.entrySet()) {
-                _networkDetailsDao.addDetail(networkId, networkDetail.getKey(), networkDetail.getValue(), false);
+                saveNetworkDetail(vspNetwork.getId(), networkDetail.getKey(), networkDetail.getValue());
             }
 
             if(vspNetwork.isVpc()) {
                 Map<String, String> vpcDetails = constructVpcDetails(networkRelatedVsdIds);
 
                 for (Map.Entry<String, String> vpcDetail : vpcDetails.entrySet()) {
-                    _vpcDetailsDao.addDetail(vpcId, vpcDetail.getKey(), vpcDetail.getValue(), false);
+                    saveVpcDetail(vpcId, vpcDetail.getKey(), vpcDetail.getValue());
                 }
             }
         }
     }
 
+    private void saveVpcDetail(Long vpcId, String key, String value) {
+        _vpcDetailsDao.addDetail(vpcId, key, value, false);
+    }
+
+    private void saveNetworkDetail(long networkId, String key, String value) {
+         _networkDetailsDao.addDetail(networkId, key, value, false);
+    }
+
     private static Map<String, String> constructNetworkDetails(NetworkRelatedVsdIds networkRelatedVsdIds, boolean isVpc) {
         Map<String, String> networkDetails = Maps.newHashMap();
 
-        if(!isVpc) {
+        if (!isVpc) {
             networkRelatedVsdIds.getVsdDomainId().ifPresent(v -> networkDetails.put(NuageVspManager.NETWORK_METADATA_VSD_DOMAIN_ID, v));
             networkRelatedVsdIds.getVsdZoneId().ifPresent(v -> networkDetails.put(NuageVspManager.NETWORK_METADATA_VSD_ZONE_ID, v));
         }
@@ -304,6 +396,9 @@ private void saveNetworkAndVpcDetails(VspNetwork vspNetwork, NetworkRelatedVsdId
 
         networkRelatedVsdIds.getVsdDomainId().ifPresent(v ->  vpcDetails.put(NuageVspManager.NETWORK_METADATA_VSD_DOMAIN_ID, v));
         networkRelatedVsdIds.getVsdZoneId().ifPresent(v ->  vpcDetails.put(NuageVspManager.NETWORK_METADATA_VSD_ZONE_ID, v));
+        if (networkRelatedVsdIds.isVsdManaged()) {
+            vpcDetails.put(NuageVspManager.NETWORK_METADATA_VSD_MANAGED, "true");
+        }
 
         return vpcDetails;
     }
@@ -355,7 +450,7 @@ public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, D
 
             if (vm.getType() == VirtualMachine.Type.DomainRouter && vspNetwork.getVirtualRouterIp().equals("null")) {
                 //In case of upgrade network offering
-                vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(vm.getVirtualMachine().getDomainId(), network, true);
+                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));
@@ -381,7 +476,7 @@ public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, D
 
                 // Make sure the shared network is present
                 NetworkOffering offering = _ntwkOfferingDao.findById(network.getNetworkOfferingId());
-                if (!implement(network.getVpcId(), network.getPhysicalNetworkId(), vspNetwork, _nuageVspEntityBuilder.buildNetworkDhcpOption(network, offering))) {
+                if (!implement(network.getVpcId(), network.getPhysicalNetworkId(), vspNetwork, null, _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());
@@ -643,6 +738,15 @@ public boolean trash(Network network, NetworkOffering offering) {
             }
 
             VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(network);
+
+            //Clean up VSD managed subnet caching
+            if (vspNetwork.getNetworkRelatedVsdIds().isVsdManaged()) {
+                final long dataCenterId = network.getDataCenterId();
+                vspNetwork.getNetworkRelatedVsdIds().getVsdSubnetId().ifPresent(subnetId -> {
+                    _dcDetailsDao.removeDetail(dataCenterId, subnetId);
+                });
+            }
+
             HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(network.getPhysicalNetworkId());
             TrashNetworkVspCommand cmd = new TrashNetworkVspCommand(vspNetwork);
             Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd);
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 056b22eab41..6f91dc34276 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,11 @@
 
 package com.cloud.network.manager;
 
+import java.util.List;
+
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.framework.config.ConfigKey.Scope;
+
 import com.cloud.agent.api.manager.EntityExistsCommand;
 import com.cloud.api.commands.AddNuageVspDeviceCmd;
 import com.cloud.api.commands.AssociateNuageVspDomainTemplateCmd;
@@ -35,12 +40,8 @@
 import com.cloud.network.NuageVspDeviceVO;
 import com.cloud.utils.component.PluggableService;
 
-import org.apache.cloudstack.framework.config.ConfigKey;
-import org.apache.cloudstack.framework.config.ConfigKey.Scope;
 
 
-import java.util.List;
-
 public interface NuageVspManager extends PluggableService {
 
     String nuageVspSharedNetworkOfferingWithSGServiceName = "DefaultNuageVspSharedNetworkOfferingWithSGService";
@@ -86,6 +87,8 @@
 
     String NETWORK_METADATA_VSD_SUBNET_ID = "vsdSubnetId";
 
+    String NETWORK_METADATA_VSD_MANAGED = "isVsdManaged";
+
     String CMSID_CONFIG_KEY = "nuagevsp.cms.id";
 
     String NUAGE_VSP_ISOLATION = "VSP";
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/resource/NuageVspResource.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/resource/NuageVspResource.java
index 502b4bda7f2..a96b67097e8 100644
--- a/plugins/network-elements/nuage-vsp/src/com/cloud/network/resource/NuageVspResource.java
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/resource/NuageVspResource.java
@@ -241,6 +241,16 @@ public PingCommand getCurrentStatus(long id) {
         return pingNuageVspCommand;
     }
 
+    public boolean getStatus() {
+        try {
+            login();
+            return true;
+        } catch (NuageVspException | ConfigurationException e) {
+            s_logger.error("Failed to ping to Nuage VSD on " + _name + " as user " +_vspHost.getCmsUserLogin(), e);
+            return false;
+        }
+    }
+
     @Override
     public Answer executeRequest(final Command cmd) {
         final NuageVspRequestWrapper wrapper = NuageVspRequestWrapper.getInstance();
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/vsp/resource/wrapper/NuageVspCheckHealthCommandWrapper.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/vsp/resource/wrapper/NuageVspCheckHealthCommandWrapper.java
new file mode 100644
index 00000000000..d66fc1b5441
--- /dev/null
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/vsp/resource/wrapper/NuageVspCheckHealthCommandWrapper.java
@@ -0,0 +1,43 @@
+//
+// 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.network.vsp.resource.wrapper;
+
+import javax.naming.ConfigurationException;
+
+import net.nuage.vsp.acs.client.exception.NuageVspException;
+
+import com.cloud.agent.api.CheckHealthCommand;
+import com.cloud.network.resource.NuageVspResource;
+import com.cloud.resource.ResourceWrapper;
+
+@ResourceWrapper(handles = CheckHealthCommand.class)
+public class NuageVspCheckHealthCommandWrapper extends NuageVspCommandWrapper<CheckHealthCommand> {
+
+    @Override
+    public boolean executeNuageVspCommand(CheckHealthCommand cmd, NuageVspResource nuageVspResource) throws ConfigurationException, NuageVspException {
+        return nuageVspResource.getStatus();
+    }
+
+    @Override
+    public StringBuilder fillDetail(StringBuilder stringBuilder, CheckHealthCommand cmd) {
+        return stringBuilder.append("Check Health");
+    }
+
+}
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/vsp/resource/wrapper/NuageVspCommandWrapper.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/vsp/resource/wrapper/NuageVspCommandWrapper.java
index 879ba812a1b..3e3c4a12c44 100644
--- a/plugins/network-elements/nuage-vsp/src/com/cloud/network/vsp/resource/wrapper/NuageVspCommandWrapper.java
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/vsp/resource/wrapper/NuageVspCommandWrapper.java
@@ -45,7 +45,7 @@ public final Answer execute(final T command, final NuageVspResource nuageVspReso
         } catch (NuageVspUnsupportedRequestException e) {
             s_logger.error("Failure during " + command + " on " + nuageVspResource.getName(), e);
             return new UnsupportedAnswer(command, e.getMessage()); //New Exception so there is no stacktrace showed in the UI when changing ACL lists.
-        } catch (NuageVspException | ConfigurationException e) {
+        } catch (Exception e) {
             s_logger.error("Failure during " + command + " on " + nuageVspResource.getName(), e);
             return new Answer(command, e);
         }
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/vsp/resource/wrapper/NuageVspGuruImplementNetworkCommandWrapper.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/vsp/resource/wrapper/NuageVspGuruImplementNetworkCommandWrapper.java
index 1e57e244e65..4d2ef637386 100644
--- a/plugins/network-elements/nuage-vsp/src/com/cloud/network/vsp/resource/wrapper/NuageVspGuruImplementNetworkCommandWrapper.java
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/vsp/resource/wrapper/NuageVspGuruImplementNetworkCommandWrapper.java
@@ -19,11 +19,9 @@
 
 package com.cloud.network.vsp.resource.wrapper;
 
-import javax.naming.ConfigurationException;
-
 import net.nuage.vsp.acs.client.api.NuageVspGuruClient;
 import net.nuage.vsp.acs.client.api.model.NetworkRelatedVsdIds;
-import net.nuage.vsp.acs.client.exception.NuageVspException;
+import net.nuage.vsp.acs.client.api.model.VspNetwork;
 
 import com.cloud.agent.api.guru.ImplementNetworkVspCommand;
 import com.cloud.agent.api.manager.ImplementNetworkVspAnswer;
@@ -38,9 +36,14 @@
     public ImplementNetworkVspAnswer execute(ImplementNetworkVspCommand command, NuageVspResource serverResource) {
         try {
             NuageVspGuruClient client = serverResource.getNuageVspGuruClient();
-            NetworkRelatedVsdIds networkRelatedVsdIds = client.implement(command.getNetwork(), command.getDhcpOption());
-            return new ImplementNetworkVspAnswer(command, networkRelatedVsdIds);
-        } catch (ConfigurationException | NuageVspException e) {
+            if (command.isVsdManaged()) {
+                VspNetwork vspNetwork = client.addPermissionL3Network(command.getNetwork());
+                return new ImplementNetworkVspAnswer(command, vspNetwork, vspNetwork.getNetworkRelatedVsdIds());
+            } else {
+                NetworkRelatedVsdIds networkRelatedVsdIds = client.implement(command.getNetwork(), command.getDhcpOption());
+                return new ImplementNetworkVspAnswer(command, command.getNetwork(), networkRelatedVsdIds);
+            }
+        } catch (Exception e) {
             return new ImplementNetworkVspAnswer(command, e);
         }
     }
diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/vsp/resource/wrapper/NuageVspShutdownVpcCommandWrapper.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/vsp/resource/wrapper/NuageVspShutdownVpcCommandWrapper.java
index d2d9ea705b2..a3910cfa5a0 100644
--- a/plugins/network-elements/nuage-vsp/src/com/cloud/network/vsp/resource/wrapper/NuageVspShutdownVpcCommandWrapper.java
+++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/vsp/resource/wrapper/NuageVspShutdownVpcCommandWrapper.java
@@ -31,7 +31,7 @@
 public final class NuageVspShutdownVpcCommandWrapper extends NuageVspCommandWrapper<ShutDownVpcVspCommand> {
 
     @Override public boolean executeNuageVspCommand(ShutDownVpcVspCommand cmd, NuageVspResource nuageVspResource) throws ConfigurationException, NuageVspException {
-        nuageVspResource.getNuageVspElementClient().shutdownVpc(cmd.getDomainUuid(), cmd.getVpcUuid(), cmd.getDomainTemplateName(), cmd.getDomainRouterUuids());
+        nuageVspResource.getNuageVspElementClient().shutdownVpc(cmd.getDomainUuid(), cmd.getVpcUuid(), cmd.getDomainTemplateName(), cmd.getDomainRouterUuids(), cmd.getRelatedVsdIds());
         return true;
     }
 
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 c024a7b6adb..b34337fe2aa 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
@@ -43,6 +43,7 @@
 import net.nuage.vsp.acs.client.api.model.VspVm;
 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;
 
@@ -50,7 +51,7 @@
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 
-import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.cloudstack.resourcedetail.dao.VpcDetailsDao;
 
 import com.cloud.dc.Vlan;
 import com.cloud.dc.VlanVO;
@@ -88,8 +89,6 @@
 import com.cloud.vm.dao.NicSecondaryIpDao;
 import com.cloud.vm.dao.NicSecondaryIpVO;
 import com.cloud.vm.dao.VMInstanceDao;
-import org.apache.cloudstack.resourcedetail.dao.VpcDetailsDao;
-import org.apache.commons.collections.MapUtils;
 
 public class NuageVspEntityBuilder {
     private static final Logger s_logger = Logger.getLogger(NuageVspEntityBuilder.class);
@@ -113,8 +112,6 @@
     @Inject
     VlanDetailsDao _vlanDetailsDao;
     @Inject
-    ConfigurationDao _configurationDao;
-    @Inject
     IPAddressDao _ipAddressDao;
     @Inject
     NetworkDetailsDao _networkDetailsDao;
@@ -160,18 +157,30 @@ public VspDomainCleanUp buildVspDomainCleanUp(Domain domain) {
     }
 
     public VspNetwork buildVspNetwork(Network network) {
-        return buildVspNetwork(network.getDomainId(), network, false);
+        return buildVspNetwork(network.getDomainId(), network, null, false);
     }
 
-    public VspNetwork buildVspNetwork(long domainId, Network network) {
-        return buildVspNetwork(domainId, network, false);
+    public VspNetwork buildVspNetwork(Network network, boolean recalculateBroadcastUri) {
+        return buildVspNetwork(network.getDomainId(), network, null, recalculateBroadcastUri);
     }
 
-    public VspNetwork buildVspNetwork(Network network, boolean recalculateBroadcastUri) {
-        return buildVspNetwork(network.getDomainId(), network, recalculateBroadcastUri);
+    public VspNetwork buildVspNetwork(Network network, String vsdSubnetId) {
+        return buildVspNetwork(network.getDomainId(), network, vsdSubnetId, false);
+    }
+
+    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);
+    }
+
+    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())
@@ -183,21 +192,26 @@ public VspNetwork buildVspNetwork(long domainId, Network network, boolean recalc
         VspDomain vspDomain = buildVspDomain(domain);
         vspNetworkBuilder.domain(vspDomain);
 
+
         AccountVO account = _accountDao.findById(network.getAccountId());
         if (account != null) {
             vspNetworkBuilder.accountUuid(account.getUuid()).accountName(account.getAccountName());
         }
 
         NetworkOfferingVO networkOffering = _networkOfferingDao.findById(network.getNetworkOfferingId());
-        vspNetworkBuilder.egressDefaultPolicy(networkOffering.getEgressDefaultPolicy()).publicAccess(networkOffering.getSupportsPublicAccess());
+        vspNetworkBuilder.egressDefaultPolicy(networkOffering.getEgressDefaultPolicy())
+                         .publicAccess(networkOffering.getSupportsPublicAccess());
 
         Map<String, String> networkDetails = _networkDetailsDao.listDetailsKeyPairs(network.getId(), false);
-        String vsdSubnetId = null;
-        String vsdZoneId = null;
-        String vsdDomainId = null;
+
+        final NetworkRelatedVsdIds.Builder relatedVsdIdsBuilder = new NetworkRelatedVsdIds.Builder();
 
         if (MapUtils.isNotEmpty(networkDetails)) {
-            vsdSubnetId = networkDetails.get(NuageVspManager.NETWORK_METADATA_VSD_SUBNET_ID);
+            relatedVsdIdsBuilder.vsdSubnetId(networkDetails.get(NuageVspManager.NETWORK_METADATA_VSD_SUBNET_ID))
+                                .withVsdManaged("true".equals(networkDetails.get(NuageVspManager.NETWORK_METADATA_VSD_MANAGED)));
+        } else if (vsdSubnetId != null) {
+            relatedVsdIdsBuilder.vsdSubnetId(vsdSubnetId)
+                                .withVsdManaged("true".equals(networkDetails.get(NuageVspManager.NETWORK_METADATA_VSD_MANAGED)));
         }
 
         if (network.getVpcId() != null) {
@@ -207,16 +221,9 @@ public VspNetwork buildVspNetwork(long domainId, Network network, boolean recalc
                     .vpcName(vpc.getName())
                     .networkType(VspNetwork.NetworkType.Vpc);
             Map<String, String> vpcDetails = _vpcDetailsDao.listDetailsKeyPairs(vpcId, false);
-            if (MapUtils.isNotEmpty(vpcDetails)) {
-                vsdDomainId = vpcDetails.get(NuageVspManager.NETWORK_METADATA_VSD_DOMAIN_ID);
-                vsdZoneId = vpcDetails.get(NuageVspManager.NETWORK_METADATA_VSD_ZONE_ID);
-            }
-
+            applyDomainAndZoneId(relatedVsdIdsBuilder, vpcDetails);
         } else {
-            if (MapUtils.isNotEmpty(networkDetails)) {
-                vsdDomainId = networkDetails.get(NuageVspManager.NETWORK_METADATA_VSD_DOMAIN_ID);
-                vsdZoneId = networkDetails.get(NuageVspManager.NETWORK_METADATA_VSD_ZONE_ID);
-            }
+            applyDomainAndZoneId(relatedVsdIdsBuilder, networkDetails);
 
             if (networkOffering.getGuestType() == Network.GuestType.Shared) {
                 List<VlanVO> vlans = _vlanDao.listVlansByNetworkIdIncludingRemoved(network.getId());
@@ -238,11 +245,7 @@ public VspNetwork buildVspNetwork(long domainId, Network network, boolean recalc
 
         }
 
-        NetworkRelatedVsdIds networkRelatedVsdIds = new NetworkRelatedVsdIds.Builder()
-                                                          .vsdDomainId(vsdDomainId)
-                                                          .vsdSubnetId(vsdSubnetId)
-                                                          .vsdZoneId(vsdZoneId)
-                                                          .build();
+        NetworkRelatedVsdIds networkRelatedVsdIds = relatedVsdIdsBuilder.build();
         vspNetworkBuilder.networkRelatedVsdIds(networkRelatedVsdIds);
 
         boolean firewallServiceSupported = _networkModel.areServicesSupportedByNetworkOffering(network.getNetworkOfferingId(), Network.Service.Firewall);
@@ -266,6 +269,14 @@ public VspNetwork buildVspNetwork(long domainId, Network network, boolean recalc
         return vspNetworkBuilder.build();
     }
 
+    private void applyDomainAndZoneId(NetworkRelatedVsdIds.Builder relatedVsdIdsBuilder, Map<String, String> details) {
+        if (MapUtils.isNotEmpty(details)) {
+            relatedVsdIdsBuilder
+                    .vsdDomainId(details.get(NuageVspManager.NETWORK_METADATA_VSD_DOMAIN_ID))
+                    .vsdZoneId(details.get(NuageVspManager.NETWORK_METADATA_VSD_ZONE_ID));
+        }
+    }
+
     public boolean usesVirtualRouter(long networkOfferingId) {
         return _networkOfferingServiceMapDao.isProviderForNetworkOffering(networkOfferingId, Network.Provider.VirtualRouter) ||
                 _networkOfferingServiceMapDao.isProviderForNetworkOffering(networkOfferingId, Network.Provider.VPCVirtualRouter);
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 fea759dccdf..ae383bfea0b 100644
--- a/plugins/network-elements/nuage-vsp/test/com/cloud/NuageTest.java
+++ b/plugins/network-elements/nuage-vsp/test/com/cloud/NuageTest.java
@@ -146,7 +146,6 @@ protected NetworkRelatedVsdIds buildNetworkRelatedIds() {
         return new NetworkRelatedVsdIds.Builder()
                 .vsdZoneId("vsdZoneId")
                 .vsdDomainId("vsdDomainId")
-                .vsdEnterpriseId("vsdEnterpriseId")
                 .vsdSubnetId("vsdSubnetId")
                 .build();
     }
diff --git a/plugins/network-elements/nuage-vsp/test/com/cloud/network/guru/NuageVspGuestNetworkGuruTest.java b/plugins/network-elements/nuage-vsp/test/com/cloud/network/guru/NuageVspGuestNetworkGuruTest.java
index d8bdd4bda18..957408d06dc 100644
--- a/plugins/network-elements/nuage-vsp/test/com/cloud/network/guru/NuageVspGuestNetworkGuruTest.java
+++ b/plugins/network-elements/nuage-vsp/test/com/cloud/network/guru/NuageVspGuestNetworkGuruTest.java
@@ -31,6 +31,7 @@
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.internal.util.collections.Sets;
+import org.mockito.invocation.InvocationOnMock;
 
 import com.google.common.collect.ImmutableMap;
 
@@ -45,6 +46,7 @@
 import com.cloud.dc.DataCenter.NetworkType;
 import com.cloud.dc.DataCenterVO;
 import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.dc.dao.DataCenterDetailsDao;
 import com.cloud.deploy.DeployDestination;
 import com.cloud.deploy.DeploymentPlan;
 import com.cloud.domain.Domain;
@@ -110,6 +112,7 @@
     @Mock private IPAddressDao _ipAddressDao;
     @Mock private NuageVspManager _nuageVspManager;
     @Mock private ConfigurationManager _configurationManager;
+    @Mock private DataCenterDetailsDao _dcDetailsDao;
     @Mock private NetworkDetailsDao _networkDetailsDao;
     @Mock private PhysicalNetworkVO physnet;
 
@@ -138,7 +141,7 @@ public void setUp() throws Exception {
         when(_hostDao.findById(NETWORK_ID)).thenReturn(host);
         when(host.getId()).thenReturn(NETWORK_ID);
         when(_agentManager.easySend(eq(NETWORK_ID), any(Command.class))).thenReturn(new Answer(null));
-        when(_agentManager.easySend(eq(NETWORK_ID), any(ImplementNetworkVspCommand.class))).thenReturn(new ImplementNetworkVspAnswer(null, new NetworkRelatedVsdIds.Builder().build()));
+        when(_agentManager.easySend(eq(NETWORK_ID), any(ImplementNetworkVspCommand.class))).thenAnswer(this::mockImplement);
         when(_nuageVspManager.getNuageVspHost(NETWORK_ID)).thenReturn(host);
 
         final NuageVspDeviceVO device = mock(NuageVspDeviceVO.class);
@@ -147,6 +150,15 @@ public void setUp() throws Exception {
         when(device.getHostId()).thenReturn(NETWORK_ID);
     }
 
+    Answer mockImplement(InvocationOnMock invocation) {
+        if (invocation.getArguments()[1] instanceof ImplementNetworkVspCommand) {
+            ImplementNetworkVspCommand command = (ImplementNetworkVspCommand)(invocation.getArguments()[1]);
+            return new ImplementNetworkVspAnswer(command, command.getNetwork(), new NetworkRelatedVsdIds.Builder().build());
+        } else {
+            return new Answer(null);
+        }
+    }
+
     @Test
     public void testCanHandle() {
         final NetworkOffering offering = mock(NetworkOffering.class);
diff --git a/plugins/network-elements/nuage-vsp/test/com/cloud/network/resource/NuageVspResourceTest.java b/plugins/network-elements/nuage-vsp/test/com/cloud/network/resource/NuageVspResourceTest.java
index fb67e6ff9d7..560f53dbda2 100644
--- a/plugins/network-elements/nuage-vsp/test/com/cloud/network/resource/NuageVspResourceTest.java
+++ b/plugins/network-elements/nuage-vsp/test/com/cloud/network/resource/NuageVspResourceTest.java
@@ -20,6 +20,7 @@
 package com.cloud.network.resource;
 
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -152,12 +153,25 @@ public void testImplementNetworkVspCommand() throws Exception {
 
         VspNetwork vspNetwork = buildVspNetwork();
         VspDhcpDomainOption vspDhcpOptions = buildspDhcpDomainOption();
-        ImplementNetworkVspCommand cmd = new ImplementNetworkVspCommand(vspNetwork, vspDhcpOptions);
+        ImplementNetworkVspCommand cmd = new ImplementNetworkVspCommand(vspNetwork, vspDhcpOptions, false);
         ImplementNetworkVspAnswer implNtwkAns = (ImplementNetworkVspAnswer)_resource.executeRequest(cmd);
         assertTrue(implNtwkAns.getResult());
         verify(_mockNuageVspGuruClient).implement(vspNetwork, vspDhcpOptions);
     }
 
+    @Test
+    public void testImplementVsdManagedNetworkVspCommand() throws Exception {
+        _resource.configure("NuageVspResource", _hostDetails);
+
+        VspNetwork vspNetwork = buildVspNetwork();
+        VspDhcpDomainOption vspDhcpOptions = buildspDhcpDomainOption();
+        when(_mockNuageVspGuruClient.addPermissionL3Network(vspNetwork)).thenReturn(vspNetwork);
+        ImplementNetworkVspCommand cmd = new ImplementNetworkVspCommand(vspNetwork, vspDhcpOptions, true);
+        ImplementNetworkVspAnswer implNtwkAns = (ImplementNetworkVspAnswer)_resource.executeRequest(cmd);
+        assertTrue(implNtwkAns.getResult());
+        verify(_mockNuageVspGuruClient).addPermissionL3Network(vspNetwork);
+    }
+
     @Test
     public void testReserveVmInterfaceVspCommand() throws Exception {
         _resource.configure("NuageVspResource", _hostDetails);
@@ -220,7 +234,7 @@ public void testApplyAclRuleVspCommand() throws Exception {
     public void testShutDownVpcVspCommand() throws Exception {
         _resource.configure("NuageVspResource", _hostDetails);
 
-        ShutDownVpcVspCommand cmd = new ShutDownVpcVspCommand("domainUuid", "vpcUuid", "domainTemplateName", Lists.<String>newArrayList());
+        ShutDownVpcVspCommand cmd = new ShutDownVpcVspCommand("domainUuid", "vpcUuid", "domainTemplateName", Lists.<String>newArrayList(), new HashMap<>());
         Answer shutVpcAns = _resource.executeRequest(cmd);
         assertTrue(shutVpcAns.getResult());
     }
diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java
index 19730d0fc9c..c4e337ed96c 100644
--- a/server/src/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/com/cloud/api/ApiResponseHelper.java
@@ -2206,6 +2206,7 @@ public NetworkResponse createNetworkResponse(ResponseView view, Network network)
             }
             response.setNetworkSpannedZones(networkSpannedZones);
         }
+        response.setExternalId(network.getExternalId());
         response.setObjectName("network");
         return response;
     }
diff --git a/server/src/com/cloud/network/IpAddressManagerImpl.java b/server/src/com/cloud/network/IpAddressManagerImpl.java
index 55e842b7741..51809589e16 100644
--- a/server/src/com/cloud/network/IpAddressManagerImpl.java
+++ b/server/src/com/cloud/network/IpAddressManagerImpl.java
@@ -1662,7 +1662,7 @@ public boolean associateIpAddressListToAccount(long userId, final long accountId
                             s_logger.debug("Creating network for account " + owner + " from the network offering id=" + requiredOfferings.get(0).getId()
                                     + " as a part of createVlanIpRange process");
                             guestNetwork = _networkMgr.createGuestNetwork(requiredOfferings.get(0).getId(), owner.getAccountName() + "-network", owner.getAccountName()
-                                    + "-network", null, null, null, false, null, owner, null, physicalNetwork, zoneId, ACLType.Account, null, null, null, null, true, null);
+                                    + "-network", null, null, null, false, null, owner, null, physicalNetwork, zoneId, ACLType.Account, null, null, null, null, true, null, null);
                             if (guestNetwork == null) {
                                 s_logger.warn("Failed to create default Virtual network for the account " + accountId + "in zone " + zoneId);
                                 throw new CloudRuntimeException("Failed to create a Guest Isolated Networks with SourceNAT "
diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java
index a2b5dc1b3f5..81ab2b141e1 100644
--- a/server/src/com/cloud/network/NetworkServiceImpl.java
+++ b/server/src/com/cloud/network/NetworkServiceImpl.java
@@ -103,6 +103,7 @@
 import com.cloud.network.dao.FirewallRulesDao;
 import com.cloud.network.dao.IPAddressDao;
 import com.cloud.network.dao.IPAddressVO;
+import com.cloud.network.dao.LoadBalancerDao;
 import com.cloud.network.dao.NetworkDao;
 import com.cloud.network.dao.NetworkDetailVO;
 import com.cloud.network.dao.NetworkDetailsDao;
@@ -192,7 +193,6 @@
 import com.cloud.vm.dao.NicSecondaryIpVO;
 import com.cloud.vm.dao.UserVmDao;
 import com.cloud.vm.dao.VMInstanceDao;
-import com.cloud.network.dao.LoadBalancerDao;
 
 /**
  * NetworkServiceImpl implements NetworkService.
@@ -1031,6 +1031,7 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac
         Boolean displayNetwork = cmd.getDisplayNetwork();
         Long aclId = cmd.getAclId();
         String isolatedPvlan = cmd.getIsolatedPvlan();
+        String externalId = cmd.getExternalId();
 
         // Validate network offering
         NetworkOfferingVO ntwkOff = _networkOfferingDao.findById(networkOfferingId);
@@ -1292,7 +1293,7 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac
 
         Network network = commitNetwork(networkOfferingId, gateway, startIP, endIP, netmask, networkDomain, vlanId, bypassVlanOverlapCheck, name, displayText, caller, physicalNetworkId, zoneId, domainId,
                 isDomainSpecific, subdomainAccess, vpcId, startIPv6, endIPv6, ip6Gateway, ip6Cidr, displayNetwork, aclId, isolatedPvlan, ntwkOff, pNtwk, aclType, owner, cidr,
-                createVlan);
+                createVlan, externalId);
 
         // if the network offering has persistent set to true, implement the network
         if (ntwkOff.getIsPersistent()) {
@@ -1325,7 +1326,7 @@ private Network commitNetwork(final Long networkOfferingId, final String gateway
                                   final String vlanId, final Boolean bypassVlanOverlapCheck, final String name, final String displayText, final Account caller, final Long physicalNetworkId, final Long zoneId, final Long domainId,
                                   final boolean isDomainSpecific, final Boolean subdomainAccessFinal, final Long vpcId, final String startIPv6, final String endIPv6, final String ip6Gateway,
                                   final String ip6Cidr, final Boolean displayNetwork, final Long aclId, final String isolatedPvlan, final NetworkOfferingVO ntwkOff, final PhysicalNetwork pNtwk,
-                                  final ACLType aclType, final Account ownerFinal, final String cidr, final boolean createVlan) throws InsufficientCapacityException, ResourceAllocationException {
+                                  final ACLType aclType, final Account ownerFinal, final String cidr, final boolean createVlan, final String externalId) throws InsufficientCapacityException, ResourceAllocationException {
         try {
             Network network = Transaction.execute(new TransactionCallbackWithException<Network, Exception>() {
                 @Override
@@ -1370,7 +1371,7 @@ public Network doInTransaction(TransactionStatus status) throws InsufficientCapa
                             }
                         }
                         network = _vpcMgr.createVpcGuestNetwork(networkOfferingId, name, displayText, gateway, cidr, vlanId, networkDomain, owner, sharedDomainId, pNtwk, zoneId,
-                                aclType, subdomainAccess, vpcId, aclId, caller, displayNetwork);
+                                aclType, subdomainAccess, vpcId, aclId, caller, displayNetwork, externalId);
                     } else {
                         if (_configMgr.isOfferingForVpc(ntwkOff)) {
                             throw new InvalidParameterValueException("Network offering can be used for VPC networks only");
@@ -1380,7 +1381,7 @@ public Network doInTransaction(TransactionStatus status) throws InsufficientCapa
                         }
 
                         network = _networkMgr.createGuestNetwork(networkOfferingId, name, displayText, gateway, cidr, vlanId, bypassVlanOverlapCheck, networkDomain, owner, sharedDomainId, pNtwk, zoneId,
-                                aclType, subdomainAccess, vpcId, ip6Gateway, ip6Cidr, displayNetwork, isolatedPvlan);
+                                aclType, subdomainAccess, vpcId, ip6Gateway, ip6Cidr, displayNetwork, isolatedPvlan, externalId);
                     }
 
                     if (_accountMgr.isRootAdmin(caller.getId()) && createVlan && network != null) {
@@ -4335,7 +4336,7 @@ public Network doInTransaction(TransactionStatus status) throws ResourceAllocati
                     if (privateNetwork == null) {
                         //create Guest network
                         privateNetwork = _networkMgr.createGuestNetwork(ntwkOffFinal.getId(), networkName, displayText, gateway, cidr, uriString, false, null, owner, null, pNtwk,
-                                pNtwk.getDataCenterId(), ACLType.Account, null, vpcId, null, null, true, null);
+                                                                        pNtwk.getDataCenterId(), ACLType.Account, null, vpcId, null, null, true, null, null);
                         if (privateNetwork != null) {
                             s_logger.debug("Successfully created guest network " + privateNetwork);
                         } else {
diff --git a/server/src/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/com/cloud/network/vpc/VpcManagerImpl.java
index d1a6fb55909..1f0753a9509 100644
--- a/server/src/com/cloud/network/vpc/VpcManagerImpl.java
+++ b/server/src/com/cloud/network/vpc/VpcManagerImpl.java
@@ -38,6 +38,9 @@
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.log4j.Logger;
+
 import org.apache.cloudstack.acl.ControlledEntity.ACLType;
 import org.apache.cloudstack.api.command.user.vpc.ListPrivateGatewaysCmd;
 import org.apache.cloudstack.api.command.user.vpc.ListStaticRoutesCmd;
@@ -45,8 +48,6 @@
 import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
 import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
 import org.apache.cloudstack.managed.context.ManagedContextRunnable;
-import org.apache.commons.collections.CollectionUtils;
-import org.apache.log4j.Logger;
 
 import com.cloud.configuration.Config;
 import com.cloud.configuration.Resource.ResourceType;
@@ -2316,7 +2317,7 @@ public boolean isIpAllocatedToVpc(final IpAddress ip) {
     @Override
     public Network createVpcGuestNetwork(final long ntwkOffId, final String name, final String displayText, final String gateway, final String cidr, final String vlanId,
             String networkDomain, final Account owner, final Long domainId, final PhysicalNetwork pNtwk, final long zoneId, final ACLType aclType, final Boolean subdomainAccess,
-            final long vpcId, final Long aclId, final Account caller, final Boolean isDisplayNetworkEnabled) throws ConcurrentOperationException, InsufficientCapacityException,
+            final long vpcId, final Long aclId, final Account caller, final Boolean isDisplayNetworkEnabled, String externalId) throws ConcurrentOperationException, InsufficientCapacityException,
             ResourceAllocationException {
 
         final Vpc vpc = getActiveVpc(vpcId);
@@ -2341,7 +2342,7 @@ public Network createVpcGuestNetwork(final long ntwkOffId, final String name, fi
 
         // 2) Create network
         final Network guestNetwork = _ntwkMgr.createGuestNetwork(ntwkOffId, name, displayText, gateway, cidr, vlanId, false, networkDomain, owner, domainId, pNtwk, zoneId, aclType,
-                subdomainAccess, vpcId, null, null, isDisplayNetworkEnabled, null);
+                                                                 subdomainAccess, vpcId, null, null, isDisplayNetworkEnabled, null, externalId);
 
         if (guestNetwork != null) {
             guestNetwork.setNetworkACLId(aclId);
diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java
index 3591e603b0a..c4edf4fa112 100644
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -3156,7 +3156,8 @@ public UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serv
                     }
                     s_logger.debug("Creating network for account " + owner + " from the network offering id=" + requiredOfferings.get(0).getId() + " as a part of deployVM process");
                     Network newNetwork = _networkMgr.createGuestNetwork(requiredOfferings.get(0).getId(), owner.getAccountName() + "-network", owner.getAccountName() + "-network",
-                            null, null, null, false, null, owner, null, physicalNetwork, zone.getId(), ACLType.Account, null, null, null, null, true, null);
+                                                                        null, null, null, false, null, owner, null, physicalNetwork, zone.getId(), ACLType.Account, null, null, null, null, true, null,
+                                                                        null);
                     if (newNetwork != null) {
                         defaultNetwork = _networkDao.findById(newNetwork.getId());
                     }
@@ -5795,8 +5796,9 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
                             s_logger.debug("Creating network for account " + newAccount + " from the network offering id=" + requiredOfferings.get(0).getId()
                                     + " as a part of deployVM process");
                             Network newNetwork = _networkMgr.createGuestNetwork(requiredOfferings.get(0).getId(), newAccount.getAccountName() + "-network",
-                                    newAccount.getAccountName() + "-network", null, null, null, false, null, newAccount, null, physicalNetwork, zone.getId(), ACLType.Account, null, null,
-                                    null, null, true, null);
+                                                                                newAccount.getAccountName() + "-network", null, null, null, false, null, newAccount,
+                                                                                null, physicalNetwork, zone.getId(), ACLType.Account, null, null,
+                                                                                null, null, true, null, null);
                             // if the network offering has persistent set to true, implement the network
                             if (requiredOfferings.get(0).getIsPersistent()) {
                                 DeployDestination dest = new DeployDestination(zone, null, null, null);
diff --git a/server/test/com/cloud/network/CreatePrivateNetworkTest.java b/server/test/com/cloud/network/CreatePrivateNetworkTest.java
index 5b6ead02559..2e06039ccd5 100644
--- a/server/test/com/cloud/network/CreatePrivateNetworkTest.java
+++ b/server/test/com/cloud/network/CreatePrivateNetworkTest.java
@@ -122,8 +122,8 @@ public void setup() throws Exception {
                 ACLType.Account, false, 1L, false);
         when(
             networkService._networkMgr.createGuestNetwork(eq(ntwkOff.getId()), eq("bla"), eq("fake"), eq("10.1.1.1"), eq("10.1.1.0/24"), anyString(), anyBoolean(), anyString(),
-                eq(account), anyLong(), eq(physicalNetwork), eq(physicalNetwork.getDataCenterId()), eq(ACLType.Account), anyBoolean(), eq(1L), anyString(), anyString(),
-                anyBoolean(), anyString())).thenReturn(net);
+                                                          eq(account), anyLong(), eq(physicalNetwork), eq(physicalNetwork.getDataCenterId()), eq(ACLType.Account), anyBoolean(), eq(1L), anyString(), anyString(),
+                                                          anyBoolean(), anyString(), anyString())).thenReturn(net);
 
         when(networkService._privateIpDao.findByIpAndSourceNetworkId(net.getId(), "10.1.1.2")).thenReturn(null);
         when(networkService._privateIpDao.findByIpAndSourceNetworkIdAndVpcId(eq(1L), anyString(), eq(1L))).thenReturn(null);
diff --git a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
index cdf7180febe..d68b7c9e96d 100644
--- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
+++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
@@ -638,7 +638,7 @@ public boolean destroyNetwork(long networkId, ReservationContext context, boolea
     @Override
     public Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway, String cidr, String vlanId, boolean bypassVlanOverlapCheck, String networkDomain,
                                       Account owner, Long domainId, PhysicalNetwork physicalNetwork, long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, String gatewayv6,
-                                      String cidrv6, Boolean displayNetworkEnabled, String isolatedPvlan) throws ConcurrentOperationException, InsufficientCapacityException,
+                                      String cidrv6, Boolean displayNetworkEnabled, String isolatedPvlan, String externalId) throws ConcurrentOperationException, InsufficientCapacityException,
         ResourceAllocationException {
         // TODO Auto-generated method stub
         return null;
diff --git a/test/integration/plugins/nuagevsp/nuageTestCase.py b/test/integration/plugins/nuagevsp/nuageTestCase.py
index aaeb97ad8d3..45db7913ceb 100644
--- a/test/integration/plugins/nuagevsp/nuageTestCase.py
+++ b/test/integration/plugins/nuagevsp/nuageTestCase.py
@@ -387,7 +387,7 @@ def create_NetworkOffering(cls, net_offering, suffix=None,
     @needscleanup
     def create_Network(cls, nw_off, gateway="10.1.1.1",
                        netmask="255.255.255.0", vpc=None, acl_list=None,
-                       testdata=None, account=None, vlan=None):
+                       testdata=None, account=None, vlan=None, externalid=None):
         if not account:
             account = cls.account
         cls.debug("Creating a network in the account - %s" % account.name)
@@ -404,6 +404,7 @@ def create_Network(cls, nw_off, gateway="10.1.1.1",
                                  zoneid=cls.zone.id,
                                  gateway=gateway,
                                  vlan=vlan,
+                                 externalid=externalid,
                                  vpcid=vpc.id if vpc else cls.vpc.id
                                  if hasattr(cls, "vpc") else None,
                                  aclid=acl_list.id if acl_list else None
diff --git a/test/integration/plugins/nuagevsp/test_nuage_vsp_mngd_subnets.py b/test/integration/plugins/nuagevsp/test_nuage_vsp_mngd_subnets.py
new file mode 100644
index 00000000000..ebbcccb7fc0
--- /dev/null
+++ b/test/integration/plugins/nuagevsp/test_nuage_vsp_mngd_subnets.py
@@ -0,0 +1,512 @@
+# 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.
+
+""" Component tests for VSP Managed Subnets functionality
+    with Nuage VSP SDN plugin
+"""
+# Import Local Modules
+from nuageTestCase import nuageTestCase
+from marvin.lib.base import (Account,
+                             VirtualMachine)
+from marvin.cloudstackAPI import updateZone
+
+# Import System Modules
+from nose.plugins.attrib import attr
+import time
+
+
+class TestNuageManagedSubnets(nuageTestCase):
+    """Test Managed Subnets functionality with Nuage VSP SDN plugin
+    """
+
+    @classmethod
+    def setUpClass(cls):
+        super(TestNuageManagedSubnets, cls).setUpClass()
+
+        # create a nuage vpc offering
+        cls.nuage_vpc_offering = \
+            cls.create_VpcOffering(cls.test_data["nuagevsp"]["vpc_offering"])
+
+        # tier network offerings
+        cls.nuage_vpc_network_offering = \
+            cls.create_NetworkOffering(cls.test_data["nuagevsp"]
+                                       ["vpc_network_offering"])
+
+        # create a Nuage isolated network offering with vr
+        cls.nuage_isolated_network_offering = cls.create_NetworkOffering(
+                cls.test_data["nuagevsp"]["isolated_network_offering"], True)
+
+        # create a Nuage isolated network offering with vr and persistent
+        cls.nuage_isolated_network_offering_persistent = \
+            cls.create_NetworkOffering(
+                    cls.test_data["nuagevsp"]
+                    ["isolated_network_offering_persistent"],
+                    True)
+
+        # create a Nuage isolated network offering without vr
+        cls.nuage_isolated_network_offering_without_vr = \
+            cls.create_NetworkOffering(
+                    cls.test_data["nuagevsp"]
+                    ["isolated_network_offering_without_vr"],
+                    True)
+
+        # create a Nuage isolated network offering without vr but persistent
+        cls.nuage_isolated_network_offering_without_vr_persistent = \
+            cls.create_NetworkOffering(
+                    cls.test_data["nuagevsp"]
+                    ["isolated_network_offering_without_vr_persistent"],
+                    True)
+
+        # create a Nuage shared network offering
+        cls.nuage_shared_network_offering = cls.create_NetworkOffering(
+                cls.test_data["nuagevsp"]["shared_nuage_network_offering"],
+                False)
+
+        cls._cleanup = [
+            cls.nuage_isolated_network_offering,
+            cls.nuage_isolated_network_offering_persistent,
+            cls.nuage_isolated_network_offering_without_vr,
+            cls.nuage_isolated_network_offering_without_vr_persistent,
+            cls.nuage_vpc_offering,
+            cls.nuage_vpc_network_offering,
+            cls.nuage_shared_network_offering
+        ]
+        return
+
+    def setUp(self):
+        # Create an account
+        self.account = Account.create(self.api_client,
+                                      self.test_data["account"],
+                                      admin=True,
+                                      domainid=self.domain.id
+                                      )
+        self.cleanup = [self.account]
+        return
+
+    def verify_pingtovmipaddress(self, ssh, pingtovmipaddress):
+        """verify ping to ipaddress of the vm and retry 3 times"""
+
+        if self.isSimulator:
+            return
+
+        successfull_ping = False
+        nbr_retries = 0
+        max_retries = 5
+        cmd = 'ping -c 2 ' + pingtovmipaddress
+
+        while not successfull_ping and nbr_retries < max_retries:
+            self.debug("ping vm by ipaddress with command: " + cmd)
+            outputlist = ssh.execute(cmd)
+            self.debug("command is executed properly " + cmd)
+            completeoutput = str(outputlist).strip('[]')
+            self.debug("complete output is " + completeoutput)
+            if '2 received' in completeoutput:
+                self.debug("PASS as vm is pingeable: " + completeoutput)
+                successfull_ping = True
+            else:
+                self.debug("FAIL as vm is not pingeable: " + completeoutput)
+                time.sleep(3)
+                nbr_retries = nbr_retries + 1
+
+        if not successfull_ping:
+            self.fail("FAILED TEST as excepted value not found in vm")
+
+    def tearDown(self):
+        super(TestNuageManagedSubnets, self).tearDown()
+        # Cleanup resources used
+        self.debug("Cleaning up the resources")
+        for obj in reversed(self.cleanup):
+            try:
+                if isinstance(obj, VirtualMachine):
+                    obj.delete(self.api_client, expunge=True)
+                else:
+                    obj.delete(self.api_client)
+            except Exception as e:
+                self.error("Failed to cleanup %s, got %s" % (obj, e))
+        # cleanup_resources(self.api_client, self.cleanup)
+        self.cleanup = []
+        self.debug("Cloudstack Cleanup complete!")
+        enterprise = self.fetch_by_externalID(self._session.user.enterprises,
+                                              self.domain)
+        domain_template = enterprise.domain_templates.get_first()
+        domain_template.delete()
+        self.debug("VSD Cleanup complete!")
+        return
+
+    @attr(tags=["advanced", "nuagevsp", "isonw"], required_hardware="false")
+    def test_01_nuage_mngd_subnets_isonw(self):
+        """Test Nuage VSP Managed Subnets for isolated networks
+        """
+
+        # 1. Create multiple L3DomainTemplate with Zone and Subnet on VSP
+        #    Create Ingress & Egress ACL Top & Bottom Templates
+        #    Add ACL rules to allow intra-subnet traffic
+        #    Instiantiate these L3Domains and store its Subnet VSD ID
+        # 2. Create a persistent and non persistent isolated network offering
+        #    create offerings with and without VirtualRouter
+        # 3. Create isolated networks specifying above offerings and
+        #    specifying the stored Subnet ID's of VSP
+        # 4. Verify ACL rules and connectivity via deploying VM's ,
+        #    Enabling staticNAT, applying firewall and egress rules
+
+        # Create all items on vsd required for this test
+        enterprise = self.fetch_by_externalID(self._session.user.enterprises,
+                                              self.domain)
+        domain_template = self.create_vsd_domain_template(enterprise)
+
+        self.create_vsd_default_acls(domain_template)
+
+        domain1 = self.create_vsd_domain(domain_template, enterprise,
+                                         "L3DomainToBeConsumedByACS")
+        zone1 = self.create_vsd_zone(domain1, "ZoneToBeConsumedByACS")
+        subnet1 = self.create_vsd_subnet(zone1, "SubnetToBeConsumedByACS",
+                                         "10.0.0.1/24")
+
+        domain2 = self.create_vsd_domain(domain_template, enterprise,
+                                         "2ndL3DomainToBeConsumedByACS")
+        zone2 = self.create_vsd_zone(domain2, "2ndZoneToBeConsumedByACS")
+        subnet2 = self.create_vsd_subnet(zone2, "2ndSubnetToBeConsumedByACS",
+                                         "10.1.0.1/24")
+
+        domain3 = self.create_vsd_domain(domain_template, enterprise,
+                                         "3rdL3DomainToBeConsumedByACS")
+        zone3 = self.create_vsd_zone(domain3, "3rdZoneToBeConsumedByACS")
+        subnet3 = self.create_vsd_subnet(zone3, "3rdSubnetToBeConsumedByACS",
+                                         "10.2.0.1/24")
+
+        # On ACS create network using non-persistent nw offering allow
+        isolated_network = self.create_Network(
+                self.nuage_isolated_network_offering,
+                gateway="10.0.0.1", netmask="255.255.255.0",
+                externalid=subnet1.id)
+
+        # On ACS create network using persistent nw offering allow
+        isolated_network2 = self.create_Network(
+                self.nuage_isolated_network_offering_persistent,
+                gateway="10.1.0.1", netmask="255.255.255.0",
+                externalid=subnet2.id)
+
+        try:
+            self.create_Network(
+                self.nuage_shared_network_offering, gateway="10.2.0.1",
+                netmask="255.255.255.0", vlan=1201, externalid=subnet3.id)
+        except Exception as e:
+            self.debug("Shared Network Creation fails with %s" % e)
+
+        # verify floating ip and intra subnet connectivity
+        vm_1 = self.create_VM(isolated_network)
+        vm_2 = self.create_VM(isolated_network)
+        self.debug("Creating Static NAT rule for the deployed VM in the "
+                   "non persistently created Isolated network...")
+        public_ip = self.acquire_PublicIPAddress(isolated_network)
+        self.validate_PublicIPAddress(public_ip, isolated_network)
+        self.create_StaticNatRule_For_VM(vm_1, public_ip, isolated_network)
+        self.validate_PublicIPAddress(
+                public_ip, isolated_network, static_nat=True, vm=vm_1)
+        self.create_FirewallRule(public_ip, self.test_data["ingress_rule"])
+
+        if not self.isSimulator:
+            vm_public_ip = public_ip.ipaddress.ipaddress
+            try:
+                vm_1.ssh_ip = vm_public_ip
+                vm_1.ssh_port = self.test_data["virtual_machine"]["ssh_port"]
+                vm_1.username = self.test_data["virtual_machine"]["username"]
+                vm_1.password = self.test_data["virtual_machine"]["password"]
+                self.debug("SSHing into VM: %s with %s" %
+                           (vm_1.ssh_ip, vm_1.password))
+
+                ssh = vm_1.get_ssh_client(ipaddress=vm_public_ip)
+
+            except Exception as e:
+                self.fail("SSH into VM failed with exception %s" % e)
+
+            self.verify_pingtovmipaddress(ssh, vm_2.ipaddress)
+
+        vm_3 = self.create_VM(isolated_network2)
+        vm_4 = self.create_VM(isolated_network2)
+        self.debug("Creating Static NAT rule for the deployed VM in the "
+                   "persistently created Isolated network...")
+        public_ip2 = self.acquire_PublicIPAddress(isolated_network2)
+        self.validate_PublicIPAddress(public_ip2, isolated_network2)
+        self.create_StaticNatRule_For_VM(vm_3, public_ip2, isolated_network2)
+        self.validate_PublicIPAddress(
+                public_ip2, isolated_network2, static_nat=True, vm=vm_3)
+        self.create_FirewallRule(public_ip2, self.test_data["ingress_rule"])
+
+        if not self.isSimulator:
+            vm_public_ip2 = public_ip2.ipaddress.ipaddress
+            try:
+                vm_3.ssh_ip = vm_public_ip2
+                vm_3.ssh_port = self.test_data["virtual_machine"]["ssh_port"]
+                vm_3.username = self.test_data["virtual_machine"]["username"]
+                vm_3.password = self.test_data["virtual_machine"]["password"]
+                self.debug("SSHing into VM: %s with %s" %
+                           (vm_3.ssh_ip, vm_3.password))
+
+                ssh2 = vm_3.get_ssh_client(ipaddress=vm_public_ip2)
+
+            except Exception as e:
+                self.fail("SSH into VM failed with exception %s" % e)
+
+            self.verify_pingtovmipaddress(ssh2, vm_4.ipaddress)
+
+    @attr(tags=["advanced", "nuagevsp", "vpc"], required_hardware="false")
+    def test_02_nuage_mngd_subnets_vpc(self):
+        """Test Nuage VSP Managed Subnets for vpc and tier networks
+        """
+
+        # 1. Create multiple L3DomainTemplate with Zone and Subnet on VSP
+        #    Create Ingress & Egress ACL Top & Bottom Templates
+        #    Add ACL rules to allow intra-subnet traffic
+        #    Instiantiate these L3Domains and store its Subnet VSD ID
+        # 2. Create a vpc network offering and create a VPC
+        #    create vpc tier network offerings with and without VirtualRouter
+        # 3. Create vpc tier networks specifying above offerings and
+        #    specifying the stored Subnet ID's of VSP
+        # 4. Verify ACL rules and connectivity via deploying VM's ,
+        #    Enabling staticNAT, applying firewall and egress rules
+
+        # Create all items on vsd required for this test
+        enterprise = self.fetch_by_externalID(self._session.user.enterprises,
+                                              self.domain)
+        domain_template = self.create_vsd_domain_template(enterprise)
+
+        self.create_vsd_default_acls(domain_template)
+
+        domain1 = self.create_vsd_domain(domain_template, enterprise,
+                                         "L3DomainToBeConsumedByACS")
+        zone1 = self.create_vsd_zone(domain1, "ZoneToBeConsumedByACS")
+        subnet1 = self.create_vsd_subnet(zone1, "SubnetToBeConsumedByACS",
+                                         "10.1.0.1/24")
+        subnet2 = self.create_vsd_subnet(zone1, "2ndSubnetToBeConsumedByACS",
+                                         "10.1.128.1/24")
+
+        cmd = updateZone.updateZoneCmd()
+        cmd.id = self.zone.id
+        cmd.domain = "vpc.com"
+        self.api_client.updateZone(cmd)
+        self.debug("Creating a VPC with Static NAT service provider as "
+                   "VpcVirtualRouter")
+        vpc = self.create_Vpc(self.nuage_vpc_offering, cidr='10.1.0.0/16')
+        self.validate_Vpc(vpc, state="Enabled")
+        acl_list = self.create_NetworkAclList(
+                name="acl", description="acl", vpc=vpc)
+        self.create_NetworkAclRule(
+                self.test_data["ingress_rule"], acl_list=acl_list)
+        self.create_NetworkAclRule(
+                self.test_data["icmprule"], acl_list=acl_list)
+        self.debug("Creating a VPC tier network with Static NAT service")
+        vpc_tier = self.create_Network(self.nuage_vpc_network_offering,
+                                       gateway='10.1.0.1',
+                                       vpc=vpc,
+                                       acl_list=acl_list,
+                                       externalid=subnet1.id)
+        self.validate_Network(vpc_tier, state="Implemented")
+        self.debug("Creating 2nd VPC tier network with Static NAT service")
+        vpc_2ndtier = self.create_Network(self.nuage_vpc_network_offering,
+                                          gateway='10.1.128.1',
+                                          vpc=vpc,
+                                          acl_list=acl_list,
+                                          externalid=subnet2.id)
+        self.validate_Network(vpc_2ndtier, state="Implemented")
+        vpc_vr = self.get_Router(vpc_tier)
+        self.check_Router_state(vpc_vr, state="Running")
+
+        self.debug("Deploying a VM in the created VPC tier network")
+        self.test_data["virtual_machine"]["displayname"] = "vpcvm1"
+        self.test_data["virtual_machine"]["name"] = "vpcvm1"
+        vpc_vm_1 = self.create_VM(vpc_tier)
+        self.check_VM_state(vpc_vm_1, state="Running")
+        self.debug("Deploying another VM in the created VPC tier network")
+        self.test_data["virtual_machine"]["displayname"] = "vpcvm2"
+        self.test_data["virtual_machine"]["name"] = "vpcvm2"
+        vpc_vm_2 = self.create_VM(vpc_tier)
+        self.check_VM_state(vpc_vm_2, state="Running")
+        self.debug("Deploying a VM in the 2nd VPC tier network")
+        self.test_data["virtual_machine"]["displayname"] = "vpcvm12"
+        self.test_data["virtual_machine"]["name"] = "vpcvm12"
+        vpc_vm_12 = self.create_VM(vpc_2ndtier)
+        self.check_VM_state(vpc_vm_2, state="Running")
+        self.test_data["virtual_machine"]["displayname"] = None
+        self.test_data["virtual_machine"]["name"] = None
+        self.debug("Creating Static NAT rule for the deployed VM "
+                   "in the created VPC network...")
+        public_ip_1 = self.acquire_PublicIPAddress(vpc_tier, vpc=vpc)
+        self.validate_PublicIPAddress(public_ip_1, vpc_tier)
+        self.create_StaticNatRule_For_VM(vpc_vm_1, public_ip_1, vpc_tier)
+        self.validate_PublicIPAddress(
+                public_ip_1, vpc_tier, static_nat=True, vm=vpc_vm_1)
+
+        if not self.isSimulator:
+            vm_public_ip_1 = public_ip_1.ipaddress.ipaddress
+            try:
+                vpc_vm_1.ssh_ip = vm_public_ip_1
+                vpc_vm_1.ssh_port = \
+                    self.test_data["virtual_machine"]["ssh_port"]
+                vpc_vm_1.username = \
+                    self.test_data["virtual_machine"]["username"]
+                vpc_vm_1.password = \
+                    self.test_data["virtual_machine"]["password"]
+                self.debug("SSHing into VM: %s with %s" %
+                           (vpc_vm_1.ssh_ip, vpc_vm_1.password))
+
+                ssh = vpc_vm_1.get_ssh_client(ipaddress=vm_public_ip_1)
+
+            except Exception as e:
+                self.fail("SSH into VM failed with exception %s" % e)
+
+            self.verify_pingtovmipaddress(ssh, vpc_vm_2.ipaddress)
+            self.verify_pingtovmipaddress(ssh, vpc_vm_12.ipaddress)
+
+    def create_vsd_ingress_acl_template(self, domain_template, priority_type="TOP"):
+        name = "Ingress ACL " + str(priority_type).capitalize()
+        acl_template = self.vsdk.NUIngressACLTemplate()
+        acl_template.name = name
+        acl_template.description = name
+        acl_template.priority_type = priority_type
+        acl_template.active = True
+        (acl_template, connection) = \
+            domain_template.create_child(acl_template)
+        return acl_template
+
+    def create_vsd_egress_acl_template(self, domain_template, priority_type='TOP'):
+        name = "Egress ACL " + str(priority_type).capitalize()
+        acl_template = self.vsdk.NUEgressACLTemplate()
+        acl_template.name = name
+        acl_template.description = name
+        acl_template.priority_type = priority_type
+        acl_template.active = True
+        (acl_template, connection) = \
+            domain_template.create_child(acl_template)
+        return acl_template
+
+    def create_vsd_domain_template(self, enterprise):
+        domain_template = self.vsdk.NUDomainTemplate()
+        domain_template.name = "L3DomainTemplateToBeConsumedByACS"
+        domain_template.description = "L3DomainTemplateToBeConsumedByACS"
+        domain_template.external_id = "L3DomainTemplateToBeConsumedByACS@" \
+                                      + str(self.cms_id)
+        (domain_template, connection) = \
+            enterprise.create_child(domain_template)
+        return domain_template
+
+    def create_vsd_default_acls(self, domain_template):
+        ingress_vsd_acl_template1 = self.create_vsd_ingress_acl_template(
+            domain_template, "TOP")
+        ingress_vsd_acl_template2 = self.create_vsd_ingress_acl_template(
+            domain_template, "BOTTOM")
+        ingress_vsd_acl_entry1 = self.vsdk.NUIngressACLEntryTemplate()
+        ingress_vsd_acl_entry1.name = "Default Intra-Subnet Allow"
+        ingress_vsd_acl_entry1.description = "Default Intra-Subnet Allow"
+        ingress_vsd_acl_entry1.external_id = "ToBeConsumedByACS@" \
+                                             + str(self.cms_id)
+        ingress_vsd_acl_entry1.priority = '1'
+        ingress_vsd_acl_entry1.protocol = 'ANY'
+        ingress_vsd_acl_template1.create_child(ingress_vsd_acl_entry1)
+
+        ingress_vsd_acl_entry2 = self.vsdk.NUIngressACLEntryTemplate()
+        ingress_vsd_acl_entry2.name = "Default Allow TCP"
+        ingress_vsd_acl_entry2.description = "Default Allow TCP"
+        ingress_vsd_acl_entry2.external_id = "ToBeConsumedByACS@" \
+                                             + str(self.cms_id)
+        ingress_vsd_acl_entry2.priority = '1'
+        ingress_vsd_acl_entry2.protocol = '6'
+        ingress_vsd_acl_entry2.source_port = '*'
+        ingress_vsd_acl_entry2.destination_port = '*'
+        ingress_vsd_acl_template2.create_child(ingress_vsd_acl_entry2)
+
+        ingress_vsd_acl_entry3 = self.vsdk.NUIngressACLEntryTemplate()
+        ingress_vsd_acl_entry3.name = "Default Allow UDP"
+        ingress_vsd_acl_entry3.description = "Default Allow UDP"
+        ingress_vsd_acl_entry3.external_id = "ToBeConsumedByACS@" \
+                                             + str(self.cms_id)
+        ingress_vsd_acl_entry3.priority = '2'
+        ingress_vsd_acl_entry3.protocol = '17'
+        ingress_vsd_acl_entry3.source_port = '*'
+        ingress_vsd_acl_entry3.destination_port = '*'
+        ingress_vsd_acl_template2.create_child(ingress_vsd_acl_entry3)
+        ingress_vsd_acl_entry4 = self.vsdk.NUIngressACLEntryTemplate()
+        ingress_vsd_acl_entry4.name = "Default Allow ICMP"
+        ingress_vsd_acl_entry4.description = "Default Allow ICMP"
+        ingress_vsd_acl_entry4.external_id = "ToBeConsumedByACS@" \
+                                             + str(self.cms_id)
+        ingress_vsd_acl_entry4.priority = '3'
+        ingress_vsd_acl_entry4.protocol = '1'
+        ingress_vsd_acl_template2.create_child(ingress_vsd_acl_entry4)
+
+        egress_vsd_acl_template1 = self.create_vsd_egress_acl_template(
+            domain_template, 'TOP')
+
+        egress_vsd_acl_template2 = self.create_vsd_egress_acl_template(
+            domain_template, 'BOTTOM')
+
+        egress_vsd_acl_entry1 = self.vsdk.NUEgressACLEntryTemplate()
+        egress_vsd_acl_entry1.name = "Default Intra-Subnet Allow"
+        egress_vsd_acl_entry1.description = "Default Intra-Subnet Allow"
+        egress_vsd_acl_entry1.external_id = "ToBeConsumedByACS@" \
+                                            + str(self.cms_id)
+        egress_vsd_acl_entry1.priority = '1'
+        egress_vsd_acl_entry1.protocol = 'ANY'
+        egress_vsd_acl_template1.create_child(egress_vsd_acl_entry1)
+        egress_vsd_acl_entry2 = self.vsdk.NUEgressACLEntryTemplate()
+        egress_vsd_acl_entry2.name = "Default Allow ICMP"
+        egress_vsd_acl_entry2.description = "Default Allow ICMP"
+        egress_vsd_acl_entry2.external_id = "ToBeConsumedByACS@" \
+                                            + str(self.cms_id)
+        egress_vsd_acl_entry2.priority = '3'
+        egress_vsd_acl_entry2.protocol = '1'
+        egress_vsd_acl_template2.create_child(egress_vsd_acl_entry2)
+
+    def create_vsd_domain(self, domain_template, enterprise, name):
+        domain = self.vsdk.NUDomain()
+        domain.name = name
+        domain.description = name
+        domain.external_id = name + "@" + str(self.cms_id)
+        (domain, connection) = \
+            enterprise.instantiate_child(domain, domain_template)
+        return domain
+
+    def create_vsd_zone(self, domain, name):
+        zone = self.vsdk.NUZone()
+        zone.name = name
+        zone.description = name
+        zone.external_id = name + "@" + str(self.cms_id)
+        (zone, connection) = domain.create_child(zone)
+        return zone
+
+    def create_vsd_subnet(self, zone, name, cidr):
+        subnet = self.vsdk.NUSubnet()
+        subnet.name = name
+        subnet.description = name
+        subnet.external_id = name + "@" + str(self.cms_id)
+        (subnet.gateway, subnet.netmask, subnet.address) = \
+            self._cidr_to_netmask(cidr)
+        (subnet, connection) = zone.create_child(subnet)
+        return subnet
+
+    def _cidr_to_netmask(self, cidr):
+        import socket
+        import struct
+        network, net_bits = cidr.split('/')
+        host_bits = 32 - int(net_bits)
+        netmask_bits = (1 << 32) - (1 << host_bits)
+        netmask = socket.inet_ntoa(struct.pack('!I', netmask_bits))
+        network_bits = struct.unpack('!I', socket.inet_aton(network))[0]
+        network_masked = socket.inet_ntoa(
+            struct.pack('!I', netmask_bits & network_bits)
+        )
+        return network, netmask, network_masked
diff --git a/tools/marvin/marvin/config/test_data.py b/tools/marvin/marvin/config/test_data.py
index 9f8e6a95f87..64733f7e179 100644
--- a/tools/marvin/marvin/config/test_data.py
+++ b/tools/marvin/marvin/config/test_data.py
@@ -2011,6 +2011,70 @@
                 "SourceNat": {"SupportedSourceNatTypes": "perzone"}
             }
         },
+        # Persistent services supported by the Nuage VSP plugin for Isolated networks
+        "isolated_network_offering_persistent": {
+            "name": 'nuage_marvin',
+            "displaytext": 'nuage_marvin',
+            "guestiptype": 'Isolated',
+            "supportedservices": 'Dhcp,SourceNat,Connectivity,StaticNat,UserData,Firewall,Dns',
+            "traffictype": 'GUEST',
+            "availability": 'Optional',
+            "ispersistent": 'True',
+            "tags": "nuage",
+            "serviceProviderList": {
+                "Dhcp": 'NuageVsp',
+                "StaticNat": 'NuageVsp',
+                "SourceNat": 'NuageVsp',
+                "Firewall": 'NuageVsp',
+                "Connectivity": 'NuageVsp',
+                "UserData": 'VirtualRouter',
+                "Dns": 'VirtualRouter'
+            },
+            "serviceCapabilityList": {
+                "SourceNat": {"SupportedSourceNatTypes": "perzone"}
+            }
+        },
+        # Purely nuage network offering
+        "isolated_network_offering_without_vr": {
+            "name": 'nuage_marvin',
+            "displaytext": 'nuage_marvin',
+            "guestiptype": 'Isolated',
+            "supportedservices": 'Dhcp,SourceNat,Connectivity,StaticNat,Firewall',
+            "traffictype": 'GUEST',
+            "availabiliy": 'Optional',
+            "tags": "nuage",
+            "serviceProviderList": {
+                "Dhcp": 'NuageVsp',
+                "StaticNat": 'NuageVsp',
+                "SourceNat": 'NuageVsp',
+                "Firewall": 'NuageVsp',
+                "Connectivity": 'NuageVsp'
+            },
+            "serviceCapabilityList": {
+                "SourceNat": {"SupportedSourceNatTypes": "perzone"}
+            }
+        },
+        # Purely persistent nuage network offering
+        "isolated_network_offering_without_vr_persistent": {
+            "name": 'nuage_marvin',
+            "displaytext": 'nuage_marvin',
+            "guestiptype": 'Isolated',
+            "supportedservices": 'Dhcp,SourceNat,Connectivity,StaticNat,Firewall',
+            "traffictype": 'GUEST',
+            "availability": 'Optional',
+            "tags": "nuage",
+            "ispersistent": 'True',
+            "serviceProviderList": {
+                "Dhcp": 'NuageVsp',
+                "StaticNat": 'NuageVsp',
+                "SourceNat": 'NuageVsp',
+                "Firewall": 'NuageVsp',
+                "Connectivity": 'NuageVsp'
+            },
+            "serviceCapabilityList": {
+                "SourceNat": {"SupportedSourceNatTypes": "perzone"}
+            }
+        },
         # Purely nuage network offering
         "isolated_network_offering_without_vr": {
             "name": 'nuage_marvin',
diff --git a/tools/marvin/marvin/lib/base.py b/tools/marvin/marvin/lib/base.py
index bd00237df17..4154e91cba2 100755
--- a/tools/marvin/marvin/lib/base.py
+++ b/tools/marvin/marvin/lib/base.py
@@ -2910,7 +2910,8 @@ def __init__(self, items):
     def create(cls, apiclient, services, accountid=None, domainid=None,
                networkofferingid=None, projectid=None,
                subdomainaccess=None, zoneid=None,
-               gateway=None, netmask=None, vpcid=None, aclid=None, vlan=None):
+               gateway=None, netmask=None, vpcid=None, aclid=None, vlan=None,
+               externalid=None):
         """Create Network for account"""
         cmd = createNetwork.createNetworkCmd()
         cmd.name = services["name"]
@@ -2958,6 +2959,8 @@ def create(cls, apiclient, services, accountid=None, domainid=None,
             cmd.vpcid = vpcid
         if aclid:
             cmd.aclid = aclid
+        if externalid:
+            cmd.externalid = externalid
         return Network(apiclient.createNetwork(cmd).__dict__)
 
     def delete(self, apiclient):
diff --git a/ui/l10n/en.js b/ui/l10n/en.js
index e3b0064b060..afd95006345 100644
--- a/ui/l10n/en.js
+++ b/ui/l10n/en.js
@@ -807,6 +807,7 @@ var dictionary = {"ICMP.code":"ICMP Code",
 "label.guest":"Guest",
 "label.guest.cidr":"Guest CIDR",
 "label.guest.end.ip":"Guest end IP",
+"label.guest.externalId":"External Id",
 "label.guest.gateway":"Guest Gateway",
 "label.guest.ip":"Guest IP Address",
 "label.guest.ip.range":"Guest IP Range",
diff --git a/ui/scripts/docs.js b/ui/scripts/docs.js
index 2908e8b5f64..a8ab405d754 100755
--- a/ui/scripts/docs.js
+++ b/ui/scripts/docs.js
@@ -395,6 +395,10 @@ cloudStack.docs = {
         desc: 'If you want to assign a special domain name to this domain\'s guest VM network, specify the DNS suffix',
         externalLink: ''
     },
+    helpDomainId: {
+        desc: 'A valid domain id. CloudStack will generate one for you if empty.',
+        externalLink: ''
+    },
     // Add F5
     helpF5IPAddress: {
         desc: 'The IP address of the device',
diff --git a/ui/scripts/domains.js b/ui/scripts/domains.js
index 04f523c2378..704195e08a9 100644
--- a/ui/scripts/domains.js
+++ b/ui/scripts/domains.js
@@ -269,6 +269,12 @@
                                 });
                             }
 
+                            if (args.data.domainid != null && args.data.domainid.length > 0) {
+                                $.extend(data, {
+                                    domainid: args.data.domainid
+                                });
+                            }
+
                             $.ajax({
                                 url: createURL('createDomain'),
                                 data: data,
@@ -308,7 +314,14 @@
                                     validation: {
                                         required: false
                                     }
-                                }
+                                },
+                                domainid: {
+                                    label: 'label.domain.id',
+                                    docID: 'helpDomainId',
+                                    validation: {
+                                        required: false
+                                        }
+                                    }
                             }
                         }
                     },
diff --git a/ui/scripts/network.js b/ui/scripts/network.js
index 7dd459dc915..7b9f75e7fda 100644
--- a/ui/scripts/network.js
+++ b/ui/scripts/network.js
@@ -657,7 +657,9 @@
                                             }
                                         }
                                     },
-
+                                    externalId: {
+                                        label: 'label.guest.externalId'
+                                    },
                                     guestGateway: {
                                         label: 'label.guest.gateway',
                                         docID: 'helpGuestNetworkGateway'
@@ -744,9 +746,14 @@
                                         gateway: args.data.guestGateway
                                     });
                                 }
-                                if (args.data.guestNetmask != null && args.data.guestNetmask.length > 0) {
+                                if (args.data.guestGateway != null && args.data.guestGateway.length > 0) {
+                                    $.extend(dataObj, {
+                                        gateway: args.data.guestGateway
+                                    });
+                                }
+                                if (args.data.externalId != null && args.data.externalId.length > 0) {
                                     $.extend(dataObj, {
-                                        netmask: args.data.guestNetmask
+                                        externalid: args.data.externalId
                                     });
                                 }
                                 if (args.$form.find('.form-item[rel=vpcid]').css("display") != "none") {
diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js
index 8416d38fd7d..14e41af2b23 100644
--- a/ui/scripts/vpc.js
+++ b/ui/scripts/vpc.js
@@ -3948,7 +3948,9 @@
                                     required: true
                                 }
                             },
-
+                            externalId: {
+                            label: 'label.guest.externalId'
+                            },
                             aclid: {
                                 label: 'label.acl',
                                 select: function(args) {
@@ -4040,11 +4042,17 @@
                                 zoneId: args.context.vpc[0].zoneid
                         });
 
+                        if (args.data.externalId != null && args.data.externalId.length > 0) {
+                            $.extend(dataObj, {
+                                externalid: args.data.externalId
+                            });
+                        }
 
-                        if (args.data.aclid != '')
+                        if (args.data.aclid != '') {
                             $.extend(dataObj, {
                                 aclid: args.data.aclid
                             });
+                        }
 
                         if (args.$form.find('.form-item[rel=vlan]').is(':visible')) {
                             $.extend(dataObj, {


 

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