Revision fac1de87 commissioning/servers/quotaholder/django_backend/models.py

b/commissioning/servers/quotaholder/django_backend/models.py
93 93
    quantity    =   BigIntegerField(null=False)
94 94

  
95 95

  
96

  
97
class QuotaholderDjangoDBCallpoint(Callpoint):
98

  
99
    http_exc_lookup = {
100
        CorruptedError:   550,
101
        InvalidDataError: 400,
102
        InvalidKeyError:  401,
103
        NoEntityError:    404,
104
        NoQuantityError:  413,
105
        NoCapacityError:  413,
106
    }
107

  
108
    def init_connection(self, connection):
109
        if connection is not None:
110
            raise ValueError("Cannot specify connection args with %s" %
111
                             type(self).__name__)
112
        pass
113

  
114
    def commit(self):
115
        transaction.commit()
116

  
117
    def rollback(self):
118
        transaction.rollback()
119

  
120
    def do_make_call(self, call_name, data):
121
        call_fn = getattr(self, call_name, None)
122
        if not call_fn:
123
            m = "cannot find call '%s'" % (call_name,)
124
            raise CorruptedError(m)
125

  
126
        return call_fn(**data)
127

  
128
    @classmethod
129
    def http_exception(cls, exc):
130
        if not isinstance(exc, CommissionException):
131
            raise exc
132

  
133
        body = str(exc.args)
134
        status = cls.http_exc_lookup.get(type(exc), 400)
135
        return status, body
136

  
137
    def create_entity(self, context={}, create_entity=()):
138
        rejected = []
139
        append = rejected.append
140

  
141
        for entity, owner, key, ownerkey in create_entity:
142
            try:
143
                owner = Entity.objects.get(entity=owner, key=ownerkey)
144
            except Entity.DoesNotExist:
145
                append(entity)
146

  
147
            Entity.objects.create(entity=entity, owner=owner, key=key)
148

  
149
        return rejected
150

  
151
    def list_entities(self, context={}, entity=None, key=None):
152
        try:
153
            e = Entity.objects.get(entity=entity, key=key)
154
        except Entity.DoesNotExist:
155
            m = "Entity '%s' does not exist" % (entity,)
156
            raise NoEntityError(m)
157

  
158
        children = e.entities.all()
159
        entities = [e.entity for e in children]
160
        return entities
161

  
162
    def get_entity(self, context={}, get_entity=()):
163
        entities = []
164
        append = entities.append
165

  
166
        for entity, key in get_entity:
167
            try:
168
                Entity.objects.get(entity=entity, key=key)
169
            except Entity.DoesNotExist:
170
                continue
171

  
172
            append((entity, key))
173

  
174
        return entities
175

  
176
    def get_limits(self, context={}, get_limits=()):
177
        limits = []
178
        append = limits.append
179

  
180
        for entity, resource, key in get_limits:
181
            try:
182
                h = Holding.objects.get(entity=entity, resource=resource)
183
            except Policy.DoesNotExist:
184
                continue
185

  
186
            if h.entity.key != key:
187
                continue
188
            p = h.policy
189
            append((h.entity, h.resource, p.quantity, p.capacity,
190
                    p.import_limit, p.export_limit, h.flags))
191

  
192
        return limits
193

  
194
    def set_limits(self, context={}, set_limits=()):
195

  
196
        for (   policy, quantity, capacity,
197
                import_limit, export_limit  ) in set_limits:
198

  
199
                #XXX: create or replace?
200
                Policy.objects.create(  policy=policy,
201
                                        quantity=quantity,
202
                                        capacity=capacity,
203
                                        import_limit=import_limit,
204
                                        export_limit=export_limit   )
205

  
206
        return ()
207

  
208
    def get_holding(self, context={}, get_holding=()):
209
        holdings = []
210
        append = holdings.append
211

  
212
        for entity, resource, key in get_holding:
213
            try:
214
                h = Holding.objects.get(entity=entity, resource=resource)
215
            except Holding.DoesNotExist:
216
                continue
217

  
218
            if h.entity.key != key:
219
                continue
220

  
221
            append((h.entity, h.resource, h.policy,
222
                    h.imported, h.exported, h.flags))
223

  
224
        return holdings
225

  
226
    def set_holding(self, context={}, set_holding=()):
227
        rejected = []
228
        append = rejected.append
