You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ro...@apache.org on 2017/12/28 09:25:19 UTC

[cloudstack] branch master updated: CLOUDSTACK-10189: Adding nuage VSD managed network support to CloudStack (#2360)

This is an automated email from the ASF dual-hosted git repository.

rohit pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/master by this push:
     new 26759d1  CLOUDSTACK-10189: Adding nuage VSD managed network support to CloudStack (#2360)
26759d1 is described below

commit 26759d1d139b52b8adfd8adba7809e32091423b5
Author: Sigert Goeminne <si...@gmail.com>
AuthorDate: Thu Dec 28 10:25:15 2017 +0100

    CLOUDSTACK-10189: Adding nuage VSD managed network support to CloudStack (#2360)
    
    Exposing externalId en domainId field in the UI to CS users.
    
    Co-Authored-By: Sigert Goeminne sigert.goeminne@nuagenetworks.net
    Co-Authored-By: Raf Smeets raf.smeets@nuagenetworks.net
---
 api/src/com/cloud/network/Network.java             |   2 +
 api/src/com/cloud/network/NetworkProfile.java      |   7 +
 .../org/apache/cloudstack/api/ApiConstants.java    |   2 +
 .../api/command/user/network/CreateNetworkCmd.java |   9 +-
 .../cloudstack/api/response/NetworkResponse.java   |   8 +
 .../service/NetworkOrchestrationService.java       |   2 +-
 .../src/com/cloud/network/vpc/VpcManager.java      |   2 +-
 .../engine/orchestration/NetworkOrchestrator.java  |  17 +-
 .../resources/META-INF/db/schema-41000to41100.sql  |   3 +
 .../src/com/cloud/network/dao/NetworkVO.java       |  14 +-
 plugins/network-elements/nuage-vsp/pom.xml         |   2 +-
 .../agent/api/element/ShutDownVpcVspCommand.java   |  16 +-
 .../agent/api/guru/ImplementNetworkVspCommand.java |   8 +-
 .../api/manager/ImplementNetworkVspAnswer.java     |  10 +-
 .../com/cloud/network/element/NuageVspElement.java |   5 +-
 .../network/guru/NuageVspGuestNetworkGuru.java     | 156 +++++--
 .../com/cloud/network/manager/NuageVspManager.java |  11 +-
 .../cloud/network/resource/NuageVspResource.java   |  10 +
 ...java => NuageVspCheckHealthCommandWrapper.java} |  19 +-
 .../resource/wrapper/NuageVspCommandWrapper.java   |   2 +-
 ...NuageVspGuruImplementNetworkCommandWrapper.java |  15 +-
 .../wrapper/NuageVspShutdownVpcCommandWrapper.java |   2 +-
 .../src/com/cloud/util/NuageVspEntityBuilder.java  |  69 +--
 .../nuage-vsp/test/com/cloud/NuageTest.java        |   1 -
 .../network/guru/NuageVspGuestNetworkGuruTest.java |  14 +-
 .../network/resource/NuageVspResourceTest.java     |  18 +-
 server/src/com/cloud/api/ApiResponseHelper.java    |   1 +
 .../com/cloud/network/IpAddressManagerImpl.java    |   2 +-
 .../src/com/cloud/network/NetworkServiceImpl.java  |  13 +-
 .../src/com/cloud/network/vpc/VpcManagerImpl.java  |   9 +-
 server/src/com/cloud/vm/UserVmManagerImpl.java     |   8 +-
 .../cloud/network/CreatePrivateNetworkTest.java    |   4 +-
 .../test/com/cloud/vpc/MockNetworkManagerImpl.java |   2 +-
 test/integration/plugins/nuagevsp/nuageTestCase.py |   3 +-
 .../nuagevsp/test_nuage_vsp_mngd_subnets.py        | 512 +++++++++++++++++++++
 tools/marvin/marvin/config/test_data.py            |  64 +++
 tools/marvin/marvin/lib/base.py                    |   5 +-
 ui/l10n/en.js                                      |   1 +
 ui/scripts/docs.js                                 |   4 +
 ui/scripts/domains.js                              |  15 +-
 ui/scripts/network.js                              |  13 +-
 ui/scripts/vpc.js                                  |  12 +-
 42 files changed, 971 insertions(+), 121 deletions(-)

diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java
index 95833d8..8b402bc 100644
--- a/api/src/com/cloud/network/Network.java
+++ b/api/src/com/cloud/network/Network.java
@@ -390,4 +390,6 @@ public interface Network extends ControlledEntity, StateObject<Network.State>, I
     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 ab033ed..127750a 100644
--- a/api/src/com/cloud/network/NetworkProfile.java
+++ b/api/src/com/cloud/network/NetworkProfile.java
@@ -57,6 +57,7 @@ public class NetworkProfile implements Network {
     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 class NetworkProfile implements Network {
         guruName = network.getGuruName();
         strechedL2Subnet = network.isStrechedL2Network();
         isRedundant = network.isRedundant();
+        externalId = network.getExternalId();
     }
 
     public String getDns1() {
@@ -300,4 +302,9 @@ public class NetworkProfile implements Network {
         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 55e8c28..24099c4 100644
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -654,6 +654,7 @@ public class ApiConstants {
     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 class ApiConstants {
     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 1731261..befef99 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.exception.ResourceAllocationException;
 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 @@ public class CreateNetworkCmd extends BaseCmd {
     @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 class CreateNetworkCmd extends BaseCmd {
         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 40c9072..f54b063 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 @@ public class NetworkResponse extends BaseResponse implements ControlledEntityRes
     @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 class NetworkResponse extends BaseResponse implements ControlledEntityRes
     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 86a8fe9..67471d0 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 @@ public interface NetworkOrchestrationService {
 
     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 28ad052..db4221f 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 @@ public interface VpcManager {
     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 d5b0244..9afd642 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 java.util.stream.Collectors;
 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.MessageBus;
 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.vm.DomainRouterVO;
 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 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
                     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 class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
     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 class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
                     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 3dbe5c3..19c9039 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 f871788..320256b 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 @@ public class NetworkVO implements Network {
     @Column(name = "streched_l2")
     boolean strechedL2Network = false;
 
+    @Column(name = "external_id")
+    String externalId;
+
     @Transient
     transient String vlanIdAsUUID;
 
@@ -216,7 +219,7 @@ public class NetworkVO implements Network {
     }
 
     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 class NetworkVO implements Network {
         uuid = UUID.randomUUID().toString();
         ip6Gateway = that.getIp6Gateway();
         ip6Cidr = that.getIp6Cidr();
+        this.externalId = externalId;
     }
 
     /**
@@ -638,4 +642,12 @@ public class NetworkVO implements Network {
     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 bea8cb9..7e0b1ef 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 77b22bc..6c98238 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 @@ public class ShutDownVpcVspCommand extends Command {
     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 class ShutDownVpcVspCommand extends Command {
         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 5dc4ba7..2f2d5fd 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 @@ public class ImplementNetworkVspCommand extends Command {
 
     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 class ImplementNetworkVspCommand extends Command {
                 .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 03ab183..8cfb715 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 @@ import com.cloud.agent.api.guru.ImplementNetworkVspCommand;
 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 class ImplementNetworkVspAnswer extends Answer {
     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 e91901a..26fdaac 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 class NuageVspElement extends AdapterBase implements ConnectivityProvider
         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 class NuageVspElement extends AdapterBase implements ConnectivityProvider
                 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 class NuageVspElement extends AdapterBase implements ConnectivityProvider
                                   .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 f43e350..a36bc0a 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.agent.api.manager.ImplementNetworkVspAnswer;
 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.InsufficientAddressCapacityException;
 import com.cloud.exception.InsufficientVirtualNetworkCapacityException;
 import com.cloud.exception.UnsupportedServiceException;
 import com.cloud.host.HostVO;
-import com.cloud.host.dao.HostDao;
 import com.cloud.network.Network;
 import com.cloud.network.Network.GuestType;
 import com.cloud.network.Network.State;
@@ -76,13 +77,10 @@ import com.cloud.network.Networks;
 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.user.dao.AccountDao;
 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.VirtualMachine;
 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 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
     @Inject
     AccountDao _accountDao;
     @Inject
-    NuageVspDao _nuageVspDao;
-    @Inject
-    HostDao _hostDao;
-    @Inject
-    VpcDao _vpcDao;
-    @Inject
     VMInstanceDao _vmInstanceDao;
     @Inject
     AgentManager _agentMgr;
@@ -135,6 +128,8 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
     VpcDetailsDao _vpcDetailsDao;
     @Inject
     NetworkOrchestrationService _networkOrchestrationService;
+    @Inject
+    DataCenterDetailsDao _dcDetailsDao;
 
     public NuageVspGuestNetworkGuru() {
         super();
@@ -158,11 +153,91 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
         }
 
         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();
         network = _networkDao.acquireInLockTable(network.getId(), 1200);
@@ -213,7 +288,7 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
 
             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 class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
             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 class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
 
             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 class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
         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 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
             }
             return false;
         }
-        saveNetworkAndVpcDetails(vspNetwork, answer.getNetworkRelatedVsdIds(), vpcId);
+
+        ImplementNetworkVspAnswer implementAnswer = (ImplementNetworkVspAnswer) answer;
+        saveNetworkAndVpcDetails(vspNetwork, implementAnswer.getNetworkRelatedVsdIds(), vpcId);
         return true;
     }
 
@@ -274,23 +358,31 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
             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 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
 
         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 class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
 
             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 class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
 
                 // 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 class NuageVspGuestNetworkGuru extends GuestNetworkGuru {
             }
 
             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 056b22e..6f91dc3 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.Network;
 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 @@ public interface NuageVspManager extends PluggableService {
 
     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 502b4bd..a96b670 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 class NuageVspResource extends ManagerBase implements ServerResource, Vsp
         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/NuageVspShutdownVpcCommandWrapper.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/vsp/resource/wrapper/NuageVspCheckHealthCommandWrapper.java
similarity index 58%
copy from plugins/network-elements/nuage-vsp/src/com/cloud/network/vsp/resource/wrapper/NuageVspShutdownVpcCommandWrapper.java
copy to plugins/network-elements/nuage-vsp/src/com/cloud/network/vsp/resource/wrapper/NuageVspCheckHealthCommandWrapper.java
index d2d9ea7..d66fc1b 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/NuageVspCheckHealthCommandWrapper.java
@@ -23,20 +23,21 @@ import javax.naming.ConfigurationException;
 
 import net.nuage.vsp.acs.client.exception.NuageVspException;
 
-import com.cloud.agent.api.element.ShutDownVpcVspCommand;
+import com.cloud.agent.api.CheckHealthCommand;
 import com.cloud.network.resource.NuageVspResource;
 import com.cloud.resource.ResourceWrapper;
 
-@ResourceWrapper(handles =  ShutDownVpcVspCommand.class)
-public final class NuageVspShutdownVpcCommandWrapper extends NuageVspCommandWrapper<ShutDownVpcVspCommand> {
+@ResourceWrapper(handles = CheckHealthCommand.class)
+public class NuageVspCheckHealthCommandWrapper extends NuageVspCommandWrapper<CheckHealthCommand> {
 
-    @Override public boolean executeNuageVspCommand(ShutDownVpcVspCommand cmd, NuageVspResource nuageVspResource) throws ConfigurationException, NuageVspException {
-        nuageVspResource.getNuageVspElementClient().shutdownVpc(cmd.getDomainUuid(), cmd.getVpcUuid(), cmd.getDomainTemplateName(), cmd.getDomainRouterUuids());
-        return true;
+    @Override
+    public boolean executeNuageVspCommand(CheckHealthCommand cmd, NuageVspResource nuageVspResource) throws ConfigurationException, NuageVspException {
+        return nuageVspResource.getStatus();
     }
 
-    @Override public StringBuilder fillDetail(StringBuilder stringBuilder, ShutDownVpcVspCommand cmd) {
-        return stringBuilder.append("Shutdown VPC " + cmd.getVpcUuid());
+    @Override
+    public StringBuilder fillDetail(StringBuilder stringBuilder, CheckHealthCommand cmd) {
+        return stringBuilder.append("Check Health");
     }
 
-}
\ No newline at end of file
+}
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 879ba81..3e3c4a1 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 abstract class NuageVspCommandWrapper<T extends Command> extends CommandW
         } 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 1e57e24..4d2ef63 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 final class NuageVspGuruImplementNetworkCommandWrapper extends CommandWra
     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 d2d9ea7..a3910cf 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 @@ import com.cloud.resource.ResourceWrapper;
 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 c024a7b..b34337f 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.VspStaticNat;
 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.Iterables;
 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.NicDao;
 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 @@ public class NuageVspEntityBuilder {
     @Inject
     VlanDetailsDao _vlanDetailsDao;
     @Inject
-    ConfigurationDao _configurationDao;
-    @Inject
     IPAddressDao _ipAddressDao;
     @Inject
     NetworkDetailsDao _networkDetailsDao;
@@ -160,18 +157,30 @@ public class NuageVspEntityBuilder {
     }
 
     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 class NuageVspEntityBuilder {
         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 class NuageVspEntityBuilder {
                     .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 class NuageVspEntityBuilder {
 
         }
 
-        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 class NuageVspEntityBuilder {
         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 fea759d..ae383bf 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 @@ public class NuageTest {
         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 d8bdd4b..957408d 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.junit.Test;
 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;
 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 @@ public class NuageVspGuestNetworkGuruTest extends NuageTest {
     @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 class NuageVspGuestNetworkGuruTest extends NuageTest {
         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 class NuageVspGuestNetworkGuruTest extends NuageTest {
         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 fb67e6f..560f53d 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,13 +153,26 @@ public class NuageVspResourceTest extends NuageTest {
 
         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 class NuageVspResourceTest extends NuageTest {
     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 19730d0..c4e337e 100644
--- a/server/src/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/com/cloud/api/ApiResponseHelper.java
@@ -2206,6 +2206,7 @@ public class ApiResponseHelper implements ResponseGenerator {
             }
             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 55e842b..5180958 100644
--- a/server/src/com/cloud/network/IpAddressManagerImpl.java
+++ b/server/src/com/cloud/network/IpAddressManagerImpl.java
@@ -1662,7 +1662,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
                             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 a2b5dc1..81ab2b1 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.AccountGuestVlanMapVO;
 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.NicSecondaryIpDao;
 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 class NetworkServiceImpl extends ManagerBase implements  NetworkService {
         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 class NetworkServiceImpl extends ManagerBase implements  NetworkService {
 
         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 @@ public class NetworkServiceImpl extends ManagerBase implements  NetworkService {
                                   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 class NetworkServiceImpl extends ManagerBase implements  NetworkService {
                             }
                         }
                         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 class NetworkServiceImpl extends ManagerBase implements  NetworkService {
                         }
 
                         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 class NetworkServiceImpl extends ManagerBase implements  NetworkService {
                     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 d1a6fb5..1f0753a 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.annotation.PostConstruct;
 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.context.CallContext;
 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 class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
     @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 class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
 
         // 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 3591e60..c4edf4f 100644
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -3156,7 +3156,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
                     }
                     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 class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
                             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 5b6ead0..2e06039 100644
--- a/server/test/com/cloud/network/CreatePrivateNetworkTest.java
+++ b/server/test/com/cloud/network/CreatePrivateNetworkTest.java
@@ -122,8 +122,8 @@ public class CreatePrivateNetworkTest {
                 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 cdf7180..d68b7c9 100644
--- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
+++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
@@ -638,7 +638,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkOrches
     @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 aaeb97a..45db791 100644
--- a/test/integration/plugins/nuagevsp/nuageTestCase.py
+++ b/test/integration/plugins/nuagevsp/nuageTestCase.py
@@ -387,7 +387,7 @@ class nuageTestCase(cloudstackTestCase):
     @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 @@ class nuageTestCase(cloudstackTestCase):
                                  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 0000000..ebbcccb
--- /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 9f8e6a9..64733f7 100644
--- a/tools/marvin/marvin/config/test_data.py
+++ b/tools/marvin/marvin/config/test_data.py
@@ -2011,6 +2011,70 @@ test_data = {
                 "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 bd00237..4154e91 100755
--- a/tools/marvin/marvin/lib/base.py
+++ b/tools/marvin/marvin/lib/base.py
@@ -2910,7 +2910,8 @@ class Network:
     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 @@ class Network:
             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 e3b0064..afd9500 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 2908e8b..a8ab405 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 04f523c..704195e 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 7dd459d..7b9f75e 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 8416d38..14e41af 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, {

-- 
To stop receiving notification emails like this one, please contact
['"commits@cloudstack.apache.org" <co...@cloudstack.apache.org>'].