This is an automated email from the ASF dual-hosted git repository. rohit pushed a commit to branch debian9-systemvmtemplate in repository https://gitbox.apache.org/repos/asf/cloudstack.git
commit c94c3c0b6f8068182952ae42cb564403476f40a7 Author: Will Stevens <williamstev...@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 <rohit.ya...@shapeblue.com> --- test/integration/smoke/test_vpc_vpn.py | 468 ++++++++++++++++++++++++++++++++- 1 file changed, 463 insertions(+), 5 deletions(-) diff --git a/test/integration/smoke/test_vpc_vpn.py b/test/integration/smoke/test_vpc_vpn.py index d8964d2..849f139 100644 --- a/test/integration/smoke/test_vpc_vpn.py +++ b/test/integration/smoke/test_vpc_vpn.py @@ -1139,8 +1139,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: @@ -1175,9 +1186,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) @@ -1190,3 +1200,451 @@ 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: + vm2.public_ip = PublicIPAddress.create( + apiclient=self.apiclient, + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + services=self.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" <commits@cloudstack.apache.org>.