Revision f590f930
b/commissioning/api/quotaholder.py | ||
---|---|---|
29 | 29 |
Resource = Name(classname='Resource') |
30 | 30 |
Policy = Name(classname='Policy') |
31 | 31 |
|
32 |
Quantity = Nonnegative(classname='Quantity')
|
|
32 |
Quantity = Integer(classname='Quantity')
|
|
33 | 33 |
Capacity = Nonnegative(classname='Capacity') |
34 | 34 |
ImportLimit = Nonnegative(classname='ImportLimit') |
35 | 35 |
ExportLimit = Nonnegative(classname='ExportLimit') |
36 | 36 |
Imported = Nonnegative(classname='Imported') |
37 | 37 |
Exported = Nonnegative(classname='Exported') |
38 |
Regained = Nonnegative(classname='Regained') |
|
39 |
Released = Nonnegative(classname='Released') |
|
38 | 40 |
Flags = Nonnegative(classname='Flags') |
39 | 41 |
|
42 |
Timepoint = Text(classname='Timepoint', maxlen=24) |
|
43 |
Reason = Text( classname = 'Reason', |
|
44 |
regex = '(ACCEPT|REJECT):.*', |
|
45 |
maxlen = 128 ) |
|
40 | 46 |
|
41 | 47 |
class QuotaholderAPI(Specificator): |
42 | 48 |
|
... | ... | |
97 | 103 |
): |
98 | 104 |
|
99 | 105 |
holdings = ListOf( Entity, Resource, Policy, |
100 |
Imported, Exported, Flags )
|
|
106 |
Imported, Exported, Regained, Released, Flags )
|
|
101 | 107 |
return holdings |
102 | 108 |
|
103 | 109 |
def set_holding ( |
... | ... | |
129 | 135 |
Quantity, Capacity, |
130 | 136 |
ImportLimit, ExportLimit, |
131 | 137 |
Imported, Exported, |
138 |
Regained, Released, |
|
132 | 139 |
Flags) |
133 | 140 |
return quotas |
134 | 141 |
|
... | ... | |
202 | 209 |
rejected = ListOf(Entity) |
203 | 210 |
return rejected |
204 | 211 |
|
212 |
def get_timeline ( |
|
213 |
self, |
|
214 |
context = Context, |
|
215 |
after = Timepoint, |
|
216 |
before = Timepoint, |
|
217 |
entities = ListOf(Entity, Key) |
|
218 |
): |
|
219 |
|
|
220 |
timeline = ListOf( Dict( serial = Serial, |
|
221 |
source = Entity, |
|
222 |
target = Entity, |
|
223 |
resource = Resource, |
|
224 |
quantity = Quantity, |
|
225 |
issue_time = Timepoint, |
|
226 |
log_time = Timepoint, |
|
227 |
reason = Reason ) ) |
|
228 |
return timeline |
|
229 |
|
b/commissioning/servers/quotaholder/django_backend/callpoint.py | ||
---|---|---|
8 | 8 |
|
9 | 9 |
|
10 | 10 |
from commissioning.utils.newname import newname |
11 |
from django.db.models import Model, BigIntegerField, CharField, ForeignKey |
|
11 |
from django.db.models import Model, BigIntegerField, CharField, ForeignKey, Q
|
|
12 | 12 |
from django.db import transaction, IntegrityError |
13 |
from .models import Holder, Entity, Policy, Holding, Commission, Provision |
|
13 |
from .models import (Holder, Entity, Policy, Holding, |
|
14 |
Commission, Provision, ProvisionLog) |
|
14 | 15 |
|
15 | 16 |
|
16 | 17 |
class QuotaholderDjangoDBCallpoint(Callpoint): |
... | ... | |
272 | 273 |
|
273 | 274 |
return rejected |
274 | 275 |
|
275 |
def issue_commission(self, context={}, clientkey=None, |
|
276 |
target=None, key=None, |
|
277 |
owner=None, ownerkey=None, |
|
278 |
provisions=() ): |
|
276 |
def issue_commission(self, context = {}, |
|
277 |
clientkey = None, |
|
278 |
target = None, |
|
279 |
key = None, |
|
280 |
owner = None, |
|
281 |
ownerkey = None, |
|
282 |
provisions = () ): |
|
279 | 283 |
|
280 | 284 |
try: |
281 | 285 |
t = Entity.objects.get(entity=target) |
... | ... | |
295 | 299 |
commission = Commission.objects.create( entity=target, |
296 | 300 |
clientkey=clientkey ) |
297 | 301 |
serial = commission.serial |
302 |
release = 0 |
|
303 |
if quantity < 0: |
|
304 |
release = 1 |
|
298 | 305 |
|
299 | 306 |
for entity, resource, quantity in provisions: |
300 | 307 |
try: |
... | ... | |
311 | 318 |
m = ("Export limit reached for %s.%s" % (entity, resource)) |
312 | 319 |
raise ExportLimitError(m) |
313 | 320 |
|
314 |
if h.importing - h.exported + hp.quantity - quantity < 0: |
|
321 |
available = (+ hp.quantity + h.imported + h.regained |
|
322 |
- h.exporting - h.releasing) |
|
323 |
|
|
324 |
if available - quantity < 0: |
|
315 | 325 |
m = ("There is not enough quantity " |
316 | 326 |
"to allocate from in %s.%s" % (entity, resource)) |
317 | 327 |
raise NoQuantityError(m) |
... | ... | |
330 | 340 |
m = ("Import limit reached for %s.%s" % (target, resource)) |
331 | 341 |
raise ImportLimitError(m) |
332 | 342 |
|
333 |
if ( th.exported - th.importing - tp.quantity
|
|
334 |
+ tp.capacity - quantity ) < 0:
|
|
343 |
capacity = (+ tp.capacity + th.exported + th.released
|
|
344 |
- th.importing - th.regaining)
|
|
335 | 345 |
|
346 |
if capacity - quantity < 0: |
|
336 | 347 |
m = ("There is not enough capacity " |
337 | 348 |
"to allocate into in %s.%s" % (target, resource)) |
338 | 349 |
raise NoCapacityError(m) |
... | ... | |
342 | 353 |
resource=resource, |
343 | 354 |
quantity=quantity ) |
344 | 355 |
|
345 |
h.exporting += quantity |
|
346 |
th.importing += quantity |
|
356 |
if release: |
|
357 |
h.regaining -= quantity |
|
358 |
th.releasing -= quantity |
|
359 |
else: |
|
360 |
h.exporting += quantity |
|
361 |
th.importing += quantity |
|
347 | 362 |
|
348 | 363 |
h.save() |
349 | 364 |
th.save() |
350 | 365 |
|
351 | 366 |
return serial |
352 | 367 |
|
353 |
def accept_commission(self, context={}, clientkey=None, serial=None): |
|
368 |
def accept_commission(self, context={}, clientkey=None, |
|
369 |
serial=None, reason=''): |
|
354 | 370 |
try: |
355 | 371 |
c = Commission.objects.get(clientkey=clientkey, serial=serial) |
356 | 372 |
except Commission.DoesNotExist: |
357 | 373 |
return |
358 | 374 |
|
359 | 375 |
t = c.entity |
376 |
log_time = now() |
|
360 | 377 |
|
361 | 378 |
provisions = Provision.objects.filter( clientkey=clientkey, |
362 | 379 |
serial=serial ) |
363 | 380 |
for pv in provisions: |
364 |
pv.entity, |
|
365 |
pv.resource |
|
366 | 381 |
try: |
367 | 382 |
h = Holding.objects.get(entity=pv.entity.entity, |
368 | 383 |
resource=pv.resource ) |
... | ... | |
371 | 386 |
m = "Corrupted provision" |
372 | 387 |
raise CorruptedError(m) |
373 | 388 |
|
374 |
h.exported += pv.quantity |
|
375 |
th.imported += pv.quantity |
|
389 |
quantity = pv.quantity |
|
390 |
release = 0 |
|
391 |
if quantity < 0: |
|
392 |
release = 1 |
|
393 |
|
|
394 |
if release: |
|
395 |
h.regained -= quantity |
|
396 |
th.released -= quantity |
|
397 |
else: |
|
398 |
h.exported += quantity |
|
399 |
th.imported += quantity |
|
400 |
|
|
401 |
reason = 'ACCEPT:' + reason[:121] |
|
402 |
ProvisionLog.objects.create(serial = serial, |
|
403 |
source = pv.entity.entity, |
|
404 |
target = t, |
|
405 |
resource = pv.resource, |
|
406 |
quantity = quantity, |
|
407 |
issue_time = pv.issue_time, |
|
408 |
log_time = log_Time, |
|
409 |
reason = reason) |
|
376 | 410 |
h.save() |
377 | 411 |
th.save() |
378 | 412 |
pv.delete() |
379 | 413 |
|
380 | 414 |
return |
381 | 415 |
|
382 |
def reject_commission(self, context={}, clientkey=None, serial=None): |
|
416 |
def reject_commission(self, context={}, clientkey=None, |
|
417 |
serial=None, reason=''): |
|
383 | 418 |
try: |
384 | 419 |
c = Commission.objects.get(clientkey=clientkey, serial=serial) |
385 | 420 |
except Commission.DoesNotExist: |
... | ... | |
390 | 425 |
provisions = Provision.objects.filter( clientkey=clientkey, |
391 | 426 |
serial=serial ) |
392 | 427 |
for pv in provisions: |
393 |
pv.entity, |
|
394 |
pv.resource |
|
395 | 428 |
try: |
396 | 429 |
h = Holding.objects.get(entity=pv.entity.entity, |
397 | 430 |
resource=pv.resource ) |
... | ... | |
400 | 433 |
m = "Corrupted provision" |
401 | 434 |
raise CorruptedError(m) |
402 | 435 |
|
403 |
h.exporting -= pv.quantity |
|
404 |
th.importing -= pv.quantity |
|
436 |
quantity = pv.quantity |
|
437 |
release = 0 |
|
438 |
if quantity < 0: |
|
439 |
release = 1 |
|
440 |
|
|
441 |
if release: |
|
442 |
h.regaining += quantity |
|
443 |
th.releasing += quantity |
|
444 |
else: |
|
445 |
h.exporting -= quantity |
|
446 |
th.importing -= quantity |
|
447 |
|
|
448 |
reason = 'ACCEPT:' + reason[:121] |
|
449 |
ProvisionLog.objects.create(serial = serial, |
|
450 |
source = pv.entity.entity, |
|
451 |
target = t, |
|
452 |
resource = pv.resource, |
|
453 |
quantity = quantity, |
|
454 |
issue_time = pv.issue_time, |
|
455 |
log_time = log_Time, |
|
456 |
reason = reason) |
|
405 | 457 |
h.save() |
406 | 458 |
th.save() |
407 | 459 |
pv.delete() |
... | ... | |
454 | 506 |
|
455 | 507 |
return rejected |
456 | 508 |
|
509 |
def get_timeline(self, context={}, after="", before="Z", entities=()): |
|
510 |
entity_set = set() |
|
511 |
add = entity_set.add |
|
512 |
|
|
513 |
for entity, key in entities: |
|
514 |
try: |
|
515 |
e = Entity.objects.get(entity=entity, key=key) |
|
516 |
add(entity) |
|
517 |
except Entity.DoesNotExist: |
|
518 |
continue |
|
519 |
|
|
520 |
chunk_size = 65536 |
|
521 |
nr = 0 |
|
522 |
timeline = [] |
|
523 |
extend = timeline.extend |
|
524 |
while 1: |
|
525 |
filterlogs = ProvisionLog.objects.filter |
|
526 |
q_entity = Q(source__in = entity_set) | Q(target__in = entity_set) |
|
527 |
logs = filterlogs( issue_time__gt = after, |
|
528 |
issue_time__lte = before, |
|
529 |
reason__startswith = 'ACCEPT:', |
|
530 |
q_entity ) |
|
531 |
|
|
532 |
logs = logs.order_by('issue_time') |
|
533 |
logs = logs.values() |
|
534 |
logs = logs[:chunk_size] |
|
535 |
nr += len(logs) |
|
536 |
if not logs: |
|
537 |
break |
|
538 |
extend(logs) |
|
539 |
after = logs[-1]['issue_time'] |
|
540 |
if after >= before: |
|
541 |
break |
|
542 |
|
|
543 |
return timeline |
|
544 |
|
|
545 |
|
|
457 | 546 |
API_Callpoint = QuotaholderDjangoDBCallpoint |
547 |
|
b/commissioning/servers/quotaholder/django_backend/models.py | ||
---|---|---|
63 | 63 |
importing = BigIntegerField(null=False, default=0) |
64 | 64 |
exported = BigIntegerField(null=False, default=0) |
65 | 65 |
exporting = BigIntegerField(null=False, default=0) |
66 |
regained = BigIntegerField(null=False, default=0) |
|
67 |
regaining = BigIntegerField(null=False, default=0) |
|
68 |
released = BigIntegerField(null=False, default=0) |
|
69 |
releasing = BigIntegerField(null=False, default=0) |
|
66 | 70 |
|
67 | 71 |
class Meta: |
68 | 72 |
unique_together = (('entity', 'resource'),) |
... | ... | |
71 | 75 |
from datetime import datetime |
72 | 76 |
|
73 | 77 |
def now(): |
74 |
return datetime.now().strftime('%Y-%m-%dT:%H:%M:%S.%f')[:24]
|
|
78 |
return datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%fZ')[:24]
|
|
75 | 79 |
|
76 | 80 |
|
77 | 81 |
class Commission(Model): |
... | ... | |
93 | 97 |
quantity = BigIntegerField(null=False) |
94 | 98 |
|
95 | 99 |
|
100 |
class ProvisionLog(Model): |
|
101 |
|
|
102 |
serial = BigIntegerField(primary_key=True) |
|
103 |
source = CharField(max_length=72) |
|
104 |
target = CharField(max_length=72) |
|
105 |
issue_time = CharField(max_length=24) |
|
106 |
log_time = CharField(max_length=24) |
|
107 |
resource = CharField(max_length=72) |
|
108 |
quantity = BigIntegerField() |
|
109 |
reason = CharField(max_length=8) |
|
110 |
|
Also available in: Unified diff