229

  
230
        for entity, resource, key, policy, flags in set_holding:
231
            try:
232
                e = Entity.objects.get(entity=entity, key=key)
233
            except Entity.DoesNotExist:
234
                append((entity, resource, policy))
235
                continue
236

  
237
            if e.key != key:
238
                append((entity, resource, policy))
239
                continue
240

  
241
            try:
242
                p = Policy.objects.get(policy=policy)
243
            except Policy.DoesNotExist:
244
                append((entity, resource, policy))
245
                continue
246

  
247
            try:
248
                h = Holding.objects.get(entity=entity, resource=resource)
249
                h.policy = p
250
                h.flags = flags
251
                h.save()
252
            except Holding.DoesNotExist:
253
                h = Holding.objects.create( entity=entity, resource=resource,
254
                                            policy=policy, flags=flags      )
255

  
256
        return rejected
257

  
258
    def list_resources(self, context={}, entity=None, key=None):
259
        try:
260
            e = Entity.objects.get()
261
        except Entity.DoesNotExist:
262
            m = "No such entity '%s'" % (entity,)
263
            raise NoEntityError(m)
264

  
265
        if e.key != key:
266
            m = "Invalid key for entity '%s'" % (entity,)
267
            raise InvalidKeyError(m)
268

  
269
        holdings = e.holdings.filter(entity=entity)
270
        resources = [h.resource for h in holdings]
271
        return resources
272

  
273
    def get_quota(self, context={}, get_quota=()):
274
        quotas = []
275
        append = quotas.append
276

  
277
        for entity, resource, key in get_quota:
278
            try:
279
                h = Holding.objects.get(entity=entity, resource=resource)
280
            except Holding.DoesNotExist:
281
                continue
282

  
283
            if h.entity.key != key:
284
                continue
285

  
286
            p = h.policy
287

  
288
            append((h.entity.entity, h.resource, p.quantity, p.capacity,
289
                    p.import_limit, p.export_limit,
290
                    h.imported, h.exported, h.flags))
291

  
292
        return quotas
293

  
294
    def set_quota(self, context={}, set_quota=()):
295
        rejected = []
296
        append = rejected.append
297

  
298
        for (   entity, resource, key,
299
                quantity, capacity,
300
                import_limit, export_limit, flags  ) in set_quota:
301

  
302
                try:
303
                    h = Holding.objects.get(entity=entity, resource=resource)
304
                    if h.entity.key != key:
305
                        append((entity, resource))
306
                        continue
307
                except Holding.DoesNotExist:
308
                    append(entity, resource)
309

  
310
                p = h.policy
311
                policy = newname()
312
                newp = Policy.objects.create    (
313
                            policy=policy,
314
                            quantity=quantity,
315
                            capacity=capacity,
316
                            import_limit=import_limit,
317
                            export_limit=export_limit
318
                )
319

  
320
                h.policy = newp
321
                h.save()
322

  
323
                if p.holdings.count() == 0:
324
                    p.delete()
325

  
326
        return rejected
327

  
328
    def issue_commission(self,  context={}, clientkey=None,
329
                                target=None, key=None,
330
                                owner=None, ownerkey=None,
331
                                provisions=()               ):
332

  
333
        try:
334
            t = Entity.objects.get(entity=target)
335
        except Entity.DoesNotExist:
336
            create_entity = ((entity, owner, key, ownerkey),)
337
            rejected = self.create_entity(  context=context,
338
                                            create_entity=create_entity )
339
            if rejected:
340
                raise NoEntityError("No target entity '%s'" % (target,))
341

  
342
            t = Entity.objects.get(entity=target)
343
        else:
344
            if t.key != key:
345
                m = "Invalid key for target entity '%s'" % (target,)
346
                raise InvalidKeyError(m)
347

  
348
        commission = Commission.objects.create( entity=target,
349
                                                clientkey=clientkey )
350
        serial = commission.serial
351

  
352
        for entity, resource, quantity in provisions:
353
            try:
354
                h = Holding.objects.get(entity=entity, resource=resource)
355
            except Holding.DoesNotExist:
356
                m = ("There is not enough quantity "
357
                     "to allocate from in %s.%s" % (entity, resource))
358
                raise NoQuantityError(m)
359

  
360
            hp = h.policy
361

  
362
            if h.importing - h.exported + hp.quantity - quantity < 0:
