From 0196519b50a2392ef79e8a70627e9d6dffccc95d Mon Sep 17 00:00:00 2001 From: madhusudhan-kandadai Date: Wed, 7 Oct 2015 17:40:53 -0700 Subject: [PATCH] Include VPN scenario test for two different tenants This test tests the vpn connection under two different tenants and validate the vpn and ipsec-site-connection status Change-Id: I15b1c15db1229c8835c46d211002fd2acfc2b9da --- .../plugins/test_vpn_tenant_scenario.py | 62 +++++++++++++++++++ rally-jobs/plugins/vpn_base.py | 56 +++++++++++++---- rally-jobs/plugins/vpn_utils.py | 37 ++++++++++- rally-jobs/rally-configs/rally_config.yaml | 25 ++++++++ 4 files changed, 165 insertions(+), 15 deletions(-) create mode 100644 rally-jobs/plugins/test_vpn_tenant_scenario.py diff --git a/rally-jobs/plugins/test_vpn_tenant_scenario.py b/rally-jobs/plugins/test_vpn_tenant_scenario.py new file mode 100644 index 000000000..c4adaaf32 --- /dev/null +++ b/rally-jobs/plugins/test_vpn_tenant_scenario.py @@ -0,0 +1,62 @@ +# Copyright 2015 Hewlett-Packard Development Company, L.P. +# +# Licensed 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 rally.common import log as logging +from rally.task import scenario +from rally.task import types as types + +import vpn_base + +LOG = logging.getLogger(__name__) + + +class VpnTenantScenario(vpn_base.VpnBase): + """Rally scenarios for VPNaaS""" + + @types.set(image=types.ImageResourceType, + flavor=types.FlavorResourceType) + @scenario.configure() + def multitenants_vpn_test( + self, **kwargs): + """Basic VPN connectivity scenario. + + 1. Create 2 private networks with 2 different tenants, subnets, routers + 2. Create public network, subnets and GW IPs on routers, if not present + 3. Execute ip netns command and get the snat and qrouter namespaces + (assuming we use DVR) + 4. Verify that there is a route between the router gateways by pinging + each other from their snat namespaces + 5. Add security group rules for SSH and ICMP + 6. Start a nova instance in each of the private networks + 7. Create IKE and IPSEC policies + 8. Create VPN service at each of the routers + 9. Create IPSEC site connections at both endpoints + 10. Verify that the vpn-service and ipsec-site-connection are ACTIVE + 11. Cleanup the resources that are setup for this test + + """ + + try: + self.setup(use_admin_client=True) + self.create_tenant() + self.create_networks_and_servers(**kwargs) + self.check_route() + self.ike_policy = self._create_ike_policy(**kwargs) + self.ipsec_policy = self._create_ipsec_policy(**kwargs) + self.create_vpn_services() + self.create_ipsec_site_connections(**kwargs) + self.assert_statuses(final_status='ACTIVE', **kwargs) + + finally: + self.cleanup() diff --git a/rally-jobs/plugins/vpn_base.py b/rally-jobs/plugins/vpn_base.py index bbd46808d..45864e26f 100644 --- a/rally-jobs/plugins/vpn_base.py +++ b/rally-jobs/plugins/vpn_base.py @@ -32,9 +32,11 @@ MAX_RESOURCES = 2 class VpnBase(rally_base.OpenStackScenario): - def setup(self): - """Creates and initializes data structures to hold various resources""" - + def setup(self, use_admin_client=False): + """Creates and initializes data structures to hold various resources + :param use_admin_client - Use admin client when it is set to True + """ + self.tenant_ids = [] self.snat_namespaces = [] self.qrouter_namespaces = [] self.router_ids = [] @@ -50,11 +52,16 @@ class VpnBase(rally_base.OpenStackScenario): self.servers = [] self.server_private_ips = [] self.suffixes = [uuidutils.generate_uuid(), uuidutils.generate_uuid()] + self.tenant_names = map(lambda x: "rally_tenant_" + x, self.suffixes) self.key_names = map(lambda x: "rally_keypair_" + x, self.suffixes) self.key_file_paths = map(lambda x: '/tmp/' + x, self.key_names) + self.nova_client = self.clients("nova") self.neutron_client = self.clients("neutron") self.neutron_admin_client = self.admin_clients("neutron") - self.nova_client = self.clients("nova") + if use_admin_client is True: + self.neutron_client = self.admin_clients("neutron") + self.keystone_client = self.admin_clients("keystone") + self.nova_client = self.admin_clients("nova") @atomic.action_timer("cleanup") def cleanup(self): @@ -70,6 +77,9 @@ class VpnBase(rally_base.OpenStackScenario): vpn_utils.delete_network( self.neutron_client, self.neutron_admin_client, self.rally_routers, self.rally_networks, self.rally_subnets) + if self.tenant_ids: + vpn_utils.delete_tenant(self.keystone_client, + self.tenant_ids) @atomic.action_timer("_create_ike_policy") def _create_ike_policy(self, **kwargs): @@ -121,7 +131,8 @@ class VpnBase(rally_base.OpenStackScenario): return ipsec_policy @atomic.action_timer("_create_vpn_service") - def _create_vpn_service(self, rally_subnet, rally_router, vpn_suffix=None): + def _create_vpn_service(self, rally_subnet, + rally_router, vpn_suffix=None): """Creates VPN service endpoints :param rally_subnet: local subnet @@ -141,7 +152,8 @@ class VpnBase(rally_base.OpenStackScenario): return vpn_service @atomic.action_timer("_create_ipsec_site_connection") - def _create_ipsec_site_connection(self, local_index, peer_index, **kwargs): + def _create_ipsec_site_connection(self, local_index, + peer_index, **kwargs): """Creates IPSEC site connection :param local_index: parameter to point to the local end-point @@ -181,12 +193,14 @@ class VpnBase(rally_base.OpenStackScenario): :return: resource (vpn_service or ipsec_site_connection) """ if resource_tag == "vpnservice": - vpn_service = self.neutron_client.show_vpnservice(resource_id) + vpn_service = self.neutron_client.show_vpnservice( + resource_id) if vpn_service: return vpn_service elif resource_tag == 'ipsec_site_connection': - ipsec_site_conn = self.neutron_client.show_ipsec_site_connection( - resource_id) + ipsec_site_conn = \ + self.neutron_client.show_ipsec_site_connection( + resource_id) if ipsec_site_conn: return ipsec_site_conn @@ -348,13 +362,31 @@ class VpnBase(rally_base.OpenStackScenario): self.neutron_client.delete_ikepolicy( self.ike_policy['ikepolicy']['id']) + def create_tenant(self): + """Creates tenant + + :param keystone_client: keystone_admin_client + :param tenant_ids : append created tenant id into the list + :return: + """ + with LOCK: + for x in range(MAX_RESOURCES): + self.tenant_ids.append((vpn_utils.create_tenant( + self.keystone_client, + self.tenant_names[x])).id) + def create_networks_and_servers(self, **kwargs): with LOCK: keypairs = [] for x in range(MAX_RESOURCES): - router, network, subnet, cidr = vpn_utils.create_network( - self.neutron_client, self.neutron_admin_client, - self.suffixes[x]) + if self.tenant_ids: + router, network, subnet, cidr = vpn_utils.create_network( + self.neutron_client, self.neutron_admin_client, + self.suffixes[x], self.tenant_ids[x]) + else: + router, network, subnet, cidr = vpn_utils.create_network( + self.neutron_client, self.neutron_admin_client, + self.suffixes[x]) self.rally_cidrs.append(cidr) self.rally_subnets.append(subnet) self.rally_networks.append(network) diff --git a/rally-jobs/plugins/vpn_utils.py b/rally-jobs/plugins/vpn_utils.py index f0b7ad762..05923902a 100644 --- a/rally-jobs/plugins/vpn_utils.py +++ b/rally-jobs/plugins/vpn_utils.py @@ -35,7 +35,8 @@ START_CIDR = "10.2.0.0/24" EXT_NET_CIDR = "172.16.1.0/24" -def create_network(neutron_client, neutron_admin_client, network_suffix): +def create_network(neutron_client, neutron_admin_client, + network_suffix, tenant_id=None): """Creates neutron network, subnet, router :param neutron_client: neutron client @@ -53,6 +54,10 @@ def create_network(neutron_client, neutron_admin_client, network_suffix): "router:external": is_external } LOG.debug("ADDING NEW NETWORK: %s", network_name) + + if tenant_id is not None: + network_args["tenant_id"] = tenant_id + return neutron_client.create_network({"network": network_args}) def _create_subnet(neutron_client, rally_network, network_suffix, cidr): @@ -66,6 +71,10 @@ def create_network(neutron_client, neutron_admin_client, network_suffix): "ip_version": SUBNET_IP_VERSION } LOG.debug("ADDING SUBNET: %s", subnet_name) + + if tenant_id is not None: + subnet_args["tenant_id"] = tenant_id + return neutron_client.create_subnet({"subnet": subnet_args}) def _create_router(neutron_client, ext_network_id, rally_subnet): @@ -82,9 +91,13 @@ def create_network(neutron_client, neutron_admin_client, network_suffix): "external_gateway_info": gw_info } LOG.debug("ADDING ROUTER: %s", router_name) - rally_router = neutron_client.create_router({"router": router_args}) - LOG.debug("ADDING ROUTER INTERFACE") + + if tenant_id is not None: + router_args["tenant_id"] = 'tenant_id' + + rally_router = neutron_client.create_router( + {"router": router_args}) neutron_client.add_interface_router( rally_router['router']["id"], {"subnet_id": rally_subnet["subnet"]["id"]}) @@ -116,6 +129,24 @@ def create_network(neutron_client, neutron_admin_client, network_suffix): return rally_router, rally_network, rally_subnet, subnet_cidr +def create_tenant(keystone_client, tenant): + """Creates keystone tenant with random name. + :param tenant: create a tenant with random name + :returns: + """ + return keystone_client.tenants.create(tenant) + + +def delete_tenant(keystone_client, tenant): + """Deletes keystone tenant + + :returns: delete keystone tenant instance + """ + if tenant: + for id in tenant: + keystone_client.tenants.delete(id) + + def create_keypair(nova_client, key_name, key_file_path): """Create keypair diff --git a/rally-jobs/rally-configs/rally_config.yaml b/rally-jobs/rally-configs/rally_config.yaml index ef594730b..b229033fb 100644 --- a/rally-jobs/rally-configs/rally_config.yaml +++ b/rally-jobs/rally-configs/rally_config.yaml @@ -59,3 +59,28 @@ sla: failure_rate: max: 0 + + VpnTenantScenario.multitenants_vpn_test: + - + args: + flavor: + name: "m1.tiny" + image: + name: {{image_name}} + nova_server_boot_timeout: 60 * 6 + vpn_service_creation_timeout: 100 + ipsec_site_connection_creation_timeout: 400 + namespace_creation_timeout: 60 + + runner: + type: "constant" + times: 1 + concurrency: 1 + + context: + users: + tenants: 1 + users_per_tenant: 1 + sla: + failure_rate: + max: 0 \ No newline at end of file