diff --git a/vmware_nsx_tempest/tests/nsxv/scenario/test_multiple_transport_zones_basic_ops.py b/vmware_nsx_tempest/tests/nsxv/scenario/test_multiple_transport_zones_basic_ops.py new file mode 100644 index 0000000000..75a5f886d1 --- /dev/null +++ b/vmware_nsx_tempest/tests/nsxv/scenario/test_multiple_transport_zones_basic_ops.py @@ -0,0 +1,255 @@ +# Copyright 2016 OpenStack Foundation +# Copyright 2016 VMware Inc +# All Rights Reserved. +# +# 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. +import re +import six + +from tempest_lib.common.utils import data_utils + +from tempest.common import waiters +from tempest import config +from tempest import test + +from vmware_nsx_tempest.services import nsxv_client +from vmware_nsx_tempest.tests.nsxv.scenario \ + import manager_topo_deployment as dmgr + +CONF = config.CONF + + +class TestMultipleTransportZonesBasicOps(dmgr.TopoDeployScenarioManager): + + """Base class provides MTZ networks basic operations: + + 1: create MTZ networks and a tenant network. + 2: create router and attached networks at step 1. + 3: Boot one VM at each network. + 4: select one VM, assign floatingip and from it ping other VMs' + fixed-ip to assure that VMs attached to different vdn_scope_ids, + and tennat network are asscessible. + """ + + @classmethod + def skip_checks(cls): + super(TestMultipleTransportZonesBasicOps, cls).skip_checks() + if not (CONF.network.tenant_networks_reachable + or CONF.network.public_network_id): + msg = ('Either tenant_networks_reachable must be "true", or ' + 'public_network_id must be defined.') + raise cls.skipException(msg) + for ext in ['router', 'provider']: + if not test.is_extension_enabled(ext, 'network'): + msg = "%s extension not enabled." % ext + raise cls.skipException(msg) + + @classmethod + def resource_setup(cls): + super(TestMultipleTransportZonesBasicOps, cls).resource_setup() + manager_ip = re.search(r"(\d{1,3}\.){3}\d{1,3}", + CONF.nsxv.manager_uri).group(0) + cls.vsm = nsxv_client.VSMClient( + manager_ip, CONF.nsxv.user, CONF.nsxv.password) + cls.nsxv_scope_ids = cls.get_all_scope_id_list(with_default_scope=True) + if len(cls.nsxv_scope_ids) < 2: + msg = "Only one transport zone deployed. Need at least 2." + raise cls.skipException(msg) + cls.provider_network_type = getattr(CONF.nsxv, + "provider_network_type", + 'vxlan') + cls.MAX_MTZ = getattr(CONF.nsxv, 'max_mtz', 0) or 3 + cls.admin_client = cls.admin_manager.network_client + cls.admin_networks_client = cls.admin_manager.networks_client + cls.admin_subnets_client = cls.admin_manager.subnets_client + + @classmethod + def resource_cleanup(cls): + super(TestMultipleTransportZonesBasicOps, cls).resource_cleanup() + + @classmethod + def get_all_scope_id_list(cls, with_default_scope=False): + """return all scope IDs w/wo the default scope defined in NSX.""" + scopes = cls.vsm.get_all_vdn_scopes() + scope_id_list = [x['objectId'] for x in scopes] + if with_default_scope: + return scope_id_list + try: + scope_id_list.remove(CONF.nsxv.vdn_scope_id) + except Exception: + pass + return scope_id_list + + def create_tenant_network_subnet(self, + name_prefix='mtz-project'): + network_name = data_utils.rand_name(name_prefix) + network, subnet = self.create_network_subnet( + name=network_name) + return (network.id, network, subnet) + + def create_mtz_network_subnet(self, scope_id, + cidr=None, cidr_offset=0): + network_name = data_utils.rand_name('mtz-net') + create_body = {'name': network_name, + 'provider:network_type': self.provider_network_type, + 'provider:physical_network': scope_id} + network = self.create_network( + client=self.admin_manager.networks_client, + **create_body) + subnet = self.create_subnet( + network, + client=self.admin_manager.subnets_client, + name=network_name, + cidr=cidr, cidr_offset=cidr_offset) + lswitch_list = self.vsm.get_all_logical_switches(scope_id) + lswitch_list = [x for x in lswitch_list if x['name'] == network.id] + msg = ("network=%s is not configured by specified vdn_scope_id=%s" + % (network.id, scope_id)) + self.assertTrue(len(lswitch_list) == 1, msg=msg) + return (network.id, network, subnet) + + def create_router_by_type(self, router_type, name=None, **kwargs): + create_kwargs = dict(namestart='mtz-', external_gateway_info={ + "network_id": CONF.network.public_network_id}) + if router_type in ('shared', 'exclusive'): + create_kwargs['router_type'] = router_type + elif router_type in ('distributed'): + create_kwargs['distributed'] = True + kwargs.update(create_kwargs) + router = self._create_router(client_mgr=self.admin_manager, + **kwargs) + return router + + def create_router_and_add_interfaces(self, router_type, nets): + router = self.create_router_by_type(router_type) + if router_type == 'exclusive': + router_nsxv_name = '%s-%s' % (router.name, router.id) + exc_edge = self.vsm.get_edge(router_nsxv_name) + self.assertIsNotNone(exc_edge) + self.assertEqual(exc_edge['edgeType'], 'gatewayServices') + for net_id, (s_id, network, subnet, sg) in six.iteritems(nets): + router.add_subnet(subnet) + return router + + def clear_router_gateway_and_interfaces(self, router, nets): + router_client = self.admin_client + router_client.update_router(router['id'], + external_gateway_info=dict()) + for net_id, (s_id, network, subnet, sg) in six.iteritems(nets): + try: + router_client.remove_router_interface_with_subnet_id( + router['id'], subnet['id']) + except Exception: + pass + + def _test_router_with_network_and_mtz_networks(self, router_type): + """router attached with multiple TZs and one tenant network.""" + scope_id_list = self.get_all_scope_id_list(with_default_scope=True) + nets = {} + net_id, network, subnet = self.create_tenant_network_subnet( + 'mtz-tenant') + # create security_group with loginable rules + security_group = self._create_security_group( + security_groups_client=self.manager.security_groups_client, + client=self.manager.network_client, + namestart='mtz-tenant') + nets[net_id] = [None, network, subnet, security_group] + admin_security_group = self._create_security_group( + security_groups_client=self.admin_manager.security_groups_client, + client=self.admin_manager.network_client, + namestart='mtz-') + for cidr_step in range(0, self.MAX_MTZ): + s_id = scope_id_list[cidr_step % len(scope_id_list)] + net_id, network, subnet = self.create_mtz_network_subnet( + s_id, cidr_offset=(cidr_step + 2)) + nets[net_id] = [s_id, network, subnet, admin_security_group] + router = self.create_router_and_add_interfaces(router_type, nets) + return router, nets + + def run_servers_connectivity_test(self, servers): + # select one from the servers + net_id_list = servers.keys() + net_id = net_id_list[0] + other_net_id_list = net_id_list[1:] + username, password = self.get_image_userpass() + nsv = self.servers[net_id] + serv = nsv['server'] + floatingip = self.create_floatingip_for_server( + serv, client_mgr=self.admin_manager) + msg = ("Associate floatingip[%s] to server[%s]" + % (floatingip, serv['name'])) + self._check_floatingip_connectivity( + floatingip, serv, should_connect=True, msg=msg) + serv_fip = floatingip.floating_ip_address + dmgr.rm_sshkey(serv_fip) + ssh_client = dmgr.get_remote_client_by_password( + serv_fip, username, password) + not_reachable_list = [] + for nid in other_net_id_list: + o_svr = servers[nid]['server'] + o_net = servers[nid]['network'] + o_ipaddr = self.get_server_fixed_ip(o_svr, o_net) + reachable = dmgr.is_reachable(ssh_client, o_ipaddr) + if not reachable: + not_reachable_list.append(o_ipaddr) + self.assertTrue( + len(not_reachable_list) == 0, + ("Following Servers are not reachable: %s" % not_reachable_list)) + + def get_server_fixed_ip(self, server, network): + addr_list = server['addresses'][network['name']] + for addr in addr_list: + if addr['OS-EXT-IPS:type'] == 'fixed': + return addr['addr'] + return None + + def wait_for_servers_become_active(self, servers): + servers_client = self.admin_manager.servers_client + net_id_list = servers.keys() + for net_id in net_id_list: + nsv = self.servers[net_id] + serv = nsv['server'] + waiters.wait_for_server_status( + servers_client, serv['id'], 'ACTIVE') + + def run_mtz_basic_ops(self, router_type): + self.servers = {} + router, nets = self._test_router_with_network_and_mtz_networks( + router_type) + for net_id in six.iterkeys(nets): + s_id, network, subnet, security_group = nets[net_id] + servers_client = (self.manager.servers_client if s_id is None + else self.admin_manager.servers_client) + security_groups = [{'name': security_group['name']}] + svr = self.create_server_on_network( + network, security_groups, + name=network['name'], + servers_client=servers_client) + self.servers[net_id] = dict(server=svr, s_id=s_id, + network=network, subnet=subnet, + security_group=security_group, + servers_client=servers_client) + self.wait_for_servers_become_active(self.servers) + self.run_servers_connectivity_test(self.servers) + + +class TestMTZBasicOpsOverSharedRouter(TestMultipleTransportZonesBasicOps): + @test.idempotent_id('190790fe-4cc4-4bb3-ae3e-4fa2031ca4e2') + def test_mtz_basic_ops_over_shared_router(self): + self.run_mtz_basic_ops(router_type='shared') + + +class TestMTZBasicOpsOverExclusiveRouter(TestMultipleTransportZonesBasicOps): + @test.idempotent_id('caf2be55-ea49-4783-87bf-103fcc5783db') + def test_mtz_basic_ops_over_exclusive_router(self): + self.run_mtz_basic_ops(router_type='exclusive')