"""
@classmethod
- def create_allocation_pools(cls, subnet_manager, session, pools):
+ def create_allocation_pools(cls, subnet_manager, session, pools, cidr):
for pool in pools:
+ # IPv6 addresses that start '::1', '::2', etc cause IP version
+ # ambiguity when converted to integers by pool.first and pool.last.
+ # Infer the IP version from the subnet cidr.
+ ip_version = cidr.version
subnet_manager.create_pool(
session,
- netaddr.IPAddress(pool.first).format(),
- netaddr.IPAddress(pool.last).format())
+ netaddr.IPAddress(pool.first, ip_version).format(),
+ netaddr.IPAddress(pool.last, ip_version).format())
@classmethod
def create_from_subnet_request(cls, subnet_request, ctx):
else:
pools = subnet_request.allocation_pools
# Create IPAM allocation pools and availability ranges
- cls.create_allocation_pools(subnet_manager, session, pools)
+ cls.create_allocation_pools(subnet_manager, session, pools,
+ subnet_request.subnet_cidr)
return cls(ipam_subnet_id,
ctx,
subnet_id=self.subnet_manager.neutron_id,
ip_address=address)
- def update_allocation_pools(self, pools):
+ def update_allocation_pools(self, pools, cidr):
# Pools have already been validated in the subnet request object which
# was sent to the subnet pool driver. Further validation should not be
# required.
session = db_api.get_session()
self.subnet_manager.delete_allocation_pools(session)
- self.create_allocation_pools(self.subnet_manager, session, pools)
+ self.create_allocation_pools(self.subnet_manager, session, pools, cidr)
self._pools = pools
def get_details(self):
subnet_request.subnet_id)
return
subnet = NeutronDbSubnet.load(subnet_request.subnet_id, self._context)
- subnet.update_allocation_pools(subnet_request.allocation_pools)
+ cidr = netaddr.IPNetwork(subnet._cidr)
+ subnet.update_allocation_pools(subnet_request.allocation_pools, cidr)
return subnet
def remove_subnet(self, subnet_id):
from oslo_config import cfg
from oslo_utils import uuidutils
+from neutron.common import constants
from neutron.common import exceptions as n_exc
from neutron.common import ipv6_utils
from neutron.db import ipam_backend_mixin
self.assertIsInstance(request, ipam_req.SpecificSubnetRequest)
self.assertEqual(netaddr.IPNetwork(cidr), request.subnet_cidr)
+ @mock.patch('neutron.ipam.driver.Pool')
+ def test_create_ipv6_pd_subnet_over_ipam(self, pool_mock):
+ mocks = self._prepare_mocks_with_pool_mock(pool_mock)
+ cfg.CONF.set_override('default_ipv6_subnet_pool',
+ constants.IPV6_PD_POOL_ID)
+ cidr = constants.PROVISIONAL_IPV6_PD_PREFIX
+ allocation_pools = [netaddr.IPRange('::2', '::ffff:ffff:ffff:ffff')]
+ with self.subnet(cidr=None, ip_version=6,
+ ipv6_ra_mode=constants.IPV6_SLAAC,
+ ipv6_address_mode=constants.IPV6_SLAAC):
+ pool_mock.get_instance.assert_called_once_with(None, mock.ANY)
+ self.assertTrue(mocks['driver'].allocate_subnet.called)
+ request = mocks['driver'].allocate_subnet.call_args[0][0]
+ self.assertIsInstance(request, ipam_req.SpecificSubnetRequest)
+ self.assertEqual(netaddr.IPNetwork(cidr), request.subnet_cidr)
+ self.assertEqual(allocation_pools, request.allocation_pools)
+
@mock.patch('neutron.ipam.driver.Pool')
def test_create_subnet_over_ipam_with_rollback(self, pool_mock):
mocks = self._prepare_mocks_with_pool_mock(pool_mock)