Revision 1d2b20aa snf-astakos-app/astakos/quotaholder/callpoint.py
b/snf-astakos-app/astakos/quotaholder/callpoint.py | ||
---|---|---|
34 | 34 |
from astakos.quotaholder.exception import ( |
35 | 35 |
QuotaholderError, |
36 | 36 |
CorruptedError, InvalidDataError, |
37 |
InvalidKeyError, NoEntityError, |
|
38 | 37 |
NoQuantityError, NoCapacityError, |
39 | 38 |
ExportLimitError, ImportLimitError, |
40 | 39 |
DuplicateError) |
... | ... | |
43 | 42 |
from astakos.quotaholder.api import QH_PRACTICALLY_INFINITE |
44 | 43 |
|
45 | 44 |
from django.db.models import Q, Count |
46 |
from .models import (Entity, Policy, Holding, |
|
45 |
from django.db.models import Q |
|
46 |
from .models import (Policy, Holding, |
|
47 | 47 |
Commission, Provision, ProvisionLog, CallSerial, |
48 | 48 |
now, |
49 |
db_get_entity, db_get_holding, db_get_policy,
|
|
49 |
db_get_holding, db_get_policy, |
|
50 | 50 |
db_get_commission, db_filter_provision, db_get_callserial) |
51 | 51 |
|
52 | 52 |
|
53 | 53 |
class QuotaholderDjangoDBCallpoint(object): |
54 | 54 |
|
55 |
def create_entity(self, context=None, create_entity=()): |
|
56 |
rejected = [] |
|
57 |
append = rejected.append |
|
58 |
|
|
59 |
for idx, (entity, owner, key, ownerkey) in enumerate(create_entity): |
|
60 |
try: |
|
61 |
owner = Entity.objects.get(entity=owner, key=ownerkey) |
|
62 |
except Entity.DoesNotExist: |
|
63 |
append(idx) |
|
64 |
continue |
|
65 |
|
|
66 |
try: |
|
67 |
e = Entity.objects.get(entity=entity) |
|
68 |
append(idx) |
|
69 |
except Entity.DoesNotExist: |
|
70 |
e = Entity.objects.create(entity=entity, |
|
71 |
owner=owner, |
|
72 |
key=key) |
|
73 |
|
|
74 |
if rejected: |
|
75 |
raise QuotaholderError(rejected) |
|
76 |
return rejected |
|
77 |
|
|
78 |
def set_entity_key(self, context=None, set_entity_key=()): |
|
79 |
rejected = [] |
|
80 |
append = rejected.append |
|
81 |
|
|
82 |
for entity, key, newkey in set_entity_key: |
|
83 |
try: |
|
84 |
e = db_get_entity(entity=entity, key=key, for_update=True) |
|
85 |
except Entity.DoesNotExist: |
|
86 |
append(entity) |
|
87 |
continue |
|
88 |
|
|
89 |
e.key = newkey |
|
90 |
e.save() |
|
91 |
|
|
92 |
if rejected: |
|
93 |
raise QuotaholderError(rejected) |
|
94 |
return rejected |
|
95 |
|
|
96 |
def list_entities(self, context=None, entity=None, key=None): |
|
97 |
try: |
|
98 |
e = Entity.objects.get(entity=entity, key=key) |
|
99 |
except Entity.DoesNotExist: |
|
100 |
m = "Entity '%s' does not exist" % (entity,) |
|
101 |
raise NoEntityError(m) |
|
102 |
|
|
103 |
children = e.entities.all() |
|
104 |
entities = [e.entity for e in children] |
|
105 |
return entities |
|
106 |
|
|
107 |
def get_entity(self, context=None, get_entity=()): |
|
108 |
entities = [] |
|
109 |
append = entities.append |
|
110 |
|
|
111 |
names = [entity for entity, key in get_entity] |
|
112 |
es = Entity.objects.select_related(depth=1).filter(entity__in=names) |
|
113 |
data = {} |
|
114 |
for e in es: |
|
115 |
data[e.entity] = e |
|
116 |
|
|
117 |
for entity, key in get_entity: |
|
118 |
e = data.get(entity, None) |
|
119 |
if e is None or e.key != key: |
|
120 |
continue |
|
121 |
append((entity, e.owner.entity)) |
|
122 |
|
|
123 |
return entities |
|
124 |
|
|
125 | 55 |
def get_limits(self, context=None, get_limits=()): |
126 | 56 |
limits = [] |
127 | 57 |
append = limits.append |
... | ... | |
163 | 93 |
holdings = [] |
164 | 94 |
append = holdings.append |
165 | 95 |
|
166 |
for entity, resource, key in get_holding:
|
|
96 |
for entity, resource in get_holding: |
|
167 | 97 |
try: |
168 | 98 |
h = Holding.objects.get(entity=entity, resource=resource) |
169 | 99 |
except Holding.DoesNotExist: |
170 | 100 |
continue |
171 | 101 |
|
172 |
if h.entity.key != key: |
|
173 |
continue |
|
174 |
|
|
175 |
append((h.entity.entity, h.resource, h.policy.policy, |
|
102 |
append((h.entity, h.resource, h.policy.policy, |
|
176 | 103 |
h.imported, h.exported, |
177 | 104 |
h.returned, h.released, h.flags)) |
178 | 105 |
|
... | ... | |
182 | 109 |
rejected = [] |
183 | 110 |
append = rejected.append |
184 | 111 |
|
185 |
for entity, resource, key, policy, flags in set_holding: |
|
186 |
try: |
|
187 |
e = Entity.objects.get(entity=entity, key=key) |
|
188 |
except Entity.DoesNotExist: |
|
189 |
append((entity, resource, policy)) |
|
190 |
continue |
|
191 |
|
|
192 |
if e.key != key: |
|
193 |
append((entity, resource, policy)) |
|
194 |
continue |
|
195 |
|
|
112 |
for entity, resource, policy, flags in set_holding: |
|
196 | 113 |
try: |
197 | 114 |
p = Policy.objects.get(policy=policy) |
198 | 115 |
except Policy.DoesNotExist: |
... | ... | |
206 | 123 |
h.flags = flags |
207 | 124 |
h.save() |
208 | 125 |
except Holding.DoesNotExist: |
209 |
h = Holding.objects.create(entity=e, resource=resource, |
|
126 |
h = Holding.objects.create(entity=entity, resource=resource,
|
|
210 | 127 |
policy=p, flags=flags) |
211 | 128 |
|
212 | 129 |
if rejected: |
... | ... | |
240 | 157 |
append = rejected.append |
241 | 158 |
|
242 | 159 |
for idx, sfh in enumerate(init_holding): |
243 |
(entity, resource, key, policy,
|
|
160 |
(entity, resource, policy, |
|
244 | 161 |
imported, exported, returned, released, |
245 | 162 |
flags) = sfh |
246 |
try: |
|
247 |
e = Entity.objects.get(entity=entity, key=key) |
|
248 |
except Entity.DoesNotExist: |
|
249 |
append(idx) |
|
250 |
continue |
|
251 |
|
|
252 |
if e.key != key: |
|
253 |
append(idx) |
|
254 |
continue |
|
255 | 163 |
|
256 | 164 |
try: |
257 | 165 |
p = Policy.objects.get(policy=policy) |
... | ... | |
259 | 167 |
append(idx) |
260 | 168 |
continue |
261 | 169 |
|
262 |
self._init_holding(e, resource, p, |
|
170 |
self._init_holding(entity, resource, p,
|
|
263 | 171 |
imported, exported, |
264 | 172 |
returned, released, |
265 | 173 |
flags) |
... | ... | |
272 | 180 |
append = rejected.append |
273 | 181 |
|
274 | 182 |
for idx, tpl in enumerate(reset_holding): |
275 |
(entity, resource, key,
|
|
183 |
(entity, resource, |
|
276 | 184 |
imported, exported, returned, released) = tpl |
277 |
try: |
|
278 |
e = Entity.objects.get(entity=entity, key=key) |
|
279 |
except Entity.DoesNotExist: |
|
280 |
append(idx) |
|
281 |
continue |
|
282 | 185 |
|
283 | 186 |
try: |
284 | 187 |
h = db_get_holding(entity=entity, resource=resource, |
... | ... | |
315 | 218 |
return hp.quantity + (holding.imported + holding.returned - |
316 | 219 |
holding.exported - holding.released) |
317 | 220 |
|
318 |
def _new_policy_name(self): |
|
319 |
return newname('policy_') |
|
320 |
|
|
321 |
def _increase_resource(self, entity, resource, amount): |
|
322 |
try: |
|
323 |
h = db_get_holding(entity=entity, resource=resource, |
|
324 |
for_update=True) |
|
325 |
except Holding.DoesNotExist: |
|
326 |
h = Holding(entity=entity, resource=resource) |
|
327 |
p = Policy.objects.create(policy=self._new_policy_name(), |
|
328 |
quantity=0, |
|
329 |
capacity=QH_PRACTICALLY_INFINITE, |
|
330 |
import_limit=QH_PRACTICALLY_INFINITE, |
|
331 |
export_limit=QH_PRACTICALLY_INFINITE) |
|
332 |
h.policy = p |
|
333 |
h.imported += amount |
|
334 |
h.save() |
|
335 |
|
|
336 | 221 |
def release_holding(self, context=None, release_holding=()): |
337 | 222 |
rejected = [] |
338 | 223 |
append = rejected.append |
339 | 224 |
|
340 |
for idx, (entity, resource, key) in enumerate(release_holding):
|
|
225 |
for idx, (entity, resource) in enumerate(release_holding): |
|
341 | 226 |
try: |
342 | 227 |
h = db_get_holding(entity=entity, resource=resource, |
343 | 228 |
for_update=True) |
... | ... | |
345 | 230 |
append(idx) |
346 | 231 |
continue |
347 | 232 |
|
348 |
if h.entity.key != key: |
|
349 |
append(idx) |
|
350 |
continue |
|
351 |
|
|
352 | 233 |
if self._check_pending(entity, resource): |
353 | 234 |
append(idx) |
354 | 235 |
continue |
355 | 236 |
|
356 | 237 |
q = self._actual_quantity(h) |
357 | 238 |
if q > 0: |
358 |
owner = h.entity.owner
|
|
359 |
self._increase_resource(owner, resource, q)
|
|
239 |
append(idx)
|
|
240 |
continue
|
|
360 | 241 |
|
361 | 242 |
h.delete() |
362 | 243 |
|
... | ... | |
364 | 245 |
raise QuotaholderError(rejected) |
365 | 246 |
return rejected |
366 | 247 |
|
367 |
def list_resources(self, context=None, entity=None, key=None): |
|
368 |
try: |
|
369 |
e = Entity.objects.get(entity=entity) |
|
370 |
except Entity.DoesNotExist: |
|
371 |
m = "No such entity '%s'" % (entity,) |
|
372 |
raise NoEntityError(m) |
|
373 |
|
|
374 |
if e.key != key: |
|
375 |
m = "Invalid key for entity '%s'" % (entity,) |
|
376 |
raise InvalidKeyError(m) |
|
377 |
|
|
378 |
holdings = e.holding_set.filter(entity=entity) |
|
248 |
def list_resources(self, context=None, entity=None): |
|
249 |
holdings = Holding.objects.filter(entity=entity) |
|
379 | 250 |
resources = [h.resource for h in holdings] |
380 | 251 |
return resources |
381 | 252 |
|
... | ... | |
385 | 256 |
holdings_list = [] |
386 | 257 |
append = holdings_list.append |
387 | 258 |
|
388 |
for entity, key in list_holdings: |
|
389 |
try: |
|
390 |
e = Entity.objects.get(entity=entity) |
|
391 |
if e.key != key: |
|
392 |
raise Entity.DoesNotExist("wrong key") |
|
393 |
except Entity.DoesNotExist: |
|
259 |
for entity in list_holdings: |
|
260 |
holdings = list(Holding.objects.filter(entity=entity)) |
|
261 |
if not holdings: |
|
394 | 262 |
reject(entity) |
395 | 263 |
continue |
396 | 264 |
|
397 |
holdings = e.holding_set.filter(entity=entity) |
|
398 | 265 |
append([[entity, h.resource, |
399 | 266 |
h.imported, h.exported, h.returned, h.released] |
400 | 267 |
for h in holdings]) |
... | ... | |
405 | 272 |
quotas = [] |
406 | 273 |
append = quotas.append |
407 | 274 |
|
408 |
entities = set(e for e, r, k in get_quota)
|
|
275 |
entities = set(e for e, r in get_quota) |
|
409 | 276 |
hs = Holding.objects.select_related().filter(entity__in=entities) |
410 | 277 |
holdings = {} |
411 | 278 |
for h in hs: |
412 |
holdings[(h.entity_id, h.resource)] = h
|
|
279 |
holdings[(h.entity, h.resource)] = h |
|
413 | 280 |
|
414 |
for entity, resource, key in get_quota:
|
|
281 |
for entity, resource in get_quota: |
|
415 | 282 |
try: |
416 | 283 |
h = holdings[(entity, resource)] |
417 | 284 |
except: |
418 | 285 |
continue |
419 | 286 |
|
420 |
if h.entity.key != key: |
|
421 |
continue |
|
422 |
|
|
423 | 287 |
p = h.policy |
424 | 288 |
|
425 |
append((h.entity.entity, h.resource, p.quantity, p.capacity,
|
|
289 |
append((h.entity, h.resource, p.quantity, p.capacity, |
|
426 | 290 |
p.import_limit, p.export_limit, |
427 | 291 |
h.imported, h.exported, |
428 | 292 |
h.returned, h.released, |
... | ... | |
436 | 300 |
|
437 | 301 |
q_holdings = Q() |
438 | 302 |
entities = [] |
439 |
for (entity, resource, key, _, _, _, _, _) in set_quota:
|
|
303 |
for (entity, resource, _, _, _, _, _) in set_quota: |
|
440 | 304 |
entities.append(entity) |
441 | 305 |
|
442 | 306 |
hs = Holding.objects.filter(entity__in=entities).select_for_update() |
443 | 307 |
holdings = {} |
444 | 308 |
for h in hs: |
445 |
holdings[(h.entity_id, h.resource)] = h |
|
446 |
|
|
447 |
entities = Entity.objects.in_bulk(entities) |
|
309 |
holdings[(h.entity, h.resource)] = h |
|
448 | 310 |
|
449 | 311 |
old_policies = [] |
450 | 312 |
|
451 |
for (entity, resource, key,
|
|
313 |
for (entity, resource, |
|
452 | 314 |
quantity, capacity, |
453 | 315 |
import_limit, export_limit, flags) in set_quota: |
454 | 316 |
|
455 |
e = entities.get(entity, None) |
|
456 |
if e is None or e.key != key: |
|
457 |
append((entity, resource)) |
|
458 |
continue |
|
459 |
|
|
460 | 317 |
policy = newname('policy_') |
461 | 318 |
newp = Policy(policy=policy, |
462 | 319 |
quantity=quantity, |
... | ... | |
470 | 327 |
h.policy = newp |
471 | 328 |
h.flags = flags |
472 | 329 |
except KeyError: |
473 |
h = Holding(entity=e, resource=resource, |
|
330 |
h = Holding(entity=entity, resource=resource,
|
|
474 | 331 |
policy=newp, flags=flags) |
475 | 332 |
|
476 | 333 |
# the order is intentionally reversed so that it |
... | ... | |
507 | 364 |
sources = sub_quota + add_quota |
508 | 365 |
q_holdings = Q() |
509 | 366 |
entities = [] |
510 |
for (entity, resource, key, _, _, _, _) in sources:
|
|
367 |
for (entity, resource, _, _, _, _) in sources: |
|
511 | 368 |
entities.append(entity) |
512 | 369 |
|
513 | 370 |
hs = Holding.objects.filter(entity__in=entities).select_for_update() |
514 | 371 |
holdings = {} |
515 | 372 |
for h in hs: |
516 |
holdings[(h.entity_id, h.resource)] = h |
|
517 |
|
|
518 |
entities = Entity.objects.in_bulk(entities) |
|
373 |
holdings[(h.entity, h.resource)] = h |
|
519 | 374 |
|
520 | 375 |
pids = [h.policy_id for h in hs] |
521 | 376 |
policies = Policy.objects.in_bulk(pids) |
... | ... | |
523 | 378 |
old_policies = [] |
524 | 379 |
|
525 | 380 |
for removing, source in [(True, sub_quota), (False, add_quota)]: |
526 |
for (entity, resource, key,
|
|
381 |
for (entity, resource, |
|
527 | 382 |
quantity, capacity, |
528 | 383 |
import_limit, export_limit) in source: |
529 | 384 |
|
530 |
e = entities.get(entity, None) |
|
531 |
if e is None or e.key != key: |
|
532 |
append((entity, resource)) |
|
533 |
continue |
|
534 |
|
|
535 | 385 |
try: |
536 | 386 |
h = holdings[(entity, resource)] |
537 | 387 |
old_policies.append(h.policy_id) |
... | ... | |
543 | 393 |
if removing: |
544 | 394 |
append((entity, resource)) |
545 | 395 |
continue |
546 |
h = Holding(entity=e, resource=resource, flags=0) |
|
396 |
|
|
397 |
h = Holding(entity=entity, resource=resource, flags=0) |
|
547 | 398 |
p = None |
548 | 399 |
|
549 | 400 |
policy = newname('policy_') |
... | ... | |
622 | 473 |
context=None, |
623 | 474 |
clientkey=None, |
624 | 475 |
target=None, |
625 |
key=None, |
|
626 | 476 |
name=None, |
627 | 477 |
provisions=()): |
628 | 478 |
|
629 |
try: |
|
630 |
t = Entity.objects.get(entity=target) |
|
631 |
except Entity.DoesNotExist: |
|
632 |
m = "No target entity '%s'" % (target,) |
|
633 |
raise NoEntityError(m) |
|
634 |
else: |
|
635 |
if t.key != key: |
|
636 |
m = "Invalid key for target entity '%s'" % (target,) |
|
637 |
raise InvalidKeyError(m) |
|
638 |
|
|
639 | 479 |
create = Commission.objects.create |
640 |
commission = create(entity_id=target, clientkey=clientkey, name=name)
|
|
480 |
commission = create(entity=target, clientkey=clientkey, name=name) |
|
641 | 481 |
serial = commission.serial |
642 | 482 |
|
643 | 483 |
checked = [] |
... | ... | |
654 | 494 |
raise DuplicateError(m) |
655 | 495 |
checked.append(ent_res) |
656 | 496 |
|
657 |
try: |
|
658 |
e = Entity.objects.get(entity=entity) |
|
659 |
except Entity.DoesNotExist: |
|
660 |
m = "No source entity '%s'" % (entity,) |
|
661 |
raise NoEntityError(m) |
|
662 |
|
|
663 | 497 |
release = 0 |
664 | 498 |
if quantity < 0: |
665 | 499 |
release = 1 |
... | ... | |
781 | 615 |
limit=limit) |
782 | 616 |
|
783 | 617 |
Provision.objects.create(serial=commission, |
784 |
entity=e, |
|
618 |
entity=entity,
|
|
785 | 619 |
resource=resource, |
786 | 620 |
quantity=quantity) |
787 | 621 |
if release: |
... | ... | |
808 | 642 |
kwargs = { |
809 | 643 |
'serial': commission.serial, |
810 | 644 |
'name': commission.name, |
811 |
'source': s_entity.entity,
|
|
812 |
'target': t_entity.entity,
|
|
645 |
'source': s_entity, |
|
646 |
'target': t_entity, |
|
813 | 647 |
'resource': provision.resource, |
814 | 648 |
'source_quantity': s_policy.quantity, |
815 | 649 |
'source_capacity': s_policy.capacity, |
... | ... | |
852 | 686 |
provisions = db_filter_provision(serial=serial, for_update=True) |
853 | 687 |
for pv in provisions: |
854 | 688 |
try: |
855 |
h = db_get_holding(entity=pv.entity.entity,
|
|
689 |
h = db_get_holding(entity=pv.entity, |
|
856 | 690 |
resource=pv.resource, for_update=True) |
857 | 691 |
th = db_get_holding(entity=t, resource=pv.resource, |
858 | 692 |
for_update=True) |
... | ... | |
898 | 732 |
provisions = db_filter_provision(serial=serial, for_update=True) |
899 | 733 |
for pv in provisions: |
900 | 734 |
try: |
901 |
h = db_get_holding(entity=pv.entity.entity,
|
|
735 |
h = db_get_holding(entity=pv.entity, |
|
902 | 736 |
resource=pv.resource, for_update=True) |
903 | 737 |
th = db_get_holding(entity=t, resource=pv.resource, |
904 | 738 |
for_update=True) |
... | ... | |
954 | 788 |
|
955 | 789 |
return |
956 | 790 |
|
957 |
def release_entity(self, context=None, release_entity=()): |
|
958 |
rejected = [] |
|
959 |
append = rejected.append |
|
960 |
for entity, key in release_entity: |
|
961 |
try: |
|
962 |
e = db_get_entity(entity=entity, key=key, for_update=True) |
|
963 |
except Entity.DoesNotExist: |
|
964 |
append(entity) |
|
965 |
continue |
|
966 |
|
|
967 |
if e.entities.count() != 0: |
|
968 |
append(entity) |
|
969 |
continue |
|
970 |
|
|
971 |
if e.holding_set.count() != 0: |
|
972 |
append(entity) |
|
973 |
continue |
|
974 |
|
|
975 |
e.delete() |
|
976 |
|
|
977 |
if rejected: |
|
978 |
raise QuotaholderError(rejected) |
|
979 |
return rejected |
|
980 |
|
|
981 | 791 |
def get_timeline(self, context=None, after="", before="Z", get_timeline=()): |
982 | 792 |
entity_set = set() |
983 | 793 |
e_add = entity_set.add |
984 | 794 |
resource_set = set() |
985 | 795 |
r_add = resource_set.add |
986 | 796 |
|
987 |
for entity, resource, key in get_timeline:
|
|
797 |
for entity, resource in get_timeline: |
|
988 | 798 |
if entity not in entity_set: |
989 |
try: |
|
990 |
e = Entity.objects.get(entity=entity, key=key) |
|
991 |
e_add(entity) |
|
992 |
except Entity.DoesNotExist: |
|
993 |
continue |
|
799 |
e_add(entity) |
|
994 | 800 |
|
995 | 801 |
r_add((entity, resource)) |
996 | 802 |
|
Also available in: Unified diff