root / snf-astakos-app / astakos / im / management / commands / user-set-initial-quota.py @ cb14cc6c
History | View | Annotate | Download (7.9 kB)
1 | 8d1636b5 | Giorgos Korfiatis | # Copyright 2012, 2013 GRNET S.A. All rights reserved.
|
---|---|---|---|
2 | 6c997921 | Sofia Papagiannaki | #
|
3 | 6c997921 | Sofia Papagiannaki | # Redistribution and use in source and binary forms, with or
|
4 | 6c997921 | Sofia Papagiannaki | # without modification, are permitted provided that the following
|
5 | 6c997921 | Sofia Papagiannaki | # conditions are met:
|
6 | 6c997921 | Sofia Papagiannaki | #
|
7 | 6c997921 | Sofia Papagiannaki | # 1. Redistributions of source code must retain the above
|
8 | 6c997921 | Sofia Papagiannaki | # copyright notice, this list of conditions and the following
|
9 | 6c997921 | Sofia Papagiannaki | # disclaimer.
|
10 | 6c997921 | Sofia Papagiannaki | #
|
11 | 6c997921 | Sofia Papagiannaki | # 2. Redistributions in binary form must reproduce the above
|
12 | 6c997921 | Sofia Papagiannaki | # copyright notice, this list of conditions and the following
|
13 | 6c997921 | Sofia Papagiannaki | # disclaimer in the documentation and/or other materials
|
14 | 6c997921 | Sofia Papagiannaki | # provided with the distribution.
|
15 | 6c997921 | Sofia Papagiannaki | #
|
16 | 6c997921 | Sofia Papagiannaki | # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
|
17 | 6c997921 | Sofia Papagiannaki | # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18 | 6c997921 | Sofia Papagiannaki | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
19 | 6c997921 | Sofia Papagiannaki | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
|
20 | 6c997921 | Sofia Papagiannaki | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
21 | 6c997921 | Sofia Papagiannaki | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
22 | 6c997921 | Sofia Papagiannaki | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
23 | 6c997921 | Sofia Papagiannaki | # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
24 | 6c997921 | Sofia Papagiannaki | # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 | 6c997921 | Sofia Papagiannaki | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
26 | 6c997921 | Sofia Papagiannaki | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27 | 6c997921 | Sofia Papagiannaki | # POSSIBILITY OF SUCH DAMAGE.
|
28 | 6c997921 | Sofia Papagiannaki | #
|
29 | 6c997921 | Sofia Papagiannaki | # The views and conclusions contained in the software and
|
30 | 6c997921 | Sofia Papagiannaki | # documentation are those of the authors and should not be
|
31 | 6c997921 | Sofia Papagiannaki | # interpreted as representing official policies, either expressed
|
32 | 6c997921 | Sofia Papagiannaki | # or implied, of GRNET S.A.
|
33 | 6c997921 | Sofia Papagiannaki | |
34 | 6c997921 | Sofia Papagiannaki | import os |
35 | 8d1636b5 | Giorgos Korfiatis | import uuid |
36 | 8d1636b5 | Giorgos Korfiatis | import string |
37 | 6c997921 | Sofia Papagiannaki | |
38 | 6c997921 | Sofia Papagiannaki | from optparse import make_option |
39 | 6c997921 | Sofia Papagiannaki | from collections import namedtuple |
40 | 6c997921 | Sofia Papagiannaki | |
41 | 6c997921 | Sofia Papagiannaki | from django.core.management.base import BaseCommand, CommandError |
42 | 8d1636b5 | Giorgos Korfiatis | from django.core.validators import validate_email |
43 | 6c997921 | Sofia Papagiannaki | |
44 | a6459f32 | Giorgos Korfiatis | from snf_django.lib.db.transaction import commit_on_success_strict |
45 | 8d1636b5 | Giorgos Korfiatis | from astakos.im.models import AstakosUser, AstakosUserQuota, Resource |
46 | 44104cd3 | Giorgos Korfiatis | from astakos.im.quotas import qh_sync_user |
47 | 6c997921 | Sofia Papagiannaki | |
48 | 6c997921 | Sofia Papagiannaki | AddResourceArgs = namedtuple('AddQuotaArgs', ('resource', |
49 | 6c997921 | Sofia Papagiannaki | 'capacity',
|
50 | 14a58548 | Giorgos Korfiatis | )) |
51 | 6c997921 | Sofia Papagiannaki | |
52 | 6c997921 | Sofia Papagiannaki | class Command(BaseCommand): |
53 | 8d1636b5 | Giorgos Korfiatis | help = """Import user quota limits from file or set quota
|
54 | 8d1636b5 | Giorgos Korfiatis | for a single user from the command line
|
55 | 4dcfe1c4 | Georgios D. Tsoukalas |
|
56 | 4dcfe1c4 | Georgios D. Tsoukalas | The file must contain non-empty lines, and each line must
|
57 | 4dcfe1c4 | Georgios D. Tsoukalas | contain a single-space-separated list of values:
|
58 | 4dcfe1c4 | Georgios D. Tsoukalas |
|
59 | e496f888 | Giorgos Korfiatis | <user> <resource name> <capacity>
|
60 | 4dcfe1c4 | Georgios D. Tsoukalas |
|
61 | 4dcfe1c4 | Georgios D. Tsoukalas | For example to grant the following user with 10 private networks
|
62 | 4dcfe1c4 | Georgios D. Tsoukalas | (independent of any he receives from projects):
|
63 | 4dcfe1c4 | Georgios D. Tsoukalas |
|
64 | e496f888 | Giorgos Korfiatis | 6119a50b-cbc7-42c0-bafc-4b6570e3f6ac cyclades.network.private 10
|
65 | 6c997921 | Sofia Papagiannaki |
|
66 | e496f888 | Giorgos Korfiatis | Similar syntax is used when setting quota from the command line:
|
67 | 8d1636b5 | Giorgos Korfiatis |
|
68 | 8d1636b5 | Giorgos Korfiatis | --set-capacity 6119a50b-cbc7-42c0-bafc-4b6570e3f6ac cyclades.vm 10
|
69 | 88f4d3b3 | Georgios D. Tsoukalas |
|
70 | 88f4d3b3 | Georgios D. Tsoukalas | The special value of 'default' sets the user setting to the default.
|
71 | 4dcfe1c4 | Georgios D. Tsoukalas | """
|
72 | 8d1636b5 | Giorgos Korfiatis | |
73 | 8d1636b5 | Giorgos Korfiatis | option_list = BaseCommand.option_list + ( |
74 | 8d1636b5 | Giorgos Korfiatis | make_option('--from-file',
|
75 | 8d1636b5 | Giorgos Korfiatis | dest='from_file',
|
76 | 8d1636b5 | Giorgos Korfiatis | metavar='<exported-quotas.txt>',
|
77 | 8d1636b5 | Giorgos Korfiatis | help="Import quotas from file"),
|
78 | 8d1636b5 | Giorgos Korfiatis | make_option('--set-capacity',
|
79 | 8d1636b5 | Giorgos Korfiatis | dest='set_capacity',
|
80 | 8d1636b5 | Giorgos Korfiatis | metavar='<uuid or email> <resource> <capacity>',
|
81 | 8d1636b5 | Giorgos Korfiatis | nargs=3,
|
82 | 8d1636b5 | Giorgos Korfiatis | help="Set capacity for a specified user/resource pair"),
|
83 | 88f4d3b3 | Georgios D. Tsoukalas | |
84 | ad977592 | Giorgos Korfiatis | make_option('-f', '--no-confirm', |
85 | 8d1636b5 | Giorgos Korfiatis | action='store_true',
|
86 | 8d1636b5 | Giorgos Korfiatis | default=False,
|
87 | 8d1636b5 | Giorgos Korfiatis | dest='force',
|
88 | 8d1636b5 | Giorgos Korfiatis | help="Do not ask for confirmation"),
|
89 | 8d1636b5 | Giorgos Korfiatis | ) |
90 | 8d1636b5 | Giorgos Korfiatis | |
91 | a6459f32 | Giorgos Korfiatis | @commit_on_success_strict()
|
92 | 6c997921 | Sofia Papagiannaki | def handle(self, *args, **options): |
93 | 8d1636b5 | Giorgos Korfiatis | from_file = options['from_file']
|
94 | 8d1636b5 | Giorgos Korfiatis | set_capacity = options['set_capacity']
|
95 | 8d1636b5 | Giorgos Korfiatis | force = options['force']
|
96 | 8d1636b5 | Giorgos Korfiatis | |
97 | 8d1636b5 | Giorgos Korfiatis | if from_file is not None: |
98 | 8d1636b5 | Giorgos Korfiatis | if set_capacity is not None: |
99 | 8d1636b5 | Giorgos Korfiatis | raise CommandError("Cannot combine option `--from-file' with " |
100 | 8d1636b5 | Giorgos Korfiatis | "`--set-capacity'.")
|
101 | 8d1636b5 | Giorgos Korfiatis | self.import_from_file(from_file)
|
102 | 00b501fc | Sofia Papagiannaki | return
|
103 | 8d1636b5 | Giorgos Korfiatis | |
104 | 8d1636b5 | Giorgos Korfiatis | if set_capacity is not None: |
105 | 8d1636b5 | Giorgos Korfiatis | user, resource, capacity = set_capacity |
106 | 8d1636b5 | Giorgos Korfiatis | self.set_limit(user, resource, capacity, force)
|
107 | 8d1636b5 | Giorgos Korfiatis | return
|
108 | 8d1636b5 | Giorgos Korfiatis | |
109 | 8d1636b5 | Giorgos Korfiatis | m = "Please use either `--from-file' or `--set-capacity' options"
|
110 | 8d1636b5 | Giorgos Korfiatis | raise CommandError(m)
|
111 | 8d1636b5 | Giorgos Korfiatis | |
112 | 8d1636b5 | Giorgos Korfiatis | def set_limit(self, user_ident, resource, capacity, force): |
113 | 8d1636b5 | Giorgos Korfiatis | if is_uuid(user_ident):
|
114 | 8d1636b5 | Giorgos Korfiatis | try:
|
115 | 8d1636b5 | Giorgos Korfiatis | user = AstakosUser.objects.get(uuid=user_ident) |
116 | 8d1636b5 | Giorgos Korfiatis | except AstakosUser.DoesNotExist:
|
117 | 8d1636b5 | Giorgos Korfiatis | raise CommandError('Not found user having uuid: %s' % |
118 | 8d1636b5 | Giorgos Korfiatis | user_ident) |
119 | 8d1636b5 | Giorgos Korfiatis | elif is_email(user_ident):
|
120 | 8d1636b5 | Giorgos Korfiatis | try:
|
121 | 8d1636b5 | Giorgos Korfiatis | user = AstakosUser.objects.get(username=user_ident) |
122 | 8d1636b5 | Giorgos Korfiatis | except AstakosUser.DoesNotExist:
|
123 | 8d1636b5 | Giorgos Korfiatis | raise CommandError('Not found user having email: %s' % |
124 | 8d1636b5 | Giorgos Korfiatis | user_ident) |
125 | 8d1636b5 | Giorgos Korfiatis | else:
|
126 | 8d1636b5 | Giorgos Korfiatis | raise CommandError('Please specify user by uuid or email') |
127 | 8d1636b5 | Giorgos Korfiatis | |
128 | 88f4d3b3 | Georgios D. Tsoukalas | if capacity != 'default': |
129 | 88f4d3b3 | Georgios D. Tsoukalas | try:
|
130 | 88f4d3b3 | Georgios D. Tsoukalas | capacity = int(capacity)
|
131 | 88f4d3b3 | Georgios D. Tsoukalas | except ValueError: |
132 | 88f4d3b3 | Georgios D. Tsoukalas | m = "Please specify capacity as a decimal integer or 'default'"
|
133 | 88f4d3b3 | Georgios D. Tsoukalas | raise CommandError(m)
|
134 | 88f4d3b3 | Georgios D. Tsoukalas | |
135 | 8d1636b5 | Giorgos Korfiatis | args = AddResourceArgs(resource=resource, |
136 | 8d1636b5 | Giorgos Korfiatis | capacity=capacity, |
137 | 8d1636b5 | Giorgos Korfiatis | ) |
138 | 8d1636b5 | Giorgos Korfiatis | |
139 | 8d1636b5 | Giorgos Korfiatis | try:
|
140 | 88f4d3b3 | Georgios D. Tsoukalas | quota, default_capacity = user.get_resource_policy(resource) |
141 | 8d1636b5 | Giorgos Korfiatis | except Resource.DoesNotExist:
|
142 | 8d1636b5 | Giorgos Korfiatis | raise CommandError("No such resource: %s" % resource) |
143 | 8d1636b5 | Giorgos Korfiatis | |
144 | 88f4d3b3 | Georgios D. Tsoukalas | current = quota.capacity if quota is not None else 'default' |
145 | 8d1636b5 | Giorgos Korfiatis | |
146 | 8d1636b5 | Giorgos Korfiatis | if not force: |
147 | 8d1636b5 | Giorgos Korfiatis | self.stdout.write("user: %s (%s)\n" % (user.uuid, user.username)) |
148 | 88f4d3b3 | Georgios D. Tsoukalas | self.stdout.write("default capacity: %s\n" % default_capacity) |
149 | 8d1636b5 | Giorgos Korfiatis | self.stdout.write("current capacity: %s\n" % current) |
150 | 8d1636b5 | Giorgos Korfiatis | self.stdout.write("new capacity: %s\n" % capacity) |
151 | 8d1636b5 | Giorgos Korfiatis | self.stdout.write("Confirm? (y/n) ") |
152 | 8d1636b5 | Giorgos Korfiatis | response = raw_input()
|
153 | 8d1636b5 | Giorgos Korfiatis | if string.lower(response) not in ['y', 'yes']: |
154 | 8d1636b5 | Giorgos Korfiatis | self.stdout.write("Aborted.\n") |
155 | 8d1636b5 | Giorgos Korfiatis | return
|
156 | 8d1636b5 | Giorgos Korfiatis | |
157 | 88f4d3b3 | Georgios D. Tsoukalas | if capacity == 'default': |
158 | 88f4d3b3 | Georgios D. Tsoukalas | try:
|
159 | 2ec5a35c | Giorgos Korfiatis | q = AstakosUserQuota.objects.get(user=user, |
160 | 2ec5a35c | Giorgos Korfiatis | resource__name=resource) |
161 | 88f4d3b3 | Georgios D. Tsoukalas | q.delete() |
162 | 88f4d3b3 | Georgios D. Tsoukalas | except Exception as e: |
163 | 88f4d3b3 | Georgios D. Tsoukalas | import traceback |
164 | 88f4d3b3 | Georgios D. Tsoukalas | traceback.print_exc() |
165 | 88f4d3b3 | Georgios D. Tsoukalas | raise CommandError("Failed to remove policy: %s" % e) |
166 | 88f4d3b3 | Georgios D. Tsoukalas | else:
|
167 | 88f4d3b3 | Georgios D. Tsoukalas | try:
|
168 | 88f4d3b3 | Georgios D. Tsoukalas | user.add_resource_policy(*args) |
169 | 88f4d3b3 | Georgios D. Tsoukalas | except Exception as e: |
170 | 88f4d3b3 | Georgios D. Tsoukalas | raise CommandError("Failed to add policy: %s" % e) |
171 | 44104cd3 | Giorgos Korfiatis | qh_sync_user(user.id) |
172 | 8d1636b5 | Giorgos Korfiatis | |
173 | 8d1636b5 | Giorgos Korfiatis | def import_from_file(self, location): |
174 | 6c997921 | Sofia Papagiannaki | try:
|
175 | 6c997921 | Sofia Papagiannaki | f = open(location, 'r') |
176 | 6c997921 | Sofia Papagiannaki | except IOError, e: |
177 | 6c997921 | Sofia Papagiannaki | raise CommandError(e)
|
178 | 6c997921 | Sofia Papagiannaki | |
179 | 6c997921 | Sofia Papagiannaki | for line in f.readlines(): |
180 | 6c997921 | Sofia Papagiannaki | try:
|
181 | 6c997921 | Sofia Papagiannaki | t = line.rstrip('\n').split(' ') |
182 | 6c997921 | Sofia Papagiannaki | user = t[0]
|
183 | 6c997921 | Sofia Papagiannaki | args = AddResourceArgs(*t[1:])
|
184 | 6c997921 | Sofia Papagiannaki | except(IndexError, TypeError): |
185 | 6c997921 | Sofia Papagiannaki | self.stdout.write('Invalid line format: %s:\n' % t) |
186 | 6c997921 | Sofia Papagiannaki | continue
|
187 | 6c997921 | Sofia Papagiannaki | else:
|
188 | 6c997921 | Sofia Papagiannaki | try:
|
189 | 6c997921 | Sofia Papagiannaki | user = AstakosUser.objects.get(uuid=user) |
190 | 6c997921 | Sofia Papagiannaki | except AstakosUser.DoesNotExist:
|
191 | db0d5f6b | Sofia Papagiannaki | self.stdout.write('Not found user having uuid: %s\n' % user) |
192 | 6c997921 | Sofia Papagiannaki | continue
|
193 | 6c997921 | Sofia Papagiannaki | else:
|
194 | 6c997921 | Sofia Papagiannaki | try:
|
195 | 6c997921 | Sofia Papagiannaki | user.add_resource_policy(*args) |
196 | 6c997921 | Sofia Papagiannaki | except Exception, e: |
197 | 6c997921 | Sofia Papagiannaki | self.stdout.write('Failed to policy: %s\n' % e) |
198 | 6c997921 | Sofia Papagiannaki | continue
|
199 | 6c997921 | Sofia Papagiannaki | finally:
|
200 | 6c997921 | Sofia Papagiannaki | f.close() |
201 | 8d1636b5 | Giorgos Korfiatis | |
202 | 8d1636b5 | Giorgos Korfiatis | |
203 | 8d1636b5 | Giorgos Korfiatis | def is_uuid(s): |
204 | 8d1636b5 | Giorgos Korfiatis | if s is None: |
205 | 8d1636b5 | Giorgos Korfiatis | return False |
206 | 8d1636b5 | Giorgos Korfiatis | try:
|
207 | 8d1636b5 | Giorgos Korfiatis | uuid.UUID(s) |
208 | 8d1636b5 | Giorgos Korfiatis | except ValueError: |
209 | 8d1636b5 | Giorgos Korfiatis | return False |
210 | 8d1636b5 | Giorgos Korfiatis | else:
|
211 | 8d1636b5 | Giorgos Korfiatis | return True |
212 | 8d1636b5 | Giorgos Korfiatis | |
213 | 8d1636b5 | Giorgos Korfiatis | |
214 | 8d1636b5 | Giorgos Korfiatis | def is_email(s): |
215 | 8d1636b5 | Giorgos Korfiatis | if s is None: |
216 | 8d1636b5 | Giorgos Korfiatis | return False |
217 | 8d1636b5 | Giorgos Korfiatis | try:
|
218 | 8d1636b5 | Giorgos Korfiatis | validate_email(s) |
219 | 8d1636b5 | Giorgos Korfiatis | except:
|
220 | 8d1636b5 | Giorgos Korfiatis | return False |
221 | 8d1636b5 | Giorgos Korfiatis | else:
|
222 | 8d1636b5 | Giorgos Korfiatis | return True |