diff --git a/docs/admin-guide.rst b/docs/admin-guide.rst index 78bb89224c03b3836e5c31907cec655f76cde144..8aee19ffbd2dd820fea498e58522210247017367 100644 --- a/docs/admin-guide.rst +++ b/docs/admin-guide.rst @@ -327,7 +327,7 @@ To inspect current default base quota limits, run:: You can modify the default base quota limit for all future users with:: - # snf-manage resource-modify <resource_name> --default-quota <value> + # snf-manage resource-modify <resource_name> --base-default <value> Set base quota for individual users ``````````````````````````````````` @@ -363,7 +363,7 @@ in ``20-snf-astakos-app-settings.conf`` set:: You can change the maximum allowed number of pending project applications per user with:: - # snf-manage resource-modify astakos.pending_app --default-quota <number> + # snf-manage resource-modify astakos.pending_app --base-default <number> You can also set a user-specific limit with:: diff --git a/docs/quick-install-admin-guide.rst b/docs/quick-install-admin-guide.rst index 1f69577779d17b401b4559cfd94789a38b6afa48..0c8a393cc8935f7478f8472d53862a1d45bc063b 100644 --- a/docs/quick-install-admin-guide.rst +++ b/docs/quick-install-admin-guide.rst @@ -912,7 +912,7 @@ resource. .. code-block:: console - # snf-manage resource-modify --default-quota-interactive + # snf-manage resource-modify cyclades.vm --base-default 2 Setting Resource Visibility --------------------------- diff --git a/snf-astakos-app/astakos/im/management/commands/resource-modify.py b/snf-astakos-app/astakos/im/management/commands/resource-modify.py index 8abe2f5ee4156ac98d4067d4a637f4f22c679f62..5d506d06b08ffd4021f39d960a82f7eba3c04091 100644 --- a/snf-astakos-app/astakos/im/management/commands/resource-modify.py +++ b/snf-astakos-app/astakos/im/management/commands/resource-modify.py @@ -1,4 +1,4 @@ -# Copyright 2013 GRNET S.A. All rights reserved. +# Copyright 2013, 2014 GRNET S.A. All rights reserved. # # Redistribution and use in source and binary forms, with or # without modification, are permitted provided that the following @@ -33,12 +33,11 @@ from optparse import make_option from django.core.management.base import BaseCommand, CommandError -from django.utils import simplejson as json from snf_django.management import utils from astakos.im.models import Resource -from astakos.im.register import update_resources -from ._common import show_resource_value, style_options, check_style, units +from astakos.im import register +from ._common import style_options, check_style, units class Command(BaseCommand): @@ -46,20 +45,9 @@ class Command(BaseCommand): help = "Modify a resource's default base quota and boolean flags." option_list = BaseCommand.option_list + ( - make_option('--default-quota', + make_option('--base-default', metavar='<limit>', help="Specify default base quota"), - make_option('--default-quota-interactive', - action='store_true', - default=None, - help=("Prompt user to change default base quota. " - "If no resource is given, prompts for all " - "resources.")), - make_option('--default-quota-from-file', - metavar='<limits_file.json>', - help=("Read default base quota from a file. " - "File should contain a json dict mapping resource " - "names to limits")), make_option('--unit-style', default='mb', help=("Specify display unit for resource values " @@ -74,11 +62,12 @@ class Command(BaseCommand): def handle(self, *args, **options): resource_name = args[0] if len(args) > 0 else None + if resource_name is None: + raise CommandError("Please provide a resource name.") + resource = self.get_resource(resource_name) actions = { - 'default_quota': self.change_limit, - 'default_quota_interactive': self.change_interactive, - 'default_quota_from_file': self.change_from_file, + 'base_default': self.change_base_default, 'api_visible': self.set_api_visible, 'ui_visible': self.set_ui_visible, } @@ -87,44 +76,29 @@ class Command(BaseCommand): for (key, value) in options.items() if key in actions and value is not None] - if len(opts) != 1: - raise CommandError("Please provide exactly one of the options: " - "--default-quota, --default-quota-interactive, " - "--default-quota-from-file, " - "--api-visible, --ui-visible.") - self.unit_style = options['unit_style'] check_style(self.unit_style) - key, value = opts[0] - action = actions[key] - action(resource_name, value) - - def set_api_visible(self, resource_name, allow): - if resource_name is None: - raise CommandError("Please provide a resource name.") + for key, value in opts: + action = actions[key] + action(resource, value) + def set_api_visible(self, resource, allow): try: allow = utils.parse_bool(allow) except ValueError: raise CommandError("Expecting a boolean value.") - resource = self.get_resource(resource_name) resource.api_visible = allow if not allow and resource.ui_visible: self.stderr.write("Also resetting 'ui_visible' for consistency.\n") resource.ui_visible = False resource.save() - def set_ui_visible(self, resource_name, allow): - if resource_name is None: - raise CommandError("Please provide a resource name.") - + def set_ui_visible(self, resource, allow): try: allow = utils.parse_bool(allow) except ValueError: raise CommandError("Expecting a boolean value.") - resource = self.get_resource(resource_name) - resource.ui_visible = allow if allow and not resource.api_visible: self.stderr.write("Also setting 'api_visible' for consistency.\n") @@ -138,83 +112,14 @@ class Command(BaseCommand): raise CommandError("Resource %s does not exist." % resource_name) - def change_limit(self, resource_name, limit): - if resource_name is None: - raise CommandError("Please provide a resource name.") - - resource = self.get_resource(resource_name) - self.change_resource_limit(resource, limit) - - def change_from_file(self, resource_name, filename): - with open(filename) as file_data: - try: - config = json.load(file_data) - except json.JSONDecodeError: - raise CommandError("Malformed JSON file.") - if not isinstance(config, dict): - raise CommandError("Malformed JSON file.") - self.change_with_conf(resource_name, config) - - def change_with_conf(self, resource_name, config): - if resource_name is None: - resources = Resource.objects.all().select_for_update() - else: - resources = [self.get_resource(resource_name)] - - updates = [] - for resource in resources: - limit = config.get(resource.name) - if limit is not None: - limit = self.parse_limit(limit) - updates.append((resource, limit)) - if updates: - update_resources(updates) - - def change_interactive(self, resource_name, _placeholder): - if resource_name is None: - resources = Resource.objects.all().select_for_update() - else: - resources = [self.get_resource(resource_name)] - - updates = [] - for resource in resources: - self.stdout.write("Resource '%s' (%s)\n" % - (resource.name, resource.desc)) - value = show_resource_value(resource.uplimit, resource.name, - self.unit_style) - self.stdout.write("Current limit: %s\n" % value) - while True: - self.stdout.write("New limit (leave blank to keep current): ") - try: - response = raw_input() - except EOFError: - self.stderr.write("Aborted.\n") - exit() - if response == "": - break - else: - try: - value = units.parse(response) - except units.ParseError: - continue - updates.append((resource, value)) - break - if updates: - self.stderr.write("Updating...\n") - update_resources(updates) + def change_base_default(self, resource, limit): + limit = self.parse_limit(limit) + register.update_base_default(resource, limit) def parse_limit(self, limit): try: - if isinstance(limit, (int, long)): - return limit - if isinstance(limit, basestring): - return units.parse(limit) - raise units.ParseError() + return units.parse(limit) except units.ParseError: - m = ("Limit should be an integer, optionally followed by a unit," - " or 'inf'.") + m = ("Quota limit should be an integer, " + "optionally followed by a unit, or 'inf'.") raise CommandError(m) - - def change_resource_limit(self, resource, limit): - limit = self.parse_limit(limit) - update_resources([(resource, limit)]) diff --git a/snf-astakos-app/astakos/im/register.py b/snf-astakos-app/astakos/im/register.py index 548c7d990f18a1841e815d48e4238570e9b81fa4..a4ab9138bb4ca6afbf89bbfc089514f57d1698cd 100644 --- a/snf-astakos-app/astakos/im/register.py +++ b/snf-astakos-app/astakos/im/register.py @@ -114,19 +114,16 @@ def add_resource(resource_dict): return r, exists -def update_resources(updates): - resources = [] - for resource, uplimit in updates: - resources.append(resource) - old_uplimit = resource.uplimit - if uplimit == old_uplimit: - logger.info("Resource %s has limit %s; no need to update." - % (resource.name, uplimit)) - else: - resource.uplimit = uplimit - resource.save() - logger.info("Updated resource %s with limit %s." - % (resource.name, uplimit)) +def update_base_default(resource, base_default): + old_base_default = resource.uplimit + if base_default == old_base_default: + logger.info("Resource %s has base default %s; no need to update." + % (resource.name, base_default)) + else: + resource.uplimit = base_default + resource.save() + logger.info("Updated resource %s with base default %s." + % (resource.name, base_default)) def resources_to_dict(resources): diff --git a/snf-astakos-app/astakos/scripts/snf-component-register b/snf-astakos-app/astakos/scripts/snf-component-register index 8c233b5be07366efc5c9b3caebf767348ce54c8a..4ea3474d3fadedcc06fe89b05a541efe2d238f61 100755 --- a/snf-astakos-app/astakos/scripts/snf-component-register +++ b/snf-astakos-app/astakos/scripts/snf-component-register @@ -109,7 +109,7 @@ fi if [ $changed -eq 1 ]; then echo 'Done with registering services and their resources.' echo 'Now run ' - echo " snf-manage resource-modify --limit-interactive" + echo " snf-manage resource-modify <resource_name> --base-default <limit>" echo 'to specify the default base quota for each resource provided by' \ 'the services.' fi diff --git a/snf-deploy/snfdeploy/components.py b/snf-deploy/snfdeploy/components.py index 381394e5ac1a853c0757794b1d01316bc0837e3c..f96d742b168f7702b50c6b1f99c423906d4995a0 100644 --- a/snf-deploy/snfdeploy/components.py +++ b/snf-deploy/snfdeploy/components.py @@ -643,7 +643,7 @@ class Astakos(SynnefoComponent): ] def set_default_quota(self): - cmd = "snf-manage resource-modify --default-quota" + cmd = "snf-manage resource-modify --base-default" return [ "%s 40G pithos.diskspace" % cmd, "%s 2 astakos.pending_app" % cmd, diff --git a/snf-deploy/snfdeploy/fabfile.py b/snf-deploy/snfdeploy/fabfile.py index 6ce3bbf1de95bebb8b274fee5a14b17310306cb0..5118b5033a17701d6fae801c502711c24d6421b3 100644 --- a/snf-deploy/snfdeploy/fabfile.py +++ b/snf-deploy/snfdeploy/fabfile.py @@ -1256,16 +1256,16 @@ def import_services(): debug(env.host, " * Setting default quota...") cmd = """ - snf-manage resource-modify --default-quota 40G pithos.diskspace - snf-manage resource-modify --default-quota 2 astakos.pending_app - snf-manage resource-modify --default-quota 4 cyclades.vm - snf-manage resource-modify --default-quota 40G cyclades.disk - snf-manage resource-modify --default-quota 16G cyclades.total_ram - snf-manage resource-modify --default-quota 8G cyclades.ram - snf-manage resource-modify --default-quota 32 cyclades.total_cpu - snf-manage resource-modify --default-quota 16 cyclades.cpu - snf-manage resource-modify --default-quota 4 cyclades.network.private - snf-manage resource-modify --default-quota 4 cyclades.floating_ip + snf-manage resource-modify --base-default 40G pithos.diskspace + snf-manage resource-modify --base-default 2 astakos.pending_app + snf-manage resource-modify --base-default 4 cyclades.vm + snf-manage resource-modify --base-default 40G cyclades.disk + snf-manage resource-modify --base-default 16G cyclades.total_ram + snf-manage resource-modify --base-default 8G cyclades.ram + snf-manage resource-modify --base-default 32 cyclades.total_cpu + snf-manage resource-modify --base-default 16 cyclades.cpu + snf-manage resource-modify --base-default 4 cyclades.network.private + snf-manage resource-modify --base-default 4 cyclades.floating_ip """ try_run(cmd)