Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (8.8 kB)

1 f557d10a Giorgos Korfiatis
# Copyright 2012, 2013 GRNET S.A. All rights reserved.
2 fc1e2f02 Sofia Papagiannaki
#
3 fc1e2f02 Sofia Papagiannaki
# Redistribution and use in source and binary forms, with or
4 fc1e2f02 Sofia Papagiannaki
# without modification, are permitted provided that the following
5 fc1e2f02 Sofia Papagiannaki
# conditions are met:
6 fc1e2f02 Sofia Papagiannaki
#
7 fc1e2f02 Sofia Papagiannaki
#   1. Redistributions of source code must retain the above
8 fc1e2f02 Sofia Papagiannaki
#      copyright notice, this list of conditions and the following
9 fc1e2f02 Sofia Papagiannaki
#      disclaimer.
10 fc1e2f02 Sofia Papagiannaki
#
11 fc1e2f02 Sofia Papagiannaki
#   2. Redistributions in binary form must reproduce the above
12 fc1e2f02 Sofia Papagiannaki
#      copyright notice, this list of conditions and the following
13 fc1e2f02 Sofia Papagiannaki
#      disclaimer in the documentation and/or other materials
14 fc1e2f02 Sofia Papagiannaki
#      provided with the distribution.
15 fc1e2f02 Sofia Papagiannaki
#
16 fc1e2f02 Sofia Papagiannaki
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 fc1e2f02 Sofia Papagiannaki
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 fc1e2f02 Sofia Papagiannaki
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 fc1e2f02 Sofia Papagiannaki
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 fc1e2f02 Sofia Papagiannaki
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 fc1e2f02 Sofia Papagiannaki
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 fc1e2f02 Sofia Papagiannaki
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 fc1e2f02 Sofia Papagiannaki
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 fc1e2f02 Sofia Papagiannaki
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 fc1e2f02 Sofia Papagiannaki
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 fc1e2f02 Sofia Papagiannaki
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 fc1e2f02 Sofia Papagiannaki
# POSSIBILITY OF SUCH DAMAGE.
28 fc1e2f02 Sofia Papagiannaki
#
29 fc1e2f02 Sofia Papagiannaki
# The views and conclusions contained in the software and
30 fc1e2f02 Sofia Papagiannaki
# documentation are those of the authors and should not be
31 fc1e2f02 Sofia Papagiannaki
# interpreted as representing official policies, either expressed
32 fc1e2f02 Sofia Papagiannaki
# or implied, of GRNET S.A.
33 fc1e2f02 Sofia Papagiannaki
34 84a3f701 Giorgos Korfiatis
from optparse import make_option
35 91eca048 Giorgos Korfiatis
from django.core.management.base import CommandError
36 a3e3917f Giorgos Korfiatis
from django.db import transaction
37 fc1e2f02 Sofia Papagiannaki
38 aa27f246 Giorgos Korfiatis
from astakos.im.models import AstakosUser
39 e336910f Giorgos Korfiatis
from astakos.im.quotas import (
40 3c22bad0 Giorgos Korfiatis
    qh_sync_users_diffs, list_user_quotas, add_base_quota)
41 3c049f6d Giorgos Korfiatis
from astakos.im.functions import get_user_by_uuid
42 db8cfc97 Giorgos Korfiatis
from astakos.im.management.commands._common import is_uuid, is_email
43 7cfc0cef Christos Stavrakakis
from snf_django.management.commands import SynnefoCommand
44 d758784b Christos Stavrakakis
from snf_django.management import utils
45 44f510e1 Giorgos Korfiatis
from ._common import show_quotas, style_options, check_style, units
46 fc1e2f02 Sofia Papagiannaki
47 9a06d96f Olga Brani
import logging
48 9a06d96f Olga Brani
logger = logging.getLogger(__name__)
49 9a06d96f Olga Brani
50 f557d10a Giorgos Korfiatis
51 91eca048 Giorgos Korfiatis
class Command(SynnefoCommand):
52 075b91de Giorgos Korfiatis
    help = "List and check the integrity of user quota"
