You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by re...@apache.org on 2015/12/03 19:56:44 UTC

[2/5] git commit: updated refs/heads/4.6 to 519ce86

CLOUDSTACK-9075 - Adds VPC static routes test

   - Adds redundant VPC tests
   - Adds support to Static Routes on VPC private gatways
   - Removes the route configuration in case static route is deleted.


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

Branch: refs/heads/4.6
Commit: a17fa48de1cfa4f0f4425f90b0f435d6cf8e6540
Parents: 3e02b89
Author: Wilder Rodrigues <wr...@schubergphilis.com>
Authored: Thu Nov 19 12:28:32 2015 +0100
Committer: Wilder Rodrigues <wr...@schubergphilis.com>
Committed: Wed Dec 2 10:36:52 2015 +0100

----------------------------------------------------------------------
 .../VirtualNetworkApplianceManagerImpl.java     |   7 +-
 .../debian/config/opt/cloud/bin/configure.py    |  27 +-
 .../config/opt/cloud/bin/cs_staticroutes.py     |  30 ++
 .../debian/config/opt/cloud/bin/merge.py        |   6 +
 test/integration/smoke/test_privategw_acl.py    | 352 +++++++++++++++----
 5 files changed, 344 insertions(+), 78 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a17fa48d/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
index ca1f67d..4f3a2b8 100644
--- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
+++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
@@ -2417,10 +2417,9 @@ Configurable, StateListener<State, VirtualMachine.Event, VirtualMachine> {
             for (final Nic routerNic : routerNics) {
                 final Network network = _networkModel.getNetwork(routerNic.getNetworkId());
                 // Send network usage command for public nic in VPC VR
-                // Send network usage command for isolated guest nic of non VPC
-                // VR
-                if (forVpc && network.getTrafficType() == TrafficType.Public || !forVpc && network.getTrafficType() == TrafficType.Guest
-                        && network.getGuestType() == Network.GuestType.Isolated) {
+                // Send network usage command for isolated guest nic of non VPC VR
+                if (network != null && (forVpc && network.getTrafficType() == TrafficType.Public || !forVpc && network.getTrafficType() == TrafficType.Guest
+                        && network.getGuestType() == Network.GuestType.Isolated)) {
                     final NetworkUsageCommand usageCmd = new NetworkUsageCommand(privateIP, router.getHostName(), forVpc, routerNic.getIPv4Address());
                     final String routerType = router.getType().toString();
                     final UserStatisticsVO previousStats = _userStatsDao.findBy(router.getAccountId(), router.getDataCenterId(), network.getId(),

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a17fa48d/systemvm/patches/debian/config/opt/cloud/bin/configure.py
----------------------------------------------------------------------
diff --git a/systemvm/patches/debian/config/opt/cloud/bin/configure.py b/systemvm/patches/debian/config/opt/cloud/bin/configure.py
index ad3705a..0a19607 100755
--- a/systemvm/patches/debian/config/opt/cloud/bin/configure.py
+++ b/systemvm/patches/debian/config/opt/cloud/bin/configure.py
@@ -74,6 +74,27 @@ class CsPassword(CsDataBag):
                 logging.debug("Update password server result ==> %s" % result)
 
 
+class CsStaticRoutes(CsDataBag):
+    
+    def process(self):
+        logging.debug("Processing CsStaticRoutes file ==> %s" % self.dbag)
+        for item in self.dbag:
+            if item == "id":
+                continue
+            self.__update(self.dbag[item])
+
+    def __update(self, route):
+        if route['revoke']:
+            command = "route del -net %s gw %s" % (route['network'], route['gateway'])
+            result = CsHelper.execute(command)
+        else:
+            command = "ip route show | grep %s | awk '{print $1, $3}'" % route['network']
+            result = CsHelper.execute(command)
+            if not result:
+                route_command = "route add -net %s gw %s" % (route['network'], route['gateway'])
+                result = CsHelper.execute(route_command)
+
+
 class CsAcl(CsDataBag):
     """
         Deal with Network acls
@@ -932,13 +953,17 @@ def main(argv):
     mon = CsMonitor("monitorservice", config)
     mon.process()
 
-    logging.debug("Configuring iptables rules .....")
+    logging.debug("Configuring iptables rules")
     nf = CsNetfilters()
     nf.compare(config.get_fw())
     
     red = CsRedundant(config)
     red.set()
 
+    logging.debug("Configuring static routes")
+    static_routes = CsStaticRoutes("staticroutes", config)
+    static_routes.process()
+
     logging.debug("Configuring iptables rules done ...saving rules")
 
     # Save iptables configuration - will be loaded on reboot by the iptables-restore that is configured on /etc/rc.local

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a17fa48d/systemvm/patches/debian/config/opt/cloud/bin/cs_staticroutes.py
----------------------------------------------------------------------
diff --git a/systemvm/patches/debian/config/opt/cloud/bin/cs_staticroutes.py b/systemvm/patches/debian/config/opt/cloud/bin/cs_staticroutes.py
new file mode 100755
index 0000000..98244db
--- /dev/null
+++ b/systemvm/patches/debian/config/opt/cloud/bin/cs_staticroutes.py
@@ -0,0 +1,30 @@
+# -- coding: utf-8 --
+# 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.
+from pprint import pprint
+
+
+def merge(dbag, staticroutes):
+    for route in staticroutes['routes']:
+        key = route['ip_address']
+        revoke = route['revoke']
+        if revoke:
+            del dbag[key]
+        else:
+            dbag[key] = route
+
+    return dbag

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a17fa48d/systemvm/patches/debian/config/opt/cloud/bin/merge.py
----------------------------------------------------------------------
diff --git a/systemvm/patches/debian/config/opt/cloud/bin/merge.py b/systemvm/patches/debian/config/opt/cloud/bin/merge.py
index cc14d6a..374cf2c 100755
--- a/systemvm/patches/debian/config/opt/cloud/bin/merge.py
+++ b/systemvm/patches/debian/config/opt/cloud/bin/merge.py
@@ -34,6 +34,7 @@ import cs_forwardingrules
 import cs_site2sitevpn
 import cs_remoteaccessvpn
 import cs_vpnusers
+import cs_staticroutes
 
 from pprint import pprint
 
@@ -126,6 +127,8 @@ class updateDataBag:
             dbag = self.process_remoteaccessvpn(self.db.getDataBag())
         elif self.qFile.type == 'vpnuserlist':
             dbag = self.process_vpnusers(self.db.getDataBag())
+        elif self.qFile.type == 'staticroutes':
+            dbag = self.process_staticroutes(self.db.getDataBag())
         else:
             logging.error("Error I do not know what to do with file of type %s", self.qFile.type)
             return
@@ -172,6 +175,9 @@ class updateDataBag:
     def process_monitorservice(self, dbag):
         return cs_monitorservice.merge(dbag, self.qFile.data)
 
+    def process_staticroutes(self, dbag):
+        return cs_staticroutes.merge(dbag, self.qFile.data)
+
     def processVMpassword(self, dbag):
         return cs_vmp.merge(dbag, self.qFile.data)
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a17fa48d/test/integration/smoke/test_privategw_acl.py
----------------------------------------------------------------------
diff --git a/test/integration/smoke/test_privategw_acl.py b/test/integration/smoke/test_privategw_acl.py
index 9f2b91d..22b3fa7 100644
--- a/test/integration/smoke/test_privategw_acl.py
+++ b/test/integration/smoke/test_privategw_acl.py
@@ -14,6 +14,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
+from marvin.cloudstackAPI.createStaticRoute import createStaticRouteCmd
 """ Tests for Network ACLs in VPC
 """
 #Import Local Modules
@@ -87,7 +88,7 @@ class Services:
                     "NetworkACL": 'VpcVirtualRouter'
                 },
             },
-            "redundsnt_vpc_offering": {
+            "redundant_vpc_offering": {
                 "name": 'Redundant VPC off',
                 "displaytext": 'Redundant VPC off',
                 "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat',
@@ -133,11 +134,19 @@ class Services:
                 "publicport": 22,
                 "protocol": 'TCP',
             },
+            "natrule": {
+                "privateport": 22,
+                "publicport": 22,
+                "startport": 22,
+                "endport": 22,
+                "protocol": "TCP",
+                "cidrlist": '0.0.0.0/0',
+            },
             "ostype": 'CentOS 5.3 (64-bit)',
             "timeout": 10,
         }
 
-class TestPrivateGWACL(cloudstackTestCase):
+class TestPrivateGwACL(cloudstackTestCase):
 
     @classmethod
     def setUpClass(cls):
@@ -163,7 +172,7 @@ class TestPrivateGWACL(cloudstackTestCase):
             cls.services["service_offering"])
         cls._cleanup = [cls.service_offering]
 
-        cls.logger = logging.getLogger('TestPrivateGWACL')
+        cls.logger = logging.getLogger('TestPrivateGwACL')
         cls.stream_handler = logging.StreamHandler()
         cls.logger.setLevel(logging.DEBUG)
         cls.logger.addHandler(cls.stream_handler)
@@ -179,13 +188,14 @@ class TestPrivateGWACL(cloudstackTestCase):
     def setUp(self):
         self.apiclient = self.testClient.getApiClient()
 
-        self.logger.debug("Creating Admin Account for Domain ID ==> %s" %self.domain.id)
+        self.logger.debug("Creating Admin Account for Domain ID ==> %s" % self.domain.id)
         self.account = Account.create(
             self.apiclient,
             self.services["account"],
             admin=True,
             domainid=self.domain.id)
 
+        self.cleanup = []
         return
 
     def tearDown(self):
@@ -195,89 +205,203 @@ class TestPrivateGWACL(cloudstackTestCase):
             raise Exception("Warning: Exception during cleanup : %s" % e)
         return
 
+    def _replaceAcl(self, command):
+        try:
+            successResponse = self.apiclient.replaceNetworkACLList(command);
+        except Exception as e:
+            self.fail("Failed to replace ACL list due to %s" % e)
+
+        self.assertTrue(successResponse.success, "Failed to replace ACL list.")
+
     @attr(tags=["advanced"], required_hardware="true")
     def test_01_vpc_privategw_acl(self):
         self.logger.debug("Creating a VPC offering..")
-        self.vpc_off = VpcOffering.create(
+        vpc_off = VpcOffering.create(
             self.apiclient,
             self.services["vpc_offering"])
 
         self.logger.debug("Enabling the VPC offering created")
-        self.vpc_off.update(self.apiclient, state='Enabled')
+        vpc_off.update(self.apiclient, state='Enabled')
 
-        self.logger.debug("Creating a VPC network in the account: %s" % self.account.name)
-        self.services["vpc"]["cidr"] = '10.1.1.1/16'
-        self.vpc = VPC.create(
-            self.apiclient,
-            self.services["vpc"],
-            vpcofferingid=self.vpc_off.id,
-            zoneid=self.zone.id,
-            account=self.account.name,
-            domainid=self.account.domainid)
+        vpc = self.createVPC(vpc_off)
         
-        self.cleanup = [self.vpc, self.vpc_off, self.account]
+        self.cleanup = [vpc, vpc_off, self.account]
         
-        self.createACL(self.vpc)
-        self.createACLItem()
-        self.createNetwork(self.vpc)
-        self.createPvtGw(self.vpc)
-        self.replaceacl()
+        physical_networks = get_physical_networks(self.apiclient, self.zone.id)
+        if not physical_networks:
+            self.fail("No Physical Networks found!")
+
+        vlans = physical_networks[0].vlan.split('-')
+        vlan_1 = int(vlans[0])
+
+        acl = self.createACL(vpc)
+        self.createACLItem(acl.id)
+        self.createNetwork(vpc)
+        privateGw = self.createPvtGw(vpc, "10.0.3.99", acl.id, vlan_1)
+        self.replacePvtGwACL(acl.id, privateGw.id)
 
     @attr(tags=["advanced"], required_hardware="true")
-    def test_02_rvpc_privategw_acl(self):
+    def test_02_vpc_privategw_static_routes(self):
+
+        self.logger.debug("Creating a VPC offering..")
+        vpc_off = VpcOffering.create(
+            self.apiclient,
+            self.services["vpc_offering"])
+
+        self.logger.debug("Enabling the VPC offering created")
+        vpc_off.update(self.apiclient, state='Enabled')
+
+        self.performVPCTests(vpc_off)
+
+    @attr(tags=["advanced"], required_hardware="true")
+    def test_03_rvpc_privategw_static_routes(self):
+        self.skipTest("Redundant VPC Routers have to be fixed. Private Gateway not working yet.")
+
         self.logger.debug("Creating a Redundant VPC offering..")
-        self.rvpc_off = VpcOffering.create(
+        vpc_off = VpcOffering.create(
             self.apiclient,
             self.services["redundant_vpc_offering"])
 
         self.logger.debug("Enabling the Redundant VPC offering created")
-        self.rvpc_off.update(self.apiclient, state='Enabled')
+        vpc_off.update(self.apiclient, state='Enabled')
 
-        self.logger.debug("Creating a VPC network in the account: %s" % self.account.name)
-        self.services["vpc"]["cidr"] = '10.1.1.1/16'
-        self.rvpc = VPC.create(
-            self.apiclient,
-            self.services["vpc"],
-            vpcofferingid=self.rvpc_off.id,
-            zoneid=self.zone.id,
-            account=self.account.name,
-            domainid=self.account.domainid)
-        
-        self.cleanup = [self.rvpc, self.rvpc_off, self.account]
+        self.performVPCTests(vpc_off)
+
+    def performVPCTests(self, vpc_off):
+
+        self.logger.debug("Creating VPCs with  offering ID %s" % vpc_off.id)
+        vpc_1 = self.createVPC(vpc_off, cidr = '10.0.1.0/24')
+        vpc_2 = self.createVPC(vpc_off, cidr = '10.0.2.0/24')
+
+        self.cleanup = [vpc_1, vpc_2, vpc_off, self.account]
+
+        physical_networks = get_physical_networks(self.apiclient, self.zone.id)
+        if not physical_networks:
+            self.fail("No Physical Networks found!")
+
+        vlans = physical_networks[0].vlan.split('-')
+        vlan_1 = int(vlans[0]) + 1
+
+        network_1 = self.createNetwork(vpc_1, gateway = '10.0.1.1')
+        network_2 = self.createNetwork(vpc_2, gateway = '10.0.2.1')
+
+        vm1 = self.createVM(network_1)
+        vm2 = self.createVM(network_2)
+
+        self.cleanup.insert(0, vm1)
+        self.cleanup.insert(0, vm2)
         
-        self.createACL(self.rvpc)
-        self.createACLItem()
-        self.createNetwork(self.rvpc)
-        self.createPvtGw(self.rvpc)
-        self.replaceacl()
+        acl1 = self.createACL(vpc_1)
+        self.createACLItem(acl1.id, cidr = "0.0.0.0/0")
+        privateGw_1 = self.createPvtGw(vpc_1, "10.0.3.100", "10.0.3.101", acl1.id, vlan_1)
+        self.replacePvtGwACL(acl1.id, privateGw_1.id)
+
+        acl2 = self.createACL(vpc_2)
+        self.createACLItem(acl2.id, cidr = "0.0.0.0/0")
+        privateGw_2 = self.createPvtGw(vpc_2, "10.0.3.101", "10.0.3.100", acl2.id, vlan_1)
+        self.replacePvtGwACL(acl2.id, privateGw_2.id)
+
+        self.replaceNetworkAcl(acl1.id, network_1)
+        self.replaceNetworkAcl(acl2.id, network_2)
+
+        staticRoute_1 = self.createStaticRoute(privateGw_1.id, cidr = '10.0.2.0/24')
+        staticRoute_2 = self.createStaticRoute(privateGw_2.id, cidr = '10.0.1.0/24')
+
+        public_ip_1 = self.acquire_publicip(vpc_1, network_1)
+        public_ip_2 = self.acquire_publicip(vpc_2, network_2)
+
+        nat_rule_1 = self.create_natrule(vpc_1, vm1, public_ip_1, network_1)
+        nat_rule_2 = self.create_natrule(vpc_2, vm2, public_ip_2, network_2)
+
+        self.check_pvt_gw_connectivity(vm1, public_ip_1, vm2.nic[0].ipaddress)
+        self.check_pvt_gw_connectivity(vm2, public_ip_2, vm1.nic[0].ipaddress)
+
+    def createVPC(self, vpc_offering, cidr = '10.1.1.1/16'):
+        try:
+            self.logger.debug("Creating a VPC network in the account: %s" % self.account.name)
+            self.services["vpc"]["cidr"] = cidr
+
+            vpc = VPC.create(
+                self.apiclient,
+                self.services["vpc"],
+                vpcofferingid=vpc_offering.id,
+                zoneid=self.zone.id,
+                account=self.account.name,
+                domainid=self.account.domainid)
+
+            self.logger.debug("Created VPC with ID: %s" % vpc.id)
+        except Exception, e:
+            self.fail('Unable to create VPC due to %s ' % e)
+
+        return vpc
+
+    def createVM(self, network):
+        try:
+            self.logger.debug('Creating VM in network=%s' % network.name)
+            vm = VirtualMachine.create(
+                self.apiclient,
+                self.services["virtual_machine"],
+                accountid=self.account.name,
+                domainid=self.account.domainid,
+                serviceofferingid=self.service_offering.id,
+                networkids=[str(network.id)]
+            )
+            self.logger.debug("Created VM with ID: %s" % vm.id)
+        except Exception, e:
+            self.fail('Unable to create virtual machine due to %s ' % e)
+
+        return vm
+
+    def createStaticRoute(self, privateGwId, cidr = '10.0.0.0/16'):
+        staticRouteCmd = createStaticRoute.createStaticRouteCmd()
+        staticRouteCmd.cidr = cidr
+        staticRouteCmd.gatewayid = privateGwId
+
+        try:
+            staticRoute = self.apiclient.createStaticRoute(staticRouteCmd)
+            self.assertIsNotNone(staticRoute.id, "Failed to create static route.")
+
+            self.logger.debug("Created staticRoute with ID: %s" % staticRoute.id)
+        except Exception, e:
+            self.fail('Unable to create static route due to %s ' % e)
+
+        return staticRoute
 
     def createACL(self, vpc):
         createAclCmd = createNetworkACLList.createNetworkACLListCmd()
-        createAclCmd.name = "acl1"
-        createAclCmd.description = "new acl"
+        createAclCmd.name = "ACL-Test-%s" % vpc.id
+        createAclCmd.description = createAclCmd.name
         createAclCmd.vpcid = vpc.id
-        createAclResponse = self.apiclient.createNetworkACLList(createAclCmd)
+        try:
+            acl = self.apiclient.createNetworkACLList(createAclCmd)
+            self.assertIsNotNone(acl.id, "Failed to create ACL.")
 
-        self.aclId = createAclResponse.id
+            self.logger.debug("Created ACL with ID: %s" % acl.id)
+        except Exception, e:
+            self.fail('Unable to create ACL due to %s ' % e)
 
-        self.assertIsNotNone(self.aclId, "Failed to create ACL.")
+        return acl
 
-    def createACLItem(self):
+    def createACLItem(self, aclId, cidr = "0.0.0.0/0"):
         createAclItemCmd = createNetworkACL.createNetworkACLCmd()
-        createAclItemCmd.cidr = "0.0.0.0/0"
-        createAclItemCmd.protocol = "TCP"
+        createAclItemCmd.cidr = cidr
+        createAclItemCmd.protocol = "All"
         createAclItemCmd.number = "1"
-        createAclItemCmd.action = "Deny"
-        createAclItemCmd.aclid = self.aclId
-        createAclItemResponse = self.apiclient.createNetworkACL(createAclItemCmd)
+        createAclItemCmd.action = "Allow"
+        createAclItemCmd.aclid = aclId
+        try:
+            aclItem = self.apiclient.createNetworkACL(createAclItemCmd)
+            self.assertIsNotNone(aclItem.id, "Failed to create ACL item.")
 
-        self.assertIsNotNone(createAclItemResponse.id, "Failed to create ACL item.")
+            self.logger.debug("Created ACL Item ID: %s" % aclItem.id)
+        except Exception, e:
+            self.fail('Unable to create ACL Item due to %s ' % e)
 
-    def createNetwork(self, vpc):
+    def createNetwork(self, vpc, gateway = '10.1.1.1'):
         try:
             self.logger.debug('Create NetworkOffering')
             net_offerring = self.services["network_offering"]
-            net_offerring["name"] = "NET_OFF-10.1.1.1"
+            net_offerring["name"] = "NET_OFF-%s" % gateway
             nw_off = NetworkOffering.create(
                 self.apiclient,
                 net_offerring,
@@ -287,7 +411,7 @@ class TestPrivateGWACL(cloudstackTestCase):
 
             self.logger.debug('Created and Enabled NetworkOffering')
 
-            self.services["network"]["name"] = "NETWORK-10.1.1.1"
+            self.services["network"]["name"] = "NETWORK-%s" % gateway
 
             self.logger.debug('Adding Network=%s' % self.services["network"])
             obj_network = Network.create(
@@ -297,7 +421,7 @@ class TestPrivateGWACL(cloudstackTestCase):
                 domainid=self.account.domainid,
                 networkofferingid=nw_off.id,
                 zoneid=self.zone.id,
-                gateway="10.1.1.1",
+                gateway=gateway,
                 vpcid=vpc.id
             )
 
@@ -305,35 +429,117 @@ class TestPrivateGWACL(cloudstackTestCase):
         except Exception, e:
             self.fail('Unable to create a Network with offering=%s because of %s ' % (net_offerring, e))
 
-        self.network = obj_network
-
         self.cleanup.insert(0, nw_off)
         self.cleanup.insert(0, obj_network)
 
-    def createPvtGw(self, vpc):
+        return obj_network
+
+    def createPvtGw(self, vpc, ip_address, gateway, aclId, vlan):
+        physical_networks = get_physical_networks(self.apiclient, self.zone.id)
+        if not physical_networks:
+            self.fail("No Physical Networks found!")
+
+        self.logger.debug('::: Physical Networks ::: ==> %s' % physical_networks)
+
         createPrivateGatewayCmd = createPrivateGateway.createPrivateGatewayCmd()
-        createPrivateGatewayCmd.physicalnetworkid = get_physical_networks(self.apiclient, self.zone.id)
-        createPrivateGatewayCmd.gateway = "10.147.30.1"
+        createPrivateGatewayCmd.physicalnetworkid = physical_networks[0].id
+        createPrivateGatewayCmd.gateway = gateway
         createPrivateGatewayCmd.netmask = "255.255.255.0"
-        createPrivateGatewayCmd.ipaddress = "10.147.30.200"
-        createPrivateGatewayCmd.vlan = "30"
+        createPrivateGatewayCmd.ipaddress = ip_address
+        createPrivateGatewayCmd.vlan = vlan
         createPrivateGatewayCmd.vpcid = vpc.id
-        createPrivateGatewayCmd.sourcenatsupported = "true"
-        createPrivateGatewayCmd.aclid = self.aclId
+        createPrivateGatewayCmd.sourcenatsupported = "false"
+        createPrivateGatewayCmd.aclid = aclId
 
         try:
-            privateGatewayResponse =  self.apiclient.createPrivateGateway(createPrivateGatewayCmd)
+            privateGw =  self.apiclient.createPrivateGateway(createPrivateGatewayCmd)
         except Exception as e:
             self.fail("Failed to create Private Gateway ==> %s" % e)
 
-        self.privateGwId = privateGatewayResponse.id
+        self.assertIsNotNone(privateGw.id, "Failed to create ACL.")
+        
+        return privateGw
 
-        self.assertIsNotNone(self.privateGwId, "Failed to create ACL.")
+    def replaceNetworkAcl(self, aclId, network):
+        self.logger.debug("Replacing Network ACL with ACL ID ==> %s" % aclId)
 
-    def replaceacl(self):
         replaceNetworkACLListCmd = replaceNetworkACLList.replaceNetworkACLListCmd()
-        replaceNetworkACLListCmd.aclid = self.aclId
-        replaceNetworkACLListCmd.gatewayid = self.privateGwId
-        successResponse = self.apiclient.replaceNetworkACLList(replaceNetworkACLListCmd);
+        replaceNetworkACLListCmd.aclid = aclId
+        replaceNetworkACLListCmd.networkid = network.id
 
-        self.assertTrue(successResponse.success, "Failed to replace ACL list.")
+        self._replaceAcl(replaceNetworkACLListCmd)
+
+    def replacePvtGwACL(self, aclId, privateGwId):
+        self.logger.debug("Replacing Private GW ACL with ACL ID ==> %s" % aclId)
+
+        replaceNetworkACLListCmd = replaceNetworkACLList.replaceNetworkACLListCmd()
+        replaceNetworkACLListCmd.aclid = aclId
+        replaceNetworkACLListCmd.gatewayid = privateGwId
+
+        self._replaceAcl(replaceNetworkACLListCmd)
+
+    def acquire_publicip(self, vpc, network):
+        self.logger.debug("Associating public IP for network: %s" % network.name)
+        public_ip = PublicIPAddress.create(
+            self.apiclient,
+            accountid=self.account.name,
+            zoneid=self.zone.id,
+            domainid=self.account.domainid,
+            networkid=network.id,
+            vpcid=vpc.id
+        )
+        self.logger.debug("Associated %s with network %s" % (
+            public_ip.ipaddress.ipaddress,
+            network.id
+        ))
+
+        return public_ip
+
+    def create_natrule(self, vpc, virtual_machine, public_ip, network):
+        self.logger.debug("Creating NAT rule in network for vm with public IP")
+
+        nat_service = self.services["natrule"]
+        nat_rule = NATRule.create(
+            self.apiclient,
+            virtual_machine,
+            nat_service,
+            ipaddressid=public_ip.ipaddress.id,
+            openfirewall=False,
+            networkid=network.id,
+            vpcid=vpc.id)
+
+        self.logger.debug("Adding NetworkACL rules to make NAT rule accessible")
+        nwacl_nat = NetworkACL.create(
+            self.apiclient,
+            networkid=network.id,
+            services=nat_service,
+            traffictype='Ingress'
+        )
+        self.logger.debug('nwacl_nat=%s' % nwacl_nat.__dict__)
+        
+        return nat_rule
+
+    def check_pvt_gw_connectivity(self, virtual_machine, public_ip, vm_ip):
+        ssh_command = "ping -c 3 %s" % vm_ip
+
+        # Should be able to SSH VM
+        result = 'failed'
+        try:
+            self.logger.debug("SSH into VM: %s" % public_ip.ipaddress.ipaddress)
+            
+            ssh = virtual_machine.get_ssh_client(ipaddress=public_ip.ipaddress.ipaddress)
+
+            self.logger.debug("Ping to VM inside another VPC")
+            result = str(ssh.execute(ssh_command))
+
+            self.logger.debug("SSH result: %s; COUNT is ==> %s" % (result, result.count("3 packets received")))
+        except Exception as e:
+            self.fail("SSH Access failed for %s: %s" % \
+                      (vmObj.get_ip(), e)
+                      )
+
+        self.assertEqual(
+                         result.count("3 packets received"),
+                         1,
+                         "Ping to outside world from VM should be successful"
+                         )