]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Block subnet create when a network hosts subnets allocated from different pools
authorRyan Tidwell <ryan.tidwell@hp.com>
Mon, 4 May 2015 22:56:41 +0000 (15:56 -0700)
committerRyan Tidwell <rktidwell85@gmail.com>
Mon, 1 Jun 2015 18:42:59 +0000 (18:42 +0000)
This change will ensure that all subnets with the same ip_version on a given
network have been allocated from the same subnet pool or no pool. This
provides cleaner subnet overlap detection.

Cherry-picked from 251f551a5fe8fe05cdc8c9b9cfad357245b39bb9

Change-Id: I3c7366c69b10c202c0511126fbee6b3aac36759e
Closes-Bug: #1451559

neutron/common/exceptions.py
neutron/db/db_base_plugin_v2.py
neutron/tests/api/test_subnetpools.py
neutron/tests/api/test_subnetpools_negative.py
neutron/tests/unit/db/test_db_base_plugin_v2.py

index d5b64c52eb2f57d2313bea5a7aa113b283947e56..db7a3d045b2bda4ad8376b54fe8cb465fd3f6dab 100644 (file)
@@ -453,3 +453,8 @@ class SubnetPoolDeleteError(BadRequest):
 
 class SubnetPoolQuotaExceeded(OverQuota):
     message = _("Per-tenant subnet pool prefix quota exceeded")
+
+
+class NetworkSubnetPoolAffinityError(BadRequest):
+    message = _("Subnets hosted on the same network must be allocated from "
+                "the same subnet pool")
index ab940f42fa03561c11b4fb3df9a9037478d7b199..016e3d3b0afb4d897b362c8711ee4a26e36a61b8 100644 (file)
@@ -646,6 +646,16 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
                           'cidr': subnet.cidr})
                 raise n_exc.InvalidInput(error_message=err_msg)
 
+    def _validate_network_subnetpools(self, network,
+                                      new_subnetpool_id, ip_version):
+        """Validate all subnets on the given network have been allocated from
+           the same subnet pool as new_subnetpool_id
+        """
+        for subnet in network.subnets:
+            if (subnet.ip_version == ip_version and
+               new_subnetpool_id != subnet.subnetpool_id):
+                raise n_exc.NetworkSubnetPoolAffinityError()
+
     def _validate_allocation_pools(self, ip_pools, subnet_cidr):
         """Validate IP allocation pools.
 
@@ -1196,6 +1206,9 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
                                                allocation_pools)
 
         self._validate_subnet_cidr(context, network, subnet_args['cidr'])
+        self._validate_network_subnetpools(network,
+                                           subnet_args['subnetpool_id'],
+                                           subnet_args['ip_version'])
 
         subnet = models_v2.Subnet(**subnet_args)
         context.session.add(subnet)
index 73aad6806171a93c16bac165f46c027a3d0bad71..454dfb86b78836a46943731fed3c1c7aae07bb6f 100644 (file)
@@ -256,3 +256,20 @@ class SubnetPoolsTestV6(SubnetPoolsTest):
         prefixes = [u'2001:db8:3::/48']
         cls._subnetpool_data = {'subnetpool': {'min_prefixlen': min_prefixlen,
                                                'prefixes': prefixes}}
+
+    @test.attr(type='smoke')
+    @test.idempotent_id('f62d73dc-cf6f-4879-b94b-dab53982bf3b')
+    def test_create_dual_stack_subnets_from_subnetpools(self):
+        pool_id_v6, subnet_v6 = self._create_subnet_from_pool()
+        self.addCleanup(self.client.delete_subnet, subnet_v6['id'])
+        pool_values_v4 = {'prefixes': ['192.168.0.0/16'],
+                          'min_prefixlen': 21,
+                          'max_prefixlen': 32}
+        pool_name_v4, pool_id_v4 = self._create_subnetpool(self.client,
+                                                  pool_values=pool_values_v4)
+        subnet_v4 = self.client.create_subnet(
+                                network_id=subnet_v6['network_id'],
+                                ip_version=4,
+                                subnetpool_id=pool_id_v4)['subnet']
+        self.addCleanup(self.client.delete_subnet, subnet_v4['id'])
+        self.assertEqual(subnet_v4['network_id'], subnet_v6['network_id'])
index 52424499a0e76ad233a8868dff180a7ed10e3ab3..c82c6f87273f904e36a7bc64371542b8685cefb5 100644 (file)
@@ -118,3 +118,24 @@ class SubnetPoolsNegativeTestJSON(base.BaseNetworkTest):
         self.assertRaises(lib_exc.BadRequest,
                           self.client.update_subnetpool,
                           pool_id, subnetpool_data)
+
+    @test.attr(type=['negative', 'smoke'])
+    @test.idempotent_id('fc011824-153e-4469-97ad-9808eb88cae1')
+    def test_create_subnet_different_pools_same_network(self):
+        network = self.create_network(network_name='smoke-network')
+        subnetpool_data = {'prefixes': ['192.168.0.0/16'],
+                           'name': 'test-pool'}
+        pool_id = self._create_subnetpool(self.admin_client, subnetpool_data)
+        subnet = self.admin_client.create_subnet(
+                    network_id=network['id'],
+                    cidr='10.10.10.0/24',
+                    ip_version=4,
+                    gateway_ip=None)
+        subnet_id = subnet['subnet']['id']
+        self.addCleanup(self.admin_client.delete_subnet, subnet_id)
+        self.addCleanup(self.admin_client.delete_subnetpool, pool_id)
+        self.assertRaises(lib_exc.BadRequest,
+                          self.admin_client.create_subnet,
+                          network_id=network['id'],
+                          ip_version=4,
+                          subnetpool_id=pool_id)
index d67adddbfe26af13e8252bd0bb67c16aa983c8c6..9f74dc2de71f6a956a6ba30f8851716ff8187688 100644 (file)
@@ -5531,6 +5531,15 @@ class NeutronDbPluginV2AsMixinTestCase(testlib_api.SqlTestCase):
         net = self.plugin.create_network(self.context, self.net_data)
         self.assertEqual(net['status'], 'BUILD')
 
+    def test__validate_network_subnetpools(self):
+        network = models_v2.Network()
+        network.subnets = [models_v2.Subnet(subnetpool_id='test_id',
+                                            ip_version=4)]
+        new_subnetpool_id = None
+        self.assertRaises(n_exc.NetworkSubnetPoolAffinityError,
+                          self.plugin._validate_network_subnetpools,
+                          network, new_subnetpool_id, 4)
+
 
 class TestNetworks(testlib_api.SqlTestCase):
     def setUp(self):