diff --git a/etc/quantum.conf b/etc/quantum.conf index 192a2ac7ce..d14aac9ff9 100644 --- a/etc/quantum.conf +++ b/etc/quantum.conf @@ -189,6 +189,15 @@ notification_topics = notifications # of number of items. # pagination_max_limit = -1 +# Maximum number of DNS nameservers per subnet +# max_dns_nameservers = 5 + +# Maximum number of host routes per subnet +# max_subnet_host_routes = 20 + +# Maximum number of fixed ips per port +# max_fixed_ips_per_port = 5 + [QUOTAS] # resource name(s) that are supported in quota features # quota_items = network,subnet,port diff --git a/quantum/common/config.py b/quantum/common/config.py index 0e41284d03..e35d9c188b 100644 --- a/quantum/common/config.py +++ b/quantum/common/config.py @@ -69,6 +69,8 @@ core_opts = [ help=_("Maximum number of DNS nameservers")), cfg.IntOpt('max_subnet_host_routes', default=20, help=_("Maximum number of host routes per subnet")), + cfg.IntOpt('max_fixed_ips_per_port', default=5, + help=_("Maximum number of fixed ips per port")), cfg.IntOpt('dhcp_lease_duration', default=120, help=_("DHCP lease duration")), cfg.BoolOpt('dhcp_agent_notification', default=True, diff --git a/quantum/db/db_base_plugin_v2.py b/quantum/db/db_base_plugin_v2.py index 675ad86eb4..209eb89393 100644 --- a/quantum/db/db_base_plugin_v2.py +++ b/quantum/db/db_base_plugin_v2.py @@ -609,6 +609,9 @@ class QuantumDbPluginV2(quantum_plugin_base_v2.QuantumPluginBaseV2): 'ip_address': fixed['ip_address']}) else: fixed_ip_set.append({'subnet_id': subnet_id}) + if len(fixed_ip_set) > cfg.CONF.max_fixed_ips_per_port: + msg = _('Exceeded maximim amount of fixed ips per port') + raise q_exc.InvalidInput(error_message=msg) return fixed_ip_set def _allocate_fixed_ips(self, context, network, fixed_ips): @@ -636,6 +639,11 @@ class QuantumDbPluginV2(quantum_plugin_base_v2.QuantumPluginBaseV2): """Add or remove IPs from the port.""" ips = [] + # the new_ips contain all of the fixed_ips that are to be updated + if len(new_ips) > cfg.CONF.max_fixed_ips_per_port: + msg = _('Exceeded maximim amount of fixed ips per port') + raise q_exc.InvalidInput(error_message=msg) + # Remove all of the intersecting elements for original_ip in original_ips[:]: for new_ip in new_ips[:]: diff --git a/quantum/tests/unit/midonet/test_midonet_plugin.py b/quantum/tests/unit/midonet/test_midonet_plugin.py index 7e80310571..180ebfa531 100644 --- a/quantum/tests/unit/midonet/test_midonet_plugin.py +++ b/quantum/tests/unit/midonet/test_midonet_plugin.py @@ -750,3 +750,9 @@ class TestMidonetPortsV2(test_plugin.TestPortsV2, def test_list_ports_with_sort_emulated(self): pass + + def test_max_fixed_ips_exceeded(self): + pass + + def test_update_max_fixed_ips_exceeded(self): + pass diff --git a/quantum/tests/unit/test_db_plugin.py b/quantum/tests/unit/test_db_plugin.py index 3ddf007ff1..611d20cd63 100644 --- a/quantum/tests/unit/test_db_plugin.py +++ b/quantum/tests/unit/test_db_plugin.py @@ -1745,6 +1745,38 @@ fixed_ips=ip_address%%3D%s&fixed_ips=ip_address%%3D%s&fixed_ips=subnet_id%%3D%s self.assertEqual(update_context._recycled_networks, set([subnet['subnet']['network_id']])) + def test_max_fixed_ips_exceeded(self): + with self.subnet(gateway_ip='10.0.0.3', + cidr='10.0.0.0/24') as subnet: + kwargs = {"fixed_ips": + [{'subnet_id': subnet['subnet']['id']}, + {'subnet_id': subnet['subnet']['id']}, + {'subnet_id': subnet['subnet']['id']}, + {'subnet_id': subnet['subnet']['id']}, + {'subnet_id': subnet['subnet']['id']}, + {'subnet_id': subnet['subnet']['id']}]} + net_id = subnet['subnet']['network_id'] + res = self._create_port(self.fmt, net_id=net_id, **kwargs) + self.assertEqual(res.status_int, 400) + + def test_update_max_fixed_ips_exceeded(self): + with self.subnet(gateway_ip='10.0.0.3', + cidr='10.0.0.0/24') as subnet: + with self.port(subnet) as port: + data = {'port': {'fixed_ips': + [{'subnet_id': subnet['subnet']['id'], + 'ip_address': '10.0.0.2'}, + {'subnet_id': subnet['subnet']['id'], + 'ip_address': '10.0.0.4'}, + {'subnet_id': subnet['subnet']['id']}, + {'subnet_id': subnet['subnet']['id']}, + {'subnet_id': subnet['subnet']['id']}, + {'subnet_id': subnet['subnet']['id']}]}} + req = self.new_update_request('ports', data, + port['port']['id']) + res = req.get_response(self.api) + self.assertEqual(res.status_int, 400) + class TestNetworksV2(QuantumDbPluginV2TestCase): # NOTE(cerberus): successful network update and delete are