]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
No IPv6 SLAAC addrs for create router intf without fixed_ips
authorDane LeBlanc <leblancd@cisco.com>
Sun, 15 Mar 2015 00:54:16 +0000 (20:54 -0400)
committerDane LeBlanc <leblancd@cisco.com>
Wed, 25 Mar 2015 19:00:51 +0000 (15:00 -0400)
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

neutron/db/db_base_plugin_v2.py
neutron/tests/unit/test_db_plugin.py

index 5866326414c4a29e16248a49841b00b87e86dec6..e5b9f8cc5e1cd980f12b1f1ef2c2d66130b64b18 100644 (file)
@@ -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:
index 9daff92822e22fb06090f48e11d31bde30d7593e..21abf8dc142cf32fee857b049caadb2325ccd7d9 100644 (file)
@@ -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(