53 5ce3ce4f Sofia Papagiannaki
54 91eca048 Giorgos Korfiatis
    option_list = SynnefoCommand.option_list + (
55 f557d10a Giorgos Korfiatis
        make_option('--list',
56 f557d10a Giorgos Korfiatis
                    action='store_true',
57 f557d10a Giorgos Korfiatis
                    dest='list',
58 f557d10a Giorgos Korfiatis
                    default=False,
59 075b91de Giorgos Korfiatis
                    help="List all quota (default)"),
60 44f510e1 Giorgos Korfiatis
        make_option('--unit-style',
61 44f510e1 Giorgos Korfiatis
                    default='mb',
62 44f510e1 Giorgos Korfiatis
                    help=("Specify display unit for resource values "
63 44f510e1 Giorgos Korfiatis
                          "(one of %s); defaults to mb") % style_options),
64 f557d10a Giorgos Korfiatis
        make_option('--verify',
65 84a3f701 Giorgos Korfiatis
                    action='store_true',
66 f557d10a Giorgos Korfiatis
                    dest='verify',
67 f557d10a Giorgos Korfiatis
                    default=False,
68 f557d10a Giorgos Korfiatis
                    help="Check if quotaholder is in sync with astakos"),
69 140da2d1 Giorgos Korfiatis
        make_option('--sync',
70 84a3f701 Giorgos Korfiatis
                    action='store_true',
71 140da2d1 Giorgos Korfiatis
                    dest='sync',
72 84a3f701 Giorgos Korfiatis
                    default=False,
73 140da2d1 Giorgos Korfiatis
                    help="Sync quotaholder"),
74 db8cfc97 Giorgos Korfiatis
        make_option('--user',
75 db8cfc97 Giorgos Korfiatis
                    metavar='<uuid or email>',
76 db8cfc97 Giorgos Korfiatis
                    dest='user',
77 075b91de Giorgos Korfiatis
                    help="List quota for a specified user"),
78 764d99c4 Giorgos Korfiatis
        make_option('--import-base-quota',
79 764d99c4 Giorgos Korfiatis
                    dest='import_base_quota',
80 075b91de Giorgos Korfiatis
                    metavar='<exported-quota.txt>',
81 075b91de Giorgos Korfiatis
                    help=("Import base quota from file. "
82 764d99c4 Giorgos Korfiatis
                          "The file must contain non-empty lines, and each "
83 764d99c4 Giorgos Korfiatis
                          "line must contain a single-space-separated list "
84 44f510e1 Giorgos Korfiatis
                          "of values: <user> <resource name> <capacity>. "
85 44f510e1 Giorgos Korfiatis
                          "Capacity can be followed by a unit with no "
86 44f510e1 Giorgos Korfiatis
                          "separating space (e.g 10GB).")
87 764d99c4 Giorgos Korfiatis
                    ),
88 84a3f701 Giorgos Korfiatis
    )
89 84a3f701 Giorgos Korfiatis
90 a3e3917f Giorgos Korfiatis
    @transaction.commit_on_success
91 84a3f701 Giorgos Korfiatis
    def handle(self, *args, **options):
92 140da2d1 Giorgos Korfiatis
        sync = options['sync']
93 2ef1e2d7 Giorgos Korfiatis
        verify = options['verify']
94 db8cfc97 Giorgos Korfiatis
        user_ident = options['user']
95 764d99c4 Giorgos Korfiatis
        list_ = options['list']
96 764d99c4 Giorgos Korfiatis
        import_base_quota = options['import_base_quota']
97 764d99c4 Giorgos Korfiatis
98 764d99c4 Giorgos Korfiatis
        if import_base_quota:
99 764d99c4 Giorgos Korfiatis
            if any([sync, verify, list_]):
100 764d99c4 Giorgos Korfiatis
                m = "--from-file cannot be combined with other options."
101 764d99c4 Giorgos Korfiatis
                raise CommandError(m)
102 764d99c4 Giorgos Korfiatis
            self.import_from_file(import_base_quota)
103 764d99c4 Giorgos Korfiatis
        else:
104 44f510e1 Giorgos Korfiatis
            unit_style = options["unit_style"]
105 44f510e1 Giorgos Korfiatis
            check_style(unit_style)
106 764d99c4 Giorgos Korfiatis
107 44f510e1 Giorgos Korfiatis
            self.quotas(sync, verify, user_ident, options["output_format"],
108 44f510e1 Giorgos Korfiatis
                        unit_style)
109 44f510e1 Giorgos Korfiatis
110 44f510e1 Giorgos Korfiatis
    def quotas(self, sync, verify, user_ident, output_format, style):
111 2ef1e2d7 Giorgos Korfiatis
        list_only = not sync and not verify
112 2ef1e2d7 Giorgos Korfiatis
113 db8cfc97 Giorgos Korfiatis
        if user_ident is not None:
