You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by bh...@apache.org on 2017/12/02 15:45:42 UTC

[cloudstack] 09/09: CLOUDSTACK-10010: Port marvin test from #2190 by @swill

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

bhaisaab pushed a commit to branch debian9-systemvmtemplate
in repository https://gitbox.apache.org/repos/asf/cloudstack.git

commit 6524593268f38af26afbbd68635950fe09bca334
Author: Will Stevens <wi...@gmail.com>
AuthorDate: Sat Dec 2 21:11:40 2017 +0530

    CLOUDSTACK-10010: Port marvin test from #2190 by @swill
    
    This ports the S2S config test by @swill from #2190 with additional
    changes to make robust and environment agnostic.
    
    Signed-off-by: Rohit Yadav <ro...@shapeblue.com>
---
 test/integration/smoke/test_vpc_vpn.py | 470 ++++++++++++++++++++++++++++++++-
 1 file changed, 465 insertions(+), 5 deletions(-)

diff --git a/test/integration/smoke/test_vpc_vpn.py b/test/integration/smoke/test_vpc_vpn.py
index 83c244b..ebcdd2d 100644
--- a/test/integration/smoke/test_vpc_vpn.py
+++ b/test/integration/smoke/test_vpc_vpn.py
@@ -1138,8 +1138,19 @@ class TestRVPCSite2SiteVpn(cloudstackTestCase):
             self.apiclient, customer2_response.id, vpn1_response['id'])
         self.debug("VPN connection created for VPC %s" % vpc1.id)
 
-        self.assertEqual(
-            vpnconn2_response['state'], "Connected", "Failed to connect between VPCs!")
+        def checkVpnConnected():
+            connections = Vpn.listVpnConnection(
+                self.apiclient,
+                listall='true',
+                vpcid=vpc2.id)
+            if isinstance(connections, list):
+                return connections[0].state == 'Connected', None
+            return False, None
+
+        # Wait up to 60 seconds for passive connection to show up as Connected
+        res, _ = wait_until(2, 30, checkVpnConnected)
+        if not res:
+            self.fail("Failed to connect between VPCs, see VPN state as Connected")
 
         # acquire an extra ip address to use to ssh into vm2
         try:
@@ -1174,9 +1185,8 @@ class TestRVPCSite2SiteVpn(cloudstackTestCase):
 
         if ssh_client:
             # run ping test
-            packet_loss = ssh_client.execute(
-                "/bin/ping -c 3 -t 10 " + vm1.nic[0].ipaddress + " |grep packet|cut -d ' ' -f 7| cut -f1 -d'%'")[0]
-            self.assert_(int(packet_loss) == 0, "Ping did not succeed")
+            packet_loss = ssh_client.execute("/bin/ping -c 3 -t 10 " + vm1.nic[0].ipaddress + " | grep packet | sed 's/.*received, //g' | sed 's/[% ]*packet.*//g'")[0]
+            self.assert_(int(packet_loss) < 50, "Ping did not succeed")
         else:
             self.fail("Failed to setup ssh connection to %s" % vm2.public_ip)
 
@@ -1189,3 +1199,453 @@ class TestRVPCSite2SiteVpn(cloudstackTestCase):
             cleanup_resources(cls.apiclient, cls.cleanup)
         except Exception, e:
             raise Exception("Cleanup failed with %s" % e)
