Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / management / commands / astakos-quota.py @ 480974e6

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 sync_all_users, sync_users
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
    def handle(self, *args, **options):
73
        sync = options['sync']
74
        verify = options['verify']
75
        user_ident = options['user']
76
        list_only = not sync and not verify
77

    
78

    
79
        if user_ident is not None:
80
            log = self.run_sync_user(user_ident, sync)
81
        else:
82
            log = self.run(sync)
83

    
84
        qh_limits, qh_quotas, astakos_i, diff_q, info = log
85

    
86
        if list_only:
87
            self.list_quotas(qh_quotas, astakos_i, info)
88
        else:
89
            if verify:
90
                self.print_verify(qh_limits, diff_q)
91
            if sync:
92
                self.print_sync(diff_q)
93

    
94
    @commit_on_success_strict()
95
    def run_sync_user(self, user_ident, sync):
96
        if is_uuid(user_ident):
97
            try:
98
                user = AstakosUser.objects.get(uuid=user_ident)
99
            except AstakosUser.DoesNotExist:
100
                raise CommandError('Not found user having uuid: %s' %
101
                                   user_ident)
102
        elif is_email(user_ident):
103
            try:
104
                user = AstakosUser.objects.get(username=user_ident)
105
            except AstakosUser.DoesNotExist:
106
                raise CommandError('Not found user having email: %s' %
107
                                   user_ident)
108
        else:
109
            raise CommandError('Please specify user by uuid or email')
110

    
111
        if not user.email_verified and sync:
112
            raise CommandError('User %s is not verified.' % user.uuid)
113

    
114
        try:
115
            return sync_users([user], sync=sync)
116
        except BaseException, e:
117
            logger.exception(e)
118
            raise CommandError("Failed to compute quotas.")
119

    
120
    @commit_on_success_strict()
121
    def run(self, sync):
122
        try:
123
            self.stderr.write("Calculating all quotas...\n")
124
            return sync_all_users(sync=sync)
125
        except BaseException, e:
126
            logger.exception(e)
127
            raise CommandError("Syncing failed.")
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))