Add API to retrieve default quotas

Currently there is no support to retrieve default quotas set
for all projects. This patch adds a new API function to get
default quotas.
GET /v2.0/quotas/<tenant-id>/default

DocImpact: Document new API to used to retrieve default quotas
APIImpact: New Read-only API to retrieve default quotas

Change-Id: If40a44348e305da444acd6196d2e0c04202b8f7a
Closes-Bug: #1204956
This commit is contained in:
Abhishek Raut 2016-04-07 13:59:15 -07:00
parent ad668e1941
commit f5a2ee300d
4 changed files with 75 additions and 0 deletions

View File

@ -33,6 +33,22 @@ class DbQuotaDriver(object):
The default driver utilizes the local database.
"""
@staticmethod
def get_default_quotas(context, resources, tenant_id):
"""Given a list of resources, retrieve the default quotas set for
a tenant.
:param context: The request context, for access checks.
:param resources: A dictionary of the registered resource keys.
:param tenant_id: The ID of the tenant to return default quotas for.
:return dict: from resource name to dict of name and limit
"""
# Currently the tenant_id parameter is unused, since all tenants
# share the same default values. This may change in the future so
# we include tenant-id to remain backwards compatible.
return dict((key, resource.default)
for key, resource in resources.items())
@staticmethod
def get_tenant_quotas(context, resources, tenant_id):
"""Given a list of resources, retrieve the quotas for the given

View File

@ -31,6 +31,8 @@ from neutron import quota
from neutron.quota import resource_registry
from neutron import wsgi
DEFAULT_QUOTAS_ACTION = 'default'
RESOURCE_NAME = 'quota'
RESOURCE_COLLECTION = RESOURCE_NAME + "s"
QUOTAS = quota.QUOTAS
@ -67,6 +69,16 @@ class QuotaSetsController(wsgi.Controller):
resource_registry.get_all_resources(),
tenant_id)
def default(self, request, id):
if id != request.context.tenant_id:
self._check_admin(request.context,
reason=_("Only admin is authorized "
"to access quotas for another tenant"))
return {self._resource_name: self._driver.get_default_quotas(
context=request.context,
resources=resource_registry.get_all_resources(),
tenant_id=id)}
def create(self, request, body=None):
msg = _('POST requests are not supported on this resource.')
raise webob.exc.HTTPNotImplemented(msg)
@ -144,6 +156,7 @@ class Quotasv2(extensions.ExtensionDescriptor):
return [extensions.ResourceExtension(
Quotasv2.get_alias(),
controller,
member_actions={DEFAULT_QUOTAS_ACTION: 'GET'},
collection_actions={'tenant': 'GET'})]
@classmethod

View File

@ -76,6 +76,13 @@ class TestDbQuotaDriver(testlib_api.SqlTestCase):
quotas = self.plugin.get_tenant_quotas(self.context, defaults, PROJECT)
self.assertEqual(4, quotas[RESOURCE])
def test_get_default_quotas(self):
defaults = {RESOURCE: TestResource(RESOURCE, 4)}
user_ctx = context.Context(user_id=PROJECT, tenant_id=PROJECT)
self.plugin.update_quota_limit(self.context, PROJECT, RESOURCE, 2)
quotas = self.plugin.get_default_quotas(user_ctx, defaults, PROJECT)
self.assertEqual(4, quotas[RESOURCE])
def test_get_tenant_quotas(self):
user_ctx = context.Context(user_id=PROJECT, tenant_id=PROJECT)
self.plugin.update_quota_limit(self.context, PROJECT, RESOURCE, 2)

View File

@ -35,6 +35,7 @@ from neutron.tests import tools
from neutron.tests.unit.api.v2 import test_base
from neutron.tests.unit import testlib_api
DEFAULT_QUOTAS_ACTION = 'default'
TARGET_PLUGIN = 'neutron.plugins.ml2.plugin.Ml2Plugin'
_get_path = test_base._get_path
@ -126,6 +127,44 @@ class QuotaExtensionDbTestCase(QuotaExtensionTestCase):
'port': -1,
'extra1': -1})
def test_show_default_quotas_with_admin(self):
tenant_id = 'tenant_id1'
env = {'neutron.context': context.Context('', tenant_id + '2',
is_admin=True)}
res = self.api.get(_get_path('quotas', id=tenant_id,
action=DEFAULT_QUOTAS_ACTION,
fmt=self.fmt),
extra_environ=env)
self.assertEqual(200, res.status_int)
quota = self.deserialize(res)
self.assertEqual(10, quota['quota']['network'])
self.assertEqual(10, quota['quota']['subnet'])
self.assertEqual(50, quota['quota']['port'])
def test_show_default_quotas_with_owner_tenant(self):
tenant_id = 'tenant_id1'
env = {'neutron.context': context.Context('', tenant_id,
is_admin=False)}
res = self.api.get(_get_path('quotas', id=tenant_id,
action=DEFAULT_QUOTAS_ACTION,
fmt=self.fmt),
extra_environ=env)
self.assertEqual(200, res.status_int)
quota = self.deserialize(res)
self.assertEqual(10, quota['quota']['network'])
self.assertEqual(10, quota['quota']['subnet'])
self.assertEqual(50, quota['quota']['port'])
def test_show_default_quotas_without_admin_forbidden_returns_403(self):
tenant_id = 'tenant_id1'
env = {'neutron.context': context.Context('', tenant_id + '2',
is_admin=False)}
res = self.api.get(_get_path('quotas', id=tenant_id,
action=DEFAULT_QUOTAS_ACTION,
fmt=self.fmt),
extra_environ=env, expect_errors=True)
self.assertEqual(403, res.status_int)
def test_show_quotas_with_admin(self):
tenant_id = 'tenant_id1'
env = {'neutron.context': context.Context('', tenant_id + '2',