From: Dane LeBlanc Date: Sun, 15 Mar 2015 00:54:16 +0000 (-0400) Subject: No IPv6 SLAAC addrs for create router intf without fixed_ips X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=d74603cb8136bf8b9574e7197892f8f762221688;p=openstack-build%2Fneutron-build.git No IPv6 SLAAC addrs for create router intf without fixed_ips Consider the following sequence: - Create a neutron network - Create multiple subnets on the network, including one or more IPv6 SLAAC subnets - Create a router port on the network without specifying fixed_ips The port created in this case is incorrectly getting associated with addresses from the SLAAC subnet(s). This patch corrects this behavior. Change-Id: Ic0ab2294c5487f85baade8f879946dfe738d109b Closes-Bug: 1432270 --- diff --git a/neutron/db/db_base_plugin_v2.py b/neutron/db/db_base_plugin_v2.py index 586632641..e5b9f8cc5 100644 --- a/neutron/db/db_base_plugin_v2.py +++ b/neutron/db/db_base_plugin_v2.py @@ -530,6 +530,9 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2, v6_stateless = [] net_id_filter = {'network_id': [p['network_id']]} subnets = self.get_subnets(context, filters=net_id_filter) + is_router_port = ( + p['device_owner'] in constants.ROUTER_INTERFACE_OWNERS or + p['device_owner'] == constants.DEVICE_OWNER_ROUTER_SNAT) fixed_configured = p['fixed_ips'] is not attributes.ATTR_NOT_SPECIFIED if fixed_configured: @@ -543,8 +546,7 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2, # For ports that are not router ports, implicitly include all # auto-address subnets for address association. - if (not p['device_owner'] in constants.ROUTER_INTERFACE_OWNERS and - p['device_owner'] != constants.DEVICE_OWNER_ROUTER_SNAT): + if not is_router_port: v6_stateless += [subnet for subnet in subnets if ipv6_utils.is_auto_address_subnet(subnet)] else: @@ -554,11 +556,11 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2, for subnet in subnets: if subnet['ip_version'] == 4: v4.append(subnet) - else: - if ipv6_utils.is_auto_address_subnet(subnet): + elif ipv6_utils.is_auto_address_subnet(subnet): + if not is_router_port: v6_stateless.append(subnet) - else: - v6_stateful.append(subnet) + else: + v6_stateful.append(subnet) version_subnets = [v4, v6_stateful] for subnets in version_subnets: diff --git a/neutron/tests/unit/test_db_plugin.py b/neutron/tests/unit/test_db_plugin.py index 9daff9282..21abf8dc1 100644 --- a/neutron/tests/unit/test_db_plugin.py +++ b/neutron/tests/unit/test_db_plugin.py @@ -1677,6 +1677,25 @@ fixed_ips=ip_address%%3D%s&fixed_ips=ip_address%%3D%s&fixed_ips=subnet_id%%3D%s self.assertIn({'ip_address': eui_addr, 'subnet_id': subnet2['subnet']['id']}, ips) + def test_create_router_port_ipv4_and_ipv6_slaac_no_fixed_ips(self): + with self.network() as network: + # Create an IPv4 and an IPv6 SLAAC subnet on the network + with contextlib.nested( + self.subnet(network), + self.subnet(network, + cidr='2607:f0d0:1002:51::/64', + ip_version=6, + gateway_ip='fe80::1', + ipv6_address_mode=constants.IPV6_SLAAC)): + # Create a router port without specifying fixed_ips + port = self._make_port( + self.fmt, network['network']['id'], + device_owner=constants.DEVICE_OWNER_ROUTER_INTF) + # Router port should only have an IPv4 address + fixed_ips = port['port']['fixed_ips'] + self.assertEqual(1, len(fixed_ips)) + self.assertEqual('10.0.0.2', fixed_ips[0]['ip_address']) + def _make_v6_subnet(self, network, ra_addr_mode): return (self._make_subnet(self.fmt, network, gateway='fe80::1', cidr='fe80::/64', ip_version=6, @@ -3025,11 +3044,13 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase): cidr='fe80::/64', ip_version=6, ipv6_ra_mode=constants.IPV6_SLAAC, ipv6_address_mode=constants.IPV6_SLAAC) + kwargs = {} if port_owner: - res = self._create_port(self.fmt, net_id=network['network']['id'], - device_owner=port_owner) - else: - res = self._create_port(self.fmt, net_id=network['network']['id']) + kwargs['device_owner'] = port_owner + if port_owner in constants.ROUTER_INTERFACE_OWNERS: + kwargs['fixed_ips'] = [{'ip_address': 'fe80::1'}] + res = self._create_port(self.fmt, net_id=network['network']['id'], + **kwargs) port = self.deserialize(self.fmt, res) self.assertEqual(1, len(port['port']['fixed_ips'])) @@ -4960,7 +4981,8 @@ class TestNeutronDbPluginV2(base.BaseTestCase): port = {'port': { 'network_id': 'fbb9b578-95eb-4b79-a116-78e5c4927176', 'fixed_ips': attributes.ATTR_NOT_SPECIFIED, - 'mac_address': '12:34:56:78:44:ab'}} + 'mac_address': '12:34:56:78:44:ab', + 'device_owner': 'compute'}} expected = [] for subnet in subnets: addr = str(ipv6_utils.get_ipv6_addr_by_EUI64(