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")
'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.
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)
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'])
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)
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):