Add list routes
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
This commit is contained in:
parent
d91f6ee911
commit
da4ee8c8d2
|
@ -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)
|
||||
|
||||
|
|
|
@ -597,19 +597,45 @@ class IpRouteCommand(IpDeviceCommandBase):
|
|||
raise exceptions.DeviceNotFoundError(
|
||||
device_name=self.name)
|
||||
|
||||
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
|
||||
def _parse_routes(self, ip_version, output, **kwargs):
|
||||
for line in output.splitlines():
|
||||
parts = line.split()
|
||||
|
||||
return [x for x in iterate_routes()]
|
||||
# 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):
|
||||
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)
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue