Revision fac1de87

b/commissioning/servers/quotaholder/django_backend/callpoint.py
1

  
2
from commissioning import ( QuotaholderAPI,
3
                            Callpoint, CommissionException,
4
                            CorruptedError, InvalidDataError,
5
                            InvalidKeyError, NoEntityError,
6
                            NoQuantityError, NoCapacityError    )
7

  
8

  
9
from django.db.models import Model, BigIntegerField, CharField, ForeignKey
10
from django.db import transaction
11
from .models import Holder, Entity, Policy, Holding, Commission, Provision
12

  
13

  
14
class QuotaholderDjangoDBCallpoint(Callpoint):
15

  
16
    api_spec = QuotaholderAPI()
17

  
18
    http_exc_lookup = {
19
        CorruptedError:   550,
20
        InvalidDataError: 400,
21
        InvalidKeyError:  401,
22
        NoEntityError:    404,
23
        NoQuantityError:  413,
24
        NoCapacityError:  413,
25
    }
26

  
27
    def init_connection(self, connection):
28
        if connection is not None:
29
            raise ValueError("Cannot specify connection args with %s" %
30
                             type(self).__name__)
31
        pass
32

  
33
    def commit(self):
34
        transaction.commit()
35

  
36
    def rollback(self):
37
        transaction.rollback()
38

  
39
    def do_make_call(self, call_name, data):
40
        call_fn = getattr(self, call_name, None)
41
        if not call_fn:
42
            m = "cannot find call '%s'" % (call_name,)
43
            raise CorruptedError(m)
44

  
45
        return call_fn(**data)
46

  
47
    @classmethod
48
    def http_exception(cls, exc):
49
        if not isinstance(exc, CommissionException):
50
            raise exc
51

  
52
        body = str(exc.args)
53
        status = cls.http_exc_lookup.get(type(exc), 400)
54
        return status, body
55

  
56
    def create_entity(self, context={}, create_entity=()):
57
        rejected = []
58
        append = rejected.append
59

  
60
        for entity, owner, key, ownerkey in create_entity:
61
            try:
62
                owner = Entity.objects.get(entity=owner, key=ownerkey)
63
            except Entity.DoesNotExist:
64
                append(entity)
65

  
66
            Entity.objects.create(entity=entity, owner=owner, key=key)
67

  
68
        return rejected
69

  
70
    def list_entities(self, context={}, entity=None, key=None):
71
        try:
72
            e = Entity.objects.get(entity=entity, key=key)
73
        except Entity.DoesNotExist:
74
            m = "Entity '%s' does not exist" % (entity,)
75
            raise NoEntityError(m)
76

  
77
        children = e.entities.all()
78
        entities = [e.entity for e in children]
79
        return entities
80

  
81
    def get_entity(self, context={}, get_entity=()):
82
        entities = []
83
        append = entities.append
84

  
85
        for entity, key in get_entity:
86
            try:
87
                Entity.objects.get(entity=entity, key=key)
88
            except Entity.DoesNotExist:
89
                continue
90

  
91
            append((entity, key))
92

  
93
        return entities
94

  
95
    def get_limits(self, context={}, get_limits=()):
96
        limits = []
97
        append = limits.append
98

  
99
        for entity, resource, key in get_limits:
100
            try:
101
                h = Holding.objects.get(entity=entity, resource=resource)
102
            except Policy.DoesNotExist:
103
                continue
104

  
105
            if h.entity.key != key:
106
                continue
107
            p = h.policy
108
            append((h.entity, h.resource, p.quantity, p.capacity,
109
                    p.import_limit, p.export_limit, h.flags))
110

  
111
        return limits
112

  
113
    def set_limits(self, context={}, set_limits=()):
114

  
115
        for (   policy, quantity, capacity,
116
                import_limit, export_limit  ) in set_limits:
117

  
118
                #XXX: create or replace?
119
                Policy.objects.create(  policy=policy,
120
                                        quantity=quantity,
121
                                        capacity=capacity,
122
                                        import_limit=import_limit,
123
                                        export_limit=export_limit   )
124

  
125
        return ()
126

  
127
    def get_holding(self, context={}, get_holding=()):
128
        holdings = []
129
        append = holdings.append
130

  
131
        for entity, resource, key in get_holding:
132
            try:
133
                h = Holding.objects.get(entity=entity, resource=resource)
134
            except Holding.DoesNotExist:
135
                continue
136

  
137
            if h.entity.key != key:
138
                continue
139

  
140
            append((h.entity, h.resource, h.policy,
141
                    h.imported, h.exported, h.flags))
142

  
143
        return holdings
144

  
145
    def set_holding(self, context={}, set_holding=()):
146
        rejected = []
147
        append = rejected.append
148

  
149
        for entity, resource, key, policy, flags in set_holding:
150
            try:
151
                e = Entity.objects.get(entity=entity, key=key)
152
            except Entity.DoesNotExist:
153
                append((entity, resource, policy))
154
                continue
155

  
156
            if e.key != key:
157
                append((entity, resource, policy))
158
                continue
159

  
160
            try:
161
                p = Policy.objects.get(policy=policy)
162
            except Policy.DoesNotExist:
163
                append((entity, resource, policy))
164
                continue
165

  
166
            try:
167
                h = Holding.objects.get(entity=entity, resource=resource)
168
                h.policy = p
169
                h.flags = flags
170
                h.save()
171
            except Holding.DoesNotExist:
172
                h = Holding.objects.create( entity=entity, resource=resource,
173
                                            policy=policy, flags=flags      )
174

  
175
        return rejected
176

  
177
    def list_resources(self, context={}, entity=None, key=None):
178
        try:
179
            e = Entity.objects.get()
180
        except Entity.DoesNotExist:
181
            m = "No such entity '%s'" % (entity,)
182
            raise NoEntityError(m)
183

  
184
        if e.key != key:
185
            m = "Invalid key for entity '%s'" % (entity,)
186
            raise InvalidKeyError(m)
187

  
188
        holdings = e.holdings.filter(entity=entity)
189
        resources = [h.resource for h in holdings]
190
        return resources
191

  
192
    def get_quota(self, context={}, get_quota=()):
193
        quotas = []
194
        append = quotas.append
195

  
196
        for entity, resource, key in get_quota:
197
            try:
198
                h = Holding.objects.get(entity=entity, resource=resource)
199
            except Holding.DoesNotExist:
200
                continue
201

  
202
            if h.entity.key != key:
203
                continue
204

  
205
            p = h.policy
206

  
207
            append((h.entity.entity, h.resource, p.quantity, p.capacity,
208
                    p.import_limit, p.export_limit,
209
                    h.imported, h.exported, h.flags))
210

  
211
        return quotas
212

  
213
    def set_quota(self, context={}, set_quota=()):
214
        rejected = []
215
        append = rejected.append
216

  
217
        for (   entity, resource, key,
218
                quantity, capacity,
219
                import_limit, export_limit, flags  ) in set_quota:
220

  
221
                try:
222
                    h = Holding.objects.get(entity=entity, resource=resource)
223
                    if h.entity.key != key:
224
                        append((entity, resource))
225
                        continue
226
                except Holding.DoesNotExist:
227
                    append(entity, resource)
228

  
229
                p = h.policy
230
                policy = newname()
231
                newp = Policy.objects.create    (
232
                            policy=policy,
233
                            quantity=quantity,
234
                            capacity=capacity,
235
                            import_limit=import_limit,
236
                            export_limit=export_limit
237
                )
238

  
239
                h.policy = newp
240
                h.save()
241

  
242
                if p.holdings.count() == 0:
243
                    p.delete()
244

  
245
        return rejected
246

  
247
    def issue_commission(self,  context={}, clientkey=None,
248
                                target=None, key=None,
249
                                owner=None, ownerkey=None,
250
                                provisions=()               ):
251

  
252
        try:
253
            t = Entity.objects.get(entity=target)
254
        except Entity.DoesNotExist:
255
            create_entity = ((entity, owner, key, ownerkey),)
256
            rejected = self.create_entity(  context=context,
257
                                            create_entity=create_entity )
258
            if rejected:
259
                raise NoEntityError("No target entity '%s'" % (target,))
260

  
261
            t = Entity.objects.get(entity=target)
262
        else:
263
            if t.key != key:
264
                m = "Invalid key for target entity '%s'" % (target,)
265
                raise InvalidKeyError(m)
266

  
267
        commission = Commission.objects.create( entity=target,
268
                                                clientkey=clientkey )
269
        serial = commission.serial
270

  
271
        for entity, resource, quantity in provisions:
272
            try:
273
                h = Holding.objects.get(entity=entity, resource=resource)
274
            except Holding.DoesNotExist:
275
                m = ("There is not enough quantity "
276
                     "to allocate from in %s.%s" % (entity, resource))
277
                raise NoQuantityError(m)
278

  
279
            hp = h.policy