363
                m = ("There is not enough quantity "
364
                     "to allocate from in %s.%s" % (entity, resource))
365
                raise NoQuantityError(m)
366

  
367
            try:
368
                th = Holding.objects.get(entity=target, resource=resource)
369
            except Holding.DoesNotExist:
370
                m = ("There is not enough capacity "
371
                     "to allocate into in %s.%s" % (target, resource))
372
                raise NoCapacityError(m)
373

  
374
            tp = th.policy
375

  
376
            if (    th.exported - th.importing - tp.quantity
377
                    + tp.capacity - quantity                ) < 0:
378

  
379
                    m = ("There is not enough capacity "
380
                         "to allocate into in %s.%s" % (target, resource))
381
                    raise NoCapacityError(m)
382

  
383
            Provision.objects.create(   serial=serial,
384
                                        entity=entity,
385
                                        resource=resource,
386
                                        quantity=quantity   )
387

  
388
            h.exporting += quantity
389
            th.importing += quantity
390

  
391
            h.save()
392
            th.save()
393

  
394
        return serial
395

  
396
    def accept_commission(self, context={}, clientkey=None, serial=None):
397
        try:
398
            c = Commission.objects.get(clientkey=clientkey, serial=serial)
399
        except Commission.DoesNotExist:
400
            return
401

  
402
        t = c.entity
403

  
404
        provisions = Provision.objects.filter(  clientkey=clientkey,
405
                                                serial=serial       )
406
        for pv in provisions:
407
            pv.entity,
408
            pv.resource
409
            try:
410
                h = Holding.objects.get(entity=pv.entity.entity,
411
                                        resource=pv.resource    )
412
                th = Holding.objects.get(entity=t, resource=pv.resource)
413
            except Holding.DoesNotExist:
414
                m = "Corrupted provision"
415
                raise CorruptedError(m)
416

  
417
            h.exported += pv.quantity
418
            th.imported += pv.quantity
419
            h.save()
420
            th.save()
421
            pv.delete()
422

  
423
        return
424

  
425
    def reject_commission(self, context={}, clientkey=None, serial=None):
426
        try:
427
            c = Commission.objects.get(clientkey=clientkey, serial=serial)
428
        except Commission.DoesNotExist:
429
            return
430

  
431
        t = c.entity
432

  
433
        provisions = Provision.objects.filter(  clientkey=clientkey,
434
                                                serial=serial       )
435
        for pv in provisions:
436
            pv.entity,
437
            pv.resource
438
            try:
439
                h = Holding.objects.get(entity=pv.entity.entity,
440
                                        resource=pv.resource    )
441
                th = Holding.objects.get(entity=t, resource=pv.resource)
442
            except Holding.DoesNotExist:
443
                m = "Corrupted provision"
444
                raise CorruptedError(m)
445

  
446
            h.exporting -= pv.quantity
447
            th.importing -= pv.quantity
448
            h.save()
449
            th.save()
450
            pv.delete()
451

  
452
        return
453

  
454
    def get_pending_commissions(self, context={}, clientkey=None):
455
        pending = Commission.objects.filter(clientkey=clientkey)
456
        return pending
457

  
458
    def resolve_pending_commissions(self,   context={}, clientkey=None,
459
                                            max_serial=None, accept_set=()  ):
460
        accept_set = set(accept_set)
461
        pending = self.get_pending_commissions(clientkey=clientkey)
462
        pending = sorted(pending)
463

  
464
        accept = self.accept_commission
465
        reject = self.reject_commission
466

  
467
        for serial in pending:
468
            if serial > max_serial:
469
                break
470

  
471
            if serial in accept_set:
472
                accept(clientkey=clientkey, serial=serial)
473
            else:
474
                reject(clientkey=clientkey, serial=serial)
475

  
476
        return
477

  
478
    def release_entity(self, context={}, release_entity=()):
479
        rejected = []
480
        append = rejected.append
481
        for entity, key in release_entity:
482
            try:
483
                e = Entity.objects.get(entity=entity, key=key)
484
            except Entity.DoesNotExist:
485
                append(entity)
486
                continue
487

  
488
            if e.entities.count() != 0:
489
                append(entity)
490
                continue
491

  
492
            if e.holdings.count() != 0:
493
                append(entity)
494
                continue
495

  
496
            e.delete()
497

  
498
        return rejected
499

  

Also available in: Unified diff