Merge "[DVR] Allow multiple subnets per external network"
This commit is contained in:
commit
8d2a6e87ac
@ -193,6 +193,12 @@ class FipNamespace(namespaces.Namespace):
|
||||
self.driver.init_l3(interface_name, ip_cidrs, namespace=ns_name,
|
||||
clean_connections=True)
|
||||
|
||||
gw_cidrs = [sn['cidr'] for sn in ex_gw_port['subnets']
|
||||
if sn.get('cidr')]
|
||||
self.driver.set_onlink_routes(
|
||||
interface_name, ns_name, ex_gw_port.get('extra_subnets', []),
|
||||
preserve_ips=gw_cidrs, is_ipv6=False)
|
||||
|
||||
self.agent_gateway_port = ex_gw_port
|
||||
|
||||
cmd = ['sysctl', '-w', 'net.ipv4.conf.%s.proxy_arp=1' % interface_name]
|
||||
@ -313,17 +319,23 @@ class FipNamespace(namespaces.Namespace):
|
||||
priority=rt_tbl_index)
|
||||
|
||||
def _update_gateway_port(self, agent_gateway_port, interface_name):
|
||||
if (self.agent_gateway_port and
|
||||
not self._check_for_gateway_ip_change(agent_gateway_port)):
|
||||
return
|
||||
# Caller already holding lock
|
||||
self._update_gateway_route(
|
||||
agent_gateway_port, interface_name, tbl_index=None)
|
||||
if (not self.agent_gateway_port or
|
||||
self._check_for_gateway_ip_change(agent_gateway_port)):
|
||||
# Caller already holding lock
|
||||
self._update_gateway_route(
|
||||
agent_gateway_port, interface_name, tbl_index=None)
|
||||
|
||||
# Cache the agent gateway port after successfully updating
|
||||
# the gateway route, so that checking on self.agent_gateway_port
|
||||
# will be a valid check
|
||||
self.agent_gateway_port = agent_gateway_port
|
||||
# Cache the agent gateway port after successfully updating
|
||||
# the gateway route, so that checking on self.agent_gateway_port
|
||||
# will be a valid check
|
||||
self.agent_gateway_port = agent_gateway_port
|
||||
|
||||
gw_cidrs = [sn['cidr'] for sn in agent_gateway_port['subnets']
|
||||
if sn.get('cidr')]
|
||||
self.driver.set_onlink_routes(
|
||||
interface_name, self.get_name(),
|
||||
agent_gateway_port.get('extra_subnets', []), preserve_ips=gw_cidrs,
|
||||
is_ipv6=False)
|
||||
|
||||
def _update_gateway_route(self, agent_gateway_port,
|
||||
interface_name, tbl_index):
|
||||
|
@ -170,22 +170,34 @@ class LinuxInterfaceDriver(object):
|
||||
namespace=namespace,
|
||||
preserve_ips=preserve_ips or [],
|
||||
clean_connections=clean_connections)
|
||||
self.set_onlink_routes(device_name, namespace, extra_subnets,
|
||||
preserve_ips)
|
||||
|
||||
def set_onlink_routes(self, device_name, namespace, extra_subnets,
|
||||
preserve_ips=None, is_ipv6=True):
|
||||
"""Manage on-link routes (routes without an associate address)
|
||||
|
||||
:param device_name: interface name
|
||||
:param namespace: namespace name
|
||||
:param extra_subnets: subnets attached to this interface without an IP
|
||||
address set in this interface
|
||||
:param preserve_ips: IPs or CIDRs not to be deleted from the device
|
||||
on-link route list
|
||||
"""
|
||||
device = ip_lib.IPDevice(device_name, namespace=namespace)
|
||||
|
||||
# Manage on-link routes (routes without an associated address)
|
||||
new_onlink_cidrs = set(s['cidr'] for s in extra_subnets or [])
|
||||
preserve_ips = set(preserve_ips if preserve_ips else [])
|
||||
|
||||
v4_onlink = device.route.list_onlink_routes(constants.IP_VERSION_4)
|
||||
v6_onlink = device.route.list_onlink_routes(constants.IP_VERSION_6)
|
||||
existing_onlink_cidrs = set(r['cidr'] for r in v4_onlink + v6_onlink)
|
||||
onlink = device.route.list_onlink_routes(constants.IP_VERSION_4)
|
||||
if is_ipv6:
|
||||
onlink += device.route.list_onlink_routes(constants.IP_VERSION_6)
|
||||
existing_onlink_cidrs = set(r['cidr'] for r in onlink)
|
||||
|
||||
for route in new_onlink_cidrs - existing_onlink_cidrs:
|
||||
LOG.debug("adding onlink route(%s)", route)
|
||||
LOG.debug('Adding onlink route (%s)', route)
|
||||
device.route.add_onlink_route(route)
|
||||
for route in (existing_onlink_cidrs - new_onlink_cidrs -
|
||||
set(preserve_ips or [])):
|
||||
LOG.debug("deleting onlink route(%s)", route)
|
||||
for route in existing_onlink_cidrs - new_onlink_cidrs - preserve_ips:
|
||||
LOG.debug('Deleting onlink route (%s)', route)
|
||||
device.route.delete_onlink_route(route)
|
||||
|
||||
def add_ipv6_addr(self, device_name, v6addr, namespace, scope='global'):
|
||||
|
@ -601,6 +601,7 @@ class TestDvrRouter(framework.L3AgentTestFramework):
|
||||
{'cidr': float_subnet['cidr'],
|
||||
'gateway_ip': float_subnet['gateway_ip'],
|
||||
'id': fixed_ip['subnet_id']}],
|
||||
'extra_subnets': external_gw_port['extra_subnets'],
|
||||
'network_id': external_gw_port['network_id'],
|
||||
'device_owner': lib_constants.DEVICE_OWNER_AGENT_GW,
|
||||
'mac_address': 'fa:16:3e:80:8d:89',
|
||||
@ -631,6 +632,7 @@ class TestDvrRouter(framework.L3AgentTestFramework):
|
||||
{'cidr': float_subnet['cidr'],
|
||||
'gateway_ip': float_subnet['gateway_ip'],
|
||||
'id': fixed_ip['subnet_id']}],
|
||||
'extra_subnets': external_gw_port['extra_subnets'],
|
||||
'network_id': external_gw_port['network_id'],
|
||||
'device_owner': lib_constants.DEVICE_OWNER_AGENT_GW,
|
||||
'mac_address': 'fa:16:3e:80:8d:89',
|
||||
@ -2037,3 +2039,29 @@ class TestDvrRouter(framework.L3AgentTestFramework):
|
||||
ip_lib.IP_NONLOCAL_BIND))
|
||||
raise
|
||||
self.assertEqual(0, ip_nonlocal_bind_value)
|
||||
|
||||
def test_dvr_router_fip_namespace_routes(self):
|
||||
"""Test to validate the floatingip namespace subnets routes."""
|
||||
self.agent.conf.agent_mode = 'dvr'
|
||||
router_info = self.generate_dvr_router_info(enable_floating_ip=False)
|
||||
fip_agent_gw_port = self._get_fip_agent_gw_port_for_router(
|
||||
router_info['gw_port'])
|
||||
self.mock_plugin_api.get_agent_gateway_port.return_value = (
|
||||
fip_agent_gw_port)
|
||||
router1 = self.manage_router(self.agent, router_info)
|
||||
|
||||
fip_namespace = router1.fip_ns.get_name()
|
||||
ip_wrapper = ip_lib.IPWrapper(namespace=fip_namespace)
|
||||
interfaces = ip_wrapper.get_devices()
|
||||
fg_interface_name = next(
|
||||
interface.name for interface in interfaces
|
||||
if interface.name.startswith(dvr_fip_ns.FIP_EXT_DEV_PREFIX))
|
||||
|
||||
ip_device = ip_lib.IPDevice(fg_interface_name, namespace=fip_namespace)
|
||||
routes = ip_device.route.list_onlink_routes(lib_constants.IP_VERSION_4)
|
||||
self.assertGreater(len(routes), 0)
|
||||
self.assertEqual(len(fip_agent_gw_port['extra_subnets']), len(routes))
|
||||
extra_subnet_cidr = set(extra_subnet['cidr'] for extra_subnet
|
||||
in fip_agent_gw_port['extra_subnets'])
|
||||
routes_cidr = set(route['cidr'] for route in routes)
|
||||
self.assertEqual(extra_subnet_cidr, routes_cidr)
|
||||
|
@ -102,13 +102,21 @@ class TestDvrFipNs(base.BaseTestCase):
|
||||
agent_gw_port = self._get_agent_gw_port()
|
||||
|
||||
device_exists.return_value = False
|
||||
self.fip_ns.create_or_update_gateway_port(agent_gw_port)
|
||||
with mock.patch.object(self.fip_ns.driver, 'set_onlink_routes') as \
|
||||
mock_set_onlink_routes:
|
||||
self.fip_ns.create_or_update_gateway_port(agent_gw_port)
|
||||
self.assertTrue(fip_create.called)
|
||||
self.assertEqual(1, self.driver.plug.call_count)
|
||||
ext_net_bridge = self.conf.external_network_bridge
|
||||
if ext_net_bridge:
|
||||
self.assertEqual(1, self.driver.remove_vlan_tag.call_count)
|
||||
self.assertEqual(1, self.driver.init_l3.call_count)
|
||||
interface_name = self.fip_ns.get_ext_device_name(agent_gw_port['id'])
|
||||
gw_cidrs = [sn['cidr'] for sn in agent_gw_port['subnets']
|
||||
if sn.get('cidr')]
|
||||
mock_set_onlink_routes.assert_called_once_with(
|
||||
interface_name, self.fip_ns.name, [], preserve_ips=gw_cidrs,
|
||||
is_ipv6=False)
|
||||
|
||||
@mock.patch.object(ip_lib, 'IPDevice')
|
||||
@mock.patch.object(ip_lib, 'send_ip_addr_adv_notif')
|
||||
@ -121,7 +129,8 @@ class TestDvrFipNs(base.BaseTestCase):
|
||||
agent_gw_port = self._get_agent_gw_port()
|
||||
interface_name = self.fip_ns.get_ext_device_name(agent_gw_port['id'])
|
||||
self.fip_ns.agent_gateway_port = agent_gw_port
|
||||
self.fip_ns.create_or_update_gateway_port(agent_gw_port)
|
||||
with mock.patch.object(self.fip_ns.driver, 'set_onlink_routes'):
|
||||
self.fip_ns.create_or_update_gateway_port(agent_gw_port)
|
||||
expected = [
|
||||
mock.call(self.fip_ns.get_name(),
|
||||
interface_name,
|
||||
@ -164,7 +173,8 @@ class TestDvrFipNs(base.BaseTestCase):
|
||||
agent_gw_port['subnets'][0]['gateway_ip'] = '20.0.1.1'
|
||||
self.fip_ns._check_for_gateway_ip_change = mock.Mock(return_value=True)
|
||||
self.fip_ns.agent_gateway_port = agent_gw_port
|
||||
self.fip_ns.create_or_update_gateway_port(agent_gw_port)
|
||||
with mock.patch.object(self.fip_ns.driver, 'set_onlink_routes'):
|
||||
self.fip_ns.create_or_update_gateway_port(agent_gw_port)
|
||||
|
||||
IPDevice().route.add_route.assert_called_once_with('20.0.1.1',
|
||||
scope='link')
|
||||
|
Loading…
x
Reference in New Issue
Block a user