diff options
| author | Dean Troyer <dtroyer@gmail.com> | 2013-07-03 16:46:00 -0500 |
|---|---|---|
| committer | Dean Troyer <dtroyer@gmail.com> | 2013-07-17 15:10:22 -0500 |
| commit | 87104a28d75bd77df8b7ceb44600cd2b3971b4ae (patch) | |
| tree | 052d5afb5f66d344d6877dcfc30571148c1c94f0 /openstackclient/common | |
| parent | aa81b8b8d538b81a21d1161dc047cb5374cfe060 (diff) | |
| download | python-openstackclient-87104a28d75bd77df8b7ceb44600cd2b3971b4ae.tar.gz | |
Add quota commands
* Add quota set and quota show commands; these work on both
the compute and volume APIs
* Add the --class variation on the above commands
Note: this replaces the existing volume-only quota commands and eliminates quota list
Blueprint: cinder-client
Bug: 1172064
Change-Id: I766d40e410e48f05e36e17e567a4f01a9411b40e
Diffstat (limited to 'openstackclient/common')
| -rw-r--r-- | openstackclient/common/quota.py | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/openstackclient/common/quota.py b/openstackclient/common/quota.py new file mode 100644 index 00000000..fd482da9 --- /dev/null +++ b/openstackclient/common/quota.py @@ -0,0 +1,192 @@ +# Copyright 2012 OpenStack Foundation +# +# 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. +# + +"""Quota action implementations""" + +import itertools +import logging +import six +import sys + +from cliff import command +from cliff import show + + +# List the quota items, map the internal argument name to the option +# name that the user sees. + +COMPUTE_QUOTAS = { + 'cores': 'cores', + 'fixed_ips': 'fixed-ips', + 'floating_ips': 'floating-ips', + 'injected_file_content_bytes': 'injected-file-size', + 'injected_file_path_bytes': 'injected-path-size', + 'injected_files': 'injected-files', + 'instances': 'instances', + 'key_pairs': 'key-pairs', + 'metadata_items': 'properties', + 'ram': 'ram', + 'security_group_rules': 'secgroup-rules', + 'security_groups': 'secgroups', +} + +VOLUME_QUOTAS = { + 'gigabytes': 'gigabytes', + 'snapshots': 'snapshots', + 'volumes': 'volumes', +} + + +class SetQuota(command.Command): + """Set quotas for project or class""" + + log = logging.getLogger(__name__ + '.SetQuota') + + def get_parser(self, prog_name): + parser = super(SetQuota, self).get_parser(prog_name) + parser.add_argument( + 'project', + metavar='<project/class>', + help='Set quotas for this project or class (name/ID)', + ) + parser.add_argument( + '--class', + dest='quota_class', + action='store_true', + default=False, + help='Set quotas for <class>', + ) + for k, v in itertools.chain( + COMPUTE_QUOTAS.items(), VOLUME_QUOTAS.items()): + parser.add_argument( + '--%s' % v, + metavar='<new-%s>' % v, + type=int, + help='New value for the %s quota' % v, + ) + return parser + + def take_action(self, parsed_args): + self.log.debug('take_action(%s)' % parsed_args) + + compute_client = self.app.client_manager.compute + volume_client = self.app.client_manager.volume + + compute_kwargs = {} + for k, v in COMPUTE_QUOTAS.items(): + if v in parsed_args: + compute_kwargs[k] = getattr(parsed_args, v, None) + + volume_kwargs = {} + for k, v in VOLUME_QUOTAS.items(): + if v in parsed_args: + volume_kwargs[k] = getattr(parsed_args, v, None) + + if compute_kwargs == {} and volume_kwargs == {}: + sys.stderr.write("No quotas updated") + return + + if parsed_args.quota_class: + if compute_kwargs: + compute_client.quota_classes.update( + parsed_args.project, + **compute_kwargs) + if volume_kwargs: + volume_client.quota_classes.update( + parsed_args.project, + **volume_kwargs) + else: + if compute_kwargs: + compute_client.quotas.update( + parsed_args.project, + **compute_kwargs) + if volume_kwargs: + volume_client.quotas.update( + parsed_args.project, + **volume_kwargs) + + +class ShowQuota(show.ShowOne): + """Show quotas for project or class""" + + log = logging.getLogger(__name__ + '.ShowQuota') + + def get_parser(self, prog_name): + parser = super(ShowQuota, self).get_parser(prog_name) + parser.add_argument( + 'project', + metavar='<project/class>', + help='Show this project or class (name/ID)', + ) + type_group = parser.add_mutually_exclusive_group() + type_group.add_argument( + '--class', + dest='quota_class', + action='store_true', + default=False, + help='Show quotas for <class>', + ) + type_group.add_argument( + '--default', + dest='default', + action='store_true', + default=False, + help='Show default quotas for <project>' + ) + return parser + + def take_action(self, parsed_args): + self.log.debug('take_action(%s)' % parsed_args) + + compute_client = self.app.client_manager.compute + volume_client = self.app.client_manager.volume + + # NOTE(dtroyer): These quota API calls do not validate the project + # or class arguments and return what appears to be + # the default quota values if the project or class + # does not exist. If this is determined to be the + # intended behaviour of the API we will validate + # the argument with Identity ourselves later. + if parsed_args.quota_class: + compute_quota = compute_client.quota_classes.get( + parsed_args.project) + volume_quota = volume_client.quota_classes.get( + parsed_args.project) + elif parsed_args.default: + compute_quota = compute_client.quotas.defaults( + parsed_args.project) + volume_quota = volume_client.quotas.defaults( + parsed_args.project) + else: + compute_quota = compute_client.quotas.get(parsed_args.project) + volume_quota = volume_client.quotas.get(parsed_args.project) + + info = {} + info.update(compute_quota._info) + info.update(volume_quota._info) + + # Map the internal quota names to the external ones + for k, v in itertools.chain( + COMPUTE_QUOTAS.items(), VOLUME_QUOTAS.items()): + if not k == v and info[k]: + info[v] = info[k] + info.pop(k) + + # Handle project ID special as it only appears in output + if info['id']: + info['project'] = info['id'] + info.pop('id') + + return zip(*sorted(six.iteritems(info))) |
