]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Fix update_subnet for prefix delegation
authorJohn Davidge <jodavidg@cisco.com>
Fri, 7 Aug 2015 15:27:47 +0000 (16:27 +0100)
committerJohn Davidge <jodavidg@cisco.com>
Wed, 12 Aug 2015 15:00:07 +0000 (16:00 +0100)
A misnamed function call and execution order issue was causing
update_subnet to fail when a PD enabled subnet received a new CIDR.

This patch fixes the issues, and introduces an rpc api test to
ensure the function works. This includes altering the process_prefix_update
RPC handler to expose the issue to the test.

Change-Id: Id1e781291f711865fd783ed5e0208694097b7024
Closes-Bug: 1482676

neutron/api/rpc/handlers/l3_rpc.py
neutron/db/db_base_plugin_v2.py
neutron/tests/unit/api/rpc/handlers/test_l3_rpc.py [new file with mode: 0644]

index 176ddb229741923ad7d1aa2511e12fbf94cc9aef..b1129cc74a6c226eb667bc8c962be6cc1a13133b 100644 (file)
@@ -269,6 +269,10 @@ class L3RpcCallback(object):
     def process_prefix_update(self, context, **kwargs):
         subnets = kwargs.get('subnets')
 
+        updated_subnets = []
         for subnet_id, prefix in subnets.items():
-            self.plugin.update_subnet(context, subnet_id,
-                                      {'subnet': {'cidr': prefix}})
+            updated_subnets.append(self.plugin.update_subnet(
+                                        context,
+                                        subnet_id,
+                                        {'subnet': {'cidr': prefix}}))
+        return updated_subnets
index 29ecf806525ffceba8ae19340126dc996ceb3259..11379b04788294603def9e6af702e2b089cf8ff0 100644 (file)
@@ -590,9 +590,8 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
 
     def _update_allocation_pools(self, subnet):
         """Gets new allocation pools and formats them correctly"""
-        allocation_pools = self.ipam.generate_allocation_pools(
-                                    subnet['cidr'],
-                                    subnet['gateway_ip'])
+        allocation_pools = self.ipam.generate_pools(subnet['cidr'],
+                                                    subnet['gateway_ip'])
         return [{'start': str(netaddr.IPAddress(p.first,
                                                 subnet['ip_version'])),
                  'end': str(netaddr.IPAddress(p.last, subnet['ip_version']))}
@@ -619,13 +618,6 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
         db_pools = [netaddr.IPRange(p['first_ip'], p['last_ip'])
                     for p in db_subnet.allocation_pools]
 
-        range_pools = None
-        if s.get('allocation_pools') is not None:
-            # Convert allocation pools to IPRange to simplify future checks
-            range_pools = self.ipam.pools_to_ip_range(s['allocation_pools'])
-            self.ipam.validate_allocation_pools(range_pools, s['cidr'])
-            s['allocation_pools'] = range_pools
-
         update_ports_needed = False
         if new_cidr and ipv6_utils.is_ipv6_pd_enabled(s):
             # This is an ipv6 prefix delegation-enabled subnet being given an
@@ -637,6 +629,13 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
             s['gateway_ip'] = utils.get_first_host_ip(net, s['ip_version'])
             s['allocation_pools'] = self._update_allocation_pools(s)
 
+        range_pools = None
+        if s.get('allocation_pools') is not None:
+            # Convert allocation pools to IPRange to simplify future checks
+            range_pools = self.ipam.pools_to_ip_range(s['allocation_pools'])
+            self.ipam.validate_allocation_pools(range_pools, s['cidr'])
+            s['allocation_pools'] = range_pools
+
         # If either gateway_ip or allocation_pools were specified
         gateway_ip = s.get('gateway_ip')
         if gateway_ip is not None or s.get('allocation_pools') is not None:
diff --git a/neutron/tests/unit/api/rpc/handlers/test_l3_rpc.py b/neutron/tests/unit/api/rpc/handlers/test_l3_rpc.py
new file mode 100644 (file)
index 0000000..68ec79d
--- /dev/null
@@ -0,0 +1,65 @@
+# Copyright (c) 2015 Cisco Systems
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from oslo_config import cfg
+
+from neutron.api.rpc.handlers import l3_rpc
+from neutron.common import constants
+from neutron import context
+from neutron import manager
+from neutron.tests.unit.db import test_db_base_plugin_v2
+from neutron.tests.unit import testlib_api
+
+
+class TestL3RpcCallback(testlib_api.SqlTestCase):
+
+    def setUp(self):
+        super(TestL3RpcCallback, self).setUp()
+        self.setup_coreplugin(test_db_base_plugin_v2.DB_PLUGIN_KLASS)
+        self.plugin = manager.NeutronManager.get_plugin()
+        self.ctx = context.get_admin_context()
+        cfg.CONF.set_override('default_ipv6_subnet_pool',
+                              constants.IPV6_PD_POOL_ID)
+        self.callbacks = l3_rpc.L3RpcCallback()
+        self.network = self._prepare_network()
+
+    def _prepare_network(self):
+        network = {'network': {'name': 'abc',
+                               'shared': False,
+                               'admin_state_up': True}}
+        return self.plugin.create_network(self.ctx, network)
+
+    def _prepare_ipv6_pd_subnet(self):
+        subnet = {'subnet': {'network_id': self.network['id'],
+                             'cidr': None,
+                             'ip_version': 6,
+                             'name': 'ipv6_pd',
+                             'enable_dhcp': True,
+                             'host_routes': None,
+                             'dns_nameservers': None,
+                             'allocation_pools': None,
+                             'ipv6_ra_mode': constants.IPV6_SLAAC,
+                             'ipv6_address_mode': constants.IPV6_SLAAC}}
+        return self.plugin.create_subnet(self.ctx, subnet)
+
+    def test_process_prefix_update(self):
+        subnet = self._prepare_ipv6_pd_subnet()
+        data = {subnet['id']: '2001:db8::/64'}
+        allocation_pools = [{'start': '2001:db8::2',
+                             'end': '2001:db8::ffff:ffff:ffff:ffff'}]
+        res = self.callbacks.process_prefix_update(self.ctx, subnets=data)
+        updated_subnet = res[0]
+        self.assertEqual(updated_subnet['cidr'], data[subnet['id']])
+        self.assertEqual(updated_subnet['allocation_pools'], allocation_pools)