Commit a6855022 authored by Giorgos Korfiatis's avatar Giorgos Korfiatis
Browse files

astakos: Separate importing resources from setting limits

`snf-manage resource-import' does not provide a way to change the
default base quota any more. When importing a resource for the first
time, it sets the limit to zero.

Use `snf-manage resource-modify' to change limits. It supports both
interactive mode and reading limits from file, either for a specified
resource or for all resources.
parent 6812a184
......@@ -39,6 +39,7 @@ from django.utils import simplejson as json
from snf_django.lib.db.transaction import commit_on_success_strict
from import add_resource
from import Service
class Command(BaseCommand):
......@@ -81,35 +82,40 @@ class Command(BaseCommand):
if json_file:
with open(json_file) as file_data:
data = json.load(file_data)
service = data.get('service')
resources = data.get('resources')
if service is None or resources is None:
m = "JSON file should contain service and resource data."
m = ('Input should be a JSON dict containing "service" '
'and "resource" keys.')
data = json.load(file_data)
except json.JSONDecodeError:
raise CommandError(m)
if not isinstance(data, dict):
raise CommandError(m)
service = data['service']
resources = data['resources']
except KeyError:
raise CommandError(m)
self.add_resources(service, resources, config)
self.add_resources(service, resources)
def add_resources(self, service, resources, config):
def add_resources(self, service, resources):
s = Service.objects.get(name=service)
except Service.DoesNotExist:
raise CommandError("Service '%s' is not registered." % (service))
for resource in resources:
if not isinstance(resource, dict):
raise CommandError("Malformed resource dict.")
exists = add_resource(s, resource)
name = resource['name']
uplimit = config.get(name)
if uplimit is None:
desc = resource['desc']
unit = resource.get('unit')
"Provide default base quota for resource '%s' (%s)" %
(name, desc))
m = (" in %s: " % unit) if unit else ": "
uplimit = raw_input()
uplimit = int(uplimit)
except ValueError:
m = "Limit for resource %s is not an integer." % (name)
raise CommandError(m)
add_resource(service, resource, uplimit)
if exists:
m = "Resource '%s' updated in database.\n" % (name)
m = ("Resource '%s' created in database with default "
"quota limit 0.\n" % (name))
......@@ -33,6 +33,7 @@
from optparse import make_option
from import BaseCommand, CommandError
from django.utils import simplejson as json
from import Resource
from import update_resource
......@@ -40,30 +41,108 @@ from import update_resource
class Command(BaseCommand):
args = "<resource name>"
help = "Modify a resource (currently only change the default base quota)"
help = ("Modify a resource (currently only change the default base quota)."
"\nIf no resource is specified, all resources are considered.")
option_list = BaseCommand.option_list + (
help="Change default base quota"),
help="Specify default base quota"),
help="Prompt user to change default base quotas"),
help="Read default base quotas from a json file"),
def handle(self, *args, **options):
if len(args) < 1:
resource_name = args[0] if len(args) > 0 else None
actions = {
'limit': self.change_limit,
'interactive': self.change_interactive,
'from_file': self.change_from_file,
opts = [(key, value)
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 option.")
key, value = opts[0]
action = actions[key]
action(resource_name, value)
def get_resource(self, resource_name):
return Resource.objects.get_for_update(name=resource_name)
except Resource.DoesNotExist:
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_name = args[0]
resource = self.get_resource(resource_name)
self.change_resource_limit(resource, limit)
limit = options['limit']
if limit is None:
raise CommandError("Use --limit to change default base quota.")
def change_from_file(self, resource_name, filename):
with open(filename) as file_data:
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()
resources = [self.get_resource(resource_name)]
for resource in resources:
limit = config.get(
if limit is not None:
self.change_resource_limit(resource, limit)
def change_interactive(self, resource_name, _placeholder):
if resource_name is None:
resources = Resource.objects.all().select_for_update()
resources = [self.get_resource(resource_name)]
for resource in resources:
self.stdout.write("Resource '%s' (%s)\n" %
(, resource.desc))
unit = (" in %s" % resource.unit) if resource.unit else ""
self.stdout.write("Current limit%s: %s\n"
% (unit, resource.uplimit))
while True:
self.stdout.write("New limit%s (leave blank to keep current): "
% (unit))
response = raw_input()
if response == "":
value = int(response)
except ValueError:
update_resource(resource, value)
def change_resource_limit(self, resource, limit):
limit = int(limit)
raise CommandError("Limit should be an integer.")
update_resource(resource_name, limit)
except Resource.DoesNotExist:
raise CommandError("Resource %s does not exist." % resource_name)
update_resource(resource, limit)
......@@ -31,57 +31,58 @@
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
from import Service, Resource
from import Resource
from import qh_add_resource_limit, qh_sync_new_resource
import logging
logger = logging.getLogger(__name__)
fields = ['name', 'desc', 'unit']
def add_resource(service, resource, uplimit):
s = Service.objects.get(name=service)
except Service.DoesNotExist:
raise Exception("Service %s is not registered." % (service))
name = resource['name']
class ResourceException(Exception):
def add_resource(service, resource_dict):
name = resource_dict.get('name')
if not name:
raise ResourceException("Malformed resource dict.")
r = Resource.objects.get_for_update(name=name)
old_uplimit = r.uplimit
exists = True
except Resource.DoesNotExist:
r = Resource()
old_uplimit = None
r = Resource(uplimit=0)
exists = False
r.uplimit = uplimit
r.service = s
for key, value in resource.iteritems():
setattr(r, key, value)
r.service = service
for field in fields:
value = resource_dict.get(field)
if value is not None:
setattr(r, field, value)
if not exists:
qh_sync_new_resource(r, 0)
if old_uplimit is not None:"Updated resource %s with limit %s." % (name, uplimit))
if exists:"Updated resource %s." % (name))
else:"Added resource %s with limit %s." % (name, uplimit))
if old_uplimit is not None:
diff = uplimit - old_uplimit
if diff != 0:
qh_add_resource_limit(r, diff)
qh_sync_new_resource(r, uplimit)"Added resource %s." % (name))
return exists
def update_resource(name, uplimit):
r = Resource.objects.get_for_update(name=name)
old_uplimit = r.uplimit
r.uplimit = uplimit
def update_resource(resource, uplimit):
old_uplimit = resource.uplimit
resource.uplimit = uplimit"Updated resource %s with limit %s." % (name, uplimit))"Updated resource %s with limit %s."
% (, uplimit))
diff = uplimit - old_uplimit
if diff != 0:
qh_add_resource_limit(r, diff)
qh_add_resource_limit(resource, diff)
def get_resources(resources=None, services=None):
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment