You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mu...@apache.org on 2014/03/20 12:35:45 UTC

[3/4] git commit: updated refs/heads/master to 2b51207

region level VPC support

introduce 'RegionLevelVpc' as capability of 'Connectivity' service. Add
support for CreateVPCOffering to take the 'regionlevelvpc' as capability
of service 'connectivity'.

introduces new capability 'StretchedL2Subnet' for 'Connectivity'
service. Also add support to createNetworkOffering api to allow
StretchedL2Subnet capablity for the connectivity service.

adds check to ensure 'Connectivity' service provider supports
'StretchedL2Subnet' and 'RegionLevelVpc' capabilities when specified in
createNetworkOffering and createVpcOffering respectivley

enable ovs plug-in to support both StretchedL2Subnet and RegionLevelVpc
capabilities

make zone id optional parameter in createVpc, zone id can be null only
if vpc offfering supports region level VPC

in region level vpc, let the network/tier to be created in any zone of
the region

keep zoneid as required param for createVpc

skip external guest network guru if 'Connectivy' service is present in
network offering

fix build break in contrail manager

permit VM's to be created in different zone that in which network is
created if the network support streched L2 subnet

add integration tests for region level VPC

rebase to master

Conflicts:
	setup/db/db/schema-430to440.sql

Conflicts:
	api/src/org/apache/cloudstack/api/ApiConstants.java
	engine/schema/src/com/cloud/network/vpc/VpcVO.java
	setup/db/db/schema-430to440.sql


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

Branch: refs/heads/master
Commit: d2d54a946310d25a8edd4cab5abf8588a9e1b4df
Parents: c838f3a
Author: Murali Reddy <mu...@gmail.com>
Authored: Fri Jan 24 11:15:38 2014 +0530
Committer: Murali Reddy <mu...@gmail.com>
Committed: Thu Mar 20 16:32:22 2014 +0530

----------------------------------------------------------------------
 api/src/com/cloud/network/Network.java          |   6 +-
 api/src/com/cloud/network/NetworkProfile.java   |   8 +
 api/src/com/cloud/network/vpc/Vpc.java          |   6 +
 api/src/com/cloud/network/vpc/VpcOffering.java  |   6 +-
 .../network/vpc/VpcProvisioningService.java     |   1 +
 api/src/com/cloud/offering/NetworkOffering.java |   2 +
 .../org/apache/cloudstack/api/ApiConstants.java |   4 +-
 .../api/command/user/vpc/CreateVPCCmd.java      |   2 +-
 .../api/response/NetworkOfferingResponse.java   |   7 +
 .../api/response/VpcOfferingResponse.java       |   8 +
 .../cloudstack/api/response/VpcResponse.java    |   9 +-
 .../src/com/cloud/network/dao/NetworkVO.java    |  12 +
 .../com/cloud/network/vpc/VpcOfferingVO.java    |  11 +-
 .../schema/src/com/cloud/network/vpc/VpcVO.java |  13 +-
 .../com/cloud/offerings/NetworkOfferingVO.java  |  11 +-
 .../com/cloud/network/element/OvsElement.java   |   2 +
 server/src/com/cloud/api/ApiResponseHelper.java |   3 +
 .../configuration/ConfigurationManagerImpl.java |  54 +-
 .../network/guru/ExternalGuestNetworkGuru.java  |   4 +
 .../com/cloud/network/vpc/VpcManagerImpl.java   | 243 ++++++---
 .../cloud/server/ConfigurationServerImpl.java   |   6 +-
 server/src/com/cloud/vm/UserVmManagerImpl.java  |   2 +-
 .../cloud/network/CreatePrivateNetworkTest.java |   2 +-
 .../com/cloud/vpc/MockNetworkManagerImpl.java   |   2 +-
 server/test/com/cloud/vpc/VpcApiUnitTest.java   |   2 +-
 .../test/com/cloud/vpc/dao/MockVpcDaoImpl.java  |   4 +-
 setup/db/db/schema-430to440.sql                 |   6 +-
 test/integration/component/test_region_vpc.py   | 517 +++++++++++++++++++
 28 files changed, 849 insertions(+), 104 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/api/src/com/cloud/network/Network.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java
index 3283a55..ef3bcdf 100644
--- a/api/src/com/cloud/network/Network.java
+++ b/api/src/com/cloud/network/Network.java
@@ -57,7 +57,7 @@ public interface Network extends ControlledEntity, StateObject<Network.State>, I
         public static final Service PortForwarding = new Service("PortForwarding");
         public static final Service SecurityGroup = new Service("SecurityGroup");
         public static final Service NetworkACL = new Service("NetworkACL", Capability.SupportedProtocols);
-        public static final Service Connectivity = new Service("Connectivity", Capability.DistributedRouter);
+        public static final Service Connectivity = new Service("Connectivity", Capability.DistributedRouter, Capability.RegionLevelVpc, Capability.StretchedL2Subnet);
 
         private final String name;
         private final Capability[] caps;
@@ -187,6 +187,8 @@ public interface Network extends ControlledEntity, StateObject<Network.State>, I
         public static final Capability LbSchemes = new Capability("LbSchemes");
         public static final Capability DhcpAccrossMultipleSubnets = new Capability("DhcpAccrossMultipleSubnets");
         public static final Capability DistributedRouter = new Capability("DistributedRouter");
+        public static final Capability StretchedL2Subnet = new Capability("StretchedL2Subnet");
+        public static final Capability RegionLevelVpc = new Capability("RegionLevelVpc");
 
         private final String name;
 
@@ -337,4 +339,6 @@ public interface Network extends ControlledEntity, StateObject<Network.State>, I
     Long getNetworkACLId();
 
     void setNetworkACLId(Long networkACLId);
+
+    boolean isStrechedL2Network();
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/api/src/com/cloud/network/NetworkProfile.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/NetworkProfile.java b/api/src/com/cloud/network/NetworkProfile.java
index 6f08e56..db3cba5 100644
--- a/api/src/com/cloud/network/NetworkProfile.java
+++ b/api/src/com/cloud/network/NetworkProfile.java
@@ -55,6 +55,7 @@ public class NetworkProfile implements Network {
     private final boolean displayNetwork;
     private Long networkAclId;
     private final String guruName;
+    private boolean strechedL2Subnet;
 
     public NetworkProfile(Network network) {
         id = network.getId();
@@ -87,6 +88,7 @@ public class NetworkProfile implements Network {
         displayNetwork = network.getDisplayNetwork();
         networkAclId = network.getNetworkACLId();
         guruName = network.getGuruName();
+        strechedL2Subnet = network.isStrechedL2Network();
     }
 
     public String getDns1() {
@@ -280,4 +282,10 @@ public class NetworkProfile implements Network {
     public Class<?> getEntityType() {
         return Network.class;
     }
+
+    @Override
+    public boolean isStrechedL2Network() {
+        return false;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/api/src/com/cloud/network/vpc/Vpc.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/vpc/Vpc.java b/api/src/com/cloud/network/vpc/Vpc.java
index 4bc8c98..2338878 100644
--- a/api/src/com/cloud/network/vpc/Vpc.java
+++ b/api/src/com/cloud/network/vpc/Vpc.java
@@ -79,4 +79,10 @@ public interface Vpc extends ControlledEntity, Identity, InternalIdentity {
      * @return true if VPC is configured to use distributed router to provides one-hop forwarding and hypervisor based ACL
      */
     boolean usesDistributedRouter();
+
+    /**
+     *
+     * @return true if VPC spans multiple zones in the region
+     */
+    boolean isRegionLevelVpc();
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/api/src/com/cloud/network/vpc/VpcOffering.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/vpc/VpcOffering.java b/api/src/com/cloud/network/vpc/VpcOffering.java
index a0a1b15..660c79d 100644
--- a/api/src/com/cloud/network/vpc/VpcOffering.java
+++ b/api/src/com/cloud/network/vpc/VpcOffering.java
@@ -56,8 +56,12 @@ public interface VpcOffering extends InternalIdentity, Identity {
     Long getServiceOfferingId();
 
     /**
-     *
      * @return true if the offering provides a distributed router capable of one-hop forwarding
      */
     boolean supportsDistributedRouter();
+
+    /**
+     * @return true if VPC created with the offering can span multiple zones in the region
+     */
+    boolean offersRegionLevelVPC();
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/api/src/com/cloud/network/vpc/VpcProvisioningService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/vpc/VpcProvisioningService.java b/api/src/com/cloud/network/vpc/VpcProvisioningService.java
index e545275..82a7baa 100644
--- a/api/src/com/cloud/network/vpc/VpcProvisioningService.java
+++ b/api/src/com/cloud/network/vpc/VpcProvisioningService.java
@@ -16,6 +16,7 @@
 // under the License.
 package com.cloud.network.vpc;
 
+
 import java.util.List;
 import java.util.Map;
 

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

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/api/src/org/apache/cloudstack/api/ApiConstants.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java
index 97b1cd7..d9070d1 100755
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -592,7 +592,9 @@ public class ApiConstants {
     public static final String REMAININGCAPACITY = "remainingcapacity";
     public static final String DISTRIBUTED_VPC_ROUTER = "distributedvpcrouter";
     public static final String READ_ONLY = "readonly";
-
+    public static final String SUPPORTS_REGION_LEVEL_VPC = "supportsregionLevelvpc";
+    public static final String SUPPORTS_STRECHED_L2_SUBNET = "supportsstrechedl2subnet";
+    public static final String REGION_LEVEL_VPC = "regionlevelvpc";
 
     public enum HostDetails {
         all, capacity, events, stats, min;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java
index 4d38454..e2f261e 100644
--- a/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java
@@ -64,7 +64,7 @@ public class CreateVPCCmd extends BaseAsyncCreateCmd {
     private Long projectId;
 
     @Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class,
-               required = true, description = "the ID of the availability zone")
+            required = true, description = "the ID of the availability zone")
     private Long zoneId;
 
     @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "the name of the VPC")

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/api/src/org/apache/cloudstack/api/response/NetworkOfferingResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/NetworkOfferingResponse.java b/api/src/org/apache/cloudstack/api/response/NetworkOfferingResponse.java
index 8219147..55ca2ce 100644
--- a/api/src/org/apache/cloudstack/api/response/NetworkOfferingResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/NetworkOfferingResponse.java
@@ -116,6 +116,10 @@ public class NetworkOfferingResponse extends BaseResponse {
     @Param(description = "maximum number of concurrents connections to be handled by lb")
     private Integer concurrentConnections;
 
+    @SerializedName(ApiConstants.SUPPORTS_STRECHED_L2_SUBNET)
+    @Param(description = "true if network offering supports network that span multiple zones")
+    private Boolean supportsStrechedL2Subnet;
+
     public void setId(String id) {
         this.id = id;
     }
@@ -200,4 +204,7 @@ public class NetworkOfferingResponse extends BaseResponse {
         this.concurrentConnections = concurrentConnections;
     }
 
+    public void setSupportsStrechedL2Subnet(Boolean supportsStrechedL2Subnet) {
+        this.supportsStrechedL2Subnet = supportsStrechedL2Subnet;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/api/src/org/apache/cloudstack/api/response/VpcOfferingResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/VpcOfferingResponse.java b/api/src/org/apache/cloudstack/api/response/VpcOfferingResponse.java
index 89697f0..de5adef 100644
--- a/api/src/org/apache/cloudstack/api/response/VpcOfferingResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/VpcOfferingResponse.java
@@ -63,6 +63,10 @@ public class VpcOfferingResponse extends BaseResponse {
     @Param(description = " indicates if the vpc offering supports distributed router for one-hop forwarding")
     private Boolean supportsDistributedRouter;
 
+    @SerializedName((ApiConstants.SUPPORTS_REGION_LEVEL_VPC))
+    @Param(description = " indicated if the offering can support region level vpc")
+    private Boolean supportsRegionLevelVpc;
+
     public void setId(String id) {
         this.id = id;
     }
@@ -94,4 +98,8 @@ public class VpcOfferingResponse extends BaseResponse {
     public void setSupportsDistributedRouter(Boolean supportsDistributedRouter) {
         this.supportsDistributedRouter = supportsDistributedRouter;
     }
+
+    public void setSupportsRegionLevelVpc(Boolean supports) {
+        this.supportsRegionLevelVpc = supports;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/api/src/org/apache/cloudstack/api/response/VpcResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/VpcResponse.java b/api/src/org/apache/cloudstack/api/response/VpcResponse.java
index e3b44f2..d860454 100644
--- a/api/src/org/apache/cloudstack/api/response/VpcResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/VpcResponse.java
@@ -111,11 +111,14 @@ public class VpcResponse extends BaseResponse implements ControlledEntityRespons
     @Param(description = "is vpc for display to the regular user", since = "4.4", authorized = {RoleType.Admin})
     private Boolean forDisplay;
 
-
     @SerializedName(ApiConstants.DISTRIBUTED_VPC_ROUTER)
     @Param(description = "is VPC uses distributed router for one hop forwarding and host based network ACL's")
     private boolean usesDistributedRouter;
 
+    @SerializedName((ApiConstants.REGION_LEVEL_VPC))
+    @Param(description = "true if VPC is region level")
+    private Boolean regionLevelVpc;
+
     public void setId(String id) {
         this.id = id;
     }
@@ -205,6 +208,10 @@ public class VpcResponse extends BaseResponse implements ControlledEntityRespons
         this.forDisplay = forDisplay;
     }
 
+    public void setRegionLevelVpc(Boolean regionLevelVpc) {
+        this.regionLevelVpc = regionLevelVpc;
+    }
+
     public void setUsesDistributedRouter(Boolean usesDistributedRouter) {
         this.usesDistributedRouter = usesDistributedRouter;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/engine/schema/src/com/cloud/network/dao/NetworkVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/network/dao/NetworkVO.java b/engine/schema/src/com/cloud/network/dao/NetworkVO.java
index ee2692d..f1d7e7e 100644
--- a/engine/schema/src/com/cloud/network/dao/NetworkVO.java
+++ b/engine/schema/src/com/cloud/network/dao/NetworkVO.java
@@ -166,6 +166,9 @@ public class NetworkVO implements Network {
     @Column(name = "network_acl_id")
     Long networkACLId;
 
+    @Column(name = "streched_l2")
+    boolean strechedL2Network = false;
+
     public NetworkVO() {
         uuid = UUID.randomUUID().toString();
     }
@@ -588,4 +591,13 @@ public class NetworkVO implements Network {
     public Class<?> getEntityType() {
         return Network.class;
     }
+
+    @Override
+    public boolean isStrechedL2Network() {
+        return strechedL2Network;
+    }
+
+    public void setStrechedL2Network(boolean strechedL2Network) {
+        this.strechedL2Network = strechedL2Network;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/engine/schema/src/com/cloud/network/vpc/VpcOfferingVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/network/vpc/VpcOfferingVO.java b/engine/schema/src/com/cloud/network/vpc/VpcOfferingVO.java
index 53f6f60..a7d61b3 100644
--- a/engine/schema/src/com/cloud/network/vpc/VpcOfferingVO.java
+++ b/engine/schema/src/com/cloud/network/vpc/VpcOfferingVO.java
@@ -70,6 +70,9 @@ public class VpcOfferingVO implements VpcOffering {
     @Column(name = "supports_distributed_router")
     boolean supportsDistributedRouter=false;
 
+    @Column(name = "supports_region_level_vpc")
+    boolean offersRegionLevelVPC = false;
+
     public VpcOfferingVO() {
         this.uuid = UUID.randomUUID().toString();
     }
@@ -84,10 +87,11 @@ public class VpcOfferingVO implements VpcOffering {
     }
 
     public VpcOfferingVO(String name, String displayText, boolean isDefault, Long serviceOfferingId,
-                         boolean supportsDistributedRouter) {
+                         boolean supportsDistributedRouter, boolean offersRegionLevelVPC) {
         this(name, displayText, serviceOfferingId);
         this.isDefault = isDefault;
         this.supportsDistributedRouter = supportsDistributedRouter;
+        this.offersRegionLevelVPC = offersRegionLevelVPC;
     }
 
     @Override
@@ -155,4 +159,9 @@ public class VpcOfferingVO implements VpcOffering {
     public boolean supportsDistributedRouter() {
         return supportsDistributedRouter;
     }
+
+    @Override
+    public boolean offersRegionLevelVPC() {
+        return offersRegionLevelVPC;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/engine/schema/src/com/cloud/network/vpc/VpcVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/network/vpc/VpcVO.java b/engine/schema/src/com/cloud/network/vpc/VpcVO.java
index a7947ac..8c124b2 100644
--- a/engine/schema/src/com/cloud/network/vpc/VpcVO.java
+++ b/engine/schema/src/com/cloud/network/vpc/VpcVO.java
@@ -82,12 +82,15 @@ public class VpcVO implements Vpc {
     @Column(name="uses_distributed_router")
     boolean usesDistributedRouter = false;
 
+    @Column(name = "region_level_vpc")
+    boolean regionLevelVpc = false;
+
     public VpcVO() {
         uuid = UUID.randomUUID().toString();
     }
 
     public VpcVO(long zoneId, String name, String displayText, long accountId, long domainId, long vpcOffId, String cidr,
-                 String networkDomain, boolean useDistributedRouter) {
+                 String networkDomain, boolean useDistributedRouter, boolean regionLevelVpc) {
         this.zoneId = zoneId;
         this.name = name;
         this.displayText = displayText;
@@ -98,7 +101,8 @@ public class VpcVO implements Vpc {
         state = State.Enabled;
         this.networkDomain = networkDomain;
         vpcOfferingId = vpcOffId;
-        usesDistributedRouter = useDistributedRouter;
+        this.usesDistributedRouter = useDistributedRouter;
+        this.regionLevelVpc = regionLevelVpc;
     }
 
     @Override
@@ -191,6 +195,11 @@ public class VpcVO implements Vpc {
         this.uuid = uuid;
     }
 
+    @Override
+    public boolean isRegionLevelVpc() {
+        return regionLevelVpc;
+    }
+
 
     public void setDisplay(boolean display) {
         this.display = display;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java b/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java
index bf07807..c3d849d 100755
--- a/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java
+++ b/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java
@@ -139,6 +139,9 @@ public class NetworkOfferingVO implements NetworkOffering {
     @Column(name = "keep_alive_enabled")
     boolean keepAliveEnabled = false;
 
+    @Column(name="supports_streched_l2")
+    boolean supportsStrechedL2 = false;
+
     @Override
     public String getDisplayText() {
         return displayText;
@@ -331,7 +334,7 @@ public class NetworkOfferingVO implements NetworkOffering {
     public NetworkOfferingVO(String name, String displayText, TrafficType trafficType, boolean systemOnly, boolean specifyVlan, Integer rateMbps,
             Integer multicastRateMbps, boolean isDefault, Availability availability, String tags, Network.GuestType guestType, boolean conserveMode, boolean dedicatedLb,
             boolean sharedSourceNat, boolean redundantRouter, boolean elasticIp, boolean elasticLb, boolean specifyIpRanges, boolean inline, boolean isPersistent,
-            boolean associatePublicIP, boolean publicLb, boolean internalLb, boolean egressdefaultpolicy) {
+            boolean associatePublicIP, boolean publicLb, boolean internalLb, boolean egressdefaultpolicy, boolean supportsStrechedL2) {
         this(name,
             displayText,
             trafficType,
@@ -356,6 +359,7 @@ public class NetworkOfferingVO implements NetworkOffering {
         this.inline = inline;
         this.eipAssociatePublicIp = associatePublicIP;
         this.egressdefaultpolicy = egressdefaultpolicy;
+        this.supportsStrechedL2 = supportsStrechedL2;
     }
 
     public NetworkOfferingVO() {
@@ -486,4 +490,9 @@ public class NetworkOfferingVO implements NetworkOffering {
     public void setPublicLb(boolean publicLb) {
         this.publicLb = publicLb;
     }
+
+    @Override
+    public boolean getSupportsStrechedL2() {
+        return supportsStrechedL2;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/plugins/network-elements/ovs/src/com/cloud/network/element/OvsElement.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/ovs/src/com/cloud/network/element/OvsElement.java b/plugins/network-elements/ovs/src/com/cloud/network/element/OvsElement.java
index 036c319..d767834 100644
--- a/plugins/network-elements/ovs/src/com/cloud/network/element/OvsElement.java
+++ b/plugins/network-elements/ovs/src/com/cloud/network/element/OvsElement.java
@@ -261,6 +261,8 @@ StaticNatServiceProvider, IpDeployer {
         // L2 Support : SDN provisioning
         Map<Capability, String> connectivityCapabilities = new HashMap<Capability, String>();
         connectivityCapabilities.put(Capability.DistributedRouter, null);
+        connectivityCapabilities.put(Capability.StretchedL2Subnet, null);
+        connectivityCapabilities.put(Capability.RegionLevelVpc, null);
         capabilities.put(Service.Connectivity, connectivityCapabilities);
 
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/server/src/com/cloud/api/ApiResponseHelper.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java
index 39c435a..3e9fc21 100755
--- a/server/src/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/com/cloud/api/ApiResponseHelper.java
@@ -1901,6 +1901,7 @@ public class ApiResponseHelper implements ResponseGenerator {
         response.setNetworkRate(ApiDBUtils.getNetworkRate(offering.getId()));
         response.setEgressDefaultPolicy(offering.getEgressDefaultPolicy());
         response.setConcurrentConnections(offering.getConcurrentConnections());
+        response.setSupportsStrechedL2Subnet(offering.getSupportsStrechedL2());
         Long so = null;
         if (offering.getServiceOfferingId() != null) {
             so = offering.getServiceOfferingId();
@@ -2766,6 +2767,7 @@ public class ApiResponseHelper implements ResponseGenerator {
         response.setIsDefault(offering.isDefault());
         response.setState(offering.getState().name());
         response.setSupportsDistributedRouter(offering.supportsDistributedRouter());
+        response.setSupportsRegionLevelVpc(offering.offersRegionLevelVPC());
 
         Map<Service, Set<Provider>> serviceProviderMap = ApiDBUtils.listVpcOffServices(offering.getId());
         List<ServiceResponse> serviceResponses = new ArrayList<ServiceResponse>();
@@ -2809,6 +2811,7 @@ public class ApiResponseHelper implements ResponseGenerator {
         response.setNetworkDomain(vpc.getNetworkDomain());
         response.setForDisplay(vpc.isDisplay());
         response.setUsesDistributedRouter(vpc.usesDistributedRouter());
+        response.setRegionLevelVpc(vpc.isRegionLevelVpc());
 
         Map<Service, Set<Provider>> serviceProviderMap = ApiDBUtils.listVpcOffServices(vpc.getVpcOfferingId());
         List<ServiceResponse> serviceResponses = new ArrayList<ServiceResponse>();

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
index 9b9bd13..bdceed7 100755
--- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
+++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
@@ -16,6 +16,7 @@
 // under the License.
 package com.cloud.configuration;
 
+import com.cloud.network.element.NetworkElement;
 import java.net.URI;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
@@ -3814,10 +3815,21 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
         }
         validateStaticNatServiceCapablities(staticNatServiceCapabilityMap);
 
+        // validate the 'Connectivity' service capabilities specified in the network offering, if 'Connectivity' service
+        // is in the supported services of network offering
+        Map<Capability, String> connectivityServiceCapabilityMap = cmd.getServiceCapabilities(Service.Connectivity);
+        if (!serviceProviderMap.containsKey(Service.Connectivity) &&
+                (connectivityServiceCapabilityMap != null && !connectivityServiceCapabilityMap.isEmpty()))  {
+            throw new InvalidParameterValueException("Capabilities for 'Connectivity' service can be specified " +
+                    "only when Connectivity service is enabled for network offering.");
+        }
+        validateConnectivityServiceCapablities(serviceProviderMap.get(Service.Connectivity), connectivityServiceCapabilityMap);
+
         Map<Service, Map<Capability, String>> serviceCapabilityMap = new HashMap<Service, Map<Capability, String>>();
         serviceCapabilityMap.put(Service.Lb, lbServiceCapabilityMap);
         serviceCapabilityMap.put(Service.SourceNat, sourceNatServiceCapabilityMap);
         serviceCapabilityMap.put(Service.StaticNat, staticNatServiceCapabilityMap);
+        serviceCapabilityMap.put(Service.Connectivity, connectivityServiceCapabilityMap);
 
         // if Firewall service is missing, add Firewall service/provider
         // combination
@@ -3952,6 +3964,36 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
             }
         }
 
+    void validateConnectivityServiceCapablities(Set<Provider> providers, Map<Capability, String> connectivityServiceCapabilityMap) {
+        if (connectivityServiceCapabilityMap != null && !connectivityServiceCapabilityMap.isEmpty()) {
+            for (Capability capability: connectivityServiceCapabilityMap.keySet()) {
+                if (capability == Capability.StretchedL2Subnet) {
+                    String value = connectivityServiceCapabilityMap.get(capability).toLowerCase();
+                    if (!(value.contains("true") ^ value.contains("false"))) {
+                        throw new InvalidParameterValueException("Invalid value (" + value + ") for " + capability +
+                        " should be true/false");
+                    }
+                } else {
+                    throw new InvalidParameterValueException("Capability " + capability.getName() + " can not be "
+                            + " specified with connectivity service.");
+                }
+            }
+        }
+
+        if (providers != null && !providers.isEmpty()) {
+            for (Provider provider: providers) {
+                NetworkElement element = _networkModel.getElementImplementingProvider(provider.getName());
+                Map<Service, Map<Capability, String>> capabilities = element.getCapabilities();
+                if (capabilities != null && !capabilities.isEmpty()) {
+                    Map<Capability, String> connectivityCapabilities =  capabilities.get(Service.Connectivity);
+                    if (connectivityCapabilities == null || (connectivityCapabilities != null && !connectivityCapabilities.keySet().contains(Capability.StretchedL2Subnet))) {
+                        throw new InvalidParameterValueException("Provider: " + provider.getName() + " does not support "
+                                + Capability.StretchedL2Subnet.getName());
+                    }
+                }
+            }
+        }
+    }
     @Override
     @DB
     public NetworkOfferingVO createNetworkOffering(String name, String displayText, TrafficType trafficType, String tags, boolean specifyVlan, Availability availability,
@@ -4012,6 +4054,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
         boolean inline = false;
         boolean publicLb = false;
         boolean internalLb = false;
+        boolean strechedL2Subnet = false;
+
         if (serviceCapabilityMap != null && !serviceCapabilityMap.isEmpty()) {
             Map<Capability, String> lbServiceCapabilityMap = serviceCapabilityMap.get(Service.Lb);
 
@@ -4079,6 +4123,14 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
                     }
                 }
             }
+
+            Map<Capability, String> connectivityServiceCapabilityMap = serviceCapabilityMap.get(Service.Connectivity);
+            if (connectivityServiceCapabilityMap != null && !connectivityServiceCapabilityMap.isEmpty()) {
+                String value = connectivityServiceCapabilityMap.get(Capability.StretchedL2Subnet);
+                if ("true".equalsIgnoreCase(value)) {
+                    strechedL2Subnet = true;
+                }
+            }
         }
 
         if (serviceProviderMap != null && serviceProviderMap.containsKey(Service.Lb) && !internalLb && !publicLb) {
@@ -4088,7 +4140,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
 
         final NetworkOfferingVO offeringFinal = new NetworkOfferingVO(name, displayText, trafficType, systemOnly, specifyVlan, networkRate, multicastRate, isDefault, availability,
                 tags, type, conserveMode, dedicatedLb, sharedSourceNat, redundantRouter, elasticIp, elasticLb, specifyIpRanges, inline, isPersistent, associatePublicIp, publicLb,
-                internalLb, egressDefaultPolicy);
+                internalLb, egressDefaultPolicy, strechedL2Subnet);
 
         if (serviceOfferingId != null) {
             offeringFinal.setServiceOfferingId(serviceOfferingId);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java b/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java
index 13246a7..ddf1f9c 100644
--- a/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java
+++ b/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java
@@ -127,6 +127,10 @@ public class ExternalGuestNetworkGuru extends GuestNetworkGuru {
         throws InsufficientVirtualNetworkCapcityException {
         assert (config.getState() == State.Implementing) : "Why are we implementing " + config;
 
+        if (_networkModel.areServicesSupportedInNetwork(config.getId(), Network.Service.Connectivity)) {
+            return null;
+        }
+
         if (!_networkModel.networkIsConfiguredForExternalNetworking(config.getDataCenterId(), config.getId())) {
             return super.implement(config, offering, dest, context);
         }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/server/src/com/cloud/network/vpc/VpcManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/com/cloud/network/vpc/VpcManagerImpl.java
index 86adb8f..8f3ad39 100644
--- a/server/src/com/cloud/network/vpc/VpcManagerImpl.java
+++ b/server/src/com/cloud/network/vpc/VpcManagerImpl.java
@@ -16,6 +16,8 @@
 // under the License.
 package com.cloud.network.vpc;
 
+
+import com.cloud.network.element.NetworkElement;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -221,44 +223,49 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
         Transaction.execute(new TransactionCallbackNoReturn() {
             @Override
             public void doInTransactionWithoutResult(TransactionStatus status) {
-        if (_vpcOffDao.findByUniqueName(VpcOffering.defaultVPCOfferingName) == null) {
-            s_logger.debug("Creating default VPC offering " + VpcOffering.defaultVPCOfferingName);
-
-            Map<Service, Set<Provider>> svcProviderMap = new HashMap<Service, Set<Provider>>();
-            Set<Provider> defaultProviders = new HashSet<Provider>();
-            defaultProviders.add(Provider.VPCVirtualRouter);
-            for (Service svc : getSupportedServices()) {
-                if (svc == Service.Lb) {
-                    Set<Provider> lbProviders = new HashSet<Provider>();
-                    lbProviders.add(Provider.VPCVirtualRouter);
-                    lbProviders.add(Provider.InternalLbVm);
-                    svcProviderMap.put(svc, lbProviders);
-                } else {
-                    svcProviderMap.put(svc, defaultProviders);
+
+                if (_vpcOffDao.findByUniqueName(VpcOffering.defaultVPCOfferingName) == null) {
+                    s_logger.debug("Creating default VPC offering " + VpcOffering.defaultVPCOfferingName);
+
+                    Map<Service, Set<Provider>> svcProviderMap = new HashMap<Service, Set<Provider>>();
+                    Set<Provider> defaultProviders = new HashSet<Provider>();
+                    defaultProviders.add(Provider.VPCVirtualRouter);
+                    for (Service svc : getSupportedServices()) {
+                        if (svc == Service.Lb) {
+                            Set<Provider> lbProviders = new HashSet<Provider>();
+                            lbProviders.add(Provider.VPCVirtualRouter);
+                            lbProviders.add(Provider.InternalLbVm);
+                            svcProviderMap.put(svc, lbProviders);
+                        } else {
+                            svcProviderMap.put(svc, defaultProviders);
+                        }
+                    }
+                    createVpcOffering(VpcOffering.defaultVPCOfferingName, VpcOffering.defaultVPCOfferingName,
+                            svcProviderMap, true, State.Enabled, null, false, false);
                 }
-            }
-                    createVpcOffering(VpcOffering.defaultVPCOfferingName, VpcOffering.defaultVPCOfferingName, svcProviderMap, true, State.Enabled, null, false);
-        }
 
-        //configure default vpc offering with Netscaler as LB Provider
+                //configure default vpc offering with Netscaler as LB Provider
                 if (_vpcOffDao.findByUniqueName(VpcOffering.defaultVPCNSOfferingName) == null) {
-            s_logger.debug("Creating default VPC offering with Netscaler as LB Provider" + VpcOffering.defaultVPCNSOfferingName);
-            Map<Service, Set<Provider>> svcProviderMap = new HashMap<Service, Set<Provider>>();
-            Set<Provider> defaultProviders = new HashSet<Provider>();
-            defaultProviders.add(Provider.VPCVirtualRouter);
-            for (Service svc : getSupportedServices()) {
-                if (svc == Service.Lb) {
-                    Set<Provider> lbProviders = new HashSet<Provider>();
-                    lbProviders.add(Provider.Netscaler);
-                    lbProviders.add(Provider.InternalLbVm);
-                    svcProviderMap.put(svc, lbProviders);
-                } else {
-                    svcProviderMap.put(svc, defaultProviders);
+                    s_logger.debug("Creating default VPC offering with Netscaler as LB Provider" + VpcOffering.defaultVPCNSOfferingName);
+                    Map<Service, Set<Provider>> svcProviderMap = new HashMap<Service, Set<Provider>>();
+                    Set<Provider> defaultProviders = new HashSet<Provider>();
+                    defaultProviders.add(Provider.VPCVirtualRouter);
+                    for (Service svc : getSupportedServices()) {
+                        if (svc == Service.Lb) {
+                            Set<Provider> lbProviders = new HashSet<Provider>();
+                            lbProviders.add(Provider.Netscaler);
+                            lbProviders.add(Provider.InternalLbVm);
+                            svcProviderMap.put(svc, lbProviders);
+                        } else {
+                            svcProviderMap.put(svc, defaultProviders);
+                        }
+                    }
+                    createVpcOffering(VpcOffering.defaultVPCNSOfferingName, VpcOffering.defaultVPCNSOfferingName,
+                            svcProviderMap, false, State.Enabled, null, false, false);
+
                 }
             }
-                    createVpcOffering(VpcOffering.defaultVPCNSOfferingName, VpcOffering.defaultVPCNSOfferingName, svcProviderMap, false, State.Enabled, null, false);
-        }
-            }
+
         });
 
         Map<String, String> configs = _configDao.getConfiguration(params);
@@ -383,9 +390,9 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
         validateConnectivtyServiceCapablitlies(svcProviderMap.get(Service.Connectivity), serviceCapabilitystList);
 
         boolean supportsDistributedRouter = isVpcOfferingSupportsDistributedRouter(serviceCapabilitystList);
-
+        boolean offersRegionLevelVPC = isVpcOfferingForRegionLevelVpc(serviceCapabilitystList);
         VpcOffering offering = createVpcOffering(name, displayText, svcProviderMap, false, null,
-                serviceOfferingId,supportsDistributedRouter);
+                serviceOfferingId, supportsDistributedRouter, offersRegionLevelVPC);
         CallContext.current().setEventDetails(" Id: " + offering.getId() + " Name: " + name);
 
         return offering;
@@ -395,45 +402,49 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
     protected VpcOffering createVpcOffering(final String name, final String displayText,
                                             final Map<Network.Service, Set<Network.Provider>> svcProviderMap,
                                             final boolean isDefault, final State state, final Long serviceOfferingId,
-                                            final boolean supportsDistributedRouter) {
+                                            final boolean supportsDistributedRouter, final boolean offersRegionLevelVPC) {
+
         return Transaction.execute(new TransactionCallback<VpcOffering>() {
             @Override
             public VpcOffering doInTransaction(TransactionStatus status) {
                 // create vpc offering object
-                VpcOfferingVO offering = new VpcOfferingVO(name, displayText, isDefault, serviceOfferingId, supportsDistributedRouter);
+                VpcOfferingVO offering = new VpcOfferingVO(name, displayText, isDefault, serviceOfferingId,
+                        supportsDistributedRouter, offersRegionLevelVPC);
 
-        if (state != null) {
-            offering.setState(state);
-        }
-        s_logger.debug("Adding vpc offering " + offering);
-        offering = _vpcOffDao.persist(offering);
-        // populate services and providers
-        if (svcProviderMap != null) {
-            for (Network.Service service : svcProviderMap.keySet()) {
-                Set<Provider> providers = svcProviderMap.get(service);
-                if (providers != null && !providers.isEmpty()) {
-                    for (Network.Provider provider : providers) {
-                        VpcOfferingServiceMapVO offService = new VpcOfferingServiceMapVO(offering.getId(), service, provider);
-                        _vpcOffSvcMapDao.persist(offService);
-                        s_logger.trace("Added service for the vpc offering: " + offService + " with provider " + provider.getName());
+                if (state != null) {
+                    offering.setState(state);
+                }
+                s_logger.debug("Adding vpc offering " + offering);
+                offering = _vpcOffDao.persist(offering);
+                // populate services and providers
+                if (svcProviderMap != null) {
+                    for (Network.Service service : svcProviderMap.keySet()) {
+                        Set<Provider> providers = svcProviderMap.get(service);
+                        if (providers != null && !providers.isEmpty()) {
+                            for (Network.Provider provider : providers) {
+                                VpcOfferingServiceMapVO offService = new VpcOfferingServiceMapVO(offering.getId(), service, provider);
+                                _vpcOffSvcMapDao.persist(offService);
+                                s_logger.trace("Added service for the vpc offering: " + offService + " with provider " + provider.getName());
+                            }
+                        } else {
+                            throw new InvalidParameterValueException("Provider is missing for the VPC offering service " + service.getName());
+                        }
                     }
-                } else {
-                    throw new InvalidParameterValueException("Provider is missing for the VPC offering service " + service.getName());
                 }
-            }
-        }
 
-        return offering;
-    }
+                return offering;
+            }
         });
     }
 
-    private boolean isVpcOfferingSupportsDistributedRouter(Map serviceCapabilitystList) {
-        boolean supportsDistributedRouter = false;
+    private void validateConnectivtyServiceCapablitlies(Set<Provider> providers, Map serviceCapabilitystList) {
+
         if (serviceCapabilitystList != null && !serviceCapabilitystList.isEmpty()) {
             Collection serviceCapabilityCollection = serviceCapabilitystList.values();
             Iterator iter = serviceCapabilityCollection.iterator();
             Map<Network.Capability, String> capabilityMap = null;
+            boolean distributedRouterCapabilitySpecified = false;
+            boolean regionLevelVpcCapabilitySpecified = false;
 
             while (iter.hasNext()) {
                 HashMap<String, String> svcCapabilityMap = (HashMap<String, String>)iter.next();
@@ -450,24 +461,56 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
                 }
 
                 if (!svc.equalsIgnoreCase(Service.Connectivity.getName())) {
-                    throw new InvalidParameterValueException("Invalid Service:" + svc + " specified. Only for 'Connectivity' service capabilities can be specified");
+                    throw new InvalidParameterValueException("Invalid Service:" + svc + " specified. Only 'Connectivity'" +
+                            " service capabilities can be specified");
                 }
 
-                if (!capabilityName.equalsIgnoreCase("DistributedRouter")) {
-                    throw new InvalidParameterValueException("Invalid Capability:" + capabilityName + " specified. Only 'DistributedRouter' capability can be specified.");
+                if (!capabilityName.equalsIgnoreCase("DistributedRouter") && !capabilityName.equalsIgnoreCase("RegionLevelVpc")) {
+                    throw new InvalidParameterValueException("Invalid Capability:" + capabilityName + " specified." +
+                            " Only 'DistributedRouter'/'RegionLevelVpc' capability can be specified.");
+                }
+
+                if (capabilityName.equalsIgnoreCase("DistributedRouter")) {
+                    distributedRouterCapabilitySpecified = true;
+                }
+
+                if (capabilityName.equalsIgnoreCase("RegionLevelVpc")) {
+                    regionLevelVpcCapabilitySpecified = true;
                 }
 
                 if (!capabilityValue.equalsIgnoreCase("true") && capabilityValue.equalsIgnoreCase("false")) {
                     throw new InvalidParameterValueException("Invalid Capability value:" + capabilityValue + " specified.");
                 }
-                supportsDistributedRouter = capabilityValue.equalsIgnoreCase("true");
+            }
+
+            if (providers != null && !providers.isEmpty()) {
+                for (Provider provider: providers) {
+                    NetworkElement element = _ntwkModel.getElementImplementingProvider(provider.getName());
+                    Map<Service, Map<Network.Capability, String>> capabilities = element.getCapabilities();
+                    if (capabilities != null && !capabilities.isEmpty()) {
+                        Map<Network.Capability, String> connectivityCapabilities =  capabilities.get(Service.Connectivity);
+                        if (regionLevelVpcCapabilitySpecified) {
+                            if (connectivityCapabilities == null || (connectivityCapabilities != null &&
+                                    !connectivityCapabilities.keySet().contains(Network.Capability.RegionLevelVpc))) {
+                                throw new InvalidParameterValueException("Provider: " + provider.getName() + " does not support "
+                                        + Network.Capability.RegionLevelVpc.getName() + " capability.");
+                            }
+                        }
+                        if (distributedRouterCapabilitySpecified) {
+                            if (connectivityCapabilities == null || (connectivityCapabilities != null &&
+                                    !connectivityCapabilities.keySet().contains(Network.Capability.DistributedRouter))) {
+                                throw new InvalidParameterValueException("Provider: " + provider.getName() + " does not support "
+                                        + Network.Capability.DistributedRouter.getName() + " capability.");
+                            }
+                        }
+                    }
+                }
             }
         }
-        return supportsDistributedRouter;
     }
 
-    private void validateConnectivtyServiceCapablitlies(Set<Provider> providers, Map serviceCapabilitystList) {
-
+    private boolean isVpcOfferingForRegionLevelVpc(Map serviceCapabilitystList) {
+        boolean offersRegionLevelVPC = false;
         if (serviceCapabilitystList != null && !serviceCapabilitystList.isEmpty()) {
             Collection serviceCapabilityCollection = serviceCapabilitystList.values();
             Iterator iter = serviceCapabilityCollection.iterator();
@@ -491,29 +534,55 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
                     throw new InvalidParameterValueException("Invalid Service:" + svc + " specified. Only for 'Connectivity' service capabilities can be specified");
                 }
 
-                if (!capabilityName.equalsIgnoreCase("DistributedRouter")) {
-                    throw new InvalidParameterValueException("Invalid Capability:" + capabilityName + " specified. Only 'DistributedRouter' capability can be specified.");
+                if (!capabilityName.equalsIgnoreCase("RegionLevelVpc")) {
+                    continue;
                 }
 
                 if (!capabilityValue.equalsIgnoreCase("true") && capabilityValue.equalsIgnoreCase("false")) {
                     throw new InvalidParameterValueException("Invalid Capability value:" + capabilityValue + " specified.");
                 }
+                offersRegionLevelVPC = capabilityValue.equalsIgnoreCase("true");
             }
+        }
+        return offersRegionLevelVPC;
+    }
 
-            if (providers != null && !providers.isEmpty()) {
-                for (Provider provider: providers) {
-                    NetworkElement element = _ntwkModel.getElementImplementingProvider(provider.getName());
-                    Map<Service, Map<Network.Capability, String>> capabilities = element.getCapabilities();
-                    if (capabilities != null && !capabilities.isEmpty()) {
-                        Map<Network.Capability, String> connectivityCapabilities =  capabilities.get(Service.Connectivity);
-                        if (connectivityCapabilities == null || (connectivityCapabilities != null && !connectivityCapabilities.keySet().contains(Network.Capability.DistributedRouter))) {
-                            throw new InvalidParameterValueException("Provider: " + provider.getName() + " does not support "
-                                    + Network.Capability.DistributedRouter.getName() + " capability.");
-                        }
-                    }
+    private boolean isVpcOfferingSupportsDistributedRouter(Map serviceCapabilitystList) {
+        boolean supportsDistributedRouter = false;
+        if (serviceCapabilitystList != null && !serviceCapabilitystList.isEmpty()) {
+            Collection serviceCapabilityCollection = serviceCapabilitystList.values();
+            Iterator iter = serviceCapabilityCollection.iterator();
+            Map<Network.Capability, String> capabilityMap = null;
+
+            while (iter.hasNext()) {
+                HashMap<String, String> svcCapabilityMap = (HashMap<String, String>)iter.next();
+                Network.Capability capability = null;
+                String svc = svcCapabilityMap.get("service");
+                String capabilityName = svcCapabilityMap.get("capabilitytype");
+                String capabilityValue = svcCapabilityMap.get("capabilityvalue");
+                if (capabilityName != null) {
+                    capability = Network.Capability.getCapability(capabilityName);
+                }
+
+                if ((capability == null) || (capabilityName == null) || (capabilityValue == null)) {
+                    throw new InvalidParameterValueException("Invalid capability:" + capabilityName + " capability value:" + capabilityValue);
                 }
+
+                if (!svc.equalsIgnoreCase(Service.Connectivity.getName())) {
+                    throw new InvalidParameterValueException("Invalid Service:" + svc + " specified. Only for 'Connectivity' service capabilities can be specified");
+                }
+
+                if (!capabilityName.equalsIgnoreCase("DistributedRouter")) {
+                    continue;
+                }
+
+                if (!capabilityValue.equalsIgnoreCase("true") && capabilityValue.equalsIgnoreCase("false")) {
+                    throw new InvalidParameterValueException("Invalid Capability value:" + capabilityValue + " specified.");
+                }
+                supportsDistributedRouter = capabilityValue.equalsIgnoreCase("true");
             }
         }
+        return supportsDistributedRouter;
     }
 
     @Override
@@ -710,6 +779,11 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
             throw ex;
         }
 
+        boolean isRegionLevelVpcOff = vpcOff.offersRegionLevelVPC();
+        if (isRegionLevelVpcOff && networkDomain == null) {
+            throw new InvalidParameterValueException("Network domain must be specified for region level VPC");
+        }
+
         //Validate zone
         DataCenter zone = _entityMgr.findById(DataCenter.class, zoneId);
         if (zone == null) {
@@ -732,13 +806,15 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
                 networkDomain = "cs" + Long.toHexString(owner.getId()) + NetworkOrchestrationService.GuestDomainSuffix.valueIn(zoneId);
             }
         }
+
         boolean useDistributedRouter = vpcOff.supportsDistributedRouter();
-        return createVpc(zoneId, vpcOffId, owner, vpcName, displayText, cidr, networkDomain, displayVpc, useDistributedRouter);
+        return createVpc(zoneId, vpcOffId, owner, vpcName, displayText, cidr, networkDomain, displayVpc,
+                useDistributedRouter, isRegionLevelVpcOff);
     }
 
     @DB
     protected Vpc createVpc(final long zoneId, final long vpcOffId, final Account vpcOwner, final String vpcName, final String displayText, final String cidr,
-            final String networkDomain, final Boolean displayVpc, final boolean useDistributedRouter) {
+            final String networkDomain, final Boolean displayVpc, final boolean useDistributedRouter, final boolean regionLevelVpc) {
 
         //Validate CIDR
         if (!NetUtils.isValidCIDR(cidr)) {
@@ -761,7 +837,8 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
             @Override
             public VpcVO doInTransaction(TransactionStatus status) {
                 VpcVO vpc = new VpcVO(zoneId, vpcName, displayText, vpcOwner.getId(), vpcOwner.getDomainId(), vpcOffId,
-                        cidr, networkDomain, useDistributedRouter);
+                        cidr, networkDomain, useDistributedRouter, regionLevelVpc);
+
                 if (displayVpc != null) {
                     vpc.setDisplay(displayVpc);
                 }
@@ -2212,7 +2289,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
             networkDomain = vpc.getNetworkDomain();
         }
 
-        if (vpc.getZoneId() != zoneId) {
+        if (!vpc.isRegionLevelVpc() && vpc.getZoneId() != zoneId) {
             throw new InvalidParameterValueException("New network doesn't belong to vpc zone");
         }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/server/src/com/cloud/server/ConfigurationServerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java
index b8da4c8..4781010 100755
--- a/server/src/com/cloud/server/ConfigurationServerImpl.java
+++ b/server/src/com/cloud/server/ConfigurationServerImpl.java
@@ -1153,9 +1153,9 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio
 
                 // Offering #5
                 NetworkOfferingVO defaultNetscalerNetworkOffering =
-                        new NetworkOfferingVO(NetworkOffering.DefaultSharedEIPandELBNetworkOffering,
-                                "Offering for Shared networks with Elastic IP and Elastic LB capabilities", TrafficType.Guest, false, true, null, null, true,
-                                Availability.Optional, null, Network.GuestType.Shared, true, false, false, false, true, true, true, false, false, true, true, false, false);
+                    new NetworkOfferingVO(NetworkOffering.DefaultSharedEIPandELBNetworkOffering,
+                        "Offering for Shared networks with Elastic IP and Elastic LB capabilities", TrafficType.Guest, false, true, null, null, true,
+                        Availability.Optional, null, Network.GuestType.Shared, true, false, false, false, true, true, true, false, false, true, true, false, false, false);
 
                 defaultNetscalerNetworkOffering.setState(NetworkOffering.State.Enabled);
                 defaultNetscalerNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultNetscalerNetworkOffering);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/server/src/com/cloud/vm/UserVmManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java
index 589883e..b4888a8 100755
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -2713,7 +2713,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
         boolean securityGroupEnabled = false;
         boolean vpcNetwork = false;
         for (NetworkVO network : networkList) {
-            if (network.getDataCenterId() != zone.getId()) {
+            if ((network.getDataCenterId() != zone.getId()) && !network.isStrechedL2Network()) {
                 throw new InvalidParameterValueException("Network id=" + network.getId() + " doesn't belong to zone " + zone.getId());
             }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/server/test/com/cloud/network/CreatePrivateNetworkTest.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/network/CreatePrivateNetworkTest.java b/server/test/com/cloud/network/CreatePrivateNetworkTest.java
index dc979d0..b124b20 100644
--- a/server/test/com/cloud/network/CreatePrivateNetworkTest.java
+++ b/server/test/com/cloud/network/CreatePrivateNetworkTest.java
@@ -103,7 +103,7 @@ public class CreatePrivateNetworkTest {
 
         NetworkOfferingVO ntwkOff =
             new NetworkOfferingVO("offer", "fakeOffer", TrafficType.Guest, true, true, null, null, false, null, null, GuestType.Isolated, false, false, false, false,
-                false, false, false, false, false, false, false, false, false);
+                false, false, false, false, false, false, false, false, false, false);
         when(networkService._networkOfferingDao.findById(anyLong())).thenReturn(ntwkOff);
         List<NetworkOfferingVO> netofferlist = new ArrayList<NetworkOfferingVO>();
         netofferlist.add(ntwkOff);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
index ac303dd..387a710 100644
--- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
+++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
@@ -606,7 +606,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkOrches
     @Override
     public Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway, String cidr, String vlanId, 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 ) throws ConcurrentOperationException, InsufficientCapacityException,
         ResourceAllocationException {
         // TODO Auto-generated method stub
         return null;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/server/test/com/cloud/vpc/VpcApiUnitTest.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/vpc/VpcApiUnitTest.java b/server/test/com/cloud/vpc/VpcApiUnitTest.java
index 5e28374..dee9afe 100644
--- a/server/test/com/cloud/vpc/VpcApiUnitTest.java
+++ b/server/test/com/cloud/vpc/VpcApiUnitTest.java
@@ -85,7 +85,7 @@ public class VpcApiUnitTest extends TestCase {
     public void validateNtwkOffForVpc() {
         //validate network offering
         //1) correct network offering
-        VpcVO vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false);
+        VpcVO vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false, false);
         boolean result = false;
         try {
             _vpcService.validateNtwkOffForNtwkInVpc(2L, 1, "0.0.0.0", "111-", vo, "10.1.1.1", new AccountVO(), null);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/server/test/com/cloud/vpc/dao/MockVpcDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/vpc/dao/MockVpcDaoImpl.java b/server/test/com/cloud/vpc/dao/MockVpcDaoImpl.java
index e1a6ac2..7492598 100644
--- a/server/test/com/cloud/vpc/dao/MockVpcDaoImpl.java
+++ b/server/test/com/cloud/vpc/dao/MockVpcDaoImpl.java
@@ -98,9 +98,9 @@ public class MockVpcDaoImpl extends GenericDaoBase<VpcVO, Long> implements VpcDa
     public VpcVO findById(Long id) {
         VpcVO vo = null;
         if (id.longValue() == 1) {
-            vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false);
+            vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false, false);
         } else if (id.longValue() == 2) {
-            vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false);
+            vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false, false);
             vo.setState(State.Inactive);
         }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d2d54a94/setup/db/db/schema-430to440.sql
----------------------------------------------------------------------
diff --git a/setup/db/db/schema-430to440.sql b/setup/db/db/schema-430to440.sql
index ed86387..761eb9a 100644
--- a/setup/db/db/schema-430to440.sql
+++ b/setup/db/db/schema-430to440.sql
@@ -742,8 +742,10 @@ UPDATE `cloud`.`guest_os` SET `created` = now();
 ALTER TABLE `cloud`.`vm_reservation` ADD COLUMN `deployment_planner` varchar(40) DEFAULT NULL COMMENT 'Preferred deployment planner for the vm';
 ALTER TABLE `cloud`.`vpc_offerings` ADD COLUMN supports_distributed_router boolean default false;
 ALTER TABLE `cloud`.`vpc` ADD COLUMN uses_distributed_router  boolean default false;
-
 INSERT INTO `cloud`.`storage_pool_details` (pool_id,name,value,display) SELECT storage_pool.id,data_center_details.name,data_center_details.value,data_center_details.display FROM `cloud`.`storage_pool` JOIN `cloud`.`data_center_details` ON data_center_details.dc_id=storage_pool.data_center_id WHERE data_center_details.name = "storage.overprovisioning.factor";
 DELETE FROM `cloud`.`data_center_details` WHERE name="storage.overprovisioning.factor";
 ALTER TABLE `cloud`.`load_balancer_vm_map` ADD COLUMN instance_ip VARCHAR(40);
-ALTER TABLE `cloud`.`load_balancer_vm_map` DROP KEY `load_balancer_id`, ADD UNIQUE KEY load_balancer_id (`load_balancer_id`, `instance_id`, `instance_ip`);
\ No newline at end of file
+ALTER TABLE `cloud`.`load_balancer_vm_map` DROP KEY `load_balancer_id`, ADD UNIQUE KEY load_balancer_id (`load_balancer_id`, `instance_id`, `instance_ip`);
+ALTER TABLE `cloud`.`vpc_offerings` ADD COLUMN supports_region_level_vpc boolean default false;
+ALTER TABLE `cloud`.`network_offerings` ADD COLUMN supports_streched_l2 boolean default false;
+ALTER TABLE `cloud`.`vpc` ADD COLUMN region_level_vpc boolean default false;