]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Add list routes
authorCarl Baldwin <carl.baldwin@hp.com>
Fri, 28 Aug 2015 21:28:39 +0000 (21:28 +0000)
committerCarl Baldwin <carl@ecbaldwin.net>
Wed, 9 Sep 2015 20:58:58 +0000 (20:58 +0000)
This adds list routes while refactoring list_onlink_routes to share
implementation.  It changes test_onlink_routes to be consistent in the
type of data that it returns with the new list_routes.

Change-Id: I386a8e2cb146385bb59a7a8387a29dddbec48d8a
Partially-Implements: blueprint address-scopes

neutron/agent/linux/interface.py
neutron/agent/linux/ip_lib.py
neutron/tests/unit/agent/linux/test_interface.py
neutron/tests/unit/agent/linux/test_ip_lib.py

index 090b62def7c6dfbefa8edc8c0191fe0ad7313fca..44a0ad834befec09aca8515b2e42604fecf0394a 100644 (file)
@@ -183,14 +183,16 @@ class LinuxInterfaceDriver(object):
         device = ip_lib.IPDevice(device_name, namespace=namespace)
 
         # Manage on-link routes (routes without an associated address)
-        new_onlink_routes = set(s['cidr'] for s in extra_subnets or [])
-        existing_onlink_routes = set(
-            device.route.list_onlink_routes(n_const.IP_VERSION_4) +
-            device.route.list_onlink_routes(n_const.IP_VERSION_6))
-        for route in new_onlink_routes - existing_onlink_routes:
+        new_onlink_cidrs = set(s['cidr'] for s in extra_subnets or [])
+
+        v4_onlink = device.route.list_onlink_routes(n_const.IP_VERSION_4)
+        v6_onlink = device.route.list_onlink_routes(n_const.IP_VERSION_6)
+        existing_onlink_cidrs = set(r['cidr'] for r in v4_onlink + v6_onlink)
+
+        for route in new_onlink_cidrs - existing_onlink_cidrs:
             LOG.debug("adding onlink route(%s)", route)
             device.route.add_onlink_route(route)
-        for route in existing_onlink_routes - new_onlink_routes:
+        for route in existing_onlink_cidrs - new_onlink_cidrs:
             LOG.debug("deleting onlink route(%s)", route)
             device.route.delete_onlink_route(route)
 
index 961d55791475748c55233046ea25ed931da50282..1f26561c7cd12cf9be39071b79080d08d5e5af92 100644 (file)
@@ -597,19 +597,45 @@ class IpRouteCommand(IpDeviceCommandBase):
                     raise exceptions.DeviceNotFoundError(
                         device_name=self.name)
 
+    def _parse_routes(self, ip_version, output, **kwargs):
+        for line in output.splitlines():
+            parts = line.split()
+
+            # Format of line is: "<cidr>|default [<key> <value>] ..."
+            route = {k: v for k, v in zip(parts[1::2], parts[2::2])}
+            route['cidr'] = parts[0]
+            # Avoids having to explicitly pass around the IP version
+            if route['cidr'] == 'default':
+                route['cidr'] = constants.IP_ANY[ip_version]
+
+            # ip route drops things like scope and dev from the output if it
+            # was specified as a filter.  This allows us to add them back.
+            if self.name:
+                route['dev'] = self.name
+            if self._table:
+                route['table'] = self._table
+            # Callers add any filters they use as kwargs
+            route.update(kwargs)
+
+            yield route
+
+    def list_routes(self, ip_version):
+        args = ['list']
+        args += self._dev_args()
+        args += self._table_args()
+
+        output = self._run([ip_version], tuple(args))
+        return [r for r in self._parse_routes(ip_version, output)]
+
     def list_onlink_routes(self, ip_version):
-        def iterate_routes():
-            args = ['list']
-            args += self._dev_args()
-            args += ['scope', 'link']
-            args += self._table_args()
-            output = self._run([ip_version], tuple(args))
-            for line in output.split('\n'):
-                line = line.strip()
-                if line and not line.count('src'):
-                    yield line
-
-        return [x for x in iterate_routes()]
+        args = ['list']
+        args += self._dev_args()
+        args += ['scope', 'link']
+        args += self._table_args()
+
+        output = self._run([ip_version], tuple(args))
+        return [r for r in self._parse_routes(ip_version, output, scope='link')
+                if 'src' not in r]
 
     def add_onlink_route(self, cidr):
         ip_version = get_ip_version(cidr)