280

  
281
            if h.importing - h.exported + hp.quantity - quantity < 0:
282
                m = ("There is not enough quantity "
283
                     "to allocate from in %s.%s" % (entity, resource))
284
                raise NoQuantityError(m)
285

  
286
            try:
287
                th = Holding.objects.get(entity=target, resource=resource)
288
            except Holding.DoesNotExist:
289
                m = ("There is not enough capacity "
290
                     "to allocate into in %s.%s" % (target, resource))
291
                raise NoCapacityError(m)
292

  
293
            tp = th.policy
294

  
295
            if (    th.exported - th.importing - tp.quantity
296
                    + tp.capacity - quantity                ) < 0:
297

  
298
                    m = ("There is not enough capacity "
299
                         "to allocate into in %s.%s" % (target, resource))
300
                    raise NoCapacityError(m)
301

  
302
            Provision.objects.create(   serial=serial,
303
                                        entity=entity,
304
                                        resource=resource,
305
                                        quantity=quantity   )
306

  
307
            h.exporting += quantity
308
            th.importing += quantity
309

  
310
            h.save()
311
            th.save()
312

  
313
        return serial
314

  
315
    def accept_commission(self, context={}, clientkey=None, serial=None):
316
        try:
317
            c = Commission.objects.get(clientkey=clientkey, serial=serial)
318
        except Commission.DoesNotExist:
319
            return
320

  
321
        t = c.entity
322

  
323
        provisions = Provision.objects.filter(  clientkey=clientkey,
324
                                                serial=serial       )
325
        for pv in provisions:
326
            pv.entity,
327
            pv.resource
328
            try:
329
                h = Holding.objects.get(entity=pv.entity.entity,
330
                                        resource=pv.resource    )
331
                th = Holding.objects.get(entity=t, resource=pv.resource)
332
            except Holding.DoesNotExist:
333
                m = "Corrupted provision"
334
                raise CorruptedError(m)
335

  
336
            h.exported += pv.quantity
337
            th.imported += pv.quantity
338
            h.save()
339
            th.save()
340
            pv.delete()
341

  
342
        return
343

  
344
    def reject_commission(self, context={}, clientkey=None, serial=None):
345
        try:
346
            c = Commission.objects.get(clientkey=clientkey, serial=serial)
347
        except Commission.DoesNotExist:
348
            return
349

  
350
        t = c.entity
351

  
352
        provisions = Provision.objects.filter(  clientkey=clientkey,
353
                                                serial=serial       )
354
        for pv in provisions:
355
            pv.entity,
356
            pv.resource
357
            try:
358
                h = Holding.objects.get(entity=pv.entity.entity,
359
                                        resource=pv.resource    )
360
                th = Holding.objects.get(entity=t, resource=pv.resource)
361
            except Holding.DoesNotExist:
362
                m = "Corrupted provision"
363
                raise CorruptedError(m)
364

  
365
            h.exporting -= pv.quantity
366
            th.importing -= pv.quantity
367
            h.save()
368
            th.save()
369
            pv.delete()
370

  
371
        return
372

  
373
    def get_pending_commissions(self, context={}, clientkey=None):
374
        pending = Commission.objects.filter(clientkey=clientkey)
375
        return pending
376

  
377
    def resolve_pending_commissions(self,   context={}, clientkey=None,
378
                                            max_serial=None, accept_set=()  ):
379
        accept_set = set(accept_set)
380
        pending = self.get_pending_commissions(clientkey=clientkey)
381
        pending = sorted(pending)
382

  
383
        accept = self.accept_commission
384
        reject = self.reject_commission
385

  
386
        for serial in pending:
387
            if serial > max_serial:
388
                break
389

  
390
            if serial in accept_set:
391
                accept(clientkey=clientkey, serial=serial)
392
            else:
393
                reject(clientkey=clientkey, serial=serial)
394

  
395
        return
396

  
397
    def release_entity(self, context={}, release_entity=()):
398
        rejected = []
399
        append = rejected.append
400
        for entity, key in release_entity:
401
            try:
402
                e = Entity.objects.get(entity=entity, key=key)
403
            except Entity.DoesNotExist:
404
                append(entity)
405
                continue
406

  
407
            if e.entities.count() != 0:
408
                append(entity)
409
                continue
410

  
411
            if e.holdings.count() != 0:
412
                append(entity)
413
                continue
414

  
415
            e.delete()
416

  
417
        return rejected
418

  
419
API_Callpoint = QuotaholderDjangoDBCallpoint
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