root / snf-astakos-app / astakos / im / quotas.py @ ec5e00aa
History | View | Annotate | Download (8.4 kB)
1 | dc9da5b9 | Giorgos Korfiatis | # Copyright 2013 GRNET S.A. All rights reserved.
|
---|---|---|---|
2 | dc9da5b9 | Giorgos Korfiatis | #
|
3 | dc9da5b9 | Giorgos Korfiatis | # Redistribution and use in source and binary forms, with or
|
4 | dc9da5b9 | Giorgos Korfiatis | # without modification, are permitted provided that the following
|
5 | dc9da5b9 | Giorgos Korfiatis | # conditions are met:
|
6 | dc9da5b9 | Giorgos Korfiatis | #
|
7 | dc9da5b9 | Giorgos Korfiatis | # 1. Redistributions of source code must retain the above
|
8 | dc9da5b9 | Giorgos Korfiatis | # copyright notice, this list of conditions and the following
|
9 | dc9da5b9 | Giorgos Korfiatis | # disclaimer.
|
10 | dc9da5b9 | Giorgos Korfiatis | #
|
11 | dc9da5b9 | Giorgos Korfiatis | # 2. Redistributions in binary form must reproduce the above
|
12 | dc9da5b9 | Giorgos Korfiatis | # copyright notice, this list of conditions and the following
|
13 | dc9da5b9 | Giorgos Korfiatis | # disclaimer in the documentation and/or other materials
|
14 | dc9da5b9 | Giorgos Korfiatis | # provided with the distribution.
|
15 | dc9da5b9 | Giorgos Korfiatis | #
|
16 | dc9da5b9 | Giorgos Korfiatis | # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
|
17 | dc9da5b9 | Giorgos Korfiatis | # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18 | dc9da5b9 | Giorgos Korfiatis | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
19 | dc9da5b9 | Giorgos Korfiatis | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
|
20 | dc9da5b9 | Giorgos Korfiatis | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
21 | dc9da5b9 | Giorgos Korfiatis | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
22 | dc9da5b9 | Giorgos Korfiatis | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
23 | dc9da5b9 | Giorgos Korfiatis | # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
24 | dc9da5b9 | Giorgos Korfiatis | # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 | dc9da5b9 | Giorgos Korfiatis | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
26 | dc9da5b9 | Giorgos Korfiatis | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27 | dc9da5b9 | Giorgos Korfiatis | # POSSIBILITY OF SUCH DAMAGE.
|
28 | dc9da5b9 | Giorgos Korfiatis | #
|
29 | dc9da5b9 | Giorgos Korfiatis | # The views and conclusions contained in the software and
|
30 | dc9da5b9 | Giorgos Korfiatis | # documentation are those of the authors and should not be
|
31 | dc9da5b9 | Giorgos Korfiatis | # interpreted as representing official policies, either expressed
|
32 | dc9da5b9 | Giorgos Korfiatis | # or implied, of GRNET S.A.
|
33 | dc9da5b9 | Giorgos Korfiatis | |
34 | aa27f246 | Giorgos Korfiatis | from astakos.im.models import ( |
35 | aa27f246 | Giorgos Korfiatis | Resource, AstakosUserQuota, AstakosUser, |
36 | aa27f246 | Giorgos Korfiatis | Project, ProjectMembership, ProjectResourceGrant, ProjectApplication) |
37 | ec5e00aa | Giorgos Korfiatis | import astakos.quotaholder_app.callpoint as qh |
38 | ae16bcad | Giorgos Korfiatis | from django.db.models import Q |
39 | dc9da5b9 | Giorgos Korfiatis | |
40 | dc9da5b9 | Giorgos Korfiatis | |
41 | dc9da5b9 | Giorgos Korfiatis | def from_holding(holding): |
42 | 68b991bc | Giorgos Korfiatis | limit, usage_min, usage_max = holding |
43 | dc9da5b9 | Giorgos Korfiatis | body = {'limit': limit,
|
44 | 68b991bc | Giorgos Korfiatis | 'usage': usage_max,
|
45 | 68b991bc | Giorgos Korfiatis | 'pending': usage_max-usage_min,
|
46 | dc9da5b9 | Giorgos Korfiatis | } |
47 | dc9da5b9 | Giorgos Korfiatis | return body
|
48 | dc9da5b9 | Giorgos Korfiatis | |
49 | dc9da5b9 | Giorgos Korfiatis | |
50 | dc9da5b9 | Giorgos Korfiatis | def limits_only(holding): |
51 | 68b991bc | Giorgos Korfiatis | limit, usage_min, usage_max = holding |
52 | dc9da5b9 | Giorgos Korfiatis | return limit
|
53 | dc9da5b9 | Giorgos Korfiatis | |
54 | dc9da5b9 | Giorgos Korfiatis | |
55 | dc9da5b9 | Giorgos Korfiatis | def transform_data(holdings, func=None): |
56 | dc9da5b9 | Giorgos Korfiatis | if func is None: |
57 | dc9da5b9 | Giorgos Korfiatis | func = from_holding |
58 | dc9da5b9 | Giorgos Korfiatis | |
59 | dc9da5b9 | Giorgos Korfiatis | quota = {} |
60 | dc9da5b9 | Giorgos Korfiatis | for (holder, source, resource), value in holdings.iteritems(): |
61 | dc9da5b9 | Giorgos Korfiatis | holder_quota = quota.get(holder, {}) |
62 | dc9da5b9 | Giorgos Korfiatis | source_quota = holder_quota.get(source, {}) |
63 | dc9da5b9 | Giorgos Korfiatis | body = func(value) |
64 | dc9da5b9 | Giorgos Korfiatis | source_quota[resource] = body |
65 | dc9da5b9 | Giorgos Korfiatis | holder_quota[source] = source_quota |
66 | dc9da5b9 | Giorgos Korfiatis | quota[holder] = holder_quota |
67 | dc9da5b9 | Giorgos Korfiatis | return quota
|
68 | dc9da5b9 | Giorgos Korfiatis | |
69 | dc9da5b9 | Giorgos Korfiatis | |
70 | 5afce44d | Giorgos Korfiatis | def get_counters(users, resources=None, sources=None): |
71 | dc9da5b9 | Giorgos Korfiatis | uuids = [user.uuid for user in users] |
72 | dc9da5b9 | Giorgos Korfiatis | |
73 | 5afce44d | Giorgos Korfiatis | counters = qh.get_quota(holders=uuids, |
74 | 5afce44d | Giorgos Korfiatis | resources=resources, |
75 | 5afce44d | Giorgos Korfiatis | sources=sources) |
76 | dc9da5b9 | Giorgos Korfiatis | return counters
|
77 | dc9da5b9 | Giorgos Korfiatis | |
78 | dc9da5b9 | Giorgos Korfiatis | |
79 | dc9da5b9 | Giorgos Korfiatis | def get_users_quotas(users, resources=None, sources=None): |
80 | dc9da5b9 | Giorgos Korfiatis | counters = get_counters(users, resources, sources) |
81 | dc9da5b9 | Giorgos Korfiatis | quotas = transform_data(counters) |
82 | dc9da5b9 | Giorgos Korfiatis | return quotas
|
83 | dc9da5b9 | Giorgos Korfiatis | |
84 | dc9da5b9 | Giorgos Korfiatis | |
85 | dc9da5b9 | Giorgos Korfiatis | def get_users_quotas_and_limits(users, resources=None, sources=None): |
86 | dc9da5b9 | Giorgos Korfiatis | counters = get_counters(users, resources, sources) |
87 | dc9da5b9 | Giorgos Korfiatis | quotas = transform_data(counters) |
88 | dc9da5b9 | Giorgos Korfiatis | limits = transform_data(counters, limits_only) |
89 | dc9da5b9 | Giorgos Korfiatis | return quotas, limits
|
90 | dc9da5b9 | Giorgos Korfiatis | |
91 | dc9da5b9 | Giorgos Korfiatis | |
92 | dc9da5b9 | Giorgos Korfiatis | def get_user_quotas(user, resources=None, sources=None): |
93 | dc9da5b9 | Giorgos Korfiatis | quotas = get_users_quotas([user], resources, sources) |
94 | dc9da5b9 | Giorgos Korfiatis | return quotas[user.uuid]
|
95 | dc9da5b9 | Giorgos Korfiatis | |
96 | dc9da5b9 | Giorgos Korfiatis | |
97 | 271d2c4c | Giorgos Korfiatis | def service_get_quotas(service, users=None): |
98 | a0b34382 | Giorgos Korfiatis | resources = Resource.objects.filter(service=service) |
99 | bb005bc2 | Giorgos Korfiatis | resource_names = [r.name for r in resources] |
100 | 5afce44d | Giorgos Korfiatis | counters = qh.get_quota(holders=users, resources=resource_names) |
101 | bb005bc2 | Giorgos Korfiatis | return transform_data(counters)
|
102 | bb005bc2 | Giorgos Korfiatis | |
103 | bb005bc2 | Giorgos Korfiatis | |
104 | 9b126f13 | Giorgos Korfiatis | def _level_quota_dict(quotas): |
105 | 9b126f13 | Giorgos Korfiatis | lst = [] |
106 | 9b126f13 | Giorgos Korfiatis | for holder, holder_quota in quotas.iteritems(): |
107 | 9b126f13 | Giorgos Korfiatis | for source, source_quota in holder_quota.iteritems(): |
108 | 9b126f13 | Giorgos Korfiatis | for resource, limit in source_quota.iteritems(): |
109 | 9b126f13 | Giorgos Korfiatis | key = (holder, source, resource) |
110 | 9b126f13 | Giorgos Korfiatis | lst.append((key, limit)) |
111 | 9b126f13 | Giorgos Korfiatis | return lst
|
112 | 9b126f13 | Giorgos Korfiatis | |
113 | 9b126f13 | Giorgos Korfiatis | |
114 | dc9da5b9 | Giorgos Korfiatis | def set_user_quota(quotas): |
115 | 9b126f13 | Giorgos Korfiatis | q = _level_quota_dict(quotas) |
116 | 9b126f13 | Giorgos Korfiatis | qh.set_quota(q) |
117 | aa27f246 | Giorgos Korfiatis | |
118 | aa27f246 | Giorgos Korfiatis | |
119 | aa27f246 | Giorgos Korfiatis | def get_default_quota(): |
120 | aa27f246 | Giorgos Korfiatis | _DEFAULT_QUOTA = {} |
121 | aa27f246 | Giorgos Korfiatis | resources = Resource.objects.select_related('service').all()
|
122 | aa27f246 | Giorgos Korfiatis | for resource in resources: |
123 | aa27f246 | Giorgos Korfiatis | capacity = resource.uplimit |
124 | aa27f246 | Giorgos Korfiatis | _DEFAULT_QUOTA[resource.full_name()] = capacity |
125 | aa27f246 | Giorgos Korfiatis | |
126 | aa27f246 | Giorgos Korfiatis | return _DEFAULT_QUOTA
|
127 | aa27f246 | Giorgos Korfiatis | |
128 | aa27f246 | Giorgos Korfiatis | |
129 | aa27f246 | Giorgos Korfiatis | SYSTEM = 'system'
|
130 | aa27f246 | Giorgos Korfiatis | |
131 | aa27f246 | Giorgos Korfiatis | |
132 | 9770ba6c | Giorgos Korfiatis | def resolve_pending_serial(serial, accept=True): |
133 | 9770ba6c | Giorgos Korfiatis | return qh.resolve_pending_commission('astakos', serial, accept) |
134 | 9770ba6c | Giorgos Korfiatis | |
135 | 9770ba6c | Giorgos Korfiatis | |
136 | f6e7a826 | Giorgos Korfiatis | def register_pending_apps(user, quantity, force=False, name=""): |
137 | 9770ba6c | Giorgos Korfiatis | provision = (user.uuid, SYSTEM, 'astakos.pending_app'), quantity
|
138 | 9770ba6c | Giorgos Korfiatis | |
139 | 9770ba6c | Giorgos Korfiatis | s = qh.issue_commission(clientkey='astakos',
|
140 | 9770ba6c | Giorgos Korfiatis | force=force, |
141 | 9770ba6c | Giorgos Korfiatis | name=name, |
142 | 9770ba6c | Giorgos Korfiatis | provisions=[provision]) |
143 | 9770ba6c | Giorgos Korfiatis | return s
|
144 | 9770ba6c | Giorgos Korfiatis | |
145 | 9770ba6c | Giorgos Korfiatis | |
146 | aa27f246 | Giorgos Korfiatis | def initial_quotas(users): |
147 | aa27f246 | Giorgos Korfiatis | initial = {} |
148 | aa27f246 | Giorgos Korfiatis | default_quotas = get_default_quota() |
149 | aa27f246 | Giorgos Korfiatis | |
150 | aa27f246 | Giorgos Korfiatis | for user in users: |
151 | aa27f246 | Giorgos Korfiatis | uuid = user.uuid |
152 | aa27f246 | Giorgos Korfiatis | source_quota = {SYSTEM: dict(default_quotas)}
|
153 | aa27f246 | Giorgos Korfiatis | initial[uuid] = source_quota |
154 | aa27f246 | Giorgos Korfiatis | |
155 | aa27f246 | Giorgos Korfiatis | objs = AstakosUserQuota.objects.select_related() |
156 | aa27f246 | Giorgos Korfiatis | orig_quotas = objs.filter(user__in=users) |
157 | aa27f246 | Giorgos Korfiatis | for user_quota in orig_quotas: |
158 | aa27f246 | Giorgos Korfiatis | uuid = user_quota.user.uuid |
159 | aa27f246 | Giorgos Korfiatis | user_init = initial.get(uuid, {}) |
160 | 003909e3 | Giorgos Korfiatis | source_quota = user_init.get(SYSTEM, {}) |
161 | aa27f246 | Giorgos Korfiatis | resource = user_quota.resource.full_name() |
162 | 003909e3 | Giorgos Korfiatis | source_quota[resource] = user_quota.capacity |
163 | 003909e3 | Giorgos Korfiatis | user_init[SYSTEM] = source_quota |
164 | aa27f246 | Giorgos Korfiatis | initial[uuid] = user_init |
165 | aa27f246 | Giorgos Korfiatis | |
166 | aa27f246 | Giorgos Korfiatis | return initial
|
167 | aa27f246 | Giorgos Korfiatis | |
168 | aa27f246 | Giorgos Korfiatis | |
169 | aa27f246 | Giorgos Korfiatis | def get_grant_source(grant): |
170 | aa27f246 | Giorgos Korfiatis | return SYSTEM
|
171 | aa27f246 | Giorgos Korfiatis | |
172 | aa27f246 | Giorgos Korfiatis | |
173 | cb14cc6c | Giorgos Korfiatis | def astakos_users_quotas(users, initial=None): |
174 | aa27f246 | Giorgos Korfiatis | if initial is None: |
175 | aa27f246 | Giorgos Korfiatis | quotas = initial_quotas(users) |
176 | aa27f246 | Giorgos Korfiatis | else:
|
177 | aa27f246 | Giorgos Korfiatis | quotas = copy.deepcopy(initial) |
178 | aa27f246 | Giorgos Korfiatis | |
179 | aa27f246 | Giorgos Korfiatis | ACTUALLY_ACCEPTED = ProjectMembership.ACTUALLY_ACCEPTED |
180 | aa27f246 | Giorgos Korfiatis | objs = ProjectMembership.objects.select_related('project', 'person') |
181 | aa27f246 | Giorgos Korfiatis | memberships = objs.filter(person__in=users, |
182 | aa27f246 | Giorgos Korfiatis | state__in=ACTUALLY_ACCEPTED, |
183 | aa27f246 | Giorgos Korfiatis | project__state=Project.APPROVED) |
184 | aa27f246 | Giorgos Korfiatis | |
185 | aa27f246 | Giorgos Korfiatis | project_ids = set(m.project_id for m in memberships) |
186 | aa27f246 | Giorgos Korfiatis | objs = ProjectApplication.objects.select_related('project')
|
187 | aa27f246 | Giorgos Korfiatis | apps = objs.filter(project__in=project_ids) |
188 | aa27f246 | Giorgos Korfiatis | |
189 | aa27f246 | Giorgos Korfiatis | project_dict = {} |
190 | aa27f246 | Giorgos Korfiatis | for app in apps: |
191 | aa27f246 | Giorgos Korfiatis | project_dict[app.project] = app |
192 | aa27f246 | Giorgos Korfiatis | |
193 | aa27f246 | Giorgos Korfiatis | objs = ProjectResourceGrant.objects.select_related() |
194 | aa27f246 | Giorgos Korfiatis | grants = objs.filter(project_application__in=apps) |
195 | aa27f246 | Giorgos Korfiatis | |
196 | aa27f246 | Giorgos Korfiatis | for membership in memberships: |
197 | aa27f246 | Giorgos Korfiatis | uuid = membership.person.uuid |
198 | aa27f246 | Giorgos Korfiatis | userquotas = quotas.get(uuid, {}) |
199 | aa27f246 | Giorgos Korfiatis | |
200 | aa27f246 | Giorgos Korfiatis | application = project_dict[membership.project] |
201 | aa27f246 | Giorgos Korfiatis | |
202 | aa27f246 | Giorgos Korfiatis | for grant in grants: |
203 | aa27f246 | Giorgos Korfiatis | if grant.project_application_id != application.id:
|
204 | aa27f246 | Giorgos Korfiatis | continue
|
205 | aa27f246 | Giorgos Korfiatis | |
206 | aa27f246 | Giorgos Korfiatis | source = get_grant_source(grant) |
207 | aa27f246 | Giorgos Korfiatis | source_quotas = userquotas.get(source, {}) |
208 | aa27f246 | Giorgos Korfiatis | |
209 | aa27f246 | Giorgos Korfiatis | resource = grant.resource.full_name() |
210 | aa27f246 | Giorgos Korfiatis | prev = source_quotas.get(resource, 0)
|
211 | aa27f246 | Giorgos Korfiatis | new = prev + grant.member_capacity |
212 | aa27f246 | Giorgos Korfiatis | source_quotas[resource] = new |
213 | aa27f246 | Giorgos Korfiatis | userquotas[source] = source_quotas |
214 | aa27f246 | Giorgos Korfiatis | quotas[uuid] = userquotas |
215 | aa27f246 | Giorgos Korfiatis | |
216 | aa27f246 | Giorgos Korfiatis | return quotas
|
217 | aa27f246 | Giorgos Korfiatis | |
218 | aa27f246 | Giorgos Korfiatis | |
219 | cb14cc6c | Giorgos Korfiatis | def astakos_user_quotas(user): |
220 | cb14cc6c | Giorgos Korfiatis | quotas = astakos_users_quotas([user]) |
221 | aa27f246 | Giorgos Korfiatis | try:
|
222 | aa27f246 | Giorgos Korfiatis | return quotas[user.uuid]
|
223 | aa27f246 | Giorgos Korfiatis | except KeyError: |
224 | aa27f246 | Giorgos Korfiatis | raise ValueError("could not compute quotas") |
225 | aa27f246 | Giorgos Korfiatis | |
226 | aa27f246 | Giorgos Korfiatis | |
227 | 3adbd562 | Giorgos Korfiatis | def list_user_quotas(users): |
228 | 3adbd562 | Giorgos Korfiatis | qh_quotas, qh_limits = get_users_quotas_and_limits(users) |
229 | 3adbd562 | Giorgos Korfiatis | astakos_initial = initial_quotas(users) |
230 | cb14cc6c | Giorgos Korfiatis | astakos_quotas = astakos_users_quotas(users) |
231 | 3adbd562 | Giorgos Korfiatis | |
232 | 3adbd562 | Giorgos Korfiatis | diff_quotas = {} |
233 | 3adbd562 | Giorgos Korfiatis | for holder, local in astakos_quotas.iteritems(): |
234 | 3adbd562 | Giorgos Korfiatis | registered = qh_limits.get(holder, None)
|
235 | 3adbd562 | Giorgos Korfiatis | if local != registered:
|
236 | 3adbd562 | Giorgos Korfiatis | diff_quotas[holder] = dict(local)
|
237 | 3adbd562 | Giorgos Korfiatis | |
238 | 3adbd562 | Giorgos Korfiatis | return (qh_limits, qh_quotas,
|
239 | 3adbd562 | Giorgos Korfiatis | astakos_initial, diff_quotas) |
240 | 9747707e | Giorgos Korfiatis | |
241 | 9747707e | Giorgos Korfiatis | |
242 | 9747707e | Giorgos Korfiatis | def qh_add_resource_limit(resource, diff): |
243 | ae16bcad | Giorgos Korfiatis | objs = AstakosUser.forupdate.filter(Q(email_verified=True) &
|
244 | ae16bcad | Giorgos Korfiatis | ~Q(policy=resource)) |
245 | ae16bcad | Giorgos Korfiatis | users = objs.select_for_update() |
246 | ae16bcad | Giorgos Korfiatis | uuids = [u.uuid for u in users] |
247 | ae16bcad | Giorgos Korfiatis | qh.add_resource_limit(holders=uuids, sources=[SYSTEM], |
248 | ae16bcad | Giorgos Korfiatis | resources=[resource.name], diff=diff) |
249 | 9747707e | Giorgos Korfiatis | |
250 | 9747707e | Giorgos Korfiatis | |
251 | 9747707e | Giorgos Korfiatis | def qh_sync_new_resource(resource, limit): |
252 | 9747707e | Giorgos Korfiatis | users = AstakosUser.forupdate.filter( |
253 | 9747707e | Giorgos Korfiatis | email_verified=True).select_for_update()
|
254 | 9747707e | Giorgos Korfiatis | |
255 | ae16bcad | Giorgos Korfiatis | resource_name = resource.name |
256 | 9747707e | Giorgos Korfiatis | data = [] |
257 | 9747707e | Giorgos Korfiatis | for user in users: |
258 | 9747707e | Giorgos Korfiatis | uuid = user.uuid |
259 | ae16bcad | Giorgos Korfiatis | key = uuid, SYSTEM, resource_name |
260 | 9747707e | Giorgos Korfiatis | data.append((key, limit)) |
261 | 9747707e | Giorgos Korfiatis | |
262 | 9747707e | Giorgos Korfiatis | qh.set_quota(data) |
263 | 44104cd3 | Giorgos Korfiatis | |
264 | 44104cd3 | Giorgos Korfiatis | |
265 | 44104cd3 | Giorgos Korfiatis | def qh_sync_users(user_ids): |
266 | 44104cd3 | Giorgos Korfiatis | users = AstakosUser.forupdate.filter(id__in=user_ids).select_for_update() |
267 | cb14cc6c | Giorgos Korfiatis | astakos_quotas = astakos_users_quotas(list(users))
|
268 | 44104cd3 | Giorgos Korfiatis | set_user_quota(astakos_quotas) |
269 | 44104cd3 | Giorgos Korfiatis | |
270 | 44104cd3 | Giorgos Korfiatis | |
271 | 44104cd3 | Giorgos Korfiatis | def qh_sync_user(user_id): |
272 | 44104cd3 | Giorgos Korfiatis | qh_sync_users([user_id]) |