Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (7 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'] or sync
74
        user_ident = options['user']
75

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

    
81
        ex, nonex, qh_l, qh_c, astakos_i, astakos_q, info = log
82

    
83
        if verify:
84
            self.print_verify(nonex, qh_l, astakos_q)
85

    
86
        else:
87
            self.list_quotas(qh_l, qh_c, astakos_i, info)
88

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

    
106
        if not user.email_verified and sync:
107
            raise CommandError('User %s is not verified.' % user.uuid)
108

    
109
        try:
110
            return sync_users([user], sync=sync)
111
        except BaseException, e:
112
            logger.exception(e)
113
            raise CommandError("Failed to compute quotas.")
114

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

    
124
    def list_quotas(self, qh_limits, qh_counters, astakos_initial, info):
125
        labels = ('uuid', 'email', 'resource', 'initial', 'total', 'usage')
126
        columns = (36, 30, 24, 12, 12, 12)
127

    
128
        line = ' '.join(l.rjust(w) for l, w in zip(labels, columns))
129
        self.stdout.write(line + '\n')
130
        sep = '-' * len(line)
131
        self.stdout.write(sep + '\n')
132

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

    
144
                fields = holder, email, resource, initial, capacity, used
145
                output = []
146
                for field, width in zip(fields, columns):
147
                    s = field.rjust(width)
148
                    output.append(s)
149

    
150
                line = ' '.join(output)
151
                self.stdout.write(line + '\n')
152

    
153
    def print_verify(self,
154
                     nonexisting,
155
                     qh_limits,
156
                     astakos_quotas):
157

    
158
            if nonexisting:
159
                self.stdout.write("Users not registered in quotaholder:\n")
160
                for user in nonexisting:
161
                    self.stdout.write("%s\n" % (user))
162
                self.stdout.write("\n")
163

    
164
            diffs = 0
165
            for holder, local in astakos_quotas.iteritems():
166
                registered = qh_limits.pop(holder, None)
167
                if registered is None:
168
                    diffs += 1
169
                    self.stdout.write("No quotas for %s in quotaholder.\n\n" %
170
                                      (get_user_by_uuid(holder)))
171
                elif local != registered:
172
                    diffs += 1
173
                    self.stdout.write("Quotas differ for %s:\n" %
174
                                      (get_user_by_uuid(holder)))
175
                    self.stdout.write("Quotas according to quotaholder:\n")
176
                    self.stdout.write("%s\n" % (registered))
177
                    self.stdout.write("Quotas according to astakos:\n")
178
                    self.stdout.write("%s\n\n" % (local))
179

    
180
            if diffs:
181
                self.stdout.write("Quotas differ for %d users.\n" % (diffs))