From: Kevin Benton Date: Thu, 11 Jun 2015 14:06:20 +0000 (-0700) Subject: Add quota enforcement hook X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=7778a38e49b52f2f47f433f4f728d4c2372a715d;p=openstack-build%2Fneutron-build.git Add quota enforcement hook Add a quota enforcement hook so quotas are enforced before they reach the controller. This spot may need to be revisited in the future if we want quotas enforced on internal AMQP APIs. Change-Id: Ia5a134d941df921e44a413613ea11b636f4b8515 Partially-Implements: blueprint wsgi-pecan-switch --- diff --git a/neutron/newapi/app.py b/neutron/newapi/app.py index e4e3ff515..b41439b48 100644 --- a/neutron/newapi/app.py +++ b/neutron/newapi/app.py @@ -47,6 +47,7 @@ def setup_app(*args, **kwargs): hooks.ResourceIdentifierHook(), # priority 95 hooks.AttributePopulationHook(), # priority 120 hooks.OwnershipValidationHook(), # priority 125 + hooks.QuotaEnforcementHook(), # priority 130 ] app = pecan.make_app( diff --git a/neutron/newapi/hooks/__init__.py b/neutron/newapi/hooks/__init__.py index d2799b57d..0b06df40c 100644 --- a/neutron/newapi/hooks/__init__.py +++ b/neutron/newapi/hooks/__init__.py @@ -16,6 +16,7 @@ from neutron.newapi.hooks import attribute_population from neutron.newapi.hooks import context from neutron.newapi.hooks import ownership_validation +from neutron.newapi.hooks import quota_enforcement from neutron.newapi.hooks import resource_identifier from neutron.newapi.hooks import translation @@ -25,3 +26,4 @@ ContextHook = context.ContextHook ResourceIdentifierHook = resource_identifier.ResourceIdentifierHook AttributePopulationHook = attribute_population.AttributePopulationHook OwnershipValidationHook = ownership_validation.OwnershipValidationHook +QuotaEnforcementHook = quota_enforcement.QuotaEnforcementHook diff --git a/neutron/newapi/hooks/quota_enforcement.py b/neutron/newapi/hooks/quota_enforcement.py new file mode 100644 index 000000000..43e3c5f9c --- /dev/null +++ b/neutron/newapi/hooks/quota_enforcement.py @@ -0,0 +1,50 @@ +# Copyright (c) 2015 Mirantis, Inc. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from neutron.common import exceptions +from neutron.newapi.hooks import attribute_population +from neutron import quota + +from oslo_log import log as logging +from pecan import hooks + +LOG = logging.getLogger(__name__) + + +class QuotaEnforcementHook(hooks.PecanHook): + + priority = 130 + + def before(self, state): + if state.request.method != 'POST': + return + items = state.request.resources + rtype = state.request.resource_type + deltas = {} + for item in items: + tenant_id = item['tenant_id'] + try: + count = quota.QUOTAS.count(state.request.context, rtype, + state.request.plugin, + attribute_population._plural(rtype), + tenant_id) + delta = deltas.get(tenant_id, 0) + 1 + kwargs = {rtype: count + delta} + except exceptions.QuotaResourceUnknown as e: + # We don't want to quota this resource + LOG.debug(e) + else: + quota.QUOTAS.limit_check(state.request.context, tenant_id, + **kwargs) diff --git a/neutron/tests/functional/newapi/test_functional.py b/neutron/tests/functional/newapi/test_functional.py index 47c01f7b2..617e52c9e 100644 --- a/neutron/tests/functional/newapi/test_functional.py +++ b/neutron/tests/functional/newapi/test_functional.py @@ -213,3 +213,7 @@ class TestEnforcementHooks(PecanFunctionalTest): 'tenant_id': 'tenid2'}}, headers={'X-Tenant-Id': 'tenid'}) self.assertEqual(response.status_int, 200) + + def test_quota_enforcement(self): + # TODO(kevinbenton): this test should do something + pass