Revision 3a527b3a

b/snf-astakos-app/astakos/im/management/commands/resource-import.py
39 39

  
40 40
from snf_django.lib.db.transaction import commit_on_success_strict
41 41
from astakos.im.resources import add_resource
42
from astakos.im.models import Service
42 43

  
43 44

  
44 45
class Command(BaseCommand):
......
81 82

  
82 83
        if json_file:
83 84
            with open(json_file) as file_data:
84
                data = json.load(file_data)
85
                service = data.get('service')
86
                resources = data.get('resources')
87
                if service is None or resources is None:
88
                    m = "JSON file should contain service and resource data."
85
                m = ('Input should be a JSON dict containing "service" '
86
                     'and "resource" keys.')
87
                try:
88
                    data = json.load(file_data)
89
                except json.JSONDecodeError:
89 90
                    raise CommandError(m)
91
                if not isinstance(data, dict):
92
                    raise CommandError(m)
93
                else:
94
                    try:
95
                        service = data['service']
96
                        resources = data['resources']
97
                    except KeyError:
98
                        raise CommandError(m)
90 99

  
91
        self.add_resources(service, resources, config)
100
        self.add_resources(service, resources)
92 101

  
93 102

  
94 103
    @commit_on_success_strict()
95
    def add_resources(self, service, resources, config):
104
    def add_resources(self, service, resources):
105

  
106
        try:
107
            s = Service.objects.get(name=service)
108
        except Service.DoesNotExist:
109
            raise CommandError("Service '%s' is not registered." % (service))
110

  
96 111
        for resource in resources:
112
            if not isinstance(resource, dict):
113
                raise CommandError("Malformed resource dict.")
114
            exists = add_resource(s, resource)
97 115
            name = resource['name']
98
            uplimit = config.get(name)
99
            if uplimit is None:
100
                desc = resource['desc']
101
                unit = resource.get('unit')
102
                self.stdout.write(
103
                    "Provide default base quota for resource '%s' (%s)" %
104
                    (name, desc))
105
                m = (" in %s: " % unit) if unit else ": "
106
                self.stdout.write(m)
107
                uplimit = raw_input()
108

  
109
            try:
110
                uplimit = int(uplimit)
111
            except ValueError:
112
                m = "Limit for resource %s is not an integer." % (name)
113
                raise CommandError(m)
114

  
115
            add_resource(service, resource, uplimit)
116
            if exists:
117
                m = "Resource '%s' updated in database.\n" % (name)
118
            else:
119
                m = ("Resource '%s' created in database with default "
120
                     "quota limit 0.\n" % (name))
121
            self.stdout.write(m)
b/snf-astakos-app/astakos/im/management/commands/resource-modify.py
33 33

  
34 34
from optparse import make_option
35 35
from django.core.management.base import BaseCommand, CommandError
36
from django.utils import simplejson as json
36 37

  
37 38
from astakos.im.models import Resource
38 39
from astakos.im.resources import update_resource
......
40 41

  
41 42
class Command(BaseCommand):
42 43
    args = "<resource name>"
43
    help = "Modify a resource (currently only change the default base quota)"
44
    help = ("Modify a resource (currently only change the default base quota)."
45
            "\nIf no resource is specified, all resources are considered.")
44 46

  
45 47
    option_list = BaseCommand.option_list + (
46 48
        make_option('--limit',
47 49
                    dest='limit',
48
                    help="Change default base quota"),
50
                    help="Specify default base quota"),
51
        make_option('--interactive',
52
                    action='store_true',
53
                    dest='interactive',
54
                    default=None,
55
                    help="Prompt user to change default base quotas"),
56
        make_option('--from-file',
57
                    dest='from_file',
58
                    metavar='<limits_file.json>',
59
                    help="Read default base quotas from a json file"),
49 60
    )
50 61

  
51 62
    def handle(self, *args, **options):
52
        if len(args) < 1:
63
        resource_name = args[0] if len(args) > 0 else None
64

  
65
        actions = {
66
            'limit': self.change_limit,
67
            'interactive': self.change_interactive,
68
            'from_file': self.change_from_file,
69
        }
70

  
71
        opts = [(key, value)
72
                for (key, value) in options.items()
73
                if key in actions and value is not None]
74

  
75
        if len(opts) != 1:
76
            raise CommandError("Please provide exactly one option.")
77

  
78
        key, value = opts[0]
79
        action = actions[key]
80
        action(resource_name, value)
81

  
82
    def get_resource(self, resource_name):
83
        try:
84
            return Resource.objects.get_for_update(name=resource_name)
85
        except Resource.DoesNotExist:
86
            raise CommandError("Resource %s does not exist."
87
                               % resource_name)
88

  
89
    def change_limit(self, resource_name, limit):
90
        if resource_name is None:
53 91
            raise CommandError("Please provide a resource name.")
54 92

  
55
        resource_name = args[0]
93
        resource = self.get_resource(resource_name)
94
        self.change_resource_limit(resource, limit)
56 95

  
57
        limit = options['limit']
58
        if limit is None:
59
            raise CommandError("Use --limit to change default base quota.")
96
    def change_from_file(self, resource_name, filename):
