From b47bd6bce125a874ab5faf0558a17a49bbe34485 Mon Sep 17 00:00:00 2001 From: Ritesh Anand Date: Wed, 3 Jun 2015 08:25:32 -0700 Subject: [PATCH] Added test cases for DVR L3 schedulers. Test cases listed below are to run for Chance and Least-routers scheduler, for both auto and explicit scheduling. 1. Legacy router scheduled on dvr_snat agent. 2. Distributed router not scheduled on legacy agent. 3. Distributed router not scheduled on dvr agent. 4. Distributed router scheduled on dvr_snat agent. 5. Already hosted legacy router not scheduled on dvr agent. 6. Already hosted legacy router not scheduled on dvr_snat agent. 7. Already hosted distributed router not scheduled on legacy agent. 8. Already hosted distributed router not scheduled on dvr agent. 9. Already hosted distributed router not scheduled on dvr_snat agent. 10. Already hosted legacy router not scheduled on additional dvr agent. 11. Distributed router not scheduled if it is on a different external network than the dvr_snat agent. Change-Id: I94d6654631b3cd66dfd469b1230c3ec20d0c0369 --- .../scheduler/test_l3_agent_scheduler.py | 293 +++++++++++++++++- 1 file changed, 287 insertions(+), 6 deletions(-) diff --git a/neutron/tests/functional/scheduler/test_l3_agent_scheduler.py b/neutron/tests/functional/scheduler/test_l3_agent_scheduler.py index 4ddf764f91d..b2aec753106 100644 --- a/neutron/tests/functional/scheduler/test_l3_agent_scheduler.py +++ b/neutron/tests/functional/scheduler/test_l3_agent_scheduler.py @@ -18,12 +18,21 @@ import random import testscenarios +from oslo_utils import uuidutils + +from neutron.api.v2 import attributes +from neutron.common import constants from neutron import context +from neutron.db import external_net_db from neutron.scheduler import l3_agent_scheduler from neutron.services.l3_router import l3_router_plugin from neutron.tests.common import helpers from neutron.tests.unit.db import test_db_base_plugin_v2 +_uuid = uuidutils.generate_uuid + +PLUGIN_NAME = 'neutron.plugins.ml2.plugin.Ml2Plugin' + # Required to generate tests from scenarios. Not compatible with nose. load_tests = testscenarios.load_tests_apply_scenarios @@ -35,15 +44,16 @@ class L3SchedulerBaseTest(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): """ def setUp(self): - super(L3SchedulerBaseTest, self).setUp() + super(L3SchedulerBaseTest, self).setUp(PLUGIN_NAME) self.l3_plugin = l3_router_plugin.L3RouterPlugin() self.adminContext = context.get_admin_context() - self.adminContext.tenant_id = '_func_test_tenant_' + self.adminContext.tenant_id = _uuid() - def _create_l3_agent(self, host, context, agent_mode='legacy', plugin=None, - state=True): - agent = helpers.register_l3_agent(host, agent_mode) + def _create_l3_agent(self, host, context, agent_mode='legacy', + state=True, ext_net_id=''): + agent = helpers.register_l3_agent(host, agent_mode, + ext_net_id=ext_net_id) helpers.set_agent_admin_state(agent.id, state) return agent @@ -58,7 +68,7 @@ class L3SchedulerBaseTest(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): # down agent count. self.hosts = ['host-%s' % i for i in range(agent_count)] self.l3_agents = [self._create_l3_agent(self.hosts[i], - self.adminContext, 'legacy', self.l3_plugin, + self.adminContext, 'legacy', (i >= down_agent_count)) for i in range(agent_count)] def _create_routers(self, scheduled_router_count, @@ -549,3 +559,274 @@ class L3AZAutoScheduleTestCaseBase(L3AZSchedulerBaseTest): for i in range(self.az_count): self.assertEqual(self.expected_scheduled_agent_count[i], scheduled_azs.get('az%s' % i, 0)) + + +class L3DVRSchedulerBaseTest(L3SchedulerBaseTest): + + """Base class for functional test of DVR L3 schedulers. + Provides basic setup and utility functions. + """ + + def setUp(self): + super(L3DVRSchedulerBaseTest, self).setUp() + + self.default_ext_net_id = _uuid() + self.default_ext_subnet_id = _uuid() + + self.router_ext_net_id = _uuid() + self.router_ext_subnet_id = _uuid() + + def _create_router(self, name, distributed, ext_net_id=None): + router = {'name': name, 'admin_state_up': True, + 'tenant_id': self.adminContext.tenant_id, + 'distributed': distributed} + + if ext_net_id: + router['external_gateway_info'] = {'network_id': ext_net_id} + + return self.l3_plugin.create_router(self.adminContext, + {'router': router}) + + def _create_network(self, net_id, name=None, external=False): + network_dict = {'tenant_id': self.adminContext.tenant_id, + 'id': net_id, + 'name': name, + 'admin_state_up': True, + 'shared': False, + 'status': constants.NET_STATUS_ACTIVE} + network = self.plugin.create_network(self.adminContext, + {'network': network_dict}) + if external: + with self.adminContext.session.begin(): + network = external_net_db.ExternalNetwork(network_id=net_id) + self.adminContext.session.add(network) + + return network + + def _create_subnet(self, sub_id, network_id, cidr, gw_ip, name='test_sub'): + subnet = {'tenant_id': self.adminContext.tenant_id, + 'id': sub_id, + 'name': name, + 'network_id': network_id, + 'ip_version': 4, + 'cidr': cidr, + 'enable_dhcp': False, + 'gateway_ip': gw_ip, + 'shared': False, + 'allocation_pools': attributes.ATTR_NOT_SPECIFIED, + 'dns_nameservers': attributes.ATTR_NOT_SPECIFIED, + 'host_routes': attributes.ATTR_NOT_SPECIFIED} + + return self.plugin.create_subnet(self.adminContext, {'subnet': subnet}) + + +class L3DVRSchedulerTestCase(L3DVRSchedulerBaseTest): + + """Test various scenarios for L3 DVR schedulers: + + agent_mode + L3 agent mode. + + second_agent_mode + Second L3 agent mode for scenarios with two agents. + + agent_has_ext_network + Is there external network on the host. + + router_is_distributed + Is router distributed. + + router_already_hosted + Is router already hosted. + + router_has_ext_gw + Does router have external gateway. + + router_agent_have_same_ext_net + Do router and agent have the same external network. + + expected_router_scheduled + To verify do we expect router to get scheduled. + """ + + def get_scenario(agent_mode=constants.L3_AGENT_MODE_DVR_SNAT, + second_agent_mode=None, + agent_has_ext_network=False, + router_is_distributed=False, + router_already_hosted=False, + router_has_ext_gw=False, + router_agent_have_same_ext_net=False, + expected_router_scheduled=False): + return dict(agent_mode=agent_mode, + second_agent_mode=second_agent_mode, + agent_has_ext_network=agent_has_ext_network, + router_is_distributed=router_is_distributed, + router_already_hosted=router_already_hosted, + router_has_ext_gw=router_has_ext_gw, + router_agent_have_same_ext_net=router_agent_have_same_ext_net, + expected_router_scheduled=expected_router_scheduled) + + scenarios = [ + ('Legacy router not scheduled on dvr agent', + get_scenario(agent_mode=constants.L3_AGENT_MODE_DVR)), + + ('Legacy router scheduled on dvr_snat agent', + get_scenario(expected_router_scheduled=True)), + + ('Distributed router not scheduled on legacy agent', + get_scenario(agent_mode=constants.L3_AGENT_MODE_LEGACY, + router_is_distributed=True)), + + ('Distributed router not scheduled on dvr agent', + get_scenario(agent_mode=constants.L3_AGENT_MODE_DVR, + router_is_distributed=True)), + + ('Distributed router scheduled on dvr_snat agent', + get_scenario(router_is_distributed=True, + expected_router_scheduled=True)), + + ('Already hosted legacy router not scheduled on dvr agent', + get_scenario(agent_mode=constants.L3_AGENT_MODE_DVR, + router_already_hosted=True)), + + ('Already hosted legacy router not scheduled on dvr_snat agent', + get_scenario(router_already_hosted=True)), + + ('Already hosted distributed router not scheduled on legacy agent', + get_scenario(agent_mode=constants.L3_AGENT_MODE_LEGACY, + router_already_hosted=True, + router_is_distributed=True)), + + ('Already hosted distributed router not scheduled on dvr agent', + get_scenario(agent_mode=constants.L3_AGENT_MODE_DVR, + router_is_distributed=True, + router_already_hosted=True)), + + ('Already hosted distributed router not scheduled on dvr_snat agent', + get_scenario(router_is_distributed=True, + router_already_hosted=True)), + + ('Already hosted legacy router not scheduled on additional dvr agent', + get_scenario(agent_mode=constants.L3_AGENT_MODE_LEGACY, + second_agent_mode=constants.L3_AGENT_MODE_DVR_SNAT, + router_already_hosted=True)), + + ('Distributed router not scheduled if it is on a different ' + 'external network than the dvr_snat agent', + get_scenario(agent_has_ext_network=True, + router_is_distributed=True, + router_has_ext_gw=True, + router_agent_have_same_ext_net=False)), + ] + + def setUp(self): + super(L3DVRSchedulerTestCase, self).setUp() + + agent_cnt = 2 if self.second_agent_mode else 1 + + # create hosts for each agent + self.hosts = ['host-%s' % i for i in range(agent_cnt)] + + # create default external network + self._create_network(self.default_ext_net_id, + name='_test-ext-net', external=True) + self._create_subnet(self.default_ext_subnet_id, + self.default_ext_net_id, + '10.10.9.0/24', '10.10.9.1', + '_test-ext-net-subnet') + + if self.router_has_ext_gw and not self.router_agent_have_same_ext_net: + # for the test cases in which router and agent are not on same + # external network, we create an external network for router + self._create_network(self.router_ext_net_id, + name='_test-ext-net2', external=True) + self._create_subnet(self.router_ext_subnet_id, + self.router_ext_net_id, + '10.10.8.0/24', '10.10.8.1', + '_test-ext-net2-subnet') + # create agents: + self.l3_agents = [self._create_l3_agent(self.hosts[0], + self.adminContext, self.agent_mode, True, + self.default_ext_net_id if self.agent_has_ext_network else '')] + if self.second_agent_mode: + self.l3_agents.append(self._create_l3_agent(self.hosts[1], + self.adminContext, self.second_agent_mode, True, + self.default_ext_net_id if self.agent_has_ext_network else '')) + + # The router to schedule: + self.router_to_schedule = self._create_router_to_schedule() + + def _create_router_to_schedule(self): + router_to_schedule = None + + if self.router_has_ext_gw: + if self.router_agent_have_same_ext_net: + router_to_schedule = self._create_router('schd_rtr', + self.router_is_distributed, + self.default_ext_net_id) + else: + router_to_schedule = self._create_router('schd_rtr', + self.router_is_distributed, + self.router_ext_net_id) + else: + router_to_schedule = self._create_router('schd_rtr', + self.router_is_distributed) + + return router_to_schedule + + def _test_schedule_router(self): + if self.router_already_hosted: + self.scheduler.bind_router(self.adminContext, + self.router_to_schedule['id'], + self.l3_agents[0]) + + # schedule: + actual_scheduled_agent = self.scheduler.schedule( + self.l3_plugin, + self.adminContext, + self.router_to_schedule['id']) + + # check for router scheduling: + self.assertEqual(self.expected_router_scheduled, + bool(actual_scheduled_agent), + message='Failed to schedule agent') + + def _test_auto_schedule_routers(self): + if self.router_already_hosted: + self.scheduler.bind_router(self.adminContext, + self.router_to_schedule['id'], + self.l3_agents[0]) + did_it_schedule = False + + # schedule: + for host in self.hosts: + did_it_schedule = self.scheduler.auto_schedule_routers( + self.l3_plugin, self.adminContext, + host, [self.router_to_schedule['id']]) + if did_it_schedule: + break + + if self.router_already_hosted: + self.assertFalse(did_it_schedule, + 'Agent pre scheduled, yet no binding found!') + elif self.expected_router_scheduled: + self.assertTrue(did_it_schedule, + 'Agent not scheduled, not expected') + else: + self.assertFalse(did_it_schedule, 'Agent scheduled, not expected') + + def test_least_routers_schedule_router(self): + self.scheduler = l3_agent_scheduler.LeastRoutersScheduler() + self._test_schedule_router() + + def test_least_routers_auto_schedule_routers(self): + self.scheduler = l3_agent_scheduler.LeastRoutersScheduler() + self._test_auto_schedule_routers() + + def test_chance_schedule_router(self): + self.scheduler = l3_agent_scheduler.ChanceScheduler() + self._test_schedule_router() + + def test_chance_auto_schedule_routers(self): + self.scheduler = l3_agent_scheduler.ChanceScheduler() + self._test_auto_schedule_routers()