root / snf-astakos-app / astakos / im / quotas.py @ 08043775
History | View | Annotate | Download (7.7 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 | dc9da5b9 | Giorgos Korfiatis | from astakos.quotaholder.callpoint import QuotaholderDjangoDBCallpoint |
38 | ae16bcad | Giorgos Korfiatis | from django.db.models import Q |
39 | dc9da5b9 | Giorgos Korfiatis | |
40 | dc9da5b9 | Giorgos Korfiatis | qh = QuotaholderDjangoDBCallpoint() |
41 | dc9da5b9 | Giorgos Korfiatis | |
42 | dc9da5b9 | Giorgos Korfiatis | |
43 | dc9da5b9 | Giorgos Korfiatis | def from_holding(holding): |
44 | dc9da5b9 | Giorgos Korfiatis | limit, imported_min, imported_max = holding |
45 | dc9da5b9 | Giorgos Korfiatis | body = {'limit': limit,
|
46 | 480974e6 | Giorgos Korfiatis | 'usage': imported_max,
|
47 | 480974e6 | Giorgos Korfiatis | 'pending': imported_max-imported_min,
|
48 | dc9da5b9 | Giorgos Korfiatis | } |
49 | dc9da5b9 | Giorgos Korfiatis | return body
|
50 | dc9da5b9 | Giorgos Korfiatis | |
51 | dc9da5b9 | Giorgos Korfiatis | |
52 | dc9da5b9 | Giorgos Korfiatis | def limits_only(holding): |
53 | dc9da5b9 | Giorgos Korfiatis | limit, imported_min, imported_max = holding |
54 | dc9da5b9 | Giorgos Korfiatis | return limit
|
55 | dc9da5b9 | Giorgos Korfiatis | |
56 | dc9da5b9 | Giorgos Korfiatis | |
57 | dc9da5b9 | Giorgos Korfiatis | def transform_data(holdings, func=None): |
58 | dc9da5b9 | Giorgos Korfiatis | if func is None: |
59 | dc9da5b9 | Giorgos Korfiatis | func = from_holding |
60 | dc9da5b9 | Giorgos Korfiatis | |
61 | dc9da5b9 | Giorgos Korfiatis | quota = {} |
62 | dc9da5b9 | Giorgos Korfiatis | for (holder, source, resource), value in holdings.iteritems(): |
63 | dc9da5b9 | Giorgos Korfiatis | holder_quota = quota.get(holder, {}) |
64 | dc9da5b9 | Giorgos Korfiatis | source_quota = holder_quota.get(source, {}) |
65 | dc9da5b9 | Giorgos Korfiatis | body = func(value) |
66 | dc9da5b9 | Giorgos Korfiatis | source_quota[resource] = body |
67 | dc9da5b9 | Giorgos Korfiatis | holder_quota[source] = source_quota |
68 | dc9da5b9 | Giorgos Korfiatis | quota[holder] = holder_quota |
69 | dc9da5b9 | Giorgos Korfiatis | return quota
|
70 | dc9da5b9 | Giorgos Korfiatis | |
71 | dc9da5b9 | Giorgos Korfiatis | |
72 | 5afce44d | Giorgos Korfiatis | def get_counters(users, resources=None, sources=None): |
73 | dc9da5b9 | Giorgos Korfiatis | uuids = [user.uuid for user in users] |
74 | dc9da5b9 | Giorgos Korfiatis | |
75 | 5afce44d | Giorgos Korfiatis | counters = qh.get_quota(holders=uuids, |
76 | 5afce44d | Giorgos Korfiatis | resources=resources, |
77 | 5afce44d | Giorgos Korfiatis | sources=sources) |
78 | dc9da5b9 | Giorgos Korfiatis | return counters
|
79 | dc9da5b9 | Giorgos Korfiatis | |
80 | dc9da5b9 | Giorgos Korfiatis | |
81 | dc9da5b9 | Giorgos Korfiatis | def get_users_quotas(users, resources=None, sources=None): |
82 | dc9da5b9 | Giorgos Korfiatis | counters = get_counters(users, resources, sources) |
83 | dc9da5b9 | Giorgos Korfiatis | quotas = transform_data(counters) |
84 | dc9da5b9 | Giorgos Korfiatis | return quotas
|
85 | dc9da5b9 | Giorgos Korfiatis | |
86 | dc9da5b9 | Giorgos Korfiatis | |
87 | dc9da5b9 | Giorgos Korfiatis | def get_users_quotas_and_limits(users, resources=None, sources=None): |
88 | dc9da5b9 | Giorgos Korfiatis | counters = get_counters(users, resources, sources) |
89 | dc9da5b9 | Giorgos Korfiatis | quotas = transform_data(counters) |
90 | dc9da5b9 | Giorgos Korfiatis | limits = transform_data(counters, limits_only) |
91 | dc9da5b9 | Giorgos Korfiatis | return quotas, limits
|
92 | dc9da5b9 | Giorgos Korfiatis | |
93 | dc9da5b9 | Giorgos Korfiatis | |
94 | dc9da5b9 | Giorgos Korfiatis | def get_user_quotas(user, resources=None, sources=None): |
95 | dc9da5b9 | Giorgos Korfiatis | quotas = get_users_quotas([user], resources, sources) |
96 | dc9da5b9 | Giorgos Korfiatis | return quotas[user.uuid]
|
97 | dc9da5b9 | Giorgos Korfiatis | |
98 | dc9da5b9 | Giorgos Korfiatis | |
99 | 5afce44d | Giorgos Korfiatis | def get_service_quotas(service, users=None): |
100 | bb005bc2 | Giorgos Korfiatis | resources = Resource.objects.filter(service=service.name) |
101 | bb005bc2 | Giorgos Korfiatis | resource_names = [r.name for r in resources] |
102 | 5afce44d | Giorgos Korfiatis | counters = qh.get_quota(holders=users, resources=resource_names) |
103 | bb005bc2 | Giorgos Korfiatis | return transform_data(counters)
|
104 | bb005bc2 | Giorgos Korfiatis | |
105 | bb005bc2 | Giorgos Korfiatis | |
106 | dc9da5b9 | Giorgos Korfiatis | def set_user_quota(quotas): |
107 | dc9da5b9 | Giorgos Korfiatis | qh.set_holder_quota(quotas) |
108 | aa27f246 | Giorgos Korfiatis | |
109 | aa27f246 | Giorgos Korfiatis | |
110 | aa27f246 | Giorgos Korfiatis | def get_default_quota(): |
111 | aa27f246 | Giorgos Korfiatis | _DEFAULT_QUOTA = {} |
112 | aa27f246 | Giorgos Korfiatis | resources = Resource.objects.select_related('service').all()
|
113 | aa27f246 | Giorgos Korfiatis | for resource in resources: |
114 | aa27f246 | Giorgos Korfiatis | capacity = resource.uplimit |
115 | aa27f246 | Giorgos Korfiatis | _DEFAULT_QUOTA[resource.full_name()] = capacity |
116 | aa27f246 | Giorgos Korfiatis | |
117 | aa27f246 | Giorgos Korfiatis | return _DEFAULT_QUOTA
|
118 | aa27f246 | Giorgos Korfiatis | |
119 | aa27f246 | Giorgos Korfiatis | |
120 | aa27f246 | Giorgos Korfiatis | SYSTEM = 'system'
|
121 | aa27f246 | Giorgos Korfiatis | |
122 | aa27f246 | Giorgos Korfiatis | |
123 | aa27f246 | Giorgos Korfiatis | def initial_quotas(users): |
124 | aa27f246 | Giorgos Korfiatis | initial = {} |
125 | aa27f246 | Giorgos Korfiatis | default_quotas = get_default_quota() |
126 | aa27f246 | Giorgos Korfiatis | |
127 | aa27f246 | Giorgos Korfiatis | for user in users: |
128 | aa27f246 | Giorgos Korfiatis | uuid = user.uuid |
129 | aa27f246 | Giorgos Korfiatis | source_quota = {SYSTEM: dict(default_quotas)}
|
130 | aa27f246 | Giorgos Korfiatis | initial[uuid] = source_quota |
131 | aa27f246 | Giorgos Korfiatis | |
132 | aa27f246 | Giorgos Korfiatis | objs = AstakosUserQuota.objects.select_related() |
133 | aa27f246 | Giorgos Korfiatis | orig_quotas = objs.filter(user__in=users) |
134 | aa27f246 | Giorgos Korfiatis | for user_quota in orig_quotas: |
135 | aa27f246 | Giorgos Korfiatis | uuid = user_quota.user.uuid |
136 | aa27f246 | Giorgos Korfiatis | user_init = initial.get(uuid, {}) |
137 | 003909e3 | Giorgos Korfiatis | source_quota = user_init.get(SYSTEM, {}) |
138 | aa27f246 | Giorgos Korfiatis | resource = user_quota.resource.full_name() |
139 | 003909e3 | Giorgos Korfiatis | source_quota[resource] = user_quota.capacity |
140 | 003909e3 | Giorgos Korfiatis | user_init[SYSTEM] = source_quota |
141 | aa27f246 | Giorgos Korfiatis | initial[uuid] = user_init |
142 | aa27f246 | Giorgos Korfiatis | |
143 | aa27f246 | Giorgos Korfiatis | return initial
|
144 | aa27f246 | Giorgos Korfiatis | |
145 | aa27f246 | Giorgos Korfiatis | |
146 | aa27f246 | Giorgos Korfiatis | def get_grant_source(grant): |
147 | aa27f246 | Giorgos Korfiatis | return SYSTEM
|
148 | aa27f246 | Giorgos Korfiatis | |
149 | aa27f246 | Giorgos Korfiatis | |
150 | cb14cc6c | Giorgos Korfiatis | def astakos_users_quotas(users, initial=None): |
151 | aa27f246 | Giorgos Korfiatis | if initial is None: |
152 | aa27f246 | Giorgos Korfiatis | quotas = initial_quotas(users) |
153 | aa27f246 | Giorgos Korfiatis | else:
|
154 | aa27f246 | Giorgos Korfiatis | quotas = copy.deepcopy(initial) |
155 | aa27f246 | Giorgos Korfiatis | |
156 | aa27f246 | Giorgos Korfiatis | ACTUALLY_ACCEPTED = ProjectMembership.ACTUALLY_ACCEPTED |
157 | aa27f246 | Giorgos Korfiatis | objs = ProjectMembership.objects.select_related('project', 'person') |
158 | aa27f246 | Giorgos Korfiatis | memberships = objs.filter(person__in=users, |
159 | aa27f246 | Giorgos Korfiatis | state__in=ACTUALLY_ACCEPTED, |
160 | aa27f246 | Giorgos Korfiatis | project__state=Project.APPROVED) |
161 | aa27f246 | Giorgos Korfiatis | |
162 | aa27f246 | Giorgos Korfiatis | project_ids = set(m.project_id for m in memberships) |
163 | aa27f246 | Giorgos Korfiatis | objs = ProjectApplication.objects.select_related('project')
|
164 | aa27f246 | Giorgos Korfiatis | apps = objs.filter(project__in=project_ids) |
165 | aa27f246 | Giorgos Korfiatis | |
166 | aa27f246 | Giorgos Korfiatis | project_dict = {} |
167 | aa27f246 | Giorgos Korfiatis | for app in apps: |
168 | aa27f246 | Giorgos Korfiatis | project_dict[app.project] = app |
169 | aa27f246 | Giorgos Korfiatis | |
170 | aa27f246 | Giorgos Korfiatis | objs = ProjectResourceGrant.objects.select_related() |
171 | aa27f246 | Giorgos Korfiatis | grants = objs.filter(project_application__in=apps) |
172 | aa27f246 | Giorgos Korfiatis | |
173 | aa27f246 | Giorgos Korfiatis | for membership in memberships: |
174 | aa27f246 | Giorgos Korfiatis | uuid = membership.person.uuid |
175 | aa27f246 | Giorgos Korfiatis | userquotas = quotas.get(uuid, {}) |
176 | aa27f246 | Giorgos Korfiatis | |
177 | aa27f246 | Giorgos Korfiatis | application = project_dict[membership.project] |
178 | aa27f246 | Giorgos Korfiatis | |
179 | aa27f246 | Giorgos Korfiatis | for grant in grants: |
180 | aa27f246 | Giorgos Korfiatis | if grant.project_application_id != application.id:
|
181 | aa27f246 | Giorgos Korfiatis | continue
|
182 | aa27f246 | Giorgos Korfiatis | |
183 | aa27f246 | Giorgos Korfiatis | source = get_grant_source(grant) |
184 | aa27f246 | Giorgos Korfiatis | source_quotas = userquotas.get(source, {}) |
185 | aa27f246 | Giorgos Korfiatis | |
186 | aa27f246 | Giorgos Korfiatis | resource = grant.resource.full_name() |
187 | aa27f246 | Giorgos Korfiatis | prev = source_quotas.get(resource, 0)
|
188 | aa27f246 | Giorgos Korfiatis | new = prev + grant.member_capacity |
189 | aa27f246 | Giorgos Korfiatis | source_quotas[resource] = new |
190 | aa27f246 | Giorgos Korfiatis | userquotas[source] = source_quotas |
191 | aa27f246 | Giorgos Korfiatis | quotas[uuid] = userquotas |
192 | aa27f246 | Giorgos Korfiatis | |
193 | aa27f246 | Giorgos Korfiatis | return quotas
|
194 | aa27f246 | Giorgos Korfiatis | |
195 | aa27f246 | Giorgos Korfiatis | |
196 | cb14cc6c | Giorgos Korfiatis | def astakos_user_quotas(user): |
197 | cb14cc6c | Giorgos Korfiatis | quotas = astakos_users_quotas([user]) |
198 | aa27f246 | Giorgos Korfiatis | try:
|
199 | aa27f246 | Giorgos Korfiatis | return quotas[user.uuid]
|
200 | aa27f246 | Giorgos Korfiatis | except KeyError: |
201 | aa27f246 | Giorgos Korfiatis | raise ValueError("could not compute quotas") |
202 | aa27f246 | Giorgos Korfiatis | |
203 | aa27f246 | Giorgos Korfiatis | |
204 | 3adbd562 | Giorgos Korfiatis | def list_user_quotas(users): |
205 | 3adbd562 | Giorgos Korfiatis | qh_quotas, qh_limits = get_users_quotas_and_limits(users) |
206 | 3adbd562 | Giorgos Korfiatis | astakos_initial = initial_quotas(users) |
207 | cb14cc6c | Giorgos Korfiatis | astakos_quotas = astakos_users_quotas(users) |
208 | 3adbd562 | Giorgos Korfiatis | |
209 | 3adbd562 | Giorgos Korfiatis | diff_quotas = {} |
210 | 3adbd562 | Giorgos Korfiatis | for holder, local in astakos_quotas.iteritems(): |
211 | 3adbd562 | Giorgos Korfiatis | registered = qh_limits.get(holder, None)
|
212 | 3adbd562 | Giorgos Korfiatis | if local != registered:
|
213 | 3adbd562 | Giorgos Korfiatis | diff_quotas[holder] = dict(local)
|
214 | 3adbd562 | Giorgos Korfiatis | |
215 | 3adbd562 | Giorgos Korfiatis | return (qh_limits, qh_quotas,
|
216 | 3adbd562 | Giorgos Korfiatis | astakos_initial, diff_quotas) |
217 | 9747707e | Giorgos Korfiatis | |
218 | 9747707e | Giorgos Korfiatis | |
219 | 9747707e | Giorgos Korfiatis | def qh_add_resource_limit(resource, diff): |
220 | ae16bcad | Giorgos Korfiatis | objs = AstakosUser.forupdate.filter(Q(email_verified=True) &
|
221 | ae16bcad | Giorgos Korfiatis | ~Q(policy=resource)) |
222 | ae16bcad | Giorgos Korfiatis | users = objs.select_for_update() |
223 | ae16bcad | Giorgos Korfiatis | uuids = [u.uuid for u in users] |
224 | ae16bcad | Giorgos Korfiatis | qh.add_resource_limit(holders=uuids, sources=[SYSTEM], |
225 | ae16bcad | Giorgos Korfiatis | resources=[resource.name], diff=diff) |
226 | 9747707e | Giorgos Korfiatis | |
227 | 9747707e | Giorgos Korfiatis | |
228 | 9747707e | Giorgos Korfiatis | def qh_sync_new_resource(resource, limit): |
229 | 9747707e | Giorgos Korfiatis | users = AstakosUser.forupdate.filter( |
230 | 9747707e | Giorgos Korfiatis | email_verified=True).select_for_update()
|
231 | 9747707e | Giorgos Korfiatis | |
232 | ae16bcad | Giorgos Korfiatis | resource_name = resource.name |
233 | 9747707e | Giorgos Korfiatis | data = [] |
234 | 9747707e | Giorgos Korfiatis | for user in users: |
235 | 9747707e | Giorgos Korfiatis | uuid = user.uuid |
236 | ae16bcad | Giorgos Korfiatis | key = uuid, SYSTEM, resource_name |
237 | 9747707e | Giorgos Korfiatis | data.append((key, limit)) |
238 | 9747707e | Giorgos Korfiatis | |
239 | 9747707e | Giorgos Korfiatis | qh.set_quota(data) |
240 | 44104cd3 | Giorgos Korfiatis | |
241 | 44104cd3 | Giorgos Korfiatis | |
242 | 44104cd3 | Giorgos Korfiatis | def qh_sync_users(user_ids): |
243 | 44104cd3 | Giorgos Korfiatis | users = AstakosUser.forupdate.filter(id__in=user_ids).select_for_update() |
244 | cb14cc6c | Giorgos Korfiatis | astakos_quotas = astakos_users_quotas(list(users))
|
245 | 44104cd3 | Giorgos Korfiatis | set_user_quota(astakos_quotas) |
246 | 44104cd3 | Giorgos Korfiatis | |
247 | 44104cd3 | Giorgos Korfiatis | |
248 | 44104cd3 | Giorgos Korfiatis | def qh_sync_user(user_id): |
249 | 44104cd3 | Giorgos Korfiatis | qh_sync_users([user_id]) |