Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / management / commands / astakos-quota.py @ 3adbd562

History | View | Annotate | Download (7.4 kB)

1
# Copyright 2012, 2013 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
from optparse import make_option
35
from django.core.management.base import BaseCommand, CommandError
36

    
37
from astakos.im.models import AstakosUser
38
from astakos.im.quotas import set_user_quota, list_user_quotas
39
from astakos.im.functions import get_user_by_uuid
40
from astakos.im.management.commands._common import is_uuid, is_email
41
from snf_django.lib.db.transaction import commit_on_success_strict
42

    
43
import logging
44
logger = logging.getLogger(__name__)
45

    
46

    
47
class Command(BaseCommand):
48
    help = "Inspect quotaholder status"
49

    
50
    option_list = BaseCommand.option_list + (
51
        make_option('--list',
52
                    action='store_true',
53
                    dest='list',
54
                    default=False,
55
                    help="List all quotas (default)"),
56
        make_option('--verify',
57
                    action='store_true',
58
                    dest='verify',
59
                    default=False,
60
                    help="Check if quotaholder is in sync with astakos"),
61
        make_option('--sync',
62
                    action='store_true',
63
                    dest='sync',
64
                    default=False,
65
                    help="Sync quotaholder"),
66
        make_option('--user',
67
                    metavar='<uuid or email>',
68
                    dest='user',
69
                    help="List quotas for a specified user"),
70
    )
71

    
72
    @commit_on_success_strict()
73
    def handle(self, *args, **options):
74
        sync = options['sync']
75
        verify = options['verify']
76
        user_ident = options['user']
77
        list_only = not sync and not verify
78

    
79

    
80
        if user_ident is not None:
81
            users = [self.get_user(user_ident)]
82
        else:
83
            users = AstakosUser.objects.verified()
84

    
85
        try:
86
            qh_limits, qh_quotas, astakos_i, diff_q = list_user_quotas(users)
87
        except BaseException as e:
88
            logger.exception(e)
89
            raise CommandError("Failed to compute quotas.")
90

    
91
        info = {}
92
        for user in users:
93
            info[user.uuid] = user.email
94

    
95
        if list_only:
96
            self.list_quotas(qh_quotas, astakos_i, info)
97
        else:
98
            if verify:
99
                self.print_verify(qh_limits, diff_q)
100
            if sync:
101
                try:
102
                    set_user_quota(diff_q)
103
                except BaseException as e:
104
                    logger.exception(e)
105
                    raise CommandError("Failed to sync quotas.")
106
                self.print_sync(diff_q)
107

    
108
    def get_user(self, user_ident):
109
        if is_uuid(user_ident):
110
            try:
111
                user = AstakosUser.objects.get(uuid=user_ident)
112
            except AstakosUser.DoesNotExist:
113
                raise CommandError('Not found user having uuid: %s' %
114
                                   user_ident)
115
        elif is_email(user_ident):
116
            try:
117
                user = AstakosUser.objects.get(username=user_ident)
118
            except AstakosUser.DoesNotExist:
119
                raise CommandError('Not found user having email: %s' %
120
                                   user_ident)
121
        else:
122
            raise CommandError('Please specify user by uuid or email')
123

    
124
        if not user.email_verified and sync:
125
            raise CommandError('User %s is not verified.' % user.uuid)
126

    
127
        return user
128

    
129
    def list_quotas(self, qh_quotas, astakos_initial, info):
130
        labels = ('uuid', 'email', 'source', 'resource', 'initial', 'total', 'usage')
131
        columns = (36, 30, 20, 24, 12, 12, 12)
132

    
133
        line = ' '.join(l.rjust(w) for l, w in zip(labels, columns))
134
        self.stdout.write(line + '\n')
135
        sep = '-' * len(line)
136
        self.stdout.write(sep + '\n')
137

    
138
        for holder, holder_quotas in qh_quotas.iteritems():
139
            h_initial = astakos_initial.get(holder)
140
            email = info.get(holder, "")
141
            for source, source_quotas in holder_quotas.iteritems():
142
                s_initial = h_initial.get(source) if h_initial else None
143
                for resource, values in source_quotas.iteritems():
144
                    initial = s_initial.get(resource) if s_initial else None
145
                    initial = str(initial)
146
                    capacity = str(values['limit'])
147
                    usage = str(values['usage'])
148

    
149
                    fields = (holder, email, source, resource,
150
                              initial, capacity, usage)
151
                    output = []
152
                    for field, width in zip(fields, columns):
153
                        s = field.rjust(width)
154
                        output.append(s)
155

    
156
                    line = ' '.join(output)
157
                    self.stdout.write(line + '\n')
158

    
159
    def print_sync(self, diff_quotas):
160
        size = len(diff_quotas)
161
        if size == 0:
162
            self.stdout.write("No sync needed.\n")
163
        else:
164
            self.stdout.write("Synced %s users:\n" % size)
165
            for holder in diff_quotas.keys():
166
                user = get_user_by_uuid(holder)
167
                self.stdout.write("%s (%s)\n" % (holder, user.username))
168

    
169
    def print_verify(self,
170
                     qh_limits,
171
                     diff_quotas):
172

    
173
            for holder, local in diff_quotas.iteritems():
174
                registered = qh_limits.pop(holder, None)
175
                user = get_user_by_uuid(holder)
176
                if registered is None:
177
                    self.stdout.write(
178
                        "No quotas for %s (%s) in quotaholder.\n" %
179
                        (holder, user.username))
180
                else:
181
                    self.stdout.write("Quotas differ for %s (%s):\n" %
182
                                      (holder, user.username))
183
                    self.stdout.write("Quotas according to quotaholder:\n")
184
                    self.stdout.write("%s\n" % (registered))
185
                    self.stdout.write("Quotas according to astakos:\n")
186
                    self.stdout.write("%s\n\n" % (local))
187

    
188
            diffs = len(diff_quotas)
189
            if diffs:
190
                self.stdout.write("Quotas differ for %d users.\n" % (diffs))