]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Fix subnet creation failure on IPv6 valid gateway
authorDavid Edery <david.edery@alcatel-lucent.com>
Sun, 21 Jun 2015 12:59:49 +0000 (15:59 +0300)
committerDavid Edery <david.edery@alcatel-lucent.com>
Mon, 22 Jun 2015 08:33:56 +0000 (11:33 +0300)
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

neutron/ipam/subnet_alloc.py
neutron/ipam/utils.py
neutron/tests/unit/ipam/test_subnet_alloc.py

index dc38f43752a2f51b31aaed5a13caee837ef84fab..d1a6f681f7c5917b42944b2e66bcb644918d1951 100644 (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")
index 74927769ad765ab3e0ad056a46a0c10e2d4f8e47..3f0bda173b747a5c8f1bae354b5e5ba818ec9871 100644 (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)
 
 
index 25021af2fdc56c9d611dc6f7f3bba9bb57627fab..8923ef8de6ad62209dcc96d44cdf62bb5ec5493f 100644 (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'],