Fix update_subnet for prefix delegation

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
This commit is contained in:
John Davidge 2015-08-07 16:27:47 +01:00
parent 0b0aa4a61d
commit a3285ac71a
3 changed files with 80 additions and 12 deletions

View 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

View 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:

View File

@ -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)