114 3adbd562 Giorgos Korfiatis
            users = [self.get_user(user_ident)]
115 db8cfc97 Giorgos Korfiatis
        else:
116 3adbd562 Giorgos Korfiatis
            users = AstakosUser.objects.verified()
117 db8cfc97 Giorgos Korfiatis
118 e336910f Giorgos Korfiatis
        if list_only:
119 e336910f Giorgos Korfiatis
            qh_quotas, astakos_i = list_user_quotas(users)
120 3adbd562 Giorgos Korfiatis
121 e336910f Giorgos Korfiatis
            info = {}
122 e336910f Giorgos Korfiatis
            for user in users:
123 e336910f Giorgos Korfiatis
                info[user.uuid] = user.email
124 f557d10a Giorgos Korfiatis
125 44f510e1 Giorgos Korfiatis
            print_data, labels = show_quotas(qh_quotas, astakos_i, info,
126 44f510e1 Giorgos Korfiatis
                                             style=style)
127 91eca048 Giorgos Korfiatis
            utils.pprint_table(self.stdout, print_data, labels,
128 764d99c4 Giorgos Korfiatis
                               output_format)
129 91eca048 Giorgos Korfiatis
130 e336910f Giorgos Korfiatis
        elif verify or sync:
131 3c22bad0 Giorgos Korfiatis
            qh_limits, diff_q = qh_sync_users_diffs(users, sync=sync)
132 2ef1e2d7 Giorgos Korfiatis
            if verify:
133 0da5e49a Giorgos Korfiatis
                self.print_verify(qh_limits, diff_q)
134 2ef1e2d7 Giorgos Korfiatis
            if sync:
135 2ef1e2d7 Giorgos Korfiatis
                self.print_sync(diff_q)
136 f557d10a Giorgos Korfiatis
137 3adbd562 Giorgos Korfiatis
    def get_user(self, user_ident):
138 db8cfc97 Giorgos Korfiatis
        if is_uuid(user_ident):
139 db8cfc97 Giorgos Korfiatis
            try:
140 db8cfc97 Giorgos Korfiatis
                user = AstakosUser.objects.get(uuid=user_ident)
141 db8cfc97 Giorgos Korfiatis
            except AstakosUser.DoesNotExist:
142 7820534a Giorgos Korfiatis
                raise CommandError('There is no user with uuid: %s' %
143 db8cfc97 Giorgos Korfiatis
                                   user_ident)
144 db8cfc97 Giorgos Korfiatis
        elif is_email(user_ident):
145 db8cfc97 Giorgos Korfiatis
            try:
146 db8cfc97 Giorgos Korfiatis
                user = AstakosUser.objects.get(username=user_ident)
147 db8cfc97 Giorgos Korfiatis
            except AstakosUser.DoesNotExist:
148 7820534a Giorgos Korfiatis
                raise CommandError('There is no user with email: %s' %
149 db8cfc97 Giorgos Korfiatis
                                   user_ident)
150 db8cfc97 Giorgos Korfiatis
        else:
151 db8cfc97 Giorgos Korfiatis
            raise CommandError('Please specify user by uuid or email')
152 db8cfc97 Giorgos Korfiatis
153 7820534a Giorgos Korfiatis
        if not user.email_verified:
154 7820534a Giorgos Korfiatis
            raise CommandError('%s is not a verified user.\n' % user.uuid)
155 cb0c401a Giorgos Korfiatis
156 3adbd562 Giorgos Korfiatis
        return user
157 f557d10a Giorgos Korfiatis
158 2ef1e2d7 Giorgos Korfiatis
    def print_sync(self, diff_quotas):
159 2ef1e2d7 Giorgos Korfiatis
        size = len(diff_quotas)
160 2ef1e2d7 Giorgos Korfiatis
        if size == 0:
161 2ef1e2d7 Giorgos Korfiatis
            self.stdout.write("No sync needed.\n")
162 2ef1e2d7 Giorgos Korfiatis
        else:
163 2ef1e2d7 Giorgos Korfiatis
            self.stdout.write("Synced %s users:\n" % size)
164 2ef1e2d7 Giorgos Korfiatis
            for holder in diff_quotas.keys():
165 2ef1e2d7 Giorgos Korfiatis
                user = get_user_by_uuid(holder)
166 2ef1e2d7 Giorgos Korfiatis
                self.stdout.write("%s (%s)\n" % (holder, user.username))