index ffa0f6e06366edee0a63ecd81190475b41ce197e..38185ead6880d46f86a055fc34c7dca97d8aa514 100644 (file)
@@ -104,7 +104,8 @@ class TestABCDriver(TestBase):
         addresses = [dict(scope='global',
                           dynamic=False, cidr='172.16.77.240/24')]
         self.ip_dev().addr.list = mock.Mock(return_value=addresses)
-        self.ip_dev().route.list_onlink_routes.return_value = ['172.20.0.0/24']
+        self.ip_dev().route.list_onlink_routes.return_value = [
+            {'cidr': '172.20.0.0/24'}]
 
         bc = BaseChild(self.conf)
         ns = '12345678-1234-5678-90ab-ba0987654321'
@@ -218,7 +219,7 @@ class TestABCDriver(TestBase):
                           dynamic=False, cidr='2001:db8:a::123/64')]
         route = '2001:db8:a::/64'
         self.ip_dev().addr.list = mock.Mock(return_value=addresses)
-        self.ip_dev().route.list_onlink_routes.return_value = [route]
+        self.ip_dev().route.list_onlink_routes.return_value = [{'cidr': route}]
 
         bc = BaseChild(self.conf)
         ns = '12345678-1234-5678-90ab-ba0987654321'
index b49a0d0ff5bf9674309ff605a6b879429a0ac40d..dfa6d04bc3b49887093f1a7d5ed7e7e952d60c86 100644 (file)
@@ -959,13 +959,34 @@ class TestIpRouteCommand(TestIPCmdBase):
                            'dev', self.parent.name,
                            'table', self.table))
 
+    def test_list_routes(self):
+        self.parent._run.return_value = (
+            "default via 172.124.4.1 dev eth0 metric 100\n"
+            "10.0.0.0/22 dev eth0 scope link\n"
+            "172.24.4.0/24 dev eth0 proto kernel src 172.24.4.2\n")
+        routes = self.route_cmd.table(self.table).list_routes(self.ip_version)
+        self.assertEqual([{'cidr': '0.0.0.0/0',
+                           'dev': 'eth0',
+                           'metric': '100',
+                           'table': 14,
+                           'via': '172.124.4.1'},
+                          {'cidr': '10.0.0.0/22',
+                           'dev': 'eth0',
+                           'scope': 'link',
+                           'table': 14},
+                          {'cidr': '172.24.4.0/24',
+                           'dev': 'eth0',
+                           'proto': 'kernel',
+                           'src': '172.24.4.2',
+                           'table': 14}], routes)
+
     def test_list_onlink_routes_subtable(self):
         self.parent._run.return_value = (
             "10.0.0.0/22\n"
             "172.24.4.0/24 proto kernel src 172.24.4.2\n")
         routes = self.route_cmd.table(self.table).list_onlink_routes(
             self.ip_version)
-        self.assertEqual(['10.0.0.0/22'], routes)
+        self.assertEqual(['10.0.0.0/22'], [r['cidr'] for r in routes])
         self._assert_call([self.ip_version],
                           ('list', 'dev', self.parent.name, 'scope', 'link',
                            'table', self.table))
@@ -1012,6 +1033,22 @@ class TestIPv6IpRouteCommand(TestIpRouteCommand):
                             {'gateway': '2001:470:9:1224:4508:b885:5fb:740b',
                              'metric': 1024}}]
 
+    def test_list_routes(self):
+        self.parent._run.return_value = (
+            "default via 2001:db8::1 dev eth0 metric 100\n"
+            "2001:db8::/64 dev eth0 proto kernel src 2001:db8::2\n")
+        routes = self.route_cmd.table(self.table).list_routes(self.ip_version)
+        self.assertEqual([{'cidr': '::/0',
+                           'dev': 'eth0',
+                           'metric': '100',
+                           'table': 14,
+                           'via': '2001:db8::1'},
+                          {'cidr': '2001:db8::/64',
+                           'dev': 'eth0',
+                           'proto': 'kernel',
+                           'src': '2001:db8::2',
+                           'table': 14}], routes)
+
 
 class TestIPRoute(TestIpRouteCommand):
     """Leverage existing tests for IpRouteCommand for IPRoute