Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / management / commands / astakos-quota.py @ 2ef1e2d7

History | View | Annotate | Download (7.5 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
from django.db import transaction
37

    
38
from astakos.im.models import sync_all_users, sync_users, AstakosUser
39
from astakos.im.functions import get_user_by_uuid
40
from astakos.im.management.commands._common import is_uuid, is_email
41

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

    
45

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

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

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

    
77

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

    
83
        ex, nonex, qh_l, qh_c, astakos_i, diff_q, info = log
84

    
85
        if list_only:
86
            self.list_quotas(qh_l, qh_c, astakos_i, info)
87
        else:
88
            if verify:
89
                self.print_verify(nonex, qh_l, diff_q)
90
            if sync:
91
                self.print_sync(diff_q)
92

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

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

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

    
119
    @transaction.commit_on_success
120
    def run(self, sync):
121
        try:
122
            self.stderr.write("Calculating all quotas...\n")
123
            return sync_all_users(sync=sync)
124
        except BaseException, e:
125
            logger.exception(e)
126
            raise CommandError("Syncing failed.")
127

    
128
    def list_quotas(self, qh_limits, qh_counters, astakos_initial, info):
129
        labels = ('uuid', 'email', 'resource', 'initial', 'total', 'usage')
130
        columns = (36, 30, 24, 12, 12, 12)
131

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

    
137
        for holder, resources in qh_limits.iteritems():
138
            h_counters = qh_counters[holder]
139
            h_initial = astakos_initial[holder]
140
            email = info[holder]
141
            for resource, limits in resources.iteritems():
142
                initials = h_initial[resource]
143
                initial = str(initials.capacity)
144
                capacity = str(limits.capacity)
145
                c = h_counters[resource]
146
                used = str(c.imported - c.exported + c.returned - c.released)
147

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

    
154
                line = ' '.join(output)
155
                self.stdout.write(line + '\n')
156

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

    
167
    def print_verify(self,
168
                     nonexisting,
169
                     qh_limits,
170
                     diff_quotas):
171

    
172
            if nonexisting:
173
                self.stdout.write("Users not registered in quotaholder:\n")
174
                for user in nonexisting:
175
                    self.stdout.write("%s\n" % (user))
176
                self.stdout.write("\n")
177

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

    
193
            diffs = len(diff_quotas)
194
            if diffs:
195
                self.stdout.write("Quotas differ for %d users.\n" % (diffs))