From 05be01c5c484425d22c46348d2f31989e47d1542 Mon Sep 17 00:00:00 2001 From: Salvatore Orlando Date: Thu, 5 Jul 2012 02:20:43 +0100 Subject: [PATCH] Verify CIDR overlaps among networks' subnets. Make sure CIDR for subnets in a given network do not overlap each other. Fixes bug 1021106 Change-Id: I212a734ad59bbba86876d372a2f559f21ac60835 --- quantum/db/db_base_plugin_v2.py | 19 ++++++++++++ quantum/tests/unit/test_db_plugin.py | 45 ++++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/quantum/db/db_base_plugin_v2.py b/quantum/db/db_base_plugin_v2.py index e834cdf66..77e900df0 100644 --- a/quantum/db/db_base_plugin_v2.py +++ b/quantum/db/db_base_plugin_v2.py @@ -482,6 +482,24 @@ class QuantumDbPluginV2(quantum_plugin_base_v2.QuantumPluginBaseV2): 'subnet_id': result['subnet_id']}) return ips + def _validate_subnet_cidr(self, network, new_subnet_cidr): + """Validate the CIDR for a subnet. + + Verifies the specified CIDR does not overlap with the ones defined + for the other subnets specified for this network. + + """ + for subnet in network.subnets: + if (netaddr.IPSet([subnet.cidr]) & + netaddr.IPSet([new_subnet_cidr])): + err_msg = ("Requested subnet with cidr: %s " + "for network: %s " + "overlaps with subnet: %s)" % (new_subnet_cidr, + network.id, + subnet.cidr)) + LOG.error(err_msg) + raise q_exc.InvalidInput(error_message=err_msg) + def _validate_allocation_pools(self, ip_pools, gateway_ip, subnet_cidr): """Validate IP allocation pools. @@ -671,6 +689,7 @@ class QuantumDbPluginV2(quantum_plugin_base_v2.QuantumPluginBaseV2): with context.session.begin(): network = self._get_network(context, s["network_id"]) + self._validate_subnet_cidr(network, s['cidr']) subnet = models_v2.Subnet(network_id=s['network_id'], ip_version=s['ip_version'], cidr=s['cidr'], diff --git a/quantum/tests/unit/test_db_plugin.py b/quantum/tests/unit/test_db_plugin.py index 4430ccb94..d95fba169 100644 --- a/quantum/tests/unit/test_db_plugin.py +++ b/quantum/tests/unit/test_db_plugin.py @@ -701,11 +701,11 @@ class TestNetworksV2(QuantumDbPluginV2TestCase): class TestSubnetsV2(QuantumDbPluginV2TestCase): - def _test_create_subnet(self, **kwargs): + def _test_create_subnet(self, network=None, **kwargs): keys = kwargs.copy() keys.setdefault('cidr', '10.0.0.0/24') keys.setdefault('ip_version', 4) - with self.subnet(**keys) as subnet: + with self.subnet(network=network, **keys) as subnet: # verify the response has each key with the correct value for k in keys: self.assertIn(k, subnet['subnet']) @@ -718,6 +718,45 @@ class TestSubnetsV2(QuantumDbPluginV2TestCase): self._test_create_subnet(gateway_ip=gateway_ip, cidr=cidr) + def test_create_two_subnets(self): + gateway_ips = ['10.0.0.1', '10.0.1.1'] + cidrs = ['10.0.0.0/24', '10.0.1.0/24'] + with self.network() as network: + with self.subnet(network=network, + gateway_ip=gateway_ips[0], + cidr=cidrs[0]): + with self.subnet(network=network, + gateway_ip=gateway_ips[1], + cidr=cidrs[1]): + net_req = self.new_show_request('networks', + network['network']['id']) + raw_res = net_req.get_response(self.api) + net_res = self.deserialize('json', raw_res) + for subnet_id in net_res['network']['subnets']: + sub_req = self.new_show_request('subnets', subnet_id) + raw_res = sub_req.get_response(self.api) + sub_res = self.deserialize('json', raw_res) + self.assertIn(sub_res['subnet']['cidr'], cidrs) + self.assertIn(sub_res['subnet']['gateway_ip'], + gateway_ips) + + def test_create_two_subnets_same_cidr_returns_400(self): + gateway_ip_1 = '10.0.0.1' + cidr_1 = '10.0.0.0/24' + gateway_ip_2 = '10.0.0.10' + cidr_2 = '10.0.0.0/24' + with self.network() as network: + with self.subnet(network=network, + gateway_ip=gateway_ip_1, + cidr=cidr_1): + with self.assertRaises( + webob.exc.HTTPClientError) as ctx_manager: + with self.subnet(network=network, + gateway_ip=gateway_ip_2, + cidr=cidr_2): + pass + self.assertEquals(ctx_manager.exception.code, 400) + def test_delete_subnet(self): gateway_ip = '10.0.0.1' cidr = '10.0.0.0/24' @@ -869,7 +908,7 @@ class TestSubnetsV2(QuantumDbPluginV2TestCase): # or just drop 2.6 support ;) with self.network() as network: with self.subnet(network=network, gateway_ip='10.0.0.1', - cidr='10.0.1.0/24') as subnet: + cidr='10.0.0.0/24') as subnet: with self.subnet(network=network, gateway_ip='10.0.1.1', cidr='10.0.1.0/24') as subnet2: req = self.new_list_request('subnets') -- 2.45.2