Revision 075b91de
b/docs/admin-guide.rst | ||
---|---|---|
140 | 140 |
Setting quota limits |
141 | 141 |
~~~~~~~~~~~~~~~~~~~~ |
142 | 142 |
|
143 |
Set default quotas
|
|
144 |
``````````````````
|
|
143 |
Set default quota |
|
144 |
````````````````` |
|
145 | 145 |
|
146 | 146 |
In 20-snf-astakos-app-settings.conf, |
147 | 147 |
uncomment the default setting ``ASTAKOS_SERVICES`` |
148 | 148 |
and customize the ``'uplimit'`` values. |
149 |
These are the default base quotas for all users.
|
|
149 |
These are the default base quota for all users. |
|
150 | 150 |
|
151 | 151 |
To apply your configuration run:: |
152 | 152 |
|
153 | 153 |
# snf-manage astakos-init --load-service-resources |
154 |
# snf-manage astakos-quota --sync
|
|
154 |
# snf-manage quota --sync |
|
155 | 155 |
|
156 |
Set base quotas for individual users
|
|
157 |
````````````````````````````````````
|
|
156 |
Set base quota for individual users |
|
157 |
``````````````````````````````````` |
|
158 | 158 |
|
159 |
For individual users that need different quotas than the default
|
|
159 |
For individual users that need different quota than the default |
|
160 | 160 |
you can set it for each resource like this:: |
161 | 161 |
|
162 |
# use this to display quotas / uuid
|
|
163 |
# snf-manage user-show 'uuid or email' --quotas
|
|
162 |
# use this to display quota / uuid |
|
163 |
# snf-manage user-show 'uuid or email' --quota |
|
164 | 164 |
|
165 |
# snf-manage user-modify 'user-uuid' --set-quota 'cyclades.vm' 10 |
|
165 |
# snf-manage user-modify 'user-uuid' --set-base-quota 'cyclades.vm' 10
|
|
166 | 166 |
|
167 | 167 |
|
168 | 168 |
Enable the Projects feature |
... | ... | |
182 | 182 |
|
183 | 183 |
You can also set a user-specific limit with:: |
184 | 184 |
|
185 |
# snf-manage user-modify 'user-uuid' --set-quota 'astakos.pending_app' 5 |
|
185 |
# snf-manage user-modify 'user-uuid' --set-base-quota 'astakos.pending_app' 5
|
|
186 | 186 |
|
187 | 187 |
When users apply for projects they are not automatically granted |
188 | 188 |
the resources. They must first be approved by the administrator. |
b/docs/quick-install-admin-guide.rst | ||
---|---|---|
2001 | 2001 |
.. code-block:: console |
2002 | 2002 |
|
2003 | 2003 |
node1 # snf-manage astakos-init --load-service-resources |
2004 |
node1 # snf-manage astakos-quota --verify
|
|
2005 |
node1 # snf-manage astakos-quota --sync
|
|
2004 |
node1 # snf-manage quota --verify |
|
2005 |
node1 # snf-manage quota --sync |
|
2006 | 2006 |
node2 # snf-manage pithos-reset-usage |
2007 | 2007 |
node1 # snf-manage reconcile-resources-cyclades --fix |
2008 | 2008 |
|
b/docs/scale/i-astakos.rst | ||
---|---|---|
140 | 140 |
# snf-manage service-add "cyclades" https://cyclades.example.com/ui/ |
141 | 141 |
# snf-manage service-add "pithos+" https://pithos.example.com/ui/ |
142 | 142 |
# snf-manage astakos-init --load-service-resources |
143 |
# snf-manage astakos-quota --sync
|
|
143 |
# snf-manage quota --sync |
|
144 | 144 |
# /etc/init.d/gunicorn restart |
145 | 145 |
# /etc/init.d/apache2 restart |
146 | 146 |
|
b/snf-astakos-app/README | ||
---|---|---|
165 | 165 |
============================ =========================== |
166 | 166 |
Name Description |
167 | 167 |
============================ =========================== |
168 |
astakos-quota Inspect quotaholder status |
|
169 | 168 |
fix-superusers Transform superusers created by syncdb into AstakosUser instances |
170 | 169 |
full-cleanup Cleanup sessions and session catalog |
171 | 170 |
invitation-list List invitation |
... | ... | |
173 | 172 |
project-control Manage projects and applications |
174 | 173 |
project-list List projects |
175 | 174 |
project-show Show project details |
175 |
quota List and check the integrity of user quota |
|
176 | 176 |
reconcile-resources-astakos Reconcile resource usage of Quotaholder with Astakos DB |
177 | 177 |
resource-add Add resource |
178 | 178 |
resource-export-astakos Export astakos resources in json format |
/dev/null | ||
---|---|---|
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 CommandError |
|
36 |
|
|
37 |
from astakos.im.models import AstakosUser |
|
38 |
from astakos.im.quotas import set_user_quota, list_user_quotas, add_base_quota |
|
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 |
from synnefo.webproject.management.commands import SynnefoCommand |
|
43 |
from synnefo.webproject.management import utils |
|
44 |
from ._common import show_quotas |
|
45 |
|
|
46 |
import logging |
|
47 |
logger = logging.getLogger(__name__) |
|
48 |
|
|
49 |
|
|
50 |
class Command(SynnefoCommand): |
|
51 |
help = "Inspect quotaholder status" |
|
52 |
|
|
53 |
option_list = SynnefoCommand.option_list + ( |
|
54 |
make_option('--list', |
|
55 |
action='store_true', |
|
56 |
dest='list', |
|
57 |
default=False, |
|
58 |
help="List all quotas (default)"), |
|
59 |
make_option('--verify', |
|
60 |
action='store_true', |
|
61 |
dest='verify', |
|
62 |
default=False, |
|
63 |
help="Check if quotaholder is in sync with astakos"), |
|
64 |
make_option('--sync', |
|
65 |
action='store_true', |
|
66 |
dest='sync', |
|
67 |
default=False, |
|
68 |
help="Sync quotaholder"), |
|
69 |
make_option('--user', |
|
70 |
metavar='<uuid or email>', |
|
71 |
dest='user', |
|
72 |
help="List quotas for a specified user"), |
|
73 |
make_option('--import-base-quota', |
|
74 |
dest='import_base_quota', |
|
75 |
metavar='<exported-quotas.txt>', |
|
76 |
help=("Import base quotas from file. " |
|
77 |
"The file must contain non-empty lines, and each " |
|
78 |
"line must contain a single-space-separated list " |
|
79 |
"of values: <user> <resource name> <capacity>") |
|
80 |
), |
|
81 |
) |
|
82 |
|
|
83 |
@commit_on_success_strict() |
|
84 |
def handle(self, *args, **options): |
|
85 |
sync = options['sync'] |
|
86 |
verify = options['verify'] |
|
87 |
user_ident = options['user'] |
|
88 |
list_ = options['list'] |
|
89 |
import_base_quota = options['import_base_quota'] |
|
90 |
|
|
91 |
if import_base_quota: |
|
92 |
if any([sync, verify, list_]): |
|
93 |
m = "--from-file cannot be combined with other options." |
|
94 |
raise CommandError(m) |
|
95 |
self.import_from_file(import_base_quota) |
|
96 |
else: |
|
97 |
self.quotas(sync, verify, user_ident, options["output_format"]) |
|
98 |
|
|
99 |
def quotas(self, sync, verify, user_ident, output_format): |
|
100 |
list_only = not sync and not verify |
|
101 |
|
|
102 |
if user_ident is not None: |
|
103 |
users = [self.get_user(user_ident)] |
|
104 |
else: |
|
105 |
users = AstakosUser.objects.verified() |
|
106 |
|
|
107 |
try: |
|
108 |
qh_limits, qh_quotas, astakos_i, diff_q = list_user_quotas(users) |
|
109 |
except BaseException as e: |
|
110 |
logger.exception(e) |
|
111 |
raise CommandError("Failed to compute quotas.") |
|
112 |
|
|
113 |
info = {} |
|
114 |
for user in users: |
|
115 |
info[user.uuid] = user.email |
|
116 |
|
|
117 |
if list_only: |
|
118 |
print_data, labels = show_quotas(qh_quotas, astakos_i, info) |
|
119 |
utils.pprint_table(self.stdout, print_data, labels, |
|
120 |
output_format) |
|
121 |
|
|
122 |
else: |
|
123 |
if verify: |
|
124 |
self.print_verify(qh_limits, diff_q) |
|
125 |
if sync: |
|
126 |
try: |
|
127 |
set_user_quota(diff_q) |
|
128 |
except BaseException as e: |
|
129 |
logger.exception(e) |
|
130 |
raise CommandError("Failed to sync quotas.") |
|
131 |
self.print_sync(diff_q) |
|
132 |
|
|
133 |
def get_user(self, user_ident): |
|
134 |
if is_uuid(user_ident): |
|
135 |
try: |
|
136 |
user = AstakosUser.objects.get(uuid=user_ident) |
|
137 |
except AstakosUser.DoesNotExist: |
|
138 |
raise CommandError('Not found user having uuid: %s' % |
|
139 |
user_ident) |
|
140 |
elif is_email(user_ident): |
|
141 |
try: |
|
142 |
user = AstakosUser.objects.get(username=user_ident) |
|
143 |
except AstakosUser.DoesNotExist: |
|
144 |
raise CommandError('Not found user having email: %s' % |
|
145 |
user_ident) |
|
146 |
else: |
|
147 |
raise CommandError('Please specify user by uuid or email') |
|
148 |
|
|
149 |
if not user.email_verified and sync: |
|
150 |
raise CommandError('User %s is not verified.' % user.uuid) |
|
151 |
|
|
152 |
return user |
|
153 |
|
|
154 |
def print_sync(self, diff_quotas): |
|
155 |
size = len(diff_quotas) |
|
156 |
if size == 0: |
|
157 |
self.stdout.write("No sync needed.\n") |
|
158 |
else: |
|
159 |
self.stdout.write("Synced %s users:\n" % size) |
|
160 |
for holder in diff_quotas.keys(): |
|
161 |
user = get_user_by_uuid(holder) |
|
162 |
self.stdout.write("%s (%s)\n" % (holder, user.username)) |
|
163 |
|
|
164 |
def print_verify(self, |
|
165 |
qh_limits, |
|
166 |
diff_quotas): |
|
167 |
|
|
168 |
for holder, local in diff_quotas.iteritems(): |
|
169 |
registered = qh_limits.pop(holder, None) |
|
170 |
user = get_user_by_uuid(holder) |
|
171 |
if registered is None: |
|
172 |
self.stdout.write( |
|
173 |
"No quotas for %s (%s) in quotaholder.\n" % |
|
174 |
(holder, user.username)) |
|
175 |
else: |
|
176 |
self.stdout.write("Quotas differ for %s (%s):\n" % |
|
177 |
(holder, user.username)) |
|
178 |
self.stdout.write("Quotas according to quotaholder:\n") |
|
179 |
self.stdout.write("%s\n" % (registered)) |
|
180 |
self.stdout.write("Quotas according to astakos:\n") |
|
181 |
self.stdout.write("%s\n\n" % (local)) |
|
182 |
|
|
183 |
diffs = len(diff_quotas) |
|
184 |
if diffs: |
|
185 |
self.stdout.write("Quotas differ for %d users.\n" % (diffs)) |
|
186 |
|
|
187 |
def import_from_file(self, location): |
|
188 |
users = set() |
|
189 |
with open(location) as f: |
|
190 |
for line in f.readlines(): |
|
191 |
try: |
|
192 |
t = line.rstrip('\n').split(' ') |
|
193 |
user = t[0] |
|
194 |
resource = t[1] |
|
195 |
capacity = t[2] |
|
196 |
except(IndexError, TypeError): |
|
197 |
self.stdout.write('Invalid line format: %s:\n' % t) |
|
198 |
continue |
|
199 |
else: |
|
200 |
try: |
|
201 |
user = self.get_user(user) |
|
202 |
users.add(user.id) |
|
203 |
except CommandError: |
|
204 |
self.stdout.write('Not found user: %s\n' % user) |
|
205 |
continue |
|
206 |
else: |
|
207 |
try: |
|
208 |
add_base_quota(user, resource, capacity) |
|
209 |
except Exception, e: |
|
210 |
self.stdout.write('Failed to add quota: %s\n' % e) |
|
211 |
continue |
b/snf-astakos-app/astakos/im/management/commands/quota.py | ||
---|---|---|
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 CommandError |
|
36 |
|
|
37 |
from astakos.im.models import AstakosUser |
|
38 |
from astakos.im.quotas import set_user_quota, list_user_quotas, add_base_quota |
|
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 |
from synnefo.webproject.management.commands import SynnefoCommand |
|
43 |
from synnefo.webproject.management import utils |
|
44 |
from ._common import show_quotas |
|
45 |
|
|
46 |
import logging |
|
47 |
logger = logging.getLogger(__name__) |
|
48 |
|
|
49 |
|
|
50 |
class Command(SynnefoCommand): |
|
51 |
help = "List and check the integrity of user quota" |
|
52 |
|
|
53 |
option_list = SynnefoCommand.option_list + ( |
|
54 |
make_option('--list', |
|
55 |
action='store_true', |
|
56 |
dest='list', |
|
57 |
default=False, |
|
58 |
help="List all quota (default)"), |
|
59 |
make_option('--verify', |
|
60 |
action='store_true', |
|
61 |
dest='verify', |
|
62 |
default=False, |
|
63 |
help="Check if quotaholder is in sync with astakos"), |
|
64 |
make_option('--sync', |
|
65 |
action='store_true', |
|
66 |
dest='sync', |
|
67 |
default=False, |
|
68 |
help="Sync quotaholder"), |
|
69 |
make_option('--user', |
|
70 |
metavar='<uuid or email>', |
|
71 |
dest='user', |
|
72 |
help="List quota for a specified user"), |
|
73 |
make_option('--import-base-quota', |
|
74 |
dest='import_base_quota', |
|
75 |
metavar='<exported-quota.txt>', |
|
76 |
help=("Import base quota from file. " |
|
77 |
"The file must contain non-empty lines, and each " |
|
78 |
"line must contain a single-space-separated list " |
|
79 |
"of values: <user> <resource name> <capacity>") |
|
80 |
), |
|
81 |
) |
|
82 |
|
|
83 |
@commit_on_success_strict() |
|
84 |
def handle(self, *args, **options): |
|
85 |
sync = options['sync'] |
|
86 |
verify = options['verify'] |
|
87 |
user_ident = options['user'] |
|
88 |
list_ = options['list'] |
|
89 |
import_base_quota = options['import_base_quota'] |
|
90 |
|
|
91 |
if import_base_quota: |
|
92 |
if any([sync, verify, list_]): |
|
93 |
m = "--from-file cannot be combined with other options." |
|
94 |
raise CommandError(m) |
|
95 |
self.import_from_file(import_base_quota) |
|
96 |
else: |
|
97 |
self.quotas(sync, verify, user_ident, options["output_format"]) |
|
98 |
|
|
99 |
def quotas(self, sync, verify, user_ident, output_format): |
|
100 |
list_only = not sync and not verify |
|
101 |
|
|
102 |
if user_ident is not None: |
|
103 |
users = [self.get_user(user_ident)] |
|
104 |
else: |
|
105 |
users = AstakosUser.objects.verified() |
|
106 |
|
|
107 |
try: |
|
108 |
qh_limits, qh_quotas, astakos_i, diff_q = list_user_quotas(users) |
|
109 |
except BaseException as e: |
|
110 |
logger.exception(e) |
|
111 |
raise CommandError("Failed to compute quota.") |
|
112 |
|
|
113 |
info = {} |
|
114 |
for user in users: |
|
115 |
info[user.uuid] = user.email |
|
116 |
|
|
117 |
if list_only: |
|
118 |
print_data, labels = show_quotas(qh_quotas, astakos_i, info) |
|
119 |
utils.pprint_table(self.stdout, print_data, labels, |
|
120 |
output_format) |
|
121 |
|
|
122 |
else: |
|
123 |
if verify: |
|
124 |
self.print_verify(qh_limits, diff_q) |
|
125 |
if sync: |
|
126 |
try: |
|
127 |
set_user_quota(diff_q) |
|
128 |
except BaseException as e: |
|
129 |
logger.exception(e) |
|
130 |
raise CommandError("Failed to sync quota.") |
|
131 |
self.print_sync(diff_q) |
|
132 |
|
|
133 |
def get_user(self, user_ident): |
|
134 |
if is_uuid(user_ident): |
|
135 |
try: |
|
136 |
user = AstakosUser.objects.get(uuid=user_ident) |
|
137 |
except AstakosUser.DoesNotExist: |
|
138 |
raise CommandError('Not found user having uuid: %s' % |
|
139 |
user_ident) |
|
140 |
elif is_email(user_ident): |
|
141 |
try: |
|
142 |
user = AstakosUser.objects.get(username=user_ident) |
|
143 |
except AstakosUser.DoesNotExist: |
|
144 |
raise CommandError('Not found user having email: %s' % |
|
145 |
user_ident) |
|
146 |
else: |
|
147 |
raise CommandError('Please specify user by uuid or email') |
|
148 |
|
|
149 |
if not user.email_verified and sync: |
|
150 |
raise CommandError('User %s is not verified.' % user.uuid) |
|
151 |
|
|
152 |
return user |
|
153 |
|
|
154 |
def print_sync(self, diff_quotas): |
|
155 |
size = len(diff_quotas) |
|
156 |
if size == 0: |
|
157 |
self.stdout.write("No sync needed.\n") |
|
158 |
else: |
|
159 |
self.stdout.write("Synced %s users:\n" % size) |
|
160 |
for holder in diff_quotas.keys(): |
|
161 |
user = get_user_by_uuid(holder) |
|
162 |
self.stdout.write("%s (%s)\n" % (holder, user.username)) |
|
163 |
|
|
164 |
def print_verify(self, |
|
165 |
qh_limits, |
|
166 |
diff_quotas): |
|
167 |
|
|
168 |
for holder, local in diff_quotas.iteritems(): |
|
169 |
registered = qh_limits.pop(holder, None) |
|
170 |
user = get_user_by_uuid(holder) |
|
171 |
if registered is None: |
|
172 |
self.stdout.write( |
|
173 |
"No quota for %s (%s) in quotaholder.\n" % |
|
174 |
(holder, user.username)) |
|
175 |
else: |
|
176 |
self.stdout.write("Quota differ for %s (%s):\n" % |
|
177 |
(holder, user.username)) |
|
178 |
self.stdout.write("Quota according to quotaholder:\n") |
|
179 |
self.stdout.write("%s\n" % (registered)) |
|
180 |
self.stdout.write("Quota according to astakos:\n") |
|
181 |
self.stdout.write("%s\n\n" % (local)) |
|
182 |
|
|
183 |
diffs = len(diff_quotas) |
|
184 |
if diffs: |
|
185 |
self.stdout.write("Quota differ for %d users.\n" % (diffs)) |
|
186 |
|
|
187 |
def import_from_file(self, location): |
|
188 |
users = set() |
|
189 |
with open(location) as f: |
|
190 |
for line in f.readlines(): |
|
191 |
try: |
|
192 |
t = line.rstrip('\n').split(' ') |
|
193 |
user = t[0] |
|
194 |
resource = t[1] |
|
195 |
capacity = t[2] |
|
196 |
except(IndexError, TypeError): |
|
197 |
self.stdout.write('Invalid line format: %s:\n' % t) |
|
198 |
continue |
|
199 |
else: |
|
200 |
try: |
|
201 |
user = self.get_user(user) |
|
202 |
users.add(user.id) |
|
203 |
except CommandError: |
|
204 |
self.stdout.write('Not found user: %s\n' % user) |
|
205 |
continue |
|
206 |
else: |
|
207 |
try: |
|
208 |
add_base_quota(user, resource, capacity) |
|
209 |
except Exception, e: |
|
210 |
self.stdout.write('Failed to add quota: %s\n' % e) |
|
211 |
continue |
b/snf-astakos-app/astakos/im/management/commands/user-show.py | ||
---|---|---|
51 | 51 |
help = "Show user info" |
52 | 52 |
|
53 | 53 |
option_list = SynnefoCommand.option_list + ( |
54 |
make_option('--quotas',
|
|
54 |
make_option('--quota', |
|
55 | 55 |
action='store_true', |
56 | 56 |
dest='list_quotas', |
57 | 57 |
default=False, |
58 |
help="Also list user quotas"),
|
|
58 |
help="Also list user quota"), |
|
59 | 59 |
) |
60 | 60 |
|
61 | 61 |
def handle(self, *args, **options): |
Also available in: Unified diff