root / snf-astakos-app / astakos / im / management / commands / project-modify.py @ 5dc97d69
History | View | Annotate | Download (6.7 kB)
1 |
# Copyright 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 |
|
36 |
from django.db.models import Q |
37 |
from django.core.management.base import BaseCommand, CommandError |
38 |
from django.db import transaction |
39 |
from synnefo.util import units |
40 |
from astakos.im import functions |
41 |
from astakos.im import models |
42 |
import astakos.api.projects as api |
43 |
import synnefo.util.date as date_util |
44 |
from snf_django.management import utils |
45 |
from astakos.im.management.commands import _common |
46 |
|
47 |
|
48 |
def make_policies(limits): |
49 |
policies = {} |
50 |
for (name, member_capacity, project_capacity) in limits: |
51 |
try:
|
52 |
member_capacity = units.parse(member_capacity) |
53 |
project_capacity = units.parse(project_capacity) |
54 |
except units.ParseError:
|
55 |
m = "Please specify capacity as a decimal integer"
|
56 |
raise CommandError(m)
|
57 |
policies[name] = {"member_capacity": member_capacity,
|
58 |
"project_capacity": project_capacity}
|
59 |
return policies
|
60 |
|
61 |
Simple = type('Simple', (), {}) |
62 |
|
63 |
|
64 |
class Param(object): |
65 |
def __init__(self, key=Simple, mod=Simple, action=Simple, nargs=Simple, |
66 |
is_main=False, help=""): |
67 |
self.key = key
|
68 |
self.mod = mod
|
69 |
self.action = action
|
70 |
self.nargs = nargs
|
71 |
self.is_main = is_main
|
72 |
self.help = help
|
73 |
|
74 |
|
75 |
PARAMS = { |
76 |
"name": Param(key="realname", help="Set project name"), |
77 |
"owner": Param(mod=_common.get_accepted_user, help="Set project owner"), |
78 |
"homepage": Param(help="Set project homepage"), |
79 |
"description": Param(help="Set project description"), |
80 |
"end_date": Param(mod=date_util.isoparse, is_main=True, |
81 |
help=("Set project end date in ISO format "
|
82 |
"(e.g. 2014-01-01T00:00Z)")),
|
83 |
"join_policy": Param(key="member_join_policy", is_main=True, |
84 |
mod=(lambda x: api.MEMBERSHIP_POLICY[x]),
|
85 |
help="Set join policy (auto, moderated, or closed)"),
|
86 |
"leave_policy": Param(key="member_leave_policy", is_main=True, |
87 |
mod=(lambda x: api.MEMBERSHIP_POLICY[x]),
|
88 |
help=("Set leave policy "
|
89 |
"(auto, moderated, or closed)")),
|
90 |
"max_members": Param(key="limit_on_members_number", mod=int, is_main=True, |
91 |
help="Set maximum members limit"),
|
92 |
"private": Param(mod=utils.parse_bool, is_main=True, |
93 |
help="Set project private"),
|
94 |
"limit": Param(key="resources", mod=make_policies, is_main=True, |
95 |
nargs=3, action="append", |
96 |
help=("Set resource limits: "
|
97 |
"resource_name member_capacity project_capacity")),
|
98 |
} |
99 |
|
100 |
|
101 |
def make_options(): |
102 |
options = [] |
103 |
for key, param in PARAMS.iteritems(): |
104 |
opt = "--" + key.replace('_', '-') |
105 |
kwargs = {} |
106 |
if param.action is not Simple: |
107 |
kwargs["action"] = param.action
|
108 |
if param.nargs is not Simple: |
109 |
kwargs["nargs"] = param.nargs
|
110 |
kwargs["help"] = param.help
|
111 |
options.append(make_option(opt, **kwargs)) |
112 |
return tuple(options) |
113 |
|
114 |
|
115 |
class Command(BaseCommand): |
116 |
args = "<project id> (or --all-base-projects)"
|
117 |
help = "Modify an already initialized project"
|
118 |
option_list = BaseCommand.option_list + make_options() + ( |
119 |
make_option('--all-base-projects',
|
120 |
action='store_true',
|
121 |
default=False,
|
122 |
help="Modify in bulk all initialized base projects"),
|
123 |
make_option('--exclude',
|
124 |
help=("If `--all-base-projects' is given, exclude projects"
|
125 |
" given as a list of uuids: uuid1,uuid2,uuid3")),
|
126 |
) |
127 |
|
128 |
def check_args(self, args, all_base, exclude): |
129 |
if all_base and args or not all_base and len(args) != 1: |
130 |
m = "Please provide a project ID or --all-base-projects"
|
131 |
raise CommandError(m)
|
132 |
if not all_base and exclude: |
133 |
m = ("Option --exclude is meaningful only combined with "
|
134 |
" --all-base-projects.")
|
135 |
raise CommandError(m)
|
136 |
|
137 |
def mk_all_base_filter(self, all_base, exclude): |
138 |
flt = Q(state__in=models.Project.INITIALIZED_STATES, is_base=True)
|
139 |
if exclude:
|
140 |
exclude = exclude.split(',')
|
141 |
flt &= ~Q(uuid__in=exclude) |
142 |
return flt
|
143 |
|
144 |
@transaction.commit_on_success
|
145 |
def handle(self, *args, **options): |
146 |
all_base = options["all_base_projects"]
|
147 |
exclude = options["exclude"]
|
148 |
self.check_args(args, all_base, exclude)
|
149 |
|
150 |
try:
|
151 |
changes = {} |
152 |
for key, value in options.iteritems(): |
153 |
param = PARAMS.get(key) |
154 |
if param is None or value is None: |
155 |
continue
|
156 |
if all_base and not param.is_main: |
157 |
m = "Cannot modify field '%s' in bulk" % key
|
158 |
raise CommandError(m)
|
159 |
k = key if param.key is Simple else param.key |
160 |
v = value if param.mod is Simple else param.mod(value) |
161 |
changes[k] = v |
162 |
|
163 |
if all_base:
|
164 |
flt = self.mk_all_base_filter(all_base, exclude)
|
165 |
functions.modify_projects_in_bulk(flt, changes) |
166 |
else:
|
167 |
functions.modify_project(args[0], changes)
|
168 |
except BaseException as e: |
169 |
raise CommandError(e)
|