Revision aa27f246
b/snf-astakos-app/astakos/im/functions.py | ||
---|---|---|
70 | 70 |
from astakos.im.models import ( |
71 | 71 |
AstakosUser, Invitation, ProjectMembership, ProjectApplication, Project, |
72 | 72 |
UserSetting, |
73 |
get_resource_names, new_chain, users_quotas) |
|
73 |
get_resource_names, new_chain) |
|
74 |
from astakos.im.quotas import users_quotas |
|
74 | 75 |
from astakos.im.project_notif import ( |
75 | 76 |
membership_change_notify, membership_enroll_notify, |
76 | 77 |
membership_request_notify, membership_leave_request_notify, |
b/snf-astakos-app/astakos/im/management/commands/astakos-quota.py | ||
---|---|---|
34 | 34 |
from optparse import make_option |
35 | 35 |
from django.core.management.base import BaseCommand, CommandError |
36 | 36 |
|
37 |
from astakos.im.models import sync_all_users, sync_users, AstakosUser |
|
37 |
from astakos.im.models import AstakosUser |
|
38 |
from astakos.im.quotas import sync_all_users, sync_users |
|
38 | 39 |
from astakos.im.functions import get_user_by_uuid |
39 | 40 |
from astakos.im.management.commands._common import is_uuid, is_email |
40 | 41 |
from synnefo.lib.db.transaction import commit_on_success_strict |
b/snf-astakos-app/astakos/im/management/commands/user-show.py | ||
---|---|---|
34 | 34 |
from django.core.management.base import BaseCommand, CommandError |
35 | 35 |
|
36 | 36 |
from astakos.im.models import AstakosUser, get_latest_terms |
37 |
from astakos.im.quotas import user_quotas |
|
37 | 38 |
from astakos.im.util import model_to_dict |
38 | 39 |
from synnefo.lib.ordereddict import OrderedDict |
39 | 40 |
|
... | ... | |
66 | 67 |
raise CommandError(msg) |
67 | 68 |
|
68 | 69 |
for user in users: |
69 |
quotas = user.all_quotas()
|
|
70 |
quotas = user_quotas(user)
|
|
70 | 71 |
|
71 | 72 |
settings_dict = {} |
72 | 73 |
settings = user.settings() |
b/snf-astakos-app/astakos/im/models.py | ||
---|---|---|
84 | 84 |
from synnefo.lib.db.intdecimalfield import intDecimalField |
85 | 85 |
from synnefo.util.text import uenc, udec |
86 | 86 |
|
87 |
from astakos.im.quotas import get_users_quotas_and_limits, set_user_quota |
|
88 |
|
|
89 | 87 |
logger = logging.getLogger(__name__) |
90 | 88 |
|
91 | 89 |
DEFAULT_CONTENT_TYPE = None |
... | ... | |
257 | 255 |
|
258 | 256 |
register_resources(rs) |
259 | 257 |
|
260 |
|
|
261 |
def get_default_quota(): |
|
262 |
_DEFAULT_QUOTA = {} |
|
263 |
resources = Resource.objects.select_related('service').all() |
|
264 |
for resource in resources: |
|
265 |
capacity = resource.uplimit |
|
266 |
_DEFAULT_QUOTA[resource.full_name()] = capacity |
|
267 |
|
|
268 |
return _DEFAULT_QUOTA |
|
269 |
|
|
270 | 258 |
def get_resource_names(): |
271 | 259 |
_RESOURCE_NAMES = [] |
272 | 260 |
resources = Resource.objects.select_related('service').all() |
... | ... | |
768 | 756 |
def settings(self): |
769 | 757 |
return UserSetting.objects.filter(user=self) |
770 | 758 |
|
771 |
def all_quotas(self): |
|
772 |
quotas = users_quotas([self]) |
|
773 |
try: |
|
774 |
return quotas[self.uuid] |
|
775 |
except: |
|
776 |
raise ValueError("could not compute quotas") |
|
777 |
|
|
778 |
|
|
779 |
SYSTEM = 'system' |
|
780 |
|
|
781 |
def initial_quotas(users): |
|
782 |
initial = {} |
|
783 |
default_quotas = get_default_quota() |
|
784 |
|
|
785 |
for user in users: |
|
786 |
uuid = user.uuid |
|
787 |
source_quota = {SYSTEM: dict(default_quotas)} |
|
788 |
initial[uuid] = source_quota |
|
789 |
|
|
790 |
objs = AstakosUserQuota.objects.select_related() |
|
791 |
orig_quotas = objs.filter(user__in=users) |
|
792 |
for user_quota in orig_quotas: |
|
793 |
uuid = user_quota.user.uuid |
|
794 |
user_init = initial.get(uuid, {}) |
|
795 |
resource = user_quota.resource.full_name() |
|
796 |
user_init[resource] = user_quota.capacity |
|
797 |
initial[uuid] = user_init |
|
798 |
|
|
799 |
return initial |
|
800 |
|
|
801 |
|
|
802 |
def get_grant_source(grant): |
|
803 |
return SYSTEM |
|
804 |
|
|
805 |
|
|
806 |
def users_quotas(users, initial=None): |
|
807 |
if initial is None: |
|
808 |
quotas = initial_quotas(users) |
|
809 |
else: |
|
810 |
quotas = copy.deepcopy(initial) |
|
811 |
|
|
812 |
ACTUALLY_ACCEPTED = ProjectMembership.ACTUALLY_ACCEPTED |
|
813 |
objs = ProjectMembership.objects.select_related('project', 'person') |
|
814 |
memberships = objs.filter(person__in=users, |
|
815 |
state__in=ACTUALLY_ACCEPTED, |
|
816 |
project__state=Project.APPROVED) |
|
817 |
|
|
818 |
project_ids = set(m.project_id for m in memberships) |
|
819 |
objs = ProjectApplication.objects.select_related('project') |
|
820 |
apps = objs.filter(project__in=project_ids) |
|
821 |
|
|
822 |
project_dict = {} |
|
823 |
for app in apps: |
|
824 |
project_dict[app.project] = app |
|
825 |
|
|
826 |
objs = ProjectResourceGrant.objects.select_related() |
|
827 |
grants = objs.filter(project_application__in=apps) |
|
828 |
|
|
829 |
for membership in memberships: |
|
830 |
uuid = membership.person.uuid |
|
831 |
userquotas = quotas.get(uuid, {}) |
|
832 |
|
|
833 |
application = project_dict[membership.project] |
|
834 |
|
|
835 |
for grant in grants: |
|
836 |
if grant.project_application_id != application.id: |
|
837 |
continue |
|
838 |
|
|
839 |
source = get_grant_source(grant) |
|
840 |
source_quotas = userquotas.get(source, {}) |
|
841 |
|
|
842 |
resource = grant.resource.full_name() |
|
843 |
prev = source_quotas.get(resource, 0) |
|
844 |
new = prev + grant.member_capacity |
|
845 |
source_quotas[resource] = new |
|
846 |
userquotas[source] = source_quotas |
|
847 |
quotas[uuid] = userquotas |
|
848 |
|
|
849 |
return quotas |
|
850 |
|
|
851 | 759 |
|
852 | 760 |
class AstakosUserAuthProviderManager(models.Manager): |
853 | 761 |
|
... | ... | |
2320 | 2228 |
serial = models.AutoField(primary_key=True) |
2321 | 2229 |
|
2322 | 2230 |
|
2323 |
def sync_users(users, sync=True): |
|
2324 |
def _sync_users(users, sync): |
|
2325 |
|
|
2326 |
info = {} |
|
2327 |
for user in users: |
|
2328 |
info[user.uuid] = user.email |
|
2329 |
|
|
2330 |
qh_quotas, qh_limits = get_users_quotas_and_limits(users) |
|
2331 |
astakos_initial = initial_quotas(users) |
|
2332 |
astakos_quotas = users_quotas(users) |
|
2333 |
|
|
2334 |
diff_quotas = {} |
|
2335 |
for holder, local in astakos_quotas.iteritems(): |
|
2336 |
registered = qh_limits.get(holder, None) |
|
2337 |
if local != registered: |
|
2338 |
diff_quotas[holder] = dict(local) |
|
2339 |
|
|
2340 |
if sync: |
|
2341 |
r = set_user_quota(diff_quotas) |
|
2342 |
|
|
2343 |
return (qh_limits, qh_quotas, |
|
2344 |
astakos_initial, diff_quotas, info) |
|
2345 |
|
|
2346 |
return _sync_users(users, sync) |
|
2347 |
|
|
2348 |
|
|
2349 |
def sync_all_users(sync=True): |
|
2350 |
users = AstakosUser.objects.verified() |
|
2351 |
return sync_users(users, sync) |
|
2352 |
|
|
2353 | 2231 |
class ProjectMembershipHistory(models.Model): |
2354 | 2232 |
reasons_list = ['ACCEPT', 'REJECT', 'REMOVE'] |
2355 | 2233 |
reasons = dict((k, v) for v, k in enumerate(reasons_list)) |
b/snf-astakos-app/astakos/im/quotas.py | ||
---|---|---|
31 | 31 |
# interpreted as representing official policies, either expressed |
32 | 32 |
# or implied, of GRNET S.A. |
33 | 33 |
|
34 |
from astakos.im.models import ( |
|
35 |
Resource, AstakosUserQuota, AstakosUser, |
|
36 |
Project, ProjectMembership, ProjectResourceGrant, ProjectApplication) |
|
34 | 37 |
from astakos.quotaholder.callpoint import QuotaholderDjangoDBCallpoint |
35 | 38 |
|
36 | 39 |
qh = QuotaholderDjangoDBCallpoint() |
... | ... | |
94 | 97 |
|
95 | 98 |
def set_user_quota(quotas): |
96 | 99 |
qh.set_holder_quota(quotas) |
100 |
|
|
101 |
|
|
102 |
def get_default_quota(): |
|
103 |
_DEFAULT_QUOTA = {} |
|
104 |
resources = Resource.objects.select_related('service').all() |
|
105 |
for resource in resources: |
|
106 |
capacity = resource.uplimit |
|
107 |
_DEFAULT_QUOTA[resource.full_name()] = capacity |
|
108 |
|
|
109 |
return _DEFAULT_QUOTA |
|
110 |
|
|
111 |
|
|
112 |
SYSTEM = 'system' |
|
113 |
|
|
114 |
|
|
115 |
def initial_quotas(users): |
|
116 |
initial = {} |
|
117 |
default_quotas = get_default_quota() |
|
118 |
|
|
119 |
for user in users: |
|
120 |
uuid = user.uuid |
|
121 |
source_quota = {SYSTEM: dict(default_quotas)} |
|
122 |
initial[uuid] = source_quota |
|
123 |
|
|
124 |
objs = AstakosUserQuota.objects.select_related() |
|
125 |
orig_quotas = objs.filter(user__in=users) |
|
126 |
for user_quota in orig_quotas: |
|
127 |
uuid = user_quota.user.uuid |
|
128 |
user_init = initial.get(uuid, {}) |
|
129 |
resource = user_quota.resource.full_name() |
|
130 |
user_init[resource] = user_quota.capacity |
|
131 |
initial[uuid] = user_init |
|
132 |
|
|
133 |
return initial |
|
134 |
|
|
135 |
|
|
136 |
def get_grant_source(grant): |
|
137 |
return SYSTEM |
|
138 |
|
|
139 |
|
|
140 |
def users_quotas(users, initial=None): |
|
141 |
if initial is None: |
|
142 |
quotas = initial_quotas(users) |
|
143 |
else: |
|
144 |
quotas = copy.deepcopy(initial) |
|
145 |
|
|
146 |
ACTUALLY_ACCEPTED = ProjectMembership.ACTUALLY_ACCEPTED |
|
147 |
objs = ProjectMembership.objects.select_related('project', 'person') |
|
148 |
memberships = objs.filter(person__in=users, |
|
149 |
state__in=ACTUALLY_ACCEPTED, |
|
150 |
project__state=Project.APPROVED) |
|
151 |
|
|
152 |
project_ids = set(m.project_id for m in memberships) |
|
153 |
objs = ProjectApplication.objects.select_related('project') |
|
154 |
apps = objs.filter(project__in=project_ids) |
|
155 |
|
|
156 |
project_dict = {} |
|
157 |
for app in apps: |
|
158 |
project_dict[app.project] = app |
|
159 |
|
|
160 |
objs = ProjectResourceGrant.objects.select_related() |
|
161 |
grants = objs.filter(project_application__in=apps) |
|
162 |
|
|
163 |
for membership in memberships: |
|
164 |
uuid = membership.person.uuid |
|
165 |
userquotas = quotas.get(uuid, {}) |
|
166 |
|
|
167 |
application = project_dict[membership.project] |
|
168 |
|
|
169 |
for grant in grants: |
|
170 |
if grant.project_application_id != application.id: |
|
171 |
continue |
|
172 |
|
|
173 |
source = get_grant_source(grant) |
|
174 |
source_quotas = userquotas.get(source, {}) |
|
175 |
|
|
176 |
resource = grant.resource.full_name() |
|
177 |
prev = source_quotas.get(resource, 0) |
|
178 |
new = prev + grant.member_capacity |
|
179 |
source_quotas[resource] = new |
|
180 |
userquotas[source] = source_quotas |
|
181 |
quotas[uuid] = userquotas |
|
182 |
|
|
183 |
return quotas |
|
184 |
|
|
185 |
|
|
186 |
def user_quotas(user): |
|
187 |
quotas = users_quotas([user]) |
|
188 |
try: |
|
189 |
return quotas[user.uuid] |
|
190 |
except KeyError: |
|
191 |
raise ValueError("could not compute quotas") |
|
192 |
|
|
193 |
|
|
194 |
def sync_users(users, sync=True): |
|
195 |
def _sync_users(users, sync): |
|
196 |
|
|
197 |
info = {} |
|
198 |
for user in users: |
|
199 |
info[user.uuid] = user.email |
|
200 |
|
|
201 |
qh_quotas, qh_limits = get_users_quotas_and_limits(users) |
|
202 |
astakos_initial = initial_quotas(users) |
|
203 |
astakos_quotas = users_quotas(users) |
|
204 |
|
|
205 |
diff_quotas = {} |
|
206 |
for holder, local in astakos_quotas.iteritems(): |
|
207 |
registered = qh_limits.get(holder, None) |
|
208 |
if local != registered: |
|
209 |
diff_quotas[holder] = dict(local) |
|
210 |
|
|
211 |
if sync: |
|
212 |
r = set_user_quota(diff_quotas) |
|
213 |
|
|
214 |
return (qh_limits, qh_quotas, |
|
215 |
astakos_initial, diff_quotas, info) |
|
216 |
|
|
217 |
return _sync_users(users, sync) |
|
218 |
|
|
219 |
|
|
220 |
def sync_all_users(sync=True): |
|
221 |
users = AstakosUser.objects.verified() |
|
222 |
return sync_users(users, sync) |
Also available in: Unified diff