Show default configuration Quotas

Fixes bug 1144076

The patch set shows the defualt quotas that exist in
the configuration file. This is if the DB_QUOTA_DRIVER
is not configured. In this case the user is required
to update the configuration file and restart the service.

Change-Id: I5517c0215e8cfa71453ee38c34d8249e74346fdf
This commit is contained in:
Gary Kotton 2013-03-04 10:21:28 +00:00
parent 72cb17b55f
commit b62324360b
3 changed files with 132 additions and 11 deletions

View File

@ -41,7 +41,7 @@ class QuotaSetsController(wsgi.Controller):
def __init__(self, plugin): def __init__(self, plugin):
self._resource_name = RESOURCE_NAME self._resource_name = RESOURCE_NAME
self._plugin = plugin self._plugin = plugin
self._driver = importutils.import_class(DB_QUOTA_DRIVER) self._driver = importutils.import_class(cfg.CONF.QUOTAS.quota_driver)
self._update_extended_attributes = True self._update_extended_attributes = True
def _update_attributes(self): def _update_attributes(self):
@ -56,7 +56,7 @@ class QuotaSetsController(wsgi.Controller):
def _get_body(self, request): def _get_body(self, request):
body = self._deserialize(request.body, body = self._deserialize(request.body,
request.best_match_content_type()) request.best_match_content_type())
if self._update_extended_attributes is True: if self._update_extended_attributes:
self._update_attributes() self._update_attributes()
attr_info = EXTENDED_ATTRIBUTES_2_0[RESOURCE_COLLECTION] attr_info = EXTENDED_ATTRIBUTES_2_0[RESOURCE_COLLECTION]
@ -69,7 +69,7 @@ class QuotaSetsController(wsgi.Controller):
request.context, QUOTAS.resources, tenant_id) request.context, QUOTAS.resources, tenant_id)
def create(self, request, body=None): def create(self, request, body=None):
raise NotImplementedError() raise webob.exc.HTTPNotImplemented()
def index(self, request): def index(self, request):
context = request.context context = request.context
@ -127,7 +127,7 @@ class Quotasv2(extensions.ExtensionDescriptor):
@classmethod @classmethod
def get_name(cls): def get_name(cls):
return "Quotas for each tenant" return "Quota management support"
@classmethod @classmethod
def get_alias(cls): def get_alias(cls):
@ -135,8 +135,10 @@ class Quotasv2(extensions.ExtensionDescriptor):
@classmethod @classmethod
def get_description(cls): def get_description(cls):
return ("Expose functions for cloud admin to update quotas" description = 'Expose functions for quotas management'
"for each tenant") if cfg.CONF.QUOTAS.quota_driver == DB_QUOTA_DRIVER:
description += ' per tenant'
return description
@classmethod @classmethod
def get_namespace(cls): def get_namespace(cls):
@ -160,8 +162,3 @@ class Quotasv2(extensions.ExtensionDescriptor):
return EXTENDED_ATTRIBUTES_2_0 return EXTENDED_ATTRIBUTES_2_0
else: else:
return {} return {}
def check_env(self):
if cfg.CONF.QUOTAS.quota_driver != DB_QUOTA_DRIVER:
msg = _('Quota driver %s is needed.') % DB_QUOTA_DRIVER
raise exceptions.InvalidExtenstionEnv(reason=msg)

View File

@ -17,6 +17,7 @@
"""Quotas for instances, volumes, and floating ips.""" """Quotas for instances, volumes, and floating ips."""
from oslo.config import cfg from oslo.config import cfg
import webob
from quantum.common import exceptions from quantum.common import exceptions
from quantum.openstack.common import importutils from quantum.openstack.common import importutils
@ -124,6 +125,26 @@ class ConfDriver(object):
raise exceptions.OverQuota(overs=sorted(overs), quotas=quotas, raise exceptions.OverQuota(overs=sorted(overs), quotas=quotas,
usages={}) usages={})
@staticmethod
def get_tenant_quotas(context, resources, tenant_id):
quotas = {}
sub_resources = dict((k, v) for k, v in resources.items())
for resource in sub_resources.values():
quotas[resource.name] = resource.default
return quotas
@staticmethod
def get_all_quotas(context, resources):
return []
@staticmethod
def delete_tenant_quota(context, tenant_id):
raise webob.exc.HTTPForbidden()
@staticmethod
def update_quota_limit(context, tenant_id, resource, limit):
raise webob.exc.HTTPForbidden()
class BaseResource(object): class BaseResource(object):
"""Describe a single resource for quota checking.""" """Describe a single resource for quota checking."""

