diff --git a/neutron/db/securitygroups_db.py b/neutron/db/securitygroups_db.py index 75a97e3104d..5b47ccfabda 100644 --- a/neutron/db/securitygroups_db.py +++ b/neutron/db/securitygroups_db.py @@ -42,6 +42,7 @@ from neutron.extensions import securitygroup as ext_sg from neutron.objects import base as base_obj from neutron.objects import ports as port_obj from neutron.objects import securitygroup as sg_obj +from neutron import quota @resource_extend.has_resource_extenders @@ -109,6 +110,12 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase, name=s['name'], is_default=default_sg) sg.create() + delta = len(ext_sg.sg_supported_ethertypes) + delta = delta * 2 if default_sg else delta + reservation = quota.QUOTAS.make_reservation( + context, tenant_id, {'security_group_rule': delta}, + self) + for ethertype in ext_sg.sg_supported_ethertypes: if default_sg: # Allow intercommunication @@ -128,6 +135,9 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase, sg.rules.append(egress_rule) sg.obj_reset_changes(['rules']) + quota.QUOTAS.commit_reservation(context, + reservation.reservation_id) + # fetch sg from db to load the sg rules with sg model. sg = sg_obj.SecurityGroup.get_object(context, id=sg.id) secgroup_dict = self._make_security_group_dict(sg) diff --git a/neutron/tests/fullstack/resources/client.py b/neutron/tests/fullstack/resources/client.py index 89e68a6d58b..ccfe13e4ecc 100644 --- a/neutron/tests/fullstack/resources/client.py +++ b/neutron/tests/fullstack/resources/client.py @@ -334,3 +334,6 @@ class ClientFixture(fixtures.Fixture): self.addCleanup( _safe_method(self.client.delete_network_log), net_log['log']['id']) return net_log + + def update_quota(self, project_id, tracked_resource, quota): + self._update_resource('quota', project_id, {tracked_resource: quota}) diff --git a/neutron/tests/fullstack/test_securitygroup.py b/neutron/tests/fullstack/test_securitygroup.py index 4f4f3118411..d573734b656 100644 --- a/neutron/tests/fullstack/test_securitygroup.py +++ b/neutron/tests/fullstack/test_securitygroup.py @@ -13,6 +13,7 @@ # under the License. from neutron_lib import constants +from neutronclient.common import exceptions as nc_exc from oslo_utils import uuidutils from neutron.cmd.sanity import checks @@ -517,3 +518,27 @@ class TestSecurityGroupsSameNetwork(BaseSecurityGroupsSameNetworkTest): vm1, vm2, net_helpers.NetcatTester.TCP, port + 1) self.verify_no_connectivity_between_vms( vm2, vm1, net_helpers.NetcatTester.TCP, port + 1) + + +class SecurityGroupRulesTest(base.BaseFullStackTestCase): + + def setUp(self): + host_descriptions = [environment.HostDescription()] + env = environment.Environment(environment.EnvironmentDescription(), + host_descriptions) + super(SecurityGroupRulesTest, self).setUp(env) + + def test_security_group_rule_quota(self): + project_id = uuidutils.generate_uuid() + quota = self.client.show_quota_details(project_id) + sg_rules_used = quota['quota']['security_group_rule']['used'] + self.assertEqual(0, sg_rules_used) + + self.safe_client.create_security_group(project_id) + quota = self.client.show_quota_details(project_id) + sg_rules_used = quota['quota']['security_group_rule']['used'] + self.safe_client.update_quota(project_id, 'security_group_rule', + sg_rules_used) + + self.assertRaises(nc_exc.OverQuotaClient, + self.safe_client.create_security_group, project_id) diff --git a/neutron/tests/functional/db/test_network.py b/neutron/tests/functional/db/test_network.py index efeb133a9b7..6532d78c503 100644 --- a/neutron/tests/functional/db/test_network.py +++ b/neutron/tests/functional/db/test_network.py @@ -21,6 +21,7 @@ from oslo_utils import uuidutils from neutron.objects import network as network_obj from neutron.plugins.ml2 import plugin as ml2_plugin +from neutron import quota from neutron.tests.unit import testlib_api @@ -43,6 +44,10 @@ class NetworkRBACTestCase(testlib_api.SqlTestCase): self.subnet_1_id = uuidutils.generate_uuid() self.subnet_2_id = uuidutils.generate_uuid() self.port_id = uuidutils.generate_uuid() + make_res = mock.patch.object(quota.QuotaEngine, 'make_reservation') + self.mock_quota_make_res = make_res.start() + commit_res = mock.patch.object(quota.QuotaEngine, 'commit_reservation') + self.mock_quota_commit_res = commit_res.start() def _create_network(self, tenant_id, network_id, shared, external=False): network = {'tenant_id': tenant_id, diff --git a/neutron/tests/unit/db/test_l3_hamode_db.py b/neutron/tests/unit/db/test_l3_hamode_db.py index 4e4c5ce8140..aa0e1beffc5 100644 --- a/neutron/tests/unit/db/test_l3_hamode_db.py +++ b/neutron/tests/unit/db/test_l3_hamode_db.py @@ -45,6 +45,7 @@ from neutron.db import common_db_mixin from neutron.db import l3_agentschedulers_db from neutron.db import l3_hamode_db from neutron.objects import l3_hamode +from neutron import quota from neutron.scheduler import l3_agent_scheduler from neutron.services.revisions import revision_plugin from neutron.tests.common import helpers @@ -71,6 +72,10 @@ class L3HATestFramework(testlib_api.SqlTestCase): notif_p = mock.patch.object(l3_hamode_db.L3_HA_NAT_db_mixin, '_notify_router_updated') self.notif_m = notif_p.start() + make_res = mock.patch.object(quota.QuotaEngine, 'make_reservation') + self.mock_quota_make_res = make_res.start() + commit_res = mock.patch.object(quota.QuotaEngine, 'commit_reservation') + self.mock_quota_commit_res = commit_res.start() cfg.CONF.set_override('allow_overlapping_ips', True) self.plugin = FakeL3PluginWithAgents() diff --git a/neutron/tests/unit/db/test_securitygroups_db.py b/neutron/tests/unit/db/test_securitygroups_db.py index 43685c2cfaf..5084f984df0 100644 --- a/neutron/tests/unit/db/test_securitygroups_db.py +++ b/neutron/tests/unit/db/test_securitygroups_db.py @@ -26,6 +26,7 @@ import testtools from neutron.db import common_db_mixin from neutron.db import securitygroups_db from neutron.extensions import securitygroup +from neutron import quota from neutron.services.revisions import revision_plugin from neutron.tests.unit import testlib_api @@ -73,6 +74,10 @@ class SecurityGroupDbMixinTestCase(testlib_api.SqlTestCase): self.setup_coreplugin(core_plugin=DB_PLUGIN_KLASS) self.ctx = context.get_admin_context() self.mixin = SecurityGroupDbMixinImpl() + make_res = mock.patch.object(quota.QuotaEngine, 'make_reservation') + self.mock_quota_make_res = make_res.start() + commit_res = mock.patch.object(quota.QuotaEngine, 'commit_reservation') + self.mock_quota_commit_res = commit_res.start() def test_create_security_group_conflict(self): with mock.patch.object(registry, "publish") as mock_publish: diff --git a/neutron/tests/unit/plugins/ml2/test_plugin.py b/neutron/tests/unit/plugins/ml2/test_plugin.py index a92efea9b6d..a89fd01dd99 100644 --- a/neutron/tests/unit/plugins/ml2/test_plugin.py +++ b/neutron/tests/unit/plugins/ml2/test_plugin.py @@ -62,6 +62,7 @@ from neutron.plugins.ml2.drivers import type_vlan from neutron.plugins.ml2 import managers from neutron.plugins.ml2 import models from neutron.plugins.ml2 import plugin as ml2_plugin +from neutron import quota from neutron.services.revisions import revision_plugin from neutron.services.segments import db as segments_plugin_db from neutron.services.segments import plugin as segments_plugin @@ -2000,6 +2001,10 @@ class TestMl2PortBinding(Ml2PluginV2TestCase, cfg.CONF.set_override( 'enable_security_group', self.ENABLE_SG, group='SECURITYGROUP') + make_res = mock.patch.object(quota.QuotaEngine, 'make_reservation') + self.mock_quota_make_res = make_res.start() + commit_res = mock.patch.object(quota.QuotaEngine, 'commit_reservation') + self.mock_quota_commit_res = commit_res.start() super(TestMl2PortBinding, self).setUp() def _check_port_binding_profile(self, port, profile=None): @@ -2720,6 +2725,10 @@ class TestMl2PortSecurity(Ml2PluginV2TestCase): cfg.CONF.set_override('enable_security_group', False, group='SECURITYGROUP') + make_res = mock.patch.object(quota.QuotaEngine, 'make_reservation') + self.mock_quota_make_res = make_res.start() + commit_res = mock.patch.object(quota.QuotaEngine, 'commit_reservation') + self.mock_quota_commit_res = commit_res.start() super(TestMl2PortSecurity, self).setUp() def test_port_update_without_security_groups(self): diff --git a/neutron/tests/unit/scheduler/test_l3_agent_scheduler.py b/neutron/tests/unit/scheduler/test_l3_agent_scheduler.py index ea29dbf13fb..15650856c1b 100644 --- a/neutron/tests/unit/scheduler/test_l3_agent_scheduler.py +++ b/neutron/tests/unit/scheduler/test_l3_agent_scheduler.py @@ -45,6 +45,7 @@ from neutron import manager from neutron.objects import agent as agent_obj from neutron.objects import l3_hamode from neutron.objects import l3agent as rb_obj +from neutron import quota from neutron.scheduler import l3_agent_scheduler from neutron.tests import base from neutron.tests.common import helpers @@ -1477,6 +1478,10 @@ class L3HATestCaseMixin(testlib_api.SqlTestCase, 'neutron.scheduler.l3_agent_scheduler.ChanceScheduler' ) self._register_l3_agents() + make_res = mock.patch.object(quota.QuotaEngine, 'make_reservation') + self.mock_make_res = make_res.start() + commit_res = mock.patch.object(quota.QuotaEngine, 'commit_reservation') + self.mock_quota_commit_res = commit_res.start() @staticmethod def get_router_l3_agent_binding(context, router_id, l3_agent_id=None,