From: Assaf Muller Date: Mon, 26 Jan 2015 15:37:43 +0000 (-0500) Subject: Add coverage for extra routes extension X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=7bbba6c738f26f49fbf18abc6a38f5a09e592221;p=openstack-build%2Fneutron-build.git Add coverage for extra routes extension Test the extra routes extension for legacy and HA routers in the L3 agent functional tests. Partially-Implements: bp/restructure-l3-agent Change-Id: I26444acf32652d1845ad0325a3a10b8a17c510c9 --- diff --git a/neutron/agent/linux/ip_lib.py b/neutron/agent/linux/ip_lib.py index dea22c466..ccb1be89e 100644 --- a/neutron/agent/linux/ip_lib.py +++ b/neutron/agent/linux/ip_lib.py @@ -597,6 +597,36 @@ def device_exists_with_ip_mac(device_name, ip_cidr, mac, namespace=None, return True +def get_routing_table(root_helper=None, namespace=None): + """Return a list of dictionaries, each representing a route. + + The dictionary format is: {'destination': cidr, + 'nexthop': ip, + 'device': device_name} + """ + + ip_wrapper = IPWrapper(root_helper, namespace=namespace) + table = ip_wrapper.netns.execute(['ip', 'route'], check_exit_code=True) + + routes = [] + # Example for route_lines: + # default via 192.168.3.120 dev wlp3s0 proto static metric 1024 + # 10.0.0.0/8 dev tun0 proto static scope link metric 1024 + # The first column is the destination, followed by key/value pairs. + # The generator splits the routing table by newline, then strips and splits + # each individual line. + route_lines = (line.split() for line in table.split('\n') if line.strip()) + for route in route_lines: + network = route[0] + # Create a dict of key/value pairs (For example - 'dev': 'tun0') + # excluding the first column. + data = dict(route[i:i + 2] for i in range(1, len(route), 2)) + routes.append({'destination': network, + 'nexthop': data.get('via'), + 'device': data.get('dev')}) + return routes + + def ensure_device_is_ready(device_name, root_helper=None, namespace=None): dev = IPDevice(device_name, root_helper, namespace) dev.set_log_fail_as_error(False) diff --git a/neutron/tests/functional/agent/linux/test_ip_lib.py b/neutron/tests/functional/agent/linux/test_ip_lib.py index 43ca327b6..ed8580437 100644 --- a/neutron/tests/functional/agent/linux/test_ip_lib.py +++ b/neutron/tests/functional/agent/linux/test_ip_lib.py @@ -15,6 +15,7 @@ import collections +import netaddr from oslo.config import cfg from oslo.utils import importutils @@ -130,3 +131,21 @@ class IpLibTestCase(IpLibTestFramework): *attr, root_helper=self.root_helper)) device.link.delete() + + def test_get_routing_table(self): + attr = self.generate_device_details() + device = self.manage_device(attr) + device_ip = attr.ip_cidr.split('/')[0] + destination = '8.8.8.0/24' + device.route.add_route(destination, device_ip) + + expected_routes = [{'nexthop': device_ip, + 'device': attr.name, + 'destination': destination}, + {'nexthop': None, + 'device': attr.name, + 'destination': str( + netaddr.IPNetwork(attr.ip_cidr).cidr)}] + + routes = ip_lib.get_routing_table(self.root_helper, attr.namespace) + self.assertEqual(expected_routes, routes) diff --git a/neutron/tests/functional/agent/test_l3_agent.py b/neutron/tests/functional/agent/test_l3_agent.py index 7ce844a21..fb1affec9 100755 --- a/neutron/tests/functional/agent/test_l3_agent.py +++ b/neutron/tests/functional/agent/test_l3_agent.py @@ -98,7 +98,8 @@ class L3AgentTestFramework(base.BaseOVSLinuxTestCase): def generate_router_info(self, enable_ha): return test_l3_agent.prepare_router_data(enable_snat=True, enable_floating_ip=True, - enable_ha=enable_ha) + enable_ha=enable_ha, + extra_routes=True) def manage_router(self, agent, router): self.addCleanup(self._delete_router, agent, router['id']) @@ -190,6 +191,7 @@ vrrp_instance VR_1 { } virtual_routes { 0.0.0.0/0 via %(default_gateway_ip)s dev %(external_device_name)s + 8.8.8.0/24 via 19.4.4.4 } }""" % { 'ha_confs_path': ha_confs_path, @@ -247,6 +249,14 @@ vrrp_instance VR_1 { self.assertTrue(self.device_exists_with_ip_mac( device, self.agent.get_internal_device_name, router.ns_name)) + def _assert_extra_routes(self, router): + routes = ip_lib.get_routing_table(self.root_helper, router.ns_name) + routes = [{'nexthop': route['nexthop'], + 'destination': route['destination']} for route in routes] + + for extra_route in router.router['routes']: + self.assertIn(extra_route, routes) + class L3AgentTestCase(L3AgentTestFramework): def test_observer_notifications_legacy_router(self): @@ -309,8 +319,15 @@ class L3AgentTestCase(L3AgentTestFramework): self.assertIn(new_fip, new_config) self.assertNotIn(old_gw, new_config) self.assertIn(new_gw, new_config) - self.assertNotIn(old_external_device_ip, new_config) - self.assertIn(new_external_device_ip, new_config) + external_port = self.agent._get_ex_gw_port(router) + external_device_name = self.agent.get_external_device_name( + external_port['id']) + self.assertNotIn('%s/24 dev %s' % + (old_external_device_ip, external_device_name), + new_config) + self.assertIn('%s/24 dev %s' % + (new_external_device_ip, external_device_name), + new_config) def _router_lifecycle(self, enable_ha): router_info = self.generate_router_info(enable_ha) @@ -343,6 +360,7 @@ class L3AgentTestCase(L3AgentTestFramework): self._assert_snat_chains(router) self._assert_floating_ip_chains(router) self._assert_metadata_chains(router) + self._assert_extra_routes(router) if enable_ha: self._assert_ha_device(router) @@ -546,6 +564,7 @@ class TestDvrRouter(L3AgentTestFramework): self._assert_snat_chains(router) self._assert_floating_ip_chains(router) self._assert_metadata_chains(router) + self._assert_extra_routes(router) self._delete_router(self.agent, router.router_id) self._assert_router_does_not_exist(router) diff --git a/neutron/tests/unit/test_l3_agent.py b/neutron/tests/unit/test_l3_agent.py index 7a1a067e8..bc28e5a8a 100644 --- a/neutron/tests/unit/test_l3_agent.py +++ b/neutron/tests/unit/test_l3_agent.py @@ -93,7 +93,8 @@ def router_append_interface(router, count=1, ip_version=4, ra_mode=None, def prepare_router_data(ip_version=4, enable_snat=None, num_internal_ports=1, - enable_floating_ip=False, enable_ha=False): + enable_floating_ip=False, enable_ha=False, + extra_routes=False): if ip_version == 4: ip_addr = '19.4.4.4' cidr = '19.4.4.0/24' @@ -114,11 +115,15 @@ def prepare_router_data(ip_version=4, enable_snat=None, num_internal_ports=1, 'subnet': {'cidr': cidr, 'gateway_ip': gateway_ip}} + routes = [] + if extra_routes: + routes = [{'destination': '8.8.8.0/24', 'nexthop': ip_addr}] + router = { 'id': router_id, 'distributed': False, l3_constants.INTERFACE_KEY: [], - 'routes': [], + 'routes': routes, 'gw_port': ex_gw_port} if enable_floating_ip: