Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (7.1 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 sync_all_users, sync_users, AstakosUser
38
from astakos.im.functions import get_user_by_uuid
39
from astakos.im.management.commands._common import is_uuid, is_email
40
from synnefo.lib.db.transaction import commit_on_success_strict
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
        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(qh_l, diff_q)
90
            if sync:
91
                self.print_sync(diff_q)
92

    
93
    @commit_on_success_strict()
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
    @commit_on_success_strict()
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
                initial = str(h_initial[resource])
143
                capacity = str(limits)
144
                used = str(h_counters[resource])
145

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

    
152
                line = ' '.join(output)
153
                self.stdout.write(line + '\n')
154

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

    
165
    def print_verify(self,
166
                     qh_limits,
167
                     diff_quotas):
168

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

    
184
            diffs = len(diff_quotas)
185
            if diffs:
186
                self.stdout.write("Quotas differ for %d users.\n" % (diffs))