Allow setting quota of other tenants
Currently, the quota API/CLI allows users to set quotas for current tenant only. However, admin users needs the ability to set quota for other tenants. For example: $ source /opt/stack/devstack/openrc admin admin $ openstack appcontainer quota update --containers 100 <DEMO_TENANT_UUID> Depends-On: https://review.openstack.org/627075 Change-Id: Ia147575d3e8d2c6d54bddd98846f0c9e3e518ec3 Related-Bug: #1807620
This commit is contained in:
parent
77046229b8
commit
eedf5c7fdd
@ -52,6 +52,10 @@ class UpdateQuota(command.ShowOne):
|
|||||||
metavar='<disk>',
|
metavar='<disk>',
|
||||||
help='The number of gigabytes of container Disk '
|
help='The number of gigabytes of container Disk '
|
||||||
'allowed per project')
|
'allowed per project')
|
||||||
|
parser.add_argument(
|
||||||
|
'project_id',
|
||||||
|
metavar='<project_id>',
|
||||||
|
help='The UUID of project in a multi-project cloud')
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
@ -61,7 +65,7 @@ class UpdateQuota(command.ShowOne):
|
|||||||
opts['memory'] = parsed_args.memory
|
opts['memory'] = parsed_args.memory
|
||||||
opts['cpu'] = parsed_args.cpu
|
opts['cpu'] = parsed_args.cpu
|
||||||
opts['disk'] = parsed_args.disk
|
opts['disk'] = parsed_args.disk
|
||||||
quota = client.quotas.update(**opts)
|
quota = client.quotas.update(parsed_args.project_id, **opts)
|
||||||
columns = _quota_columns(quota)
|
columns = _quota_columns(quota)
|
||||||
return columns, utils.get_item_properties(quota, columns)
|
return columns, utils.get_item_properties(quota, columns)
|
||||||
|
|
||||||
@ -77,11 +81,17 @@ class GetQuota(command.ShowOne):
|
|||||||
'--usages',
|
'--usages',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Whether show quota usage statistic or not')
|
help='Whether show quota usage statistic or not')
|
||||||
|
parser.add_argument(
|
||||||
|
'project_id',
|
||||||
|
metavar='<project_id>',
|
||||||
|
help='The UUID of project in a multi-project cloud')
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
client = _get_client(self, parsed_args)
|
client = _get_client(self, parsed_args)
|
||||||
quota = client.quotas.get(usages=parsed_args.usages)
|
quota = client.quotas.get(
|
||||||
|
parsed_args.project_id,
|
||||||
|
usages=parsed_args.usages)
|
||||||
columns = _quota_columns(quota)
|
columns = _quota_columns(quota)
|
||||||
return columns, utils.get_item_properties(quota, columns)
|
return columns, utils.get_item_properties(quota, columns)
|
||||||
|
|
||||||
@ -91,9 +101,17 @@ class GetDefaultQuota(command.ShowOne):
|
|||||||
|
|
||||||
log = logging.getLogger(__name__ + '.GetDefeaultQuota')
|
log = logging.getLogger(__name__ + '.GetDefeaultQuota')
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(GetDefaultQuota, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
'project_id',
|
||||||
|
metavar='<project_id>',
|
||||||
|
help='The UUID of project in a multi-project cloud')
|
||||||
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
client = _get_client(self, parsed_args)
|
client = _get_client(self, parsed_args)
|
||||||
default_quota = client.quotas.defaults()
|
default_quota = client.quotas.defaults(parsed_args.project_id)
|
||||||
columns = _quota_columns(default_quota)
|
columns = _quota_columns(default_quota)
|
||||||
return columns, utils.get_item_properties(
|
return columns, utils.get_item_properties(
|
||||||
default_quota, columns)
|
default_quota, columns)
|
||||||
@ -104,10 +122,18 @@ class DeleteQuota(command.Command):
|
|||||||
|
|
||||||
log = logging.getLogger(__name__ + '.DeleteQuota')
|
log = logging.getLogger(__name__ + '.DeleteQuota')
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(DeleteQuota, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
'project_id',
|
||||||
|
metavar='<project_id>',
|
||||||
|
help='The UUID of project in a multi-project cloud')
|
||||||
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
client = _get_client(self, parsed_args)
|
client = _get_client(self, parsed_args)
|
||||||
try:
|
try:
|
||||||
client.quotas.delete()
|
client.quotas.delete(parsed_args.project_id)
|
||||||
print(_('Request to delete quotas has been accepted.'))
|
print(_('Request to delete quotas has been accepted.'))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("Delete for quotas failed: %(e)s" % {'e': e})
|
print("Delete for quotas failed: %(e)s" % {'e': e})
|
||||||
|
@ -40,7 +40,7 @@ MODIFIED_USAGE_QUOTAS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fake_responses = {
|
fake_responses = {
|
||||||
'/v1/quotas':
|
'/v1/quotas/test_project_id':
|
||||||
{
|
{
|
||||||
'GET': (
|
'GET': (
|
||||||
{},
|
{},
|
||||||
@ -55,14 +55,14 @@ fake_responses = {
|
|||||||
None
|
None
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
'/v1/quotas/defaults':
|
'/v1/quotas/test_project_id/defaults':
|
||||||
{
|
{
|
||||||
'GET': (
|
'GET': (
|
||||||
{},
|
{},
|
||||||
DEFAULT_QUOTAS
|
DEFAULT_QUOTAS
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
'/v1/quotas?usages=True':
|
'/v1/quotas/test_project_id?usages=True':
|
||||||
{
|
{
|
||||||
'GET': (
|
'GET': (
|
||||||
{},
|
{},
|
||||||
@ -80,9 +80,9 @@ class QuotaManagerTest(testtools.TestCase):
|
|||||||
self.mgr = quotas.QuotaManager(self.api)
|
self.mgr = quotas.QuotaManager(self.api)
|
||||||
|
|
||||||
def test_quotas_get_defaults(self):
|
def test_quotas_get_defaults(self):
|
||||||
quotas = self.mgr.defaults()
|
quotas = self.mgr.defaults('test_project_id')
|
||||||
expect = [
|
expect = [
|
||||||
('GET', '/v1/quotas/defaults', {}, None)
|
('GET', '/v1/quotas/test_project_id/defaults', {}, None)
|
||||||
]
|
]
|
||||||
self.assertEqual(expect, self.api.calls)
|
self.assertEqual(expect, self.api.calls)
|
||||||
self.assertEqual(quotas.containers, DEFAULT_QUOTAS['containers'])
|
self.assertEqual(quotas.containers, DEFAULT_QUOTAS['containers'])
|
||||||
|
@ -22,16 +22,18 @@ class QuotaManager(base.Manager):
|
|||||||
resource_class = Quota
|
resource_class = Quota
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _path():
|
def _path(project_id):
|
||||||
|
if project_id is not None:
|
||||||
|
return '/v1/quotas/{}'.format(project_id)
|
||||||
return '/v1/quotas'
|
return '/v1/quotas'
|
||||||
|
|
||||||
def get(self, **kwargs):
|
def get(self, project_id, **kwargs):
|
||||||
if not kwargs.get('usages'):
|
if not kwargs.get('usages'):
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
return self._list(self._path(), qparams=kwargs)[0]
|
return self._list(self._path(project_id), qparams=kwargs)[0]
|
||||||
|
|
||||||
def update(self, containers=None, memory=None,
|
def update(self, project_id, containers=None,
|
||||||
cpu=None, disk=None):
|
memory=None, cpu=None, disk=None):
|
||||||
resources = {}
|
resources = {}
|
||||||
if cpu is not None:
|
if cpu is not None:
|
||||||
resources['cpu'] = cpu
|
resources['cpu'] = cpu
|
||||||
@ -41,10 +43,10 @@ class QuotaManager(base.Manager):
|
|||||||
resources['containers'] = containers
|
resources['containers'] = containers
|
||||||
if disk is not None:
|
if disk is not None:
|
||||||
resources['disk'] = disk
|
resources['disk'] = disk
|
||||||
return self._update(self._path(), resources, method='PUT')
|
return self._update(self._path(project_id), resources, method='PUT')
|
||||||
|
|
||||||
def defaults(self):
|
def defaults(self, project_id):
|
||||||
return self._list(self._path() + '/defaults')[0]
|
return self._list(self._path(project_id) + '/defaults')[0]
|
||||||
|
|
||||||
def delete(self):
|
def delete(self, project_id):
|
||||||
return self._delete(self._path())
|
return self._delete(self._path(project_id))
|
||||||
|
@ -33,9 +33,14 @@ from zunclient.common import cliutils as utils
|
|||||||
metavar='<disk>',
|
metavar='<disk>',
|
||||||
type=int,
|
type=int,
|
||||||
help='The number of gigabytes of container Disk allowed per project')
|
help='The number of gigabytes of container Disk allowed per project')
|
||||||
|
@utils.arg(
|
||||||
|
'project_id',
|
||||||
|
metavar='<project_id>',
|
||||||
|
help='The UUID of project in a multi-project cloud')
|
||||||
def do_quota_update(cs, args):
|
def do_quota_update(cs, args):
|
||||||
"""Print an updated quotas for a project"""
|
"""Print an updated quotas for a project"""
|
||||||
utils.print_dict(cs.quotas.update(containers=args.containers,
|
utils.print_dict(cs.quotas.update(args.project_id,
|
||||||
|
containers=args.containers,
|
||||||
memory=args.memory,
|
memory=args.memory,
|
||||||
cpu=args.cpu,
|
cpu=args.cpu,
|
||||||
disk=args.disk)._info)
|
disk=args.disk)._info)
|
||||||
@ -46,20 +51,34 @@ def do_quota_update(cs, args):
|
|||||||
default=False,
|
default=False,
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Whether show quota usage statistic or not')
|
help='Whether show quota usage statistic or not')
|
||||||
|
@utils.arg(
|
||||||
|
'project_id',
|
||||||
|
metavar='<project_id>',
|
||||||
|
help='The UUID of project in a multi-project cloud')
|
||||||
def do_quota_get(cs, args):
|
def do_quota_get(cs, args):
|
||||||
"""Print a quotas for a project with usages (optional)"""
|
"""Print a quotas for a project with usages (optional)"""
|
||||||
if args.usages:
|
if args.usages:
|
||||||
utils.print_dict(cs.quotas.get(usages=args.usages)._info,
|
utils.print_dict(
|
||||||
|
cs.quotas.get(args.project_id, usages=args.usages)._info,
|
||||||
value_fields=('limit', 'in_use'))
|
value_fields=('limit', 'in_use'))
|
||||||
else:
|
else:
|
||||||
utils.print_dict(cs.quotas.get(usages=args.usages)._info)
|
utils.print_dict(
|
||||||
|
cs.quotas.get(args.project_id, usages=args.usages)._info)
|
||||||
|
|
||||||
|
|
||||||
|
@utils.arg(
|
||||||
|
'project_id',
|
||||||
|
metavar='<project_id>',
|
||||||
|
help='The UUID of project in a multi-project cloud')
|
||||||
def do_quota_defaults(cs, args):
|
def do_quota_defaults(cs, args):
|
||||||
"""Print a default quotas for a project"""
|
"""Print a default quotas for a project"""
|
||||||
utils.print_dict(cs.quotas.defaults()._info)
|
utils.print_dict(cs.quotas.defaults(args.project_id)._info)
|
||||||
|
|
||||||
|
|
||||||
|
@utils.arg(
|
||||||
|
'project_id',
|
||||||
|
metavar='<project_id>',
|
||||||
|
help='The UUID of project in a multi-project cloud')
|
||||||
def do_quota_delete(cs, args):
|
def do_quota_delete(cs, args):
|
||||||
"""Delete quotas for a project"""
|
"""Delete quotas for a project"""
|
||||||
cs.quotas.delete()
|
cs.quotas.delete(args.project_id)
|
||||||
|
Loading…
Reference in New Issue
Block a user