View File

@ -213,3 +213,106 @@ class QuotaExtensionTestCase(testlib_api.WebTestCase):
class QuotaExtensionTestCaseXML(QuotaExtensionTestCase): class QuotaExtensionTestCaseXML(QuotaExtensionTestCase):
fmt = 'xml' fmt = 'xml'
class QuotaExtensionCfgTestCase(testlib_api.WebTestCase):
fmt = 'json'
def setUp(self):
super(QuotaExtensionCfgTestCase, self).setUp()
db._ENGINE = None
db._MAKER = None
# Ensure 'stale' patched copies of the plugin are never returned
manager.QuantumManager._instance = None
# Ensure existing ExtensionManager is not used
extensions.PluginAwareExtensionManager._instance = None
# Save the global RESOURCE_ATTRIBUTE_MAP
self.saved_attr_map = {}
for resource, attrs in attributes.RESOURCE_ATTRIBUTE_MAP.iteritems():
self.saved_attr_map[resource] = attrs.copy()
# Create the default configurations
args = ['--config-file', test_extensions.etcdir('quantum.conf.test')]
config.parse(args=args)
# Update the plugin and extensions path
cfg.CONF.set_override('core_plugin', TARGET_PLUGIN)
cfg.CONF.set_override(
'quota_items',
['network', 'subnet', 'port', 'extra1'],
group='QUOTAS')
quota.QUOTAS = quota.QuotaEngine()
quota.register_resources_from_config()
self._plugin_patcher = mock.patch(TARGET_PLUGIN, autospec=True)
self.plugin = self._plugin_patcher.start()
self.plugin.return_value.supported_extension_aliases = ['quotas']
# QUOTAS will regester the items in conf when starting
# extra1 here is added later, so have to do it manually
quota.QUOTAS.register_resource_by_name('extra1')
ext_mgr = extensions.PluginAwareExtensionManager.get_instance()
l2network_db_v2.initialize()
app = config.load_paste_app('extensions_test_app')
ext_middleware = extensions.ExtensionMiddleware(app, ext_mgr=ext_mgr)
self.api = webtest.TestApp(ext_middleware)
super(QuotaExtensionCfgTestCase, self).setUp()
def tearDown(self):
self._plugin_patcher.stop()
self.api = None
self.plugin = None
db._ENGINE = None
db._MAKER = None
cfg.CONF.reset()
# Restore the global RESOURCE_ATTRIBUTE_MAP
attributes.RESOURCE_ATTRIBUTE_MAP = self.saved_attr_map
super(QuotaExtensionCfgTestCase, self).tearDown()
def test_quotas_default_values(self):
tenant_id = 'tenant_id1'
env = {'quantum.context': context.Context('', tenant_id)}
res = self.api.get(_get_path('quotas', id=tenant_id, fmt=self.fmt),
extra_environ=env)
quota = self.deserialize(res)
self.assertEqual(10, quota['quota']['network'])
self.assertEqual(10, quota['quota']['subnet'])
self.assertEqual(50, quota['quota']['port'])
self.assertEqual(-1, quota['quota']['extra1'])
def test_show_quotas_with_admin(self):
tenant_id = 'tenant_id1'
env = {'quantum.context': context.Context('', tenant_id + '2',
is_admin=True)}
res = self.api.get(_get_path('quotas', id=tenant_id, fmt=self.fmt),
extra_environ=env)
self.assertEqual(200, res.status_int)
def test_show_quotas_without_admin_forbidden(self):
tenant_id = 'tenant_id1'
env = {'quantum.context': context.Context('', tenant_id + '2',
is_admin=False)}
res = self.api.get(_get_path('quotas', id=tenant_id, fmt=self.fmt),
extra_environ=env, expect_errors=True)
self.assertEqual(403, res.status_int)
def test_update_quotas_forbidden(self):
tenant_id = 'tenant_id1'
quotas = {'quota': {'network': 100}}
res = self.api.put(_get_path('quotas', id=tenant_id, fmt=self.fmt),
self.serialize(quotas),
expect_errors=True)
self.assertEqual(403, res.status_int)
def test_delete_quotas_forbidden(self):
tenant_id = 'tenant_id1'
env = {'quantum.context': context.Context('', tenant_id,
is_admin=False)}
res = self.api.delete(_get_path('quotas', id=tenant_id, fmt=self.fmt),
extra_environ=env, expect_errors=True)
self.assertEqual(403, res.status_int)
class QuotaExtensionCfgTestCaseXML(QuotaExtensionCfgTestCase):
fmt = 'xml'