Statistics
| Branch: | Tag: | Revision:

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])