Fix subnet creation failure on IPv6 valid gateway

Currently a valid IPv6 address gateway of the "*::ffff:ffff:ffff:ffff"
pattern is failing due to netaddr.broadcast returning value for both IPv6
and IPv4 addresses. IPv6 has no broadcast address so the fix checks if
the gateway is the subnet broadcast address only in the case of IPv4
subnet

Change-Id: I849f95b30343d0b1c90cf91203df220bf731d8d5
Closes-Bug: 1466322
This commit is contained in:
David Edery 2015-06-21 15:59:49 +03:00
parent acf78cc3c8
commit ee51ef72d3
3 changed files with 41 additions and 3 deletions

View File

@ -126,13 +126,19 @@ class SubnetAllocator(driver.Pool):
self._check_subnetpool_tenant_quota(request.tenant_id,
request.prefixlen)
cidr = request.subnet_cidr
gateway = request.gateway_ip
if gateway and not ipam_utils.check_subnet_ip(cidr, gateway):
msg = _("Cannot allocate requested subnet due to bad gateway "
"address")
raise n_exc.SubnetAllocationError(reason=msg)
available = self._get_available_prefix_list()
matched = netaddr.all_matching_cidrs(cidr, available)
if len(matched) is 1 and matched[0].prefixlen <= cidr.prefixlen:
return IpamSubnet(request.tenant_id,
request.subnet_id,
cidr,
gateway_ip=request.gateway_ip,
gateway_ip=gateway,
allocation_pools=request.allocation_pools)
msg = _("Cannot allocate requested subnet from the available "
"set of prefixes")

View File

@ -21,8 +21,9 @@ def check_subnet_ip(cidr, ip_address):
ip = netaddr.IPAddress(ip_address)
net = netaddr.IPNetwork(cidr)
# Check that the IP is valid on subnet. This cannot be the
# network or the broadcast address
return (ip != net.network and ip != net.broadcast
# network or the broadcast address (which exists only in IPv4)
return (ip != net.network
and (net.version == 6 or ip != net.broadcast)
and net.netmask & ip == net.network)

View File

@ -146,6 +146,37 @@ class TestSubnetAllocation(testlib_api.SqlTestCase):
self.assertEqual(detail.gateway_ip,
netaddr.IPAddress('10.1.2.254'))
def test_allocate_specific_ipv6_subnet_specific_gateway(self):
# Same scenario as described in bug #1466322
sp = self._create_subnet_pool(self.plugin, self.ctx, 'test-sp',
['2210::/64'],
64, 6)
sp = self.plugin._get_subnetpool(self.ctx, sp['id'])
with self.ctx.session.begin(subtransactions=True):
sa = subnet_alloc.SubnetAllocator(sp, self.ctx)
req = ipam.SpecificSubnetRequest(self._tenant_id,
uuidutils.generate_uuid(),
'2210::/64',
'2210::ffff:ffff:ffff:ffff')
res = sa.allocate_subnet(req)
detail = res.get_details()
self.assertEqual(detail.gateway_ip,
netaddr.IPAddress('2210::ffff:ffff:ffff:ffff'))
def test_allocate_specific_ipv4_subnet_specific_broadcast_gateway(self):
# Valid failure in subnet creation due to gateway==broadcast ip
sp = self._create_subnet_pool(self.plugin, self.ctx, 'test-sp',
['10.1.0.0/24'],
24, 4)
sa = subnet_alloc.SubnetAllocator(sp, self.ctx)
req = ipam.SpecificSubnetRequest(self._tenant_id,
uuidutils.generate_uuid(),
'10.1.0.0/24',
gateway_ip='10.1.0.255')
self.assertRaises(n_exc.SubnetAllocationError,
sa.allocate_subnet,
req)
def test__allocation_value_for_tenant_no_allocations(self):
sp = self._create_subnet_pool(self.plugin, self.ctx, 'test-sp',
['10.1.0.0/16', '192.168.1.0/24'],