97
        with open(filename) as file_data:
98
            try:
99
                config = json.load(file_data)
100
            except json.JSONDecodeError:
101
                raise CommandError("Malformed JSON file.")
102
            if not isinstance(config, dict):
103
                raise CommandError("Malformed JSON file.")
104
            self.change_with_conf(resource_name, config)
60 105

  
106
    def change_with_conf(self, resource_name, config):
107
        if resource_name is None:
108
            resources = Resource.objects.all().select_for_update()
109
        else:
110
            resources = [self.get_resource(resource_name)]
111

  
112
        for resource in resources:
113
            limit = config.get(resource.name)
114
            if limit is not None:
115
                self.change_resource_limit(resource, limit)
116

  
117
    def change_interactive(self, resource_name, _placeholder):
118
        if resource_name is None:
119
            resources = Resource.objects.all().select_for_update()
120
        else:
121
            resources = [self.get_resource(resource_name)]
122

  
123
        for resource in resources:
124
            self.stdout.write("Resource '%s' (%s)\n" %
125
                              (resource.name, resource.desc))
126
            unit = (" in %s" % resource.unit) if resource.unit else ""
127
            self.stdout.write("Current limit%s: %s\n"
128
                              % (unit, resource.uplimit))
129
            while True:
130
                self.stdout.write("New limit%s (leave blank to keep current): "
131
                                  % (unit))
132
                response = raw_input()
133
                if response == "":
134
                    break
135
                else:
136
                    try:
137
                        value = int(response)
138
                    except ValueError:
139
                        continue
140
                    update_resource(resource, value)
141
                    break
142

  
143
    def change_resource_limit(self, resource, limit):
61 144
        try:
62 145
            limit = int(limit)
63 146
        except:
64 147
            raise CommandError("Limit should be an integer.")
65

  
66
        try:
67
            update_resource(resource_name, limit)
68
        except Resource.DoesNotExist:
69
            raise CommandError("Resource %s does not exist." % resource_name)
148
        update_resource(resource, limit)
b/snf-astakos-app/astakos/im/resources.py
31 31
# interpreted as representing official policies, either expressed
32 32
# or implied, of GRNET S.A.
33 33

  
34
from astakos.im.models import Service, Resource
34
from astakos.im.models import Resource
35 35
from astakos.im.quotas import qh_add_resource_limit, qh_sync_new_resource
36 36
import logging
37 37

  
38 38
logger = logging.getLogger(__name__)
39 39

  
40
fields = ['name', 'desc', 'unit']
40 41

  
41
def add_resource(service, resource, uplimit):
42
    try:
43
        s = Service.objects.get(name=service)
44
    except Service.DoesNotExist:
45
        raise Exception("Service %s is not registered." % (service))
46 42

  
47
    name = resource['name']
43
class ResourceException(Exception):
44
    pass
45

  
46

  
47
def add_resource(service, resource_dict):
48
    name = resource_dict.get('name')
49
    if not name:
50
        raise ResourceException("Malformed resource dict.")
51

  
48 52
    try:
49 53
        r = Resource.objects.get_for_update(name=name)
50
        old_uplimit = r.uplimit
54
        exists = True
51 55
    except Resource.DoesNotExist:
52
        r = Resource()
53
        old_uplimit = None
56
        r = Resource(uplimit=0)
57
        exists = False
54 58

  
55
    r.uplimit = uplimit
56
    r.service = s
57
    for key, value in resource.iteritems():
58
        setattr(r, key, value)
59
    r.service = service
60
    for field in fields:
61
        value = resource_dict.get(field)
62
        if value is not None:
63
            setattr(r, field, value)
59 64

  
60 65
    r.save()
66
    if not exists:
67
        qh_sync_new_resource(r, 0)
61 68

  
62
    if old_uplimit is not None:
63
        logger.info("Updated resource %s with limit %s." % (name, uplimit))
69
    if exists:
70
        logger.info("Updated resource %s." % (name))
64 71
    else:
65
        logger.info("Added resource %s with limit %s." % (name, uplimit))
66

  
67
    if old_uplimit is not None:
68
        diff = uplimit - old_uplimit
69
        if diff != 0:
70
            qh_add_resource_limit(r, diff)
71
    else:
72
        qh_sync_new_resource(r, uplimit)
72
        logger.info("Added resource %s." % (name))
73
    return exists
73 74

  
74 75

  
75
def update_resource(name, uplimit):
76
    r = Resource.objects.get_for_update(name=name)
77
    old_uplimit = r.uplimit
78
    r.uplimit = uplimit
79
    r.save()
76
def update_resource(resource, uplimit):
77
    old_uplimit = resource.uplimit
78
    resource.uplimit = uplimit
79
    resource.save()
80 80

  
81
    logger.info("Updated resource %s with limit %s." % (name, uplimit))
81
    logger.info("Updated resource %s with limit %s."
82
                % (resource.name, uplimit))
82 83
    diff = uplimit - old_uplimit
83 84
    if diff != 0:
84
        qh_add_resource_limit(r, diff)
85
        qh_add_resource_limit(resource, diff)
85 86

  
86 87

  
87 88
def get_resources(resources=None, services=None):

Also available in: Unified diff