167 2ef1e2d7 Giorgos Korfiatis
168 f557d10a Giorgos Korfiatis
    def print_verify(self,
169 f557d10a Giorgos Korfiatis
                     qh_limits,
170 2ef1e2d7 Giorgos Korfiatis
                     diff_quotas):
171 62fda315 Giorgos Korfiatis
172 2ef1e2d7 Giorgos Korfiatis
            for holder, local in diff_quotas.iteritems():
173 f557d10a Giorgos Korfiatis
                registered = qh_limits.pop(holder, None)
174 2ef1e2d7 Giorgos Korfiatis
                user = get_user_by_uuid(holder)
175 3c049f6d Giorgos Korfiatis
                if registered is None:
176 2ef1e2d7 Giorgos Korfiatis
                    self.stdout.write(
177 075b91de Giorgos Korfiatis
                        "No quota for %s (%s) in quotaholder.\n" %
178 2ef1e2d7 Giorgos Korfiatis
                        (holder, user.username))
179 2ef1e2d7 Giorgos Korfiatis
                else:
180 075b91de Giorgos Korfiatis
                    self.stdout.write("Quota differ for %s (%s):\n" %
181 2ef1e2d7 Giorgos Korfiatis
                                      (holder, user.username))
182 075b91de Giorgos Korfiatis
                    self.stdout.write("Quota according to quotaholder:\n")
183 3c049f6d Giorgos Korfiatis
                    self.stdout.write("%s\n" % (registered))
184 075b91de Giorgos Korfiatis
                    self.stdout.write("Quota according to astakos:\n")
185 3c049f6d Giorgos Korfiatis
                    self.stdout.write("%s\n\n" % (local))
186 3c049f6d Giorgos Korfiatis
187 2ef1e2d7 Giorgos Korfiatis
            diffs = len(diff_quotas)
188 3c049f6d Giorgos Korfiatis
            if diffs:
189 075b91de Giorgos Korfiatis
                self.stdout.write("Quota differ for %d users.\n" % (diffs))
190 764d99c4 Giorgos Korfiatis
191 764d99c4 Giorgos Korfiatis
    def import_from_file(self, location):
192 764d99c4 Giorgos Korfiatis
        users = set()
193 764d99c4 Giorgos Korfiatis
        with open(location) as f:
194 764d99c4 Giorgos Korfiatis
            for line in f.readlines():
195 764d99c4 Giorgos Korfiatis
                try:
196 764d99c4 Giorgos Korfiatis
                    t = line.rstrip('\n').split(' ')
197 764d99c4 Giorgos Korfiatis
                    user = t[0]
198 764d99c4 Giorgos Korfiatis
                    resource = t[1]
199 764d99c4 Giorgos Korfiatis
                    capacity = t[2]
200 44f510e1 Giorgos Korfiatis
                    try:
201 44f510e1 Giorgos Korfiatis
                        capacity = units.parse(capacity)
202 44f510e1 Giorgos Korfiatis
                    except units.ParseError:
203 44f510e1 Giorgos Korfiatis
                        m = ("Capacity should be an integer, optionally "
204 44f510e1 Giorgos Korfiatis
                             "followed by a unit.")
205 44f510e1 Giorgos Korfiatis
                        raise CommandError(m)
206 764d99c4 Giorgos Korfiatis
                except(IndexError, TypeError):
207 764d99c4 Giorgos Korfiatis
                    self.stdout.write('Invalid line format: %s:\n' % t)
208 764d99c4 Giorgos Korfiatis
                    continue
209 764d99c4 Giorgos Korfiatis
                else:
210 764d99c4 Giorgos Korfiatis
                    try:
211 764d99c4 Giorgos Korfiatis
                        user = self.get_user(user)
212 764d99c4 Giorgos Korfiatis
                        users.add(user.id)
213 764d99c4 Giorgos Korfiatis
                    except CommandError:
214 764d99c4 Giorgos Korfiatis
                        self.stdout.write('Not found user: %s\n' % user)
215 764d99c4 Giorgos Korfiatis
                        continue
216 764d99c4 Giorgos Korfiatis
                    else:
217 764d99c4 Giorgos Korfiatis
                        try:
218 764d99c4 Giorgos Korfiatis
                            add_base_quota(user, resource, capacity)
219 764d99c4 Giorgos Korfiatis
                        except Exception, e:
220 764d99c4 Giorgos Korfiatis
                            self.stdout.write('Failed to add quota: %s\n' % e)
221 764d99c4 Giorgos Korfiatis
                            continue