Statistics
| Branch: | Tag: | Revision:

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