Merge "Implement "RouterInfo.update_routing_table" with Pyroute2"
This commit is contained in:
commit
82339b9211
@ -230,8 +230,7 @@ class DvrEdgeRouter(dvr_local_router.DvrLocalRouter):
|
|||||||
# NOTE: For now let us apply the static routes both in SNAT
|
# NOTE: For now let us apply the static routes both in SNAT
|
||||||
# namespace and Router Namespace, to reduce the complexity.
|
# namespace and Router Namespace, to reduce the complexity.
|
||||||
if self.snat_namespace.exists():
|
if self.snat_namespace.exists():
|
||||||
super(DvrEdgeRouter, self)._update_routing_table(
|
self._update_routing_table(operation, route, ns_name)
|
||||||
operation, route, namespace=ns_name)
|
|
||||||
else:
|
else:
|
||||||
LOG.error("The SNAT namespace %s does not exist for "
|
LOG.error("The SNAT namespace %s does not exist for "
|
||||||
"the router.", ns_name)
|
"the router.", ns_name)
|
||||||
|
@ -20,6 +20,7 @@ from neutron_lib import constants as lib_constants
|
|||||||
from neutron_lib.exceptions import l3 as l3_exc
|
from neutron_lib.exceptions import l3 as l3_exc
|
||||||
from neutron_lib.utils import helpers
|
from neutron_lib.utils import helpers
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
from pyroute2.netlink import exceptions as pyroute2_exc
|
||||||
|
|
||||||
from neutron._i18n import _
|
from neutron._i18n import _
|
||||||
from neutron.agent.l3 import namespaces
|
from neutron.agent.l3 import namespaces
|
||||||
@ -173,10 +174,12 @@ class RouterInfo(BaseRouterInfo):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def _update_routing_table(self, operation, route, namespace):
|
def _update_routing_table(self, operation, route, namespace):
|
||||||
cmd = ['ip', 'route', operation, 'to', route['destination'],
|
method = (ip_lib.add_ip_route if operation == 'replace' else
|
||||||
'via', route['nexthop']]
|
ip_lib.delete_ip_route)
|
||||||
ip_wrapper = ip_lib.IPWrapper(namespace=namespace)
|
try:
|
||||||
ip_wrapper.netns.execute(cmd, check_exit_code=False)
|
method(namespace, route['destination'], via=route['nexthop'])
|
||||||
|
except (RuntimeError, OSError, pyroute2_exc.NetlinkError):
|
||||||
|
pass
|
||||||
|
|
||||||
def update_routing_table(self, operation, route):
|
def update_routing_table(self, operation, route):
|
||||||
self._update_routing_table(operation, route, self.ns_name)
|
self._update_routing_table(operation, route, self.ns_name)
|
||||||
|
@ -37,13 +37,20 @@ class TestRouterInfo(base.BaseTestCase):
|
|||||||
ip_cls = self.ip_cls_p.start()
|
ip_cls = self.ip_cls_p.start()
|
||||||
self.mock_ip = mock.MagicMock()
|
self.mock_ip = mock.MagicMock()
|
||||||
ip_cls.return_value = self.mock_ip
|
ip_cls.return_value = self.mock_ip
|
||||||
|
self.mock_add_ip_route = mock.patch.object(
|
||||||
|
ip_lib, 'add_ip_route').start()
|
||||||
|
self.mock_delete_ip_route = mock.patch.object(
|
||||||
|
ip_lib, 'delete_ip_route').start()
|
||||||
self.ri_kwargs = {'agent_conf': conf,
|
self.ri_kwargs = {'agent_conf': conf,
|
||||||
'interface_driver': mock.sentinel.interface_driver}
|
'interface_driver': mock.sentinel.interface_driver}
|
||||||
|
|
||||||
def _check_agent_method_called(self, calls):
|
def _check_agent_method_called(self, router, action_calls):
|
||||||
self.mock_ip.netns.execute.assert_has_calls(
|
for action, calls in action_calls.items():
|
||||||
[mock.call(call, check_exit_code=False) for call in calls],
|
mock_calls = [mock.call(router.ns_name, c[0], via=c[1])
|
||||||
any_order=True)
|
for c in calls]
|
||||||
|
mock_method = (self.mock_add_ip_route if action == 'replace' else
|
||||||
|
self.mock_delete_ip_route)
|
||||||
|
mock_method.assert_has_calls(mock_calls, any_order=True)
|
||||||
|
|
||||||
def test_routing_table_update(self):
|
def test_routing_table_update(self):
|
||||||
ri = router_info.RouterInfo(mock.Mock(), _uuid(), {}, **self.ri_kwargs)
|
ri = router_info.RouterInfo(mock.Mock(), _uuid(), {}, **self.ri_kwargs)
|
||||||
@ -55,24 +62,20 @@ class TestRouterInfo(base.BaseTestCase):
|
|||||||
'nexthop': '1.2.3.4'}
|
'nexthop': '1.2.3.4'}
|
||||||
|
|
||||||
ri.update_routing_table('replace', fake_route1)
|
ri.update_routing_table('replace', fake_route1)
|
||||||
expected = [['ip', 'route', 'replace', 'to', '135.207.0.0/16',
|
expected = {'replace': [('135.207.0.0/16', '1.2.3.4')]}
|
||||||
'via', '1.2.3.4']]
|
self._check_agent_method_called(ri, expected)
|
||||||
self._check_agent_method_called(expected)
|
|
||||||
|
|
||||||
ri.update_routing_table('delete', fake_route1)
|
ri.update_routing_table('delete', fake_route1)
|
||||||
expected = [['ip', 'route', 'delete', 'to', '135.207.0.0/16',
|
expected = {'delete': [('135.207.0.0/16', '1.2.3.4')]}
|
||||||
'via', '1.2.3.4']]
|
self._check_agent_method_called(ri, expected)
|
||||||
self._check_agent_method_called(expected)
|
|
||||||
|
|
||||||
ri.update_routing_table('replace', fake_route2)
|
ri.update_routing_table('replace', fake_route2)
|
||||||
expected = [['ip', 'route', 'replace', 'to', '135.207.111.111/32',
|
expected = {'replace': [('135.207.111.111/32', '1.2.3.4')]}
|
||||||
'via', '1.2.3.4']]
|
self._check_agent_method_called(ri, expected)
|
||||||
self._check_agent_method_called(expected)
|
|
||||||
|
|
||||||
ri.update_routing_table('delete', fake_route2)
|
ri.update_routing_table('delete', fake_route2)
|
||||||
expected = [['ip', 'route', 'delete', 'to', '135.207.111.111/32',
|
expected = {'delete': [('135.207.111.111/32', '1.2.3.4')]}
|
||||||
'via', '1.2.3.4']]
|
self._check_agent_method_called(ri, expected)
|
||||||
self._check_agent_method_called(expected)
|
|
||||||
|
|
||||||
def test_update_routing_table(self):
|
def test_update_routing_table(self):
|
||||||
# Just verify the correct namespace was used in the call
|
# Just verify the correct namespace was used in the call
|
||||||
@ -103,28 +106,22 @@ class TestRouterInfo(base.BaseTestCase):
|
|||||||
ri.router['routes'] = fake_new_routes
|
ri.router['routes'] = fake_new_routes
|
||||||
ri.routes_updated(fake_old_routes, fake_new_routes)
|
ri.routes_updated(fake_old_routes, fake_new_routes)
|
||||||
|
|
||||||
expected = [['ip', 'route', 'replace', 'to', '110.100.30.0/24',
|
expected = {'replace': [('110.100.30.0/24', '10.100.10.30'),
|
||||||
'via', '10.100.10.30'],
|
('110.100.31.0/24', '10.100.10.30')]}
|
||||||
['ip', 'route', 'replace', 'to', '110.100.31.0/24',
|
self._check_agent_method_called(ri, expected)
|
||||||
'via', '10.100.10.30']]
|
|
||||||
|
|
||||||
self._check_agent_method_called(expected)
|
|
||||||
ri.routes = fake_new_routes
|
ri.routes = fake_new_routes
|
||||||
fake_new_routes = [{'destination': "110.100.30.0/24",
|
fake_new_routes = [{'destination': "110.100.30.0/24",
|
||||||
'nexthop': "10.100.10.30"}]
|
'nexthop': "10.100.10.30"}]
|
||||||
ri.router['routes'] = fake_new_routes
|
ri.router['routes'] = fake_new_routes
|
||||||
ri.routes_updated(ri.routes, fake_new_routes)
|
ri.routes_updated(ri.routes, fake_new_routes)
|
||||||
expected = [['ip', 'route', 'delete', 'to', '110.100.31.0/24',
|
expected = {'delete': [('110.100.31.0/24', '10.100.10.30')]}
|
||||||
'via', '10.100.10.30']]
|
self._check_agent_method_called(ri, expected)
|
||||||
|
|
||||||
self._check_agent_method_called(expected)
|
|
||||||
fake_new_routes = []
|
fake_new_routes = []
|
||||||
ri.router['routes'] = fake_new_routes
|
ri.router['routes'] = fake_new_routes
|
||||||
ri.routes_updated(ri.routes, fake_new_routes)
|
ri.routes_updated(ri.routes, fake_new_routes)
|
||||||
|
|
||||||
expected = [['ip', 'route', 'delete', 'to', '110.100.30.0/24',
|
expected = {'delete': [('110.100.30.0/24', '10.100.10.30')]}
|
||||||
'via', '10.100.10.30']]
|
self._check_agent_method_called(ri, expected)
|
||||||
self._check_agent_method_called(expected)
|
|
||||||
|
|
||||||
def test__process_pd_iptables_rules(self):
|
def test__process_pd_iptables_rules(self):
|
||||||
subnet_id = _uuid()
|
subnet_id = _uuid()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user