+
+
+class TestVPCSite2SiteVPNMultipleOptions(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        cls.logger = logging.getLogger('TestVPCSite2SiteVPNMultipleOptions')
+        cls.stream_handler = logging.StreamHandler()
+        cls.logger.setLevel(logging.DEBUG)
+        cls.logger.addHandler(cls.stream_handler)
+
+        testClient = super(TestVPCSite2SiteVPNMultipleOptions, cls).getClsTestClient()
+        cls.apiclient = testClient.getApiClient()
+        cls.services = Services().services
+
+        cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
+        cls.domain = get_domain(cls.apiclient)
+
+        cls.compute_offering = ServiceOffering.create(
+            cls.apiclient,
+            cls.services["compute_offering"]
+        )
+
+        cls.account = Account.create(
+            cls.apiclient, services=cls.services["account"])
+
+        cls.hypervisor = testClient.getHypervisorInfo()
+
+        cls.logger.debug("Downloading Template: %s from: %s" % (cls.services["template"][
+                         cls.hypervisor.lower()], cls.services["template"][cls.hypervisor.lower()]["url"]))
+        cls.template = Template.register(cls.apiclient, cls.services["template"][cls.hypervisor.lower(
+        )], cls.zone.id, hypervisor=cls.hypervisor.lower(), account=cls.account.name, domainid=cls.domain.id)
+        cls.template.download(cls.apiclient)
+
+        if cls.template == FAILED:
+            assert False, "get_template() failed to return template"
+
+        cls.logger.debug("Successfully created account: %s, id: \
+                   %s" % (cls.account.name,
+                          cls.account.id))
+
+        cls.cleanup = [cls.account, cls.compute_offering]
+        return
+
+    def _get_ssh_client(self, virtual_machine, services, retries):
+        """ Setup ssh client connection and return connection
+        vm requires attributes public_ip, public_port, username, password """
+
+        try:
+            ssh_client = SshClient(
+                virtual_machine.public_ip,
+                services["virtual_machine"]["ssh_port"],
+                services["virtual_machine"]["username"],
+                services["virtual_machine"]["password"],
+                retries)
+
+        except Exception as e:
+            self.fail("Unable to create ssh connection: " % e)
+
+        self.assertIsNotNone(
+            ssh_client, "Failed to setup ssh connection to vm=%s on public_ip=%s" % (virtual_machine.name, virtual_machine.public_ip))
+
+        return ssh_client
+
+    def _create_natrule(self, vpc, vm, public_port, private_port, public_ip, network, services=None):
+        self.logger.debug("Creating NAT rule in network for vm with public IP")
+        if not services:
+            self.services["natrule"]["privateport"] = private_port
+            self.services["natrule"]["publicport"] = public_port
+            self.services["natrule"]["startport"] = public_port
+            self.services["natrule"]["endport"] = public_port
+            services = self.services["natrule"]
+
+        nat_rule = NATRule.create(
+            apiclient=self.apiclient,
+            services=services,
+            ipaddressid=public_ip.ipaddress.id,
+            virtual_machine=vm,
+            networkid=network.id
+        )
+        self.assertIsNotNone(
+            nat_rule, "Failed to create NAT Rule for %s" % public_ip.ipaddress.ipaddress)
+        self.logger.debug(
+            "Adding NetworkACL rules to make NAT rule accessible")
+
+        vm.ssh_ip = nat_rule.ipaddress
+        vm.public_ip = nat_rule.ipaddress
+        vm.public_port = int(public_port)
+        return nat_rule
+
+    def _validate_vpc_offering(self, vpc_offering):
+
+        self.logger.debug("Check if the VPC offering is created successfully?")
+        vpc_offs = VpcOffering.list(
+            self.apiclient,
+            id=vpc_offering.id
+        )
+        offering_list = validateList(vpc_offs)
+        self.assertEqual(offering_list[0],
+                         PASS,
+                         "List VPC offerings should return a valid list"
+                         )
+        self.assertEqual(
+            vpc_offering.name,
+            vpc_offs[0].name,
+            "Name of the VPC offering should match with listVPCOff data"
+        )
+        self.logger.debug(
+            "VPC offering is created successfully - %s" %
+            vpc_offering.name)
+        return
+
+    def _create_vpc_offering(self, offering_name):
+
+        vpc_off = None
+        if offering_name is not None:
+
+            self.logger.debug("Creating VPC offering: %s", offering_name)
+            vpc_off = VpcOffering.create(
+                self.apiclient,
+                self.services[offering_name]
+            )
+
+            self._validate_vpc_offering(vpc_off)
+            self.cleanup.append(vpc_off)
+
+        return vpc_off
+
+    @attr(tags=["advanced"], required_hardware="true")
+    def test_01_vpc_site2site_vpn_multiple_options(self):
+        """Test Site 2 Site VPN Across VPCs"""
+        self.logger.debug("Starting test: test_01_vpc_site2site_vpn_multiple_options")
+        # 0) Get the default network offering for VPC
+        networkOffering = NetworkOffering.list(
+            self.apiclient, name="DefaultIsolatedNetworkOfferingForVpcNetworks")
+        self.assert_(networkOffering is not None and len(
+            networkOffering) > 0, "No VPC based network offering")
+
+        # Create and Enable VPC offering
+        vpc_offering = self._create_vpc_offering('vpc_offering')
+        self.assert_(vpc_offering is not None, "Failed to create VPC Offering")
+        vpc_offering.update(self.apiclient, state='Enabled')
+
+        vpc1 = None
+        # Create VPC 1
+        try:
+            vpc1 = VPC.create(
+                apiclient=self.apiclient,
+                services=self.services["vpc"],
+                networkDomain="vpc1.vpn",
+                vpcofferingid=vpc_offering.id,
+                zoneid=self.zone.id,
+                account=self.account.name,
+                domainid=self.domain.id
+            )
+        except Exception as e:
+            self.fail(e)
+        finally:
+            self.assert_(vpc1 is not None, "VPC1 creation failed")
+
+        self.logger.debug("VPC1 %s created" % vpc1.id)
+
+        vpc2 = None
+        # Create VPC 2
+        try:
+            vpc2 = VPC.create(
+                apiclient=self.apiclient,
+                services=self.services["vpc2"],
+                networkDomain="vpc2.vpn",
+                vpcofferingid=vpc_offering.id,
+                zoneid=self.zone.id,
+                account=self.account.name,
+                domainid=self.domain.id
+            )
+        except Exception as e:
+            self.fail(e)
+        finally:
+            self.assert_(vpc2 is not None, "VPC2 creation failed")
+
+        self.logger.debug("VPC2 %s created" % vpc2.id)
+
+        default_acl = NetworkACLList.list(
+            self.apiclient, name="default_allow")[0]
+
+        ntwk1 = None
+        # Create network in VPC 1
+        try:
+            ntwk1 = Network.create(
+                apiclient=self.apiclient,
+                services=self.services["network_1"],
+                accountid=self.account.name,
+                domainid=self.account.domainid,
+                networkofferingid=networkOffering[0].id,
+                zoneid=self.zone.id,
+                vpcid=vpc1.id,
+                aclid=default_acl.id
+            )
+        except Exception as e:
+            self.fail(e)
+        finally:
+            self.assertIsNotNone(ntwk1, "Network failed to create")
+
+        self.logger.debug("Network %s created in VPC %s" % (ntwk1.id, vpc1.id))
+
+        ntwk2 = None
+        # Create network in VPC 2
+        try:
+            ntwk2 = Network.create(
+                apiclient=self.apiclient,
+                services=self.services["network_2"],
+                accountid=self.account.name,
+                domainid=self.account.domainid,
+                networkofferingid=networkOffering[0].id,
+                zoneid=self.zone.id,
+                vpcid=vpc2.id,
+                aclid=default_acl.id
+            )
+        except Exception as e:
+            self.fail(e)
+        finally:
+            self.assertIsNotNone(ntwk2, "Network failed to create")
+
+        self.logger.debug("Network %s created in VPC %s" % (ntwk2.id, vpc2.id))
+
+        vm1 = None
+        # Deploy a vm in network 2
+        try:
+            vm1 = VirtualMachine.create(self.apiclient, services=self.services["virtual_machine"],
+                                        templateid=self.template.id,
+                                        zoneid=self.zone.id,
+                                        accountid=self.account.name,
+                                        domainid=self.account.domainid,
+                                        serviceofferingid=self.compute_offering.id,
+                                        networkids=ntwk1.id,
+                                        hypervisor=self.hypervisor
+                                        )
+        except Exception as e:
+            self.fail(e)
+        finally:
+            self.assert_(vm1 is not None, "VM failed to deploy")
+            self.assert_(vm1.state == 'Running', "VM is not running")
+
+        self.logger.debug("VM %s deployed in VPC %s" % (vm1.id, vpc1.id))
+
+        vm2 = None
+        # Deploy a vm in network 2
+        try:
+            vm2 = VirtualMachine.create(self.apiclient, services=self.services["virtual_machine"],
+                                        templateid=self.template.id,
+                                        zoneid=self.zone.id,
+                                        accountid=self.account.name,
+                                        domainid=self.account.domainid,
+                                        serviceofferingid=self.compute_offering.id,
+                                        networkids=ntwk2.id,
+                                        hypervisor=self.hypervisor
+                                        )
+        except Exception as e:
+            self.fail(e)
+        finally:
+            self.assert_(vm2 is not None, "VM failed to deploy")
+            self.assert_(vm2.state == 'Running', "VM is not running")
+
+        self.debug("VM %s deployed in VPC %s" % (vm2.id, vpc2.id))
+
+        # default config
+        config = {
+            'ike_enc'       :'aes128',
+            'ike_hash'      :'sha1',
+            'ike_dh'        :'modp1536',
+            'esp_enc'       :'aes128',
+            'esp_hash'      :'sha1',
+            'esp_pfs'       :'modp1536',
+            'psk'           :'secreatKey',
+            'ike_life'      :86400,
+            'esp_life'      :3600,
+            'dpd'           :True,
+            'force_encap'   :False,
+            'passive_1'     :False,
+            'passive_2'     :False
+        }
+        test_confs = [
+            {}, # default
+            {'force_encap': True},
+            {'ike_life': ''},
+            {'esp_life': ''},
+            {'ike_life': '', 'esp_life': ''},
+            {'passive_1': True, 'passive_2': True},
+            {'passive_1': False, 'passive_2': True},
+            {'passive_1': True, 'passive_2': False},
+            {'passive_1': False, 'passive_2': False, 'dpd': False},
+            {'passive_1': True, 'passive_2': True, 'dpd': False},
+            {'passive_1': True, 'passive_2': False, 'dpd': False},
+            {'passive_1': False, 'passive_2': True, 'dpd': False},
+            {'passive_1': True, 'passive_2': False, 'esp_pfs': ''},
+            {'ike_dh': 'modp3072', 'ike_hash': 'sha256', 'esp_pfs': 'modp2048', 'esp_hash':'sha384'},
+            {'ike_dh': 'modp4096', 'ike_hash': 'sha384', 'esp_pfs': 'modp6144', 'esp_hash':'sha512'},
+            {'ike_dh': 'modp8192', 'ike_hash': 'sha512', 'esp_pfs': 'modp8192', 'esp_hash':'sha384'}
+        ]
+
+        # 4) Enable Site-to-Site VPN for VPC
+        vpn1_response = Vpn.createVpnGateway(self.apiclient, vpc1.id)
+        self.assert_(
+            vpn1_response is not None, "Failed to enable VPN Gateway 1")
+        self.logger.debug("VPN gateway for VPC %s enabled" % vpc1.id)
+
+        vpn2_response = Vpn.createVpnGateway(self.apiclient, vpc2.id)
+        self.assert_(
+            vpn2_response is not None, "Failed to enable VPN Gateway 2")
+        self.logger.debug("VPN gateway for VPC %s enabled" % vpc2.id)
+
+        # 5) Add VPN Customer gateway info
+        src_nat_list = PublicIPAddress.list(
+            self.apiclient,
+            account=self.account.name,
+            domainid=self.account.domainid,
+            listall=True,
+            issourcenat=True,
+            vpcid=vpc1.id
+        )
+        ip1 = src_nat_list[0]
+        src_nat_list = PublicIPAddress.list(
+            self.apiclient,
+            account=self.account.name,
+            domainid=self.account.domainid,
+            listall=True,
+            issourcenat=True,
+            vpcid=vpc2.id
+        )
+        ip2 = src_nat_list[0]
+
+        # acquire an extra ip address to use to ssh into vm2
+        try:
+            services = self.services.copy()
+            del services["account"]
+            vm2.public_ip = PublicIPAddress.create(
+                apiclient=self.apiclient,
+                zoneid=self.zone.id,
+                account=self.account.name,
+                domainid=self.account.domainid,
+                services=services,
+                networkid=ntwk2.id,
+                vpcid=vpc2.id)
+        except Exception as e:
+            self.fail(e)
+        finally:
+            self.assert_(
+                vm2.public_ip is not None, "Failed to aqcuire public ip for vm2")
+
+        natrule = None
+        # Create port forward to be able to ssh into vm2
+        try:
+            natrule = self._create_natrule(
+                vpc2, vm2, 22, 22, vm2.public_ip, ntwk2)
+        except Exception as e:
+            self.fail(e)
+        finally:
+            self.assert_(
+                natrule is not None, "Failed to create portforward for vm2")
+            time.sleep(20)
+
+        # setup ssh connection to vm2
+        ssh_client = self._get_ssh_client(vm2, self.services, 10)
+        if not ssh_client:
+            self.fail("Failed to setup ssh connection to %s" % vm2.public_ip)
+
+        for test_c in test_confs:
+            c = config.copy()
+            c.update(test_c)
+            services = self._get_vpn_config(c)
+            self.logger.debug(services)
+            customer1_response = VpnCustomerGateway.create(
+                self.apiclient,
+                services,
+                "Peer VPC1",
+                ip1.ipaddress,
+                vpc1.cidr,
+                account=self.account.name,
+                domainid=self.account.domainid)
+            self.logger.debug("VPN customer gateway added for VPC %s enabled" % vpc1.id)
+
+            customer2_response = VpnCustomerGateway.create(
+                self.apiclient,
+                services,
+                "Peer VPC2",
+                ip2.ipaddress,
+                vpc2.cidr,
+                account=self.account.name,
+                domainid=self.account.domainid)
+            self.logger.debug("VPN customer gateway added for VPC %s enabled" % vpc2.id)
+
+            # 6) Connect two VPCs
+            vpnconn1_response = Vpn.createVpnConnection(
+                self.apiclient, customer1_response.id, vpn2_response['id'], c['passive_1'])
+            self.logger.debug("VPN connection created for VPC %s" % vpc2.id)
+            time.sleep(5)
+            vpnconn2_response = Vpn.createVpnConnection(
+                self.apiclient, customer2_response.id, vpn1_response['id'], c['passive_2'])
+            self.logger.debug("VPN connection created for VPC %s" % vpc1.id)
+
+            def checkVpnConnected():
+                connections = Vpn.listVpnConnection(
+                    self.apiclient,
+                    listall='true',
+                    vpcid=vpc2.id)
+                if isinstance(connections, list):
+                    return connections[0].state == 'Connected', None
+                return False, None
+
+            # Wait up to 60 seconds for passive connection to show up as Connected
+            res, _ = wait_until(2, 30, checkVpnConnected)
+            if not res:
+                self.logger.debug("Failed to see VPN state as Connected, we'll attempt ssh+pinging")
+
+            # run ping test
+            packet_loss = ssh_client.execute("/bin/ping -c 3 -t 10 " + vm1.nic[0].ipaddress + " | grep packet | sed 's/.*received, //g' | sed 's/[% ]*packet.*//g'")[0]
+            self.logger.debug("Packet loss %s" % packet_loss)
+            self.assert_(int(packet_loss) < 50, "Ping did not succeed")
+
+            # Cleanup
+            Vpn.deleteVpnConnection(self.apiclient, vpnconn1_response['id'])
+            Vpn.deleteVpnConnection(self.apiclient, vpnconn2_response['id'])
+            customer1_response.delete(self.apiclient)
+            customer2_response.delete(self.apiclient)
+
+    def _get_vpn_config(self, c):
+        ike_policy = '%s-%s;%s' % (c['ike_enc'], c['ike_hash'], c['ike_dh']) if c['ike_dh'] else '%s-%s' % (c['ike_enc'], c['ike_hash'])
+        esp_policy = '%s-%s;%s' % (c['esp_enc'], c['esp_hash'], c['esp_pfs']) if c['esp_pfs'] else '%s-%s' % (c['esp_enc'], c['esp_hash'])
+        out =  {
+            'ipsecpsk': c['psk'],
+            'ikepolicy':ike_policy,
+            'esppolicy':esp_policy,
+            'dpd':c['dpd'],
+            'forceencap':c['force_encap']
+        }
+        if c['ike_life']:
+            out['ikelifetime'] = c['ike_life']
+        if c['esp_life']:
+            out['esplifetime'] = c['esp_life']
+        return out
+
+
+    @classmethod
+    def tearDownClass(cls):
+        try:
+            try:
+                cls.template.delete(cls.apiclient)
+            except Exception: pass
+            cleanup_resources(cls.apiclient, cls.cleanup)
+        except Exception, e:
+            raise Exception("Cleanup failed with %s" % e)

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