Revision d03796c2
b/snf-astakos-app/astakos/quotaholder/callpoint.py | ||
---|---|---|
34 | 34 |
from astakos.quotaholder.exception import ( |
35 | 35 |
QuotaholderError, |
36 | 36 |
CorruptedError, InvalidDataError, |
37 |
NoQuantityError, NoCapacityError,
|
|
37 |
NoStockError, NoCapacityError,
|
|
38 | 38 |
DuplicateError) |
39 | 39 |
|
40 |
from astakos.quotaholder.commission import ( |
|
41 |
Import, Export, Reclaim, Release, Operations) |
|
42 |
|
|
40 | 43 |
from astakos.quotaholder.utils.newname import newname |
41 | 44 |
from astakos.quotaholder.api import QH_PRACTICALLY_INFINITE |
42 | 45 |
|
... | ... | |
61 | 64 |
except Policy.DoesNotExist: |
62 | 65 |
continue |
63 | 66 |
|
64 |
append((policy, p.quantity, p.capacity))
|
|
67 |
append((policy, p.capacity)) |
|
65 | 68 |
|
66 | 69 |
return limits |
67 | 70 |
|
68 | 71 |
def set_limits(self, context=None, set_limits=[]): |
69 | 72 |
|
70 |
for (policy, quantity, capacity) in set_limits:
|
|
73 |
for (policy, capacity) in set_limits: |
|
71 | 74 |
|
72 | 75 |
try: |
73 | 76 |
policy = db_get_policy(policy=policy, for_update=True) |
74 | 77 |
except Policy.DoesNotExist: |
75 | 78 |
Policy.objects.create(policy=policy, |
76 |
quantity=quantity, |
|
77 | 79 |
capacity=capacity, |
78 | 80 |
) |
79 | 81 |
else: |
80 |
policy.quantity = quantity |
|
81 | 82 |
policy.capacity = capacity |
82 | 83 |
policy.save() |
83 | 84 |
|
... | ... | |
94 | 95 |
continue |
95 | 96 |
|
96 | 97 |
append((h.holder, h.resource, h.policy.policy, |
97 |
h.imported, h.exported,
|
|
98 |
h.returned, h.released, h.flags))
|
|
98 |
h.imported_min, h.imported_max,
|
|
99 |
h.stock_min, h.stock_max, h.flags))
|
|
99 | 100 |
|
100 | 101 |
return holdings |
101 | 102 |
|
... | ... | |
126 | 127 |
|
127 | 128 |
def _init_holding(self, |
128 | 129 |
holder, resource, policy, |
129 |
imported, exported, returned, released,
|
|
130 |
imported_min, imported_max, stock_min, stock_max,
|
|
130 | 131 |
flags): |
131 | 132 |
try: |
132 | 133 |
h = db_get_holding(holder=holder, resource=resource, |
... | ... | |
136 | 137 |
|
137 | 138 |
h.policy = policy |
138 | 139 |
h.flags = flags |
139 |
h.imported = imported |
|
140 |
h.importing = imported |
|
141 |
h.exported = exported |
|
142 |
h.exporting = exported |
|
143 |
h.returned = returned |
|
144 |
h.returning = returned |
|
145 |
h.released = released |
|
146 |
h.releasing = released |
|
140 |
h.imported_min = imported_min |
|
141 |
h.imported_max = imported_max |
|
142 |
h.stock_min = stock_min |
|
143 |
h.stock_max = stock_max |
|
147 | 144 |
h.save() |
148 | 145 |
|
149 | 146 |
def init_holding(self, context=None, init_holding=[]): |
... | ... | |
152 | 149 |
|
153 | 150 |
for idx, sfh in enumerate(init_holding): |
154 | 151 |
(holder, resource, policy, |
155 |
imported, exported, returned, released,
|
|
152 |
imported_min, imported_max, stock_min, stock_max,
|
|
156 | 153 |
flags) = sfh |
157 | 154 |
|
158 | 155 |
try: |
... | ... | |
162 | 159 |
continue |
163 | 160 |
|
164 | 161 |
self._init_holding(holder, resource, p, |
165 |
imported, exported,
|
|
166 |
returned, released,
|
|
162 |
imported_min, imported_max,
|
|
163 |
stock_min, stock_max,
|
|
167 | 164 |
flags) |
168 | 165 |
if rejected: |
169 | 166 |
raise QuotaholderError(rejected) |
... | ... | |
175 | 172 |
|
176 | 173 |
for idx, tpl in enumerate(reset_holding): |
177 | 174 |
(holder, resource, |
178 |
imported, exported, returned, released) = tpl
|
|
175 |
imported_min, imported_max, stock_min, stock_max) = tpl
|
|
179 | 176 |
|
180 | 177 |
try: |
181 | 178 |
h = db_get_holding(holder=holder, resource=resource, |
182 | 179 |
for_update=True) |
183 |
h.imported = imported |
|
184 |
h.importing = imported |
|
185 |
h.exported = exported |
|
186 |
h.exporting = exported |
|
187 |
h.returned = returned |
|
188 |
h.returning = returned |
|
189 |
h.released = released |
|
190 |
h.releasing = released |
|
180 |
h.imported_min = imported_min |
|
181 |
h.imported_max = imported_max |
|
182 |
h.stock_min = stock_min |
|
183 |
h.stock_max = stock_max |
|
191 | 184 |
h.save() |
192 | 185 |
except Holding.DoesNotExist: |
193 | 186 |
append(idx) |
... | ... | |
207 | 200 |
|
208 | 201 |
return as_target + as_source |
209 | 202 |
|
210 |
def _actual_quantity(self, holding): |
|
211 |
hp = holding.policy |
|
212 |
return hp.quantity + (holding.imported + holding.returned - |
|
213 |
holding.exported - holding.released) |
|
214 |
|
|
215 | 203 |
def release_holding(self, context=None, release_holding=[]): |
216 | 204 |
rejected = [] |
217 | 205 |
append = rejected.append |
... | ... | |
228 | 216 |
append(idx) |
229 | 217 |
continue |
230 | 218 |
|
231 |
q = self._actual_quantity(h) |
|
232 |
if q > 0: |
|
219 |
if h.imported_max > 0: |
|
233 | 220 |
append(idx) |
234 | 221 |
continue |
235 | 222 |
|
... | ... | |
257 | 244 |
continue |
258 | 245 |
|
259 | 246 |
append([(holder, h.resource, |
260 |
h.imported, h.exported, h.returned, h.released)
|
|
247 |
h.imported_min, h.imported_max, h.stock_min, h.stock_max)
|
|
261 | 248 |
for h in holdings]) |
262 | 249 |
|
263 | 250 |
return holdings_list, rejected |
... | ... | |
280 | 267 |
|
281 | 268 |
p = h.policy |
282 | 269 |
|
283 |
append((h.holder, h.resource, p.quantity, p.capacity,
|
|
284 |
h.imported, h.exported,
|
|
285 |
h.returned, h.released,
|
|
270 |
append((h.holder, h.resource, p.capacity, |
|
271 |
h.imported_min, h.imported_max,
|
|
272 |
h.stock_min, h.stock_max,
|
|
286 | 273 |
h.flags)) |
287 | 274 |
|
288 | 275 |
return quotas |
... | ... | |
293 | 280 |
|
294 | 281 |
q_holdings = Q() |
295 | 282 |
holders = [] |
296 |
for (holder, resource, _, _, _) in set_quota:
|
|
283 |
for (holder, resource, _, _) in set_quota: |
|
297 | 284 |
holders.append(holder) |
298 | 285 |
|
299 | 286 |
hs = Holding.objects.filter(holder__in=holders).select_for_update() |
... | ... | |
304 | 291 |
old_policies = [] |
305 | 292 |
|
306 | 293 |
for (holder, resource, |
307 |
quantity, capacity,
|
|
294 |
capacity, |
|
308 | 295 |
flags) in set_quota: |
309 | 296 |
|
310 | 297 |
policy = newname('policy_') |
311 | 298 |
newp = Policy(policy=policy, |
312 |
quantity=quantity, |
|
313 | 299 |
capacity=capacity, |
314 | 300 |
) |
315 | 301 |
|
... | ... | |
345 | 331 |
sources = sub_quota + add_quota |
346 | 332 |
q_holdings = Q() |
347 | 333 |
holders = [] |
348 |
for (holder, resource, _, _) in sources:
|
|
334 |
for (holder, resource, _) in sources: |
|
349 | 335 |
holders.append(holder) |
350 | 336 |
|
351 | 337 |
hs = Holding.objects.filter(holder__in=holders).select_for_update() |
... | ... | |
360 | 346 |
|
361 | 347 |
for removing, source in [(True, sub_quota), (False, add_quota)]: |
362 | 348 |
for (holder, resource, |
363 |
quantity, capacity,
|
|
349 |
capacity, |
|
364 | 350 |
) in source: |
365 | 351 |
|
366 | 352 |
try: |
... | ... | |
381 | 367 |
policy = newname('policy_') |
382 | 368 |
newp = Policy(policy=policy) |
383 | 369 |
|
384 |
newp.quantity = _add(p.quantity if p else 0, quantity, |
|
385 |
invert=removing) |
|
386 | 370 |
newp.capacity = _add(p.capacity if p else 0, capacity, |
387 | 371 |
invert=removing) |
388 | 372 |
|
... | ... | |
413 | 397 |
clientkey=None, |
414 | 398 |
target=None, |
415 | 399 |
name=None, |
416 |
provisions=[]):
|
|
400 |
provisions=()):
|
|
417 | 401 |
|
418 | 402 |
create = Commission.objects.create |
419 | 403 |
commission = create(holder=target, clientkey=clientkey, name=name) |
420 | 404 |
serial = commission.serial |
421 | 405 |
|
422 |
checked = [] |
|
423 |
for holder, resource, quantity in provisions: |
|
406 |
operations = Operations() |
|
424 | 407 |
|
425 |
if holder == target: |
|
426 |
m = "Cannot issue commission from an holder to itself (%s)" % ( |
|
427 |
holder,) |
|
428 |
raise InvalidDataError(m) |
|
429 |
|
|
430 |
ent_res = holder, resource |
|
431 |
if ent_res in checked: |
|
432 |
m = "Duplicate provision for %s.%s" % ent_res |
|
433 |
raise DuplicateError(m) |
|
434 |
checked.append(ent_res) |
|
408 |
try: |
|
409 |
checked = [] |
|
410 |
for holder, resource, quantity in provisions: |
|
435 | 411 |
|
436 |
release = 0 |
|
437 |
if quantity < 0: |
|
438 |
release = 1 |
|
412 |
if holder == target: |
|
413 |
m = ("Cannot issue commission from a holder " |
|
414 |
"to itself (%s)" % (holder,)) |
|
415 |
raise InvalidDataError(m) |
|
439 | 416 |
|
440 |
# Source limits checks |
|
441 |
try: |
|
442 |
h = db_get_holding(holder=holder, resource=resource, |
|
443 |
for_update=True) |
|
444 |
except Holding.DoesNotExist: |
|
445 |
m = ("There is no quantity " |
|
446 |
"to allocate from in %s.%s" % (holder, resource)) |
|
447 |
raise NoQuantityError(m, |
|
448 |
source=holder, target=target, |
|
449 |
resource=resource, requested=quantity, |
|
450 |
current=0, limit=0) |
|
451 |
|
|
452 |
hp = h.policy |
|
453 |
|
|
454 |
if not release: |
|
455 |
limit = hp.quantity + h.imported - h.releasing |
|
456 |
unavailable = h.exporting - h.returned |
|
457 |
available = limit - unavailable |
|
458 |
|
|
459 |
if quantity > available: |
|
460 |
m = ("There is not enough quantity " |
|
461 |
"to allocate from in %s.%s" % (holder, resource)) |
|
462 |
raise NoQuantityError(m, |
|
463 |
source=holder, |
|
464 |
target=target, |
|
465 |
resource=resource, |
|
466 |
requested=quantity, |
|
467 |
current=unavailable, |
|
468 |
limit=limit) |
|
469 |
else: |
|
470 |
current = (+ h.importing + h.returning |
|
471 |
- h.exported - h.returned) |
|
472 |
limit = hp.capacity |
|
473 |
if current - quantity > limit: |
|
474 |
m = ("There is not enough capacity " |
|
475 |
"to release to in %s.%s" % (holder, resource)) |
|
476 |
raise NoQuantityError(m, |
|
477 |
source=holder, |
|
478 |
target=target, |
|
479 |
resource=resource, |
|
480 |
requested=quantity, |
|
481 |
current=current, |
|
482 |
limit=limit) |
|
417 |
ent_res = holder, resource |
|
418 |
if ent_res in checked: |
|
419 |
m = "Duplicate provision for %s.%s" % ent_res |
|
420 |
raise DuplicateError(m) |
|
421 |
checked.append(ent_res) |
|
483 | 422 |
|
484 |
# Target limits checks |
|
485 |
try: |
|
486 |
th = db_get_holding(holder=target, resource=resource, |
|
487 |
for_update=True) |
|
488 |
except Holding.DoesNotExist: |
|
489 |
m = ("There is no capacity " |
|
490 |
"to allocate into in %s.%s" % (target, resource)) |
|
491 |
raise NoCapacityError(m, |
|
492 |
source=holder, |
|
493 |
target=target, |
|
494 |
resource=resource, |
|
495 |
requested=quantity, |
|
496 |
current=0, |
|
497 |
limit=0) |
|
498 |
|
|
499 |
tp = th.policy |
|
500 |
|
|
501 |
if not release: |
|
502 |
limit = tp.quantity + tp.capacity |
|
503 |
current = (+ th.importing + th.returning + tp.quantity |
|
504 |
- th.exported - th.released) |
|
505 |
|
|
506 |
if current + quantity > limit: |
|
507 |
m = ("There is not enough capacity " |
|
423 |
# Source |
|
424 |
try: |
|
425 |
h = db_get_holding(holder=holder, resource=resource, |
|
426 |
for_update=True) |
|
427 |
except Holding.DoesNotExist: |
|
428 |
m = ("%s has no stock of %s." % (holder, resource)) |
|
429 |
raise NoStockError(m, |
|
430 |
holder=holder, |
|
431 |
resource=resource, |
|
432 |
requested=quantity, |
|
433 |
current=0, |
|
434 |
limit=0) |
|
435 |
|
|
436 |
# Target |
|
437 |
try: |
|
438 |
th = db_get_holding(holder=target, resource=resource, |
|
439 |
for_update=True) |
|
440 |
except Holding.DoesNotExist: |
|
441 |
m = ("There is no capacity " |
|
508 | 442 |
"to allocate into in %s.%s" % (target, resource)) |
509 | 443 |
raise NoCapacityError(m, |
510 |
source=holder, |
|
511 |
target=target, |
|
444 |
holder=holder, |
|
512 | 445 |
resource=resource, |
513 | 446 |
requested=quantity, |
514 |
current=current, |
|
515 |
limit=limit) |
|
516 |
else: |
|
517 |
limit = tp.quantity + th.imported - th.releasing |
|
518 |
unavailable = th.exporting - th.returned |
|
519 |
available = limit - unavailable |
|
447 |
current=0, |
|
448 |
limit=0) |
|
520 | 449 |
|
521 |
if available + quantity < 0: |
|
522 |
m = ("There is not enough quantity " |
|
523 |
"to release from in %s.%s" % (target, resource)) |
|
524 |
raise NoCapacityError(m, |
|
525 |
source=holder, |
|
526 |
target=target, |
|
527 |
resource=resource, |
|
528 |
requested=quantity, |
|
529 |
current=unavailable, |
|
530 |
limit=limit) |
|
531 |
|
|
532 |
Provision.objects.create(serial=commission, |
|
533 |
holder=holder, |
|
534 |
resource=resource, |
|
535 |
quantity=quantity) |
|
536 |
if release: |
|
537 |
h.returning -= quantity |
|
538 |
th.releasing -= quantity |
|
539 |
else: |
|
540 |
h.exporting += quantity |
|
541 |
th.importing += quantity |
|
450 |
if quantity >= 0: |
|
451 |
operations.prepare(Export, h, quantity) |
|
452 |
operations.prepare(Import, th, quantity) |
|
542 | 453 |
|
543 |
h.save() |
|
544 |
th.save() |
|
454 |
else: # release |
|
455 |
abs_quantity = -quantity |
|
456 |
|
|
457 |
operations.prepare(Reclaim, h, abs_quantity) |
|
458 |
operations.prepare(Release, th, abs_quantity) |
|
459 |
|
|
460 |
Provision.objects.create(serial=commission, |
|
461 |
holder=holder, |
|
462 |
resource=resource, |
|
463 |
quantity=quantity) |
|
464 |
|
|
465 |
except QuotaholderError: |
|
466 |
operations.revert() |
|
467 |
raise |
|
545 | 468 |
|
546 | 469 |
return serial |
547 | 470 |
|
... | ... | |
560 | 483 |
'source': s_holder, |
561 | 484 |
'target': t_holder, |
562 | 485 |
'resource': provision.resource, |
563 |
'source_quantity': s_policy.quantity, |
|
564 | 486 |
'source_capacity': s_policy.capacity, |
565 |
'source_imported': s_holding.imported, |
|
566 |
'source_exported': s_holding.exported, |
|
567 |
'source_returned': s_holding.returned, |
|
568 |
'source_released': s_holding.released, |
|
569 |
'target_quantity': t_policy.quantity, |
|
487 |
'source_imported_min': s_holding.imported_min, |
|
488 |
'source_imported_max': s_holding.imported_max, |
|
489 |
'source_stock_min': s_holding.stock_min, |
|
490 |
'source_stock_max': s_holding.stock_max, |
|
570 | 491 |
'target_capacity': t_policy.capacity, |
571 |
'target_imported': t_holding.imported,
|
|
572 |
'target_exported': t_holding.exported,
|
|
573 |
'target_returned': t_holding.returned,
|
|
574 |
'target_released': t_holding.released,
|
|
492 |
'target_imported_min': t_holding.imported_min,
|
|
493 |
'target_imported_max': t_holding.imported_max,
|
|
494 |
'target_stock_min': t_holding.stock_min,
|
|
495 |
'target_stock_max': t_holding.stock_max,
|
|
575 | 496 |
'delta_quantity': provision.quantity, |
576 | 497 |
'issue_time': commission.issue_time, |
577 | 498 |
'log_time': log_time, |
... | ... | |
594 | 515 |
|
595 | 516 |
t = c.holder |
596 | 517 |
|
518 |
operations = Operations() |
|
519 |
|
|
597 | 520 |
provisions = db_filter_provision(serial=serial, for_update=True) |
598 | 521 |
for pv in provisions: |
599 | 522 |
try: |
... | ... | |
606 | 529 |
raise CorruptedError(m) |
607 | 530 |
|
608 | 531 |
quantity = pv.quantity |
609 |
release = 0 |
|
610 |
if quantity < 0: |
|
611 |
release = 1 |
|
612 | 532 |
|
613 |
if release: |
|
614 |
h.returned -= quantity |
|
615 |
th.released -= quantity |
|
616 |
else: |
|
617 |
h.exported += quantity |
|
618 |
th.imported += quantity |
|
533 |
if quantity >= 0: |
|
534 |
operations.finalize(Export, h, quantity) |
|
535 |
operations.finalize(Import, th, quantity) |
|
536 |
else: # release |
|
537 |
abs_quantity = -quantity |
|
538 |
|
|
539 |
operations.finalize(Reclaim, h, abs_quantity) |
|
540 |
operations.finalize(Release, th, abs_quantity) |
|
619 | 541 |
|
620 | 542 |
reason = 'ACCEPT:' + reason[-121:] |
621 | 543 |
self._log_provision(c, h, th, pv, log_time, reason) |
622 |
h.save() |
|
623 |
th.save() |
|
624 | 544 |
pv.delete() |
625 | 545 |
c.delete() |
626 | 546 |
|
... | ... | |
640 | 560 |
|
641 | 561 |
t = c.holder |
642 | 562 |
|
563 |
operations = Operations() |
|
564 |
|
|
643 | 565 |
provisions = db_filter_provision(serial=serial, for_update=True) |
644 | 566 |
for pv in provisions: |
645 | 567 |
try: |
... | ... | |
652 | 574 |
raise CorruptedError(m) |
653 | 575 |
|
654 | 576 |
quantity = pv.quantity |
655 |
release = 0 |
|
656 |
if quantity < 0: |
|
657 |
release = 1 |
|
658 | 577 |
|
659 |
if release: |
|
660 |
h.returning += quantity |
|
661 |
th.releasing += quantity |
|
662 |
else: |
|
663 |
h.exporting -= quantity |
|
664 |
th.importing -= quantity |
|
578 |
if quantity >= 0: |
|
579 |
operations.undo(Export, h, quantity) |
|
580 |
operations.undo(Import, th, quantity) |
|
581 |
else: # release |
|
582 |
abs_quantity = -quantity |
|
583 |
|
|
584 |
operations.undo(Reclaim, h, abs_quantity) |
|
585 |
operations.undo(Release, th, abs_quantity) |
|
665 | 586 |
|
666 | 587 |
reason = 'REJECT:' + reason[-121:] |
667 | 588 |
self._log_provision(c, h, th, pv, log_time, reason) |
668 |
h.save() |
|
669 |
th.save() |
|
670 | 589 |
pv.delete() |
671 | 590 |
c.delete() |
672 | 591 |
|
b/snf-astakos-app/astakos/quotaholder/commission.py | ||
---|---|---|
1 |
# Copyright 2013 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or |
|
4 |
# without modification, are permitted provided that the following |
|
5 |
# conditions are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above |
|
8 |
# copyright notice, this list of conditions and the following |
|
9 |
# disclaimer. |
|
10 |
# |
|
11 |
# 2. Redistributions in binary form must reproduce the above |
|
12 |
# copyright notice, this list of conditions and the following |
|
13 |
# disclaimer in the documentation and/or other materials |
|
14 |
# provided with the distribution. |
|
15 |
# |
|
16 |
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
|
17 |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
18 |
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
19 |
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
|
20 |
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
21 |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
22 |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
|
23 |
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
|
24 |
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
25 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|
26 |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
27 |
# POSSIBILITY OF SUCH DAMAGE. |
|
28 |
# |
|
29 |
# The views and conclusions contained in the software and |
|
30 |
# documentation are those of the authors and should not be |
|
31 |
# interpreted as representing official policies, either expressed |
|
32 |
# or implied, of GRNET S.A. |
|
33 |
|
|
34 |
from astakos.quotaholder.exception import ( |
|
35 |
NoCapacityError, NoStockError, |
|
36 |
NonImportedError, NoStockReleaseError, NonExportedError) |
|
37 |
|
|
38 |
|
|
39 |
class Operation(object): |
|
40 |
|
|
41 |
@staticmethod |
|
42 |
def assertions(holding): |
|
43 |
assert(0 <= holding.imported_min) |
|
44 |
assert(holding.imported_min <= holding.imported_max) |
|
45 |
assert(0 <= holding.stock_min) |
|
46 |
assert(holding.stock_min <= holding.stock_max) |
|
47 |
|
|
48 |
@classmethod |
|
49 |
def _prepare(cls, holding, quantity, check=True): |
|
50 |
raise NotImplementedError |
|
51 |
|
|
52 |
@classmethod |
|
53 |
def prepare(cls, holding, quantity, check=True): |
|
54 |
cls.assertions(holding) |
|
55 |
cls._prepare(holding, quantity, check=True) |
|
56 |
|
|
57 |
@classmethod |
|
58 |
def _finalize(cls, holding, quantity): |
|
59 |
raise NotImplementedError |
|
60 |
|
|
61 |
@classmethod |
|
62 |
def finalize(cls, holding, quantity): |
|
63 |
cls.assertions(holding) |
|
64 |
cls._finalize(holding, quantity) |
|
65 |
|
|
66 |
@classmethod |
|
67 |
def undo(cls, holding, quantity): |
|
68 |
cls.prepare(holding, -quantity, check=False) |
|
69 |
|
|
70 |
@classmethod |
|
71 |
def revert(cls, holding, quantity): |
|
72 |
# Assertions do not hold when reverting |
|
73 |
cls._prepare(holding, -quantity, check=False) |
|
74 |
|
|
75 |
|
|
76 |
class Import(Operation): |
|
77 |
|
|
78 |
@classmethod |
|
79 |
def _prepare(cls, holding, quantity, check=True): |
|
80 |
imported_max = holding.imported_max |
|
81 |
new_imported_max = imported_max + quantity |
|
82 |
|
|
83 |
capacity = holding.policy.capacity |
|
84 |
if check and new_imported_max > capacity: |
|
85 |
holder = holding.holder |
|
86 |
resource = holding.resource |
|
87 |
m = ("%s has not enough capacity of %s." % (holder, resource)) |
|
88 |
raise NoCapacityError(m, |
|
89 |
holder=holder, |
|
90 |
resource=resource, |
|
91 |
requested=quantity, |
|
92 |
current=imported_max, |
|
93 |
limit=capacity) |
|
94 |
|
|
95 |
holding.imported_max = new_imported_max |
|
96 |
holding.save() |
|
97 |
|
|
98 |
@classmethod |
|
99 |
def _finalize(cls, holding, quantity): |
|
100 |
holding.imported_min += quantity |
|
101 |
holding.stock_min += quantity |
|
102 |
holding.stock_max += quantity |
|
103 |
holding.save() |
|
104 |
|
|
105 |
|
|
106 |
class Export(Operation): |
|
107 |
|
|
108 |
@classmethod |
|
109 |
def _prepare(cls, holding, quantity, check=True): |
|
110 |
stock_min = holding.stock_min |
|
111 |
new_stock_min = stock_min - quantity |
|
112 |
|
|
113 |
if check and new_stock_min < 0: |
|
114 |
holder = holding.holder |
|
115 |
resource = holding.resource |
|
116 |
m = ("%s has not enough stock of %s." % (holder, resource)) |
|
117 |
raise NoStockError(m, |
|
118 |
holder=holder, |
|
119 |
resource=resource, |
|
120 |
requested=quantity, |
|
121 |
limit=stock_min) |
|
122 |
|
|
123 |
holding.stock_min = new_stock_min |
|
124 |
holding.save() |
|
125 |
|
|
126 |
@classmethod |
|
127 |
def _finalize(cls, holding, quantity): |
|
128 |
holding.stock_max -= quantity |
|
129 |
holding.save() |
|
130 |
|
|
131 |
|
|
132 |
class Release(Operation): |
|
133 |
|
|
134 |
@classmethod |
|
135 |
def _prepare(cls, holding, quantity, check=True): |
|
136 |
imported_min = holding.imported_min |
|
137 |
new_imported_min = imported_min - quantity |
|
138 |
|
|
139 |
stock_min = holding.stock_min |
|
140 |
new_stock_min = stock_min - quantity |
|
141 |
stock_max = holding.stock_max |
|
142 |
new_stock_max = stock_max - quantity |
|
143 |
|
|
144 |
if check and new_imported_min < 0: |
|
145 |
holder = holding.holder |
|
146 |
resource = holding.resource |
|
147 |
m = ("%s attempts to release more %s than it contains." % |
|
148 |
(holder, resource)) |
|
149 |
raise NonImportedError(m, |
|
150 |
holder=holder, |
|
151 |
resource=resource, |
|
152 |
requested=quantity, |
|
153 |
limit=imported_min) |
|
154 |
|
|
155 |
if check and new_stock_min < 0: |
|
156 |
holder = holding.holder |
|
157 |
resource = holding.resource |
|
158 |
m = ("%s attempts to release %s that has been reexported." % |
|
159 |
(holder, resource)) |
|
160 |
raise NoStockReleaseError(m, |
|
161 |
holder=holder, |
|
162 |
resource=resource, |
|
163 |
requested=quantity, |
|
164 |
limit=stock_min) |
|
165 |
|
|
166 |
holding.imported_min = new_imported_min |
|
167 |
holding.stock_min = new_stock_min |
|
168 |
holding.stock_max = new_stock_max |
|
169 |
holding.save() |
|
170 |
|
|
171 |
@classmethod |
|
172 |
def _finalize(cls, holding, quantity): |
|
173 |
holding.imported_max -= quantity |
|
174 |
holding.save() |
|
175 |
|
|
176 |
|
|
177 |
class Reclaim(Operation): |
|
178 |
|
|
179 |
@classmethod |
|
180 |
def _prepare(cls, holding, quantity, check=True): |
|
181 |
stock_max = holding.stock_max |
|
182 |
new_stock_max = stock_max + quantity |
|
183 |
|
|
184 |
imported_min = holding.imported_min |
|
185 |
if check and new_stock_max > imported_min: |
|
186 |
holder = holding.holder |
|
187 |
resource = holding.resource |
|
188 |
m = ("%s attempts to reclaim %s not originating by itself." % |
|
189 |
(holder, resource)) |
|
190 |
raise NonExportedError(m, |
|
191 |
holder=holder, |
|
192 |
resource=resource, |
|
193 |
requested=quantity, |
|
194 |
current=stock_max, |
|
195 |
limit=imported_min) |
|
196 |
|
|
197 |
holding.stock_max = new_stock_max |
|
198 |
holding.save() |
|
199 |
|
|
200 |
@classmethod |
|
201 |
def _finalize(cls, holding, quantity): |
|
202 |
holding.stock_min += quantity |
|
203 |
holding.save() |
|
204 |
|
|
205 |
|
|
206 |
class Operations(object): |
|
207 |
def __init__(self): |
|
208 |
self.operations = [] |
|
209 |
|
|
210 |
def prepare(self, operation, holding, quantity): |
|
211 |
operation.prepare(holding, quantity) |
|
212 |
self.operations.append((operation, holding, quantity)) |
|
213 |
|
|
214 |
def finalize(self, operation, holding, quantity): |
|
215 |
operation.finalize(holding, quantity) |
|
216 |
self.operations.append((operation, holding, quantity)) |
|
217 |
|
|
218 |
def undo(self, operation, holding, quantity): |
|
219 |
operation.undo(holding, quantity) |
|
220 |
self.operations.append((operation, holding, quantity)) |
|
221 |
|
|
222 |
def revert(self): |
|
223 |
for (operation, holding, quantity) in self.operations: |
|
224 |
operation.revert(holding, quantity) |
b/snf-astakos-app/astakos/quotaholder/exception.py | ||
---|---|---|
51 | 51 |
class CommissionValueException(CommissionException): |
52 | 52 |
def __init__(self, *args, **kwargs): |
53 | 53 |
|
54 |
self.source = kwargs['source']
|
|
55 |
self.target = kwargs['target']
|
|
56 |
self.resource = kwargs['resource']
|
|
57 |
self.requested = kwargs['requested']
|
|
58 |
self.current = kwargs['current']
|
|
59 |
self.limit = kwargs['limit']
|
|
54 |
self.holder = kwargs.pop('holder', None)
|
|
55 |
self.resource = kwargs.pop('resource', None)
|
|
56 |
self.requested = kwargs.pop('requested', None)
|
|
57 |
self.current = kwargs.pop('current', None)
|
|
58 |
self.limit = kwargs.pop('limit', None)
|
|
59 |
CommissionException.__init__(self, *args, **kwargs)
|
|
60 | 60 |
|
61 | 61 |
|
62 |
class NoQuantityError(CommissionValueException):
|
|
62 |
class NoStockError(CommissionValueException):
|
|
63 | 63 |
pass |
64 | 64 |
|
65 | 65 |
|
... | ... | |
67 | 67 |
pass |
68 | 68 |
|
69 | 69 |
|
70 |
class NonImportedError(CommissionValueException): |
|
71 |
pass |
|
72 |
|
|
73 |
|
|
74 |
class NoStockReleaseError(CommissionValueException): |
|
75 |
pass |
|
76 |
|
|
77 |
|
|
78 |
class NonExportedError(CommissionValueException): |
|
79 |
pass |
|
80 |
|
|
81 |
|
|
70 | 82 |
class DuplicateError(CommissionException): |
71 | 83 |
pass |
b/snf-astakos-app/astakos/quotaholder/models.py | ||
---|---|---|
42 | 42 |
class Policy(Model): |
43 | 43 |
|
44 | 44 |
policy = CharField(max_length=4096, primary_key=True) |
45 |
quantity = intDecimalField() |
|
46 | 45 |
capacity = intDecimalField() |
47 | 46 |
|
48 | 47 |
objects = ForUpdateManager() |
... | ... | |
55 | 54 |
policy = ForeignKey(Policy, to_field='policy') |
56 | 55 |
flags = BigIntegerField(null=False, default=0) |
57 | 56 |
|
58 |
imported = intDecimalField(default=0) |
|
59 |
importing = intDecimalField(default=0) |
|
60 |
exported = intDecimalField(default=0) |
|
61 |
exporting = intDecimalField(default=0) |
|
62 |
returned = intDecimalField(default=0) |
|
63 |
returning = intDecimalField(default=0) |
|
64 |
released = intDecimalField(default=0) |
|
65 |
releasing = intDecimalField(default=0) |
|
57 |
imported_min = intDecimalField(default=0) |
|
58 |
imported_max = intDecimalField(default=0) |
|
59 |
stock_min = intDecimalField(default=0) |
|
60 |
stock_max = intDecimalField(default=0) |
|
66 | 61 |
|
67 | 62 |
objects = ForUpdateManager() |
68 | 63 |
|
... | ... | |
107 | 102 |
issue_time = CharField(max_length=4096) |
108 | 103 |
log_time = CharField(max_length=4096) |
109 | 104 |
resource = CharField(max_length=4096) |
110 |
source_quantity = intDecimalField() |
|
111 | 105 |
source_capacity = intDecimalField() |
112 |
source_imported = intDecimalField() |
|
113 |
source_exported = intDecimalField() |
|
114 |
source_returned = intDecimalField() |
|
115 |
source_released = intDecimalField() |
|
116 |
target_quantity = intDecimalField() |
|
106 |
source_imported_min = intDecimalField() |
|
107 |
source_imported_max = intDecimalField() |
|
108 |
source_stock_min = intDecimalField() |
|
109 |
source_stock_max = intDecimalField() |
|
117 | 110 |
target_capacity = intDecimalField() |
118 |
target_imported = intDecimalField()
|
|
119 |
target_exported = intDecimalField()
|
|
120 |
target_returned = intDecimalField()
|
|
121 |
target_released = intDecimalField()
|
|
111 |
target_imported_min = intDecimalField()
|
|
112 |
target_imported_max = intDecimalField()
|
|
113 |
target_stock_min = intDecimalField()
|
|
114 |
target_stock_max = intDecimalField()
|
|
122 | 115 |
delta_quantity = intDecimalField() |
123 | 116 |
reason = CharField(max_length=4096) |
124 | 117 |
|
125 | 118 |
objects = ForUpdateManager() |
126 | 119 |
|
127 |
def source_allocated_through(self): |
|
128 |
return self.source_imported - self.source_released |
|
129 |
|
|
130 |
def source_allocated(self): |
|
131 |
return (+ self.source_allocated_through() |
|
132 |
- self.source_exported |
|
133 |
+ self.source_returned) |
|
134 |
|
|
135 |
def source_inbound_through(self): |
|
136 |
return self.source_imported |
|
137 |
|
|
138 |
def source_inbound(self): |
|
139 |
return self.source_inbound_through() + self.source_returned |
|
140 |
|
|
141 |
def source_outbound_through(self): |
|
142 |
return self.source_released |
|
143 |
|
|
144 |
def source_outbound(self): |
|
145 |
return self.source_outbound_through() + self.source_exported |
|
146 |
|
|
147 |
def target_allocated_through(self): |
|
148 |
return self.target_imported - self.target_released |
|
149 |
|
|
150 |
def target_allocated(self): |
|
151 |
return (+ self.target_allocated_through() |
|
152 |
- self.target_exported |
|
153 |
+ self.target_returned) |
|
154 |
|
|
155 |
def target_inbound_through(self): |
|
156 |
return self.target_imported |
|
157 |
|
|
158 |
def target_inbound(self): |
|
159 |
return self.target_inbound_through() + self.target_returned |
|
160 |
|
|
161 |
def target_outbound_through(self): |
|
162 |
return self.target_released |
|
163 |
|
|
164 |
def target_outbound(self): |
|
165 |
return self.target_outbound_through() + self.target_exported |
|
166 |
|
|
167 | 120 |
|
168 | 121 |
def _get(*args, **kwargs): |
169 | 122 |
model = args[0] |
b/snf-astakos-app/astakos/quotaholder/test/simpletests.py | ||
---|---|---|
38 | 38 |
from astakos.quotaholder.exception import ( |
39 | 39 |
QuotaholderError, |
40 | 40 |
InvalidDataError, |
41 |
NoQuantityError, NoCapacityError, |
|
41 |
NoCapacityError, |
|
42 |
NoStockError, |
|
43 |
NonExportedError, |
|
42 | 44 |
CommissionValueException, |
43 | 45 |
DuplicateError) |
44 | 46 |
|
... | ... | |
84 | 86 |
return self.rand_name(self.used_resources) |
85 | 87 |
|
86 | 88 |
def rand_limits(self): |
87 |
q = random_nat() |
|
88 | 89 |
c = random_nat() |
89 |
return q, c,
|
|
90 |
return (c,)
|
|
90 | 91 |
|
91 | 92 |
def rand_policy_limits(self): |
92 | 93 |
p = self.rand_policy() |
... | ... | |
180 | 181 |
resource1 = self.rand_resource() |
181 | 182 |
|
182 | 183 |
self.qh.set_quota( |
183 |
set_quota=[(e0, resource0) + (5, QH_PRACTICALLY_INFINITE) + (0,),
|
|
184 |
(e1, resource0) + (5, 5) + (0,)])
|
|
184 |
set_quota=[(e0, resource0) + (QH_PRACTICALLY_INFINITE, 0),
|
|
185 |
(e1, resource0) + (5, 0)])
|
|
185 | 186 |
|
186 | 187 |
self.qh.add_quota(sub_quota=[(e0, resource0, |
187 |
0, QH_PRACTICALLY_INFINITE)],
|
|
188 |
QH_PRACTICALLY_INFINITE)], |
|
188 | 189 |
add_quota=[(e0, resource0, |
189 |
0, 3),
|
|
190 |
3), |
|
190 | 191 |
# new holding |
191 | 192 |
(e0, resource1, |
192 |
0, QH_PRACTICALLY_INFINITE)])
|
|
193 |
QH_PRACTICALLY_INFINITE)]) |
|
193 | 194 |
|
194 | 195 |
r = self.qh.get_quota(get_quota=[(e0, resource0), |
195 | 196 |
(e0, resource1)]) |
196 |
self.assertEqual(r, [(e0, resource0, 5, 3)
|
|
197 |
self.assertEqual(r, [(e0, resource0, 3) |
|
197 | 198 |
+ DEFAULT_HOLDING + (0,), |
198 |
(e0, resource1, 0, QH_PRACTICALLY_INFINITE)
|
|
199 |
(e0, resource1, QH_PRACTICALLY_INFINITE) |
|
199 | 200 |
+ DEFAULT_HOLDING + (0,)]) |
200 | 201 |
|
201 | 202 |
with self.assertRaises(QuotaholderError) as cm: |
202 | 203 |
self.qh.add_quota(add_quota=[(e1, resource0, |
203 |
0, (-10)),
|
|
204 |
(e0, resource1, 1, 0)])
|
|
204 |
(-10)), |
|
205 |
(e0, resource1, 0)]) |
|
205 | 206 |
|
206 | 207 |
err = cm.exception |
207 | 208 |
self.assertEqual(err.message, [(e1, resource0)]) |
... | ... | |
222 | 223 |
|
223 | 224 |
self.qh.set_quota( |
224 | 225 |
set_quota=[(e0, resource0) + |
225 |
(5, QH_PRACTICALLY_INFINITE) + (0,)])
|
|
226 |
(QH_PRACTICALLY_INFINITE,) + (0,)])
|
|
226 | 227 |
|
227 | 228 |
self.qh.add_quota(add_quota=[(e0, resource0, |
228 |
0, QH_PRACTICALLY_INFINITE)])
|
|
229 |
QH_PRACTICALLY_INFINITE)]) |
|
229 | 230 |
|
230 | 231 |
r = self.qh.get_quota(get_quota=[(e0, resource0)]) |
231 |
self.assertEqual(r, [(e0, resource0, 5, 2*QH_PRACTICALLY_INFINITE)
|
|
232 |
self.assertEqual(r, [(e0, resource0, 2*QH_PRACTICALLY_INFINITE) |
|
232 | 233 |
+ DEFAULT_HOLDING + (0,)]) |
233 | 234 |
|
234 | 235 |
@transaction.commit_on_success |
... | ... | |
236 | 237 |
e0 = self.rand_holder() |
237 | 238 |
e1 = self.rand_holder() |
238 | 239 |
resource = self.rand_resource() |
239 |
q0, c0 = self.new_quota(e0, resource) |
|
240 |
q1, c1 = self.new_quota(e1, resource) |
|
241 |
|
|
242 |
most = min(c0, q1) |
|
243 |
if most < 0: |
|
244 |
raise AssertionError("%s <= 0" % most) |
|
240 |
c0, = self.new_quota(e0, resource) |
|
241 |
c1, = self.new_quota(e1, resource) |
|
245 | 242 |
|
246 | 243 |
@transaction.commit_on_success |
247 | 244 |
def f(): |
245 |
self.qh.reset_holding( |
|
246 |
reset_holding=[(e1, resource, c1, c1, c1, c1)]) |
|
247 |
|
|
248 |
most = min(c0, c1) |
|
249 |
if most < 0: |
|
250 |
raise AssertionError("%s <= 0" % most) |
|
251 |
|
|
248 | 252 |
return self.qh.issue_commission(clientkey=self.client, target=e0, |
249 | 253 |
name='something', |
250 | 254 |
provisions=[(e1, resource, most)]) |
251 | 255 |
|
252 | 256 |
r = f() |
257 |
|
|
253 | 258 |
self.assertEqual(r, 1) |
254 | 259 |
|
255 | 260 |
@transaction.commit_on_success |
... | ... | |
275 | 280 |
et1 = self.rand_holder() |
276 | 281 |
et2 = self.rand_holder() |
277 | 282 |
resource = self.rand_resource() |
278 |
self.new_quota(es1, resource, (10, 5))
|
|
279 |
self.new_quota(es2, resource, (10, 5))
|
|
280 |
self.new_quota(et1, resource, (0, 15))
|
|
281 |
self.new_quota(et2, resource, (0, 15))
|
|
283 |
self.new_quota(es1, resource, (10,)) |
|
284 |
self.new_quota(es2, resource, (10,)) |
|
285 |
self.new_quota(et1, resource, (15,))
|
|
286 |
self.new_quota(et2, resource, (15,))
|
|
282 | 287 |
|
283 |
with self.assertRaises(NoQuantityError) as cm: |
|
288 |
self.qh.reset_holding( |
|
289 |
reset_holding=[(es1, resource, 10, 10, 10, 10), |
|
290 |
(es2, resource, 10, 10, 10, 10)]) |
|
291 |
|
|
292 |
with self.assertRaises(NoStockError) as cm: |
|
284 | 293 |
self.qh.issue_commission(clientkey=self.client, target=et1, |
285 | 294 |
name='something', |
286 | 295 |
provisions=[(es1, resource, 12)]) |
287 | 296 |
e = cm.exception |
288 |
self.assertEqual(e.source, es1) |
|
289 |
self.assertEqual(e.target, et1) |
|
297 |
self.assertEqual(e.holder, es1) |
|
290 | 298 |
self.assertEqual(e.resource, resource) |
291 | 299 |
self.assertEqual(int(e.limit), 10) |
292 | 300 |
self.assertEqual(int(e.requested), 12) |
293 |
self.assertEqual(int(e.current), 0) |
|
294 | 301 |
|
295 | 302 |
r = self.qh.issue_commission(clientkey=self.client, target=et1, |
296 | 303 |
name='something', |
297 | 304 |
provisions=[(es1, resource, 2)]) |
298 | 305 |
self.assertGreater(r, 0) |
299 | 306 |
|
300 |
# with self.assertRaises(ImportLimitError) as cm: |
|
301 |
# self.qh.issue_commission(clientkey=self.client, target=et1, |
|
302 |
# name='something', |
|
303 |
# provisions=[(es1, resource, 2)]) |
|
304 |
# e = cm.exception |
|
305 |
# self.assertEqual(e.source, es1) |
|
306 |
# self.assertEqual(e.target, et1) |
|
307 |
# self.assertEqual(e.resource, resource) |
|
308 |
# self.assertEqual(int(e.limit), 3) |
|
309 |
# self.assertEqual(int(e.requested), 2) |
|
310 |
# self.assertEqual(int(e.current), 2) |
|
307 |
|
|
311 | 308 |
|
312 | 309 |
r = self.qh.issue_commission(clientkey=self.client, target=et2, |
313 | 310 |
name='something', |
... | ... | |
320 | 317 |
provisions=[(es2, resource, 1), |
321 | 318 |
(es1, resource, 6)]) |
322 | 319 |
e = cm.exception |
323 |
self.assertEqual(e.source, es1) |
|
324 |
self.assertEqual(e.target, et2) |
|
320 |
self.assertEqual(e.holder, et2) |
|
325 | 321 |
self.assertEqual(e.resource, resource) |
326 | 322 |
self.assertEqual(int(e.limit), 15) |
327 | 323 |
self.assertEqual(int(e.requested), 6) |
... | ... | |
335 | 331 |
resource = 'list_holdings_resource' |
336 | 332 |
sys = 'system' |
337 | 333 |
|
338 |
self.qh.set_quota(set_quota=[(sys, resource, 10, 0, 0), |
|
339 |
(e0, resource, 0, 10, 0), |
|
340 |
(e1, resource, 0, 10, 0)]) |
|
334 |
self.qh.set_quota(set_quota=[(sys, resource, 10, 0), |
|
335 |
(e0, resource, 10, 0), |
|
336 |
(e1, resource, 10, 0)]) |
|
337 |
|
|
338 |
self.qh.reset_holding( |
|
339 |
reset_holding=[(sys, resource, 10, 10, 10, 10)]) |
|
341 | 340 |
|
342 | 341 |
s0 = self.qh.issue_commission(clientkey=self.client, target=e0, |
343 | 342 |
name='a commission', |
... | ... | |
347 | 346 |
name='a commission', |
348 | 347 |
provisions=[('system', resource, 4)]) |
349 | 348 |
|
349 |
holdings_list, rejected = self.qh.list_holdings( |
|
350 |
list_holdings=[e0, e1, e0+e1]) |
|
351 |
|
|
352 |
self.assertEqual(rejected, [e0+e1]) |
|
353 |
self.assertEqual(holdings_list, [[(e0, resource, 0, 3, 0, 0)], |
|
354 |
[(e1, resource, 0, 4, 0, 0)]]) |
|
355 |
|
|
350 | 356 |
self.qh.accept_commission(clientkey=self.client, serials=[s0, s1]) |
351 | 357 |
|
352 | 358 |
holdings_list, rejected = self.qh.list_holdings( |
353 | 359 |
list_holdings=[e0, e1, e0+e1]) |
354 | 360 |
|
355 | 361 |
self.assertEqual(rejected, [e0+e1]) |
356 |
self.assertEqual(holdings_list, [[(e0, resource, 3, 0, 0, 0)],
|
|
357 |
[(e1, resource, 4, 0, 0, 0)]])
|
|
362 |
self.assertEqual(holdings_list, [[(e0, resource, 3, 3, 3, 3)],
|
|
363 |
[(e1, resource, 4, 4, 4, 4)]])
|
|
358 | 364 |
|
359 | 365 |
|
360 | 366 |
@transaction.commit_on_success |
361 | 367 |
def test_0130_release_holding(self): |
362 | 368 |
e = self.rand_holder() |
363 | 369 |
resource = self.rand_resource() |
364 |
limits = self.new_quota(e, resource, (1, 2)) |
|
370 |
limits = self.new_quota(e, resource, (2,)) |
|
371 |
self.qh.reset_holding( |
|
372 |
reset_holding=[(e, resource, 1, 1, 1, 1)]) |
|
365 | 373 |
|
366 | 374 |
with self.assertRaises(QuotaholderError) as cm: |
367 | 375 |
self.qh.release_holding(release_holding=[(e, resource)]) |
... | ... | |
373 | 381 |
def test_0131_release_holding(self): |
374 | 382 |
e = self.rand_holder() |
375 | 383 |
resource = self.rand_resource() |
376 |
limits = self.new_quota(e, resource, (0, 2))
|
|
384 |
limits = self.new_quota(e, resource, (2,))
|
|
377 | 385 |
|
378 | 386 |
self.qh.release_holding(release_holding=[(e, resource)]) |
379 | 387 |
|
... | ... | |
382 | 390 |
resource = self.rand_resource() |
383 | 391 |
|
384 | 392 |
es = self.rand_holder() |
385 |
limits_s = self.new_quota(es, resource, (3, 3)) |
|
393 |
limits_s = self.new_quota(es, resource, (3,)) |
|
394 |
|
|
395 |
self.qh.reset_holding( |
|
396 |
reset_holding=[(es, resource, 3, 3, 3, 3)]) |
|
397 |
|
|
386 | 398 |
e = self.rand_holder() |
387 |
limits = self.new_quota(e, resource, (0, 2))
|
|
399 |
limits = self.new_quota(e, resource, (2,))
|
|
388 | 400 |
|
389 | 401 |
r = self.qh.issue_commission(clientkey=self.client, target=e, |
390 | 402 |
name='something', |
... | ... | |
427 | 439 |
resource = "resource" |
428 | 440 |
target = "test_015_release_nocapacity_target" |
429 | 441 |
flags = 0 |
430 |
source_limits = [source, 6, 0]
|
|
442 |
source_limits = [source, 6] |
|
431 | 443 |
source_holding = [source, resource, source, flags] |
432 |
target_limits = [target, 0, 5]
|
|
444 |
target_limits = [target, 5] |
|
433 | 445 |
target_holding = [target, resource, target, flags] |
434 | 446 |
|
435 | 447 |
failed = AssertionError("Quotaholder call failed") |
... | ... | |
438 | 450 |
if qh.set_holding(set_holding=[source_holding, target_holding]): |
439 | 451 |
raise failed |
440 | 452 |
|
453 |
self.qh.reset_holding( |
|
454 |
reset_holding=[(source, resource, 6, 6, 6, 6)]) |
|
455 |
|
|
441 | 456 |
serial = qh.issue_commission(clientkey=self.client, target=target, |
442 | 457 |
name="something", |
443 | 458 |
provisions=[(source, resource, 5)]) |
... | ... | |
445 | 460 |
|
446 | 461 |
holding = qh.get_holding(get_holding=[[source, resource]]) |
447 | 462 |
self.assertEqual(tuple(holding[0]), |
448 |
(source, resource, source, 0, 5, 0, 0, flags))
|
|
463 |
(source, resource, source, 6, 6, 1, 1, flags))
|
|
449 | 464 |
holding = qh.get_holding(get_holding=[[target, resource]]) |
450 | 465 |
self.assertEqual(tuple(holding[0]), |
451 |
(target, resource, target, 5, 0, 0, 0, flags))
|
|
466 |
(target, resource, target, 5, 5, 5, 5, flags))
|
|
452 | 467 |
|
453 |
if qh.reset_holding(reset_holding=[[target, resource, 10, 0, 0, 0]]): |
|
468 |
if qh.reset_holding( |
|
469 |
reset_holding=[[target, resource, 10, 10, 10, 10]]): |
|
454 | 470 |
raise failed |
455 | 471 |
|
456 | 472 |
with self.assertRaises(NoCapacityError): |
... | ... | |
458 | 474 |
name="something", |
459 | 475 |
provisions=[(source, resource, 1)]) |
460 | 476 |
|
461 |
with self.assertRaises(NoQuantityError):
|
|
477 |
with self.assertRaises(NonExportedError):
|
|
462 | 478 |
qh.issue_commission(clientkey=self.client, target=target, |
463 | 479 |
name="something", |
464 | 480 |
provisions=[(source, resource, -7)]) |
465 | 481 |
|
466 |
source_limits = [source, 6, 10] |
|
467 |
if qh.set_limits(set_limits=[source_limits]): |
|
468 |
raise failed |
|
469 |
|
|
470 | 482 |
serial = qh.issue_commission(clientkey=self.client, target=target, |
471 | 483 |
name="something", |
472 | 484 |
provisions=[(source, resource, -1)]) |
... | ... | |
474 | 486 |
|
475 | 487 |
holding = qh.get_holding(get_holding=[[source, resource]]) |
476 | 488 |
self.assertEqual(tuple(holding[0]), |
477 |
(source, resource, source, 0, 5, 1, 0, flags))
|
|
489 |
(source, resource, source, 6, 6, 2, 2, flags))
|
|
478 | 490 |
holding = qh.get_holding(get_holding=[[target, resource]]) |
479 | 491 |
self.assertEqual(tuple(holding[0]), |
480 |
(target, resource, target, 10, 0, 0, 1, flags))
|
|
492 |
(target, resource, target, 9, 9, 9, 9, flags))
|
|
481 | 493 |
|
482 |
with self.assertRaises(NoCapacityError):
|
|
494 |
with self.assertRaises(NonExportedError):
|
|
483 | 495 |
qh.issue_commission(clientkey=self.client, target=target, |
484 | 496 |
name="something", |
485 | 497 |
provisions=[(source, resource, -10)]) |
Also available in: Unified diff