1 # -*- coding: utf-8 -*-
3 # Copyright 2012 GRNET S.A. All rights reserved.
5 # Redistribution and use in source and binary forms, with or
6 # without modification, are permitted provided that the following
9 # 1. Redistributions of source code must retain the above
10 # copyright notice, this list of conditions and the following
13 # 2. Redistributions in binary form must reproduce the above
14 # copyright notice, this list of conditions and the following
15 # disclaimer in the documentation and/or other materials
16 # provided with the distribution.
18 # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
19 # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
22 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25 # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 # POSSIBILITY OF SUCH DAMAGE.
31 # The views and conclusions contained in the software and
32 # documentation are those of the authors and should not be
33 # interpreted as representing official policies, either expressed
34 # or implied, of GRNET S.A.
37 from kamaki.clients.commissioning import (
48 from random import choice, randint
50 Context = Dict(classname='Context', null=True, show=False)
55 self.opts.update({'regex': "[\w.:@+/-]+", 'maxlen': 512})
58 def _random_choice(self, kw):
59 alphabet = u'abcdef_1233490.:@/-αβγδεζ'
60 length = randint(1, 48)
61 return ''.join(choice(alphabet) for _ in xrange(length))
64 class Nonnegative(Integer):
66 self.opts.update({'minimum': 0})
69 class Positive(Integer):
71 self.opts.update({'minimum': 1})
74 QH_PRACTICALLY_INFINITE = 10 ** 32
76 Serial = Positive(classname='Serial')
78 ClientKey = Name(classname='ClientKey')
79 Nothing = Null(classname='Nothing')
81 Entity = Name(classname='Entity')
82 Owner = Name(classname='Owner')
83 Key = Text(classname='Key')
84 NewKey = Text(classname='Newkey')
85 OwnerKey = Text(classname='OwnerKey')
86 Resource = Name(classname='Resource')
87 Policy = Name(classname='Policy')
89 Quantity = Integer(classname='Quantity')
90 Capacity = Nonnegative(classname='Capacity')
91 ImportLimit = Nonnegative(classname='ImportLimit')
92 ExportLimit = Nonnegative(classname='ExportLimit')
93 QuantityDelta = Integer(classname='QuantityDelta')
94 CapacityDelta = Integer(classname='CapacityDelta')
95 ImportLimitDelta = Integer(classname='ImportLimitDelta')
96 ExportLimitDelta = Integer(classname='ExportLimitDelta')
97 Imported = Nonnegative(classname='Imported')
98 Exported = Nonnegative(classname='Exported')
99 Returned = Nonnegative(classname='Returned')
100 Released = Nonnegative(classname='Released')
101 Flags = Nonnegative(classname='Flags')
102 Index = Nonnegative(classname='Index')
104 Timepoint = Text(classname='Timepoint', maxlen=24)
105 Reason = Text(classname='Reason', regex='(ACCEPT|REJECT):.*', maxlen=128)
108 class QuotaholderAPI(Specificator):
110 def create_entity(self, context=Context, create_entity=ListOf(
111 Entity, Owner, Key, OwnerKey, nonempty=1)):
112 rejected = ListOf(Index)
118 set_entity_key=ListOf(Entity, Key, NewKey)
120 rejected = ListOf(Entity)
129 entities = ListOf(Entity)
135 get_entity=ListOf(Entity, Key, nonempty=1)
137 entities = ListOf(Entity, Owner)
143 get_limits=ListOf(Policy, nonempty=1)
145 limits = ListOf(Policy, Quantity, Capacity,
146 ImportLimit, ExportLimit)
160 rejected = ListOf(Policy)
166 get_holding=ListOf(Entity, Resource, Key)
182 set_holding=ListOf(Entity, Resource, Key, Policy, Flags)
184 rejected = ListOf(Entity, Resource, Policy)
201 rejected = ListOf(Index)
207 reset_holding=ListOf(
216 rejected = ListOf(Index)
222 release_holding=ListOf(Entity, Resource, Key)
224 rejected = ListOf(Index)
227 def list_resources(self, context=Context, entity=Entity, key=Key):
228 resources = ListOf(Resource)
234 list_holdings=ListOf(Entity, Key)
236 rejected = ListOf(Entity)
237 holdings_list = ListOf(ListOf(Entity, Resource,
240 return Tuple(holdings_list, rejected)
245 get_quota=ListOf(Entity, Resource, Key)
247 quotas = ListOf(Entity, Resource,
249 ImportLimit, ExportLimit,
268 rejected = ListOf(Entity, Resource)
293 rejected = ListOf(Entity, Resource)
300 serials=ListOf(Serial)
302 return ListOf(Serial)
308 serials=ListOf(Serial)
312 def issue_commission(
318 name=Text(default=''),
319 provisions=ListOf(Entity, Resource, Quantity)
323 def accept_commission(
327 serials=ListOf(Serial),
328 reason=Text(default='ACCEPT')
332 def reject_commission(
336 serials=ListOf(Serial),
337 reason=Text(default='REJECT')
341 def get_pending_commissions(
346 pending = ListOf(Serial)
349 def resolve_pending_commissions(
354 accept_set=ListOf(Serial)
361 release_entity=ListOf(Entity, Key, nonempty=1)
363 rejected = ListOf(Entity)
371 get_timeline=ListOf(Entity, Resource, Key)
373 timeline = ListOf(Dict(
380 source_allocated=Quantity,
381 source_allocated_through=Quantity,
382 source_inbound=Quantity,
383 source_inbound_through=Quantity,
384 source_outbound=Quantity,
385 source_outbound_through=Quantity,
386 target_allocated=Quantity,
387 target_allocated_through=Quantity,
388 target_inbound=Quantity,
389 target_inbound_through=Quantity,
390 target_outbound=Quantity,
391 target_outbound_through=Quantity,
392 issue_time=Timepoint,