diff --git a/neutron/agent/l3/router_info.py b/neutron/agent/l3/router_info.py index 4568d704e7b..beac1c8c903 100644 --- a/neutron/agent/l3/router_info.py +++ b/neutron/agent/l3/router_info.py @@ -567,6 +567,9 @@ class RouterInfo(object): self.agent.pd.enable_subnet(self.router_id, subnet['id'], subnet['cidr'], interface_name, p['mac_address']) + if (subnet['cidr'] != + lib_constants.PROVISIONAL_IPV6_PD_PREFIX): + self.pd_subnets[subnet['id']] = subnet['cidr'] for p in old_ports: self.internal_network_removed(p) diff --git a/neutron/tests/common/l3_test_common.py b/neutron/tests/common/l3_test_common.py index b70eb9ecf1c..4929c3fb78e 100644 --- a/neutron/tests/common/l3_test_common.py +++ b/neutron/tests/common/l3_test_common.py @@ -269,7 +269,9 @@ def router_append_subnet(router, count=1, ip_version=4, router[lib_constants.INTERFACE_KEY] = interfaces -def router_append_pd_enabled_subnet(router, count=1): +def router_append_pd_enabled_subnet(router, count=1, prefix=None): + if not prefix: + prefix = lib_constants.PROVISIONAL_IPV6_PD_PREFIX interfaces = router[lib_constants.INTERFACE_KEY] current = sum(netaddr.IPNetwork(subnet['cidr']).version == 6 for p in interfaces for subnet in p['subnets']) @@ -288,7 +290,7 @@ def router_append_pd_enabled_subnet(router, count=1): 'subnet_id': subnet_id}], 'mac_address': str(mac_address), 'subnets': [{'id': subnet_id, - 'cidr': lib_constants.PROVISIONAL_IPV6_PD_PREFIX, + 'cidr': prefix, 'gateway_ip': '::1', 'ipv6_ra_mode': lib_constants.IPV6_SLAAC, 'subnetpool_id': lib_constants.IPV6_PD_POOL_ID}]} @@ -308,6 +310,17 @@ def get_unassigned_pd_interfaces(router): return pd_intfs +def get_assigned_pd_interfaces(router): + pd_intfs = [] + for intf in router[lib_constants.INTERFACE_KEY]: + for subnet in intf['subnets']: + if (ipv6_utils.is_ipv6_pd_enabled(subnet) and + subnet['cidr'] != + lib_constants.PROVISIONAL_IPV6_PD_PREFIX): + pd_intfs.append(intf) + return pd_intfs + + def assign_prefix_for_pd_interfaces(router): pd_intfs = [] for ifno, intf in enumerate(router[lib_constants.INTERFACE_KEY]): diff --git a/neutron/tests/unit/agent/l3/test_agent.py b/neutron/tests/unit/agent/l3/test_agent.py index 33f24b97150..50b13d9465c 100644 --- a/neutron/tests/unit/agent/l3/test_agent.py +++ b/neutron/tests/unit/agent/l3/test_agent.py @@ -3143,6 +3143,36 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework): gw_ifname = ri.get_external_device_name(ri.router['gw_port']['id']) agent.pd.add_gw_interface(ri.router['id'], gw_ifname) + @mock.patch.object(pd.PrefixDelegation, 'update_subnet') + @mock.patch.object(dibbler.PDDibbler, 'get_prefix', autospec=True) + @mock.patch.object(dibbler.os, 'getpid', return_value=1234) + @mock.patch.object(pd.PrefixDelegation, '_is_lla_active', + return_value=True) + @mock.patch.object(dibbler.os, 'chmod') + @mock.patch.object(dibbler.shutil, 'rmtree') + @mock.patch.object(pd.PrefixDelegation, '_get_sync_data') + def test_pd_have_subnet(self, mock1, mock2, mock3, mock4, + mock_getpid, mock_get_prefix, + mock_pd_update_subnet): + '''Add one pd-enabled subnet that has already been assigned + ''' + prefix = '2001:db8:10::/64' + + # Initial setup + agent, router, ri = self._pd_setup_agent_router() + + # Create one pd-enabled subnet and add router interface + l3_test_common.router_append_pd_enabled_subnet(router, prefix=prefix) + ri.process() + + pd_intfs = l3_test_common.get_assigned_pd_interfaces(router) + subnet_id = pd_intfs[0]['subnets'][0]['id'] + + # Check that _process_pd_iptables_rules() is called correctly + self.assertEqual({subnet_id: prefix}, ri.pd_subnets) + ri._process_pd_iptables_rules.assert_called_once_with(prefix, + subnet_id) + @mock.patch.object(pd.PrefixDelegation, 'update_subnet') @mock.patch.object(dibbler.PDDibbler, 'get_prefix', autospec=True) @mock.patch.object(dibbler.os, 'getpid', return_value=1234) @@ -3164,6 +3194,9 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework): l3_test_common.router_append_pd_enabled_subnet(router) ri.process() + # Provisional PD prefix on startup, so nothing cached + self.assertEqual({}, ri.pd_subnets) + # No client should be started since there is no gateway port self.assertFalse(self.external_process.call_count) self.assertFalse(mock_get_prefix.call_count)