Revision 9619cc64

b/commissioning/servers/fscrud/__init__.py
1

  
1
 
/dev/null
1

  
2
from commissioning import ControlledCallpoint, get_callpoint, mkcallargs
3
from commissioning.controllers.django_controller \
4
    import Controller as DjangoController
5
from commissioning.specs.fscrud import API_Spec as FSCrudAPI
6
from commissioning.physicals.fscrud import FSCrudPhysical
7
from django.conf import settings
8

  
9

  
10
qh_callpoint = get_callpoint('clients.quotaholder', automake='http')
11
fscrud_api_spec = FSCrudAPI()
12

  
13
class FSCrudDjangoController(DjangoController):
14

  
15
    def controller_init(self):
16
        self.context = {}
17
        self.clientkey = 'fscrudck'
18
        self.entitykey = 'fscrudek'
19
        self.entityroot = 'fscrud'
20

  
21
    def get_commission_issue(self, commission_spec):
22
        call_data = commission_spec['call_data']
23
        path = call_data['path']
24
        args = mkcallargs (
25
                context     =   self.context,
26
                entity      =   path,
27
                key         =   self.entitykey,
28
                clientkey   =   self.clientkey,
29
                owner       =   self.entityroot,
30
                ownerkey    =   self.entitykey,
31
                provisions  =   [('access', 'path', 1)]
32
        )
33

  
34
        return args
35

  
36

  
37
class FSCrudControlled(ControlledCallpoint):
38

  
39
    api_spec = fscrud_api_spec
40

  
41
    def init_connection(self, connection):
42
	# ignore connection
43
	queuepath = settings.FSCRUD_QUEUE_PATH
44
	dataroot = settings.FSCRUD_DATA_ROOT
45
        physical = FSCrudPhysical(queuepath, dataroot)
46
        quotaholder = qh_callpoint('null://wherever/')
47
        self.controller = FSCrudDjangoController(quotaholder, physical)
48

  
49
    def commit(self):
50
        pass
51

  
52
    def rollback(self):
53
        pass
54

  
55
API_Callpoint = FSCrudControlled
56

  
/dev/null
1
#!/usr/bin/env python
2
from os import environ
3
from os.path import basename
4
from sys import argv
5

  
6

  
7
environ['COMMISSIONING_APP_NAME'] = 'fscrud'
8

  
9
from django.core.management import execute_manager
10
try:
11
    import commissioning.servers.fscrud.settings as settings
12
except ImportError:
13
    import sys
14
    sys.stderr.write("%s: Can't import settings." % __file__)
15
    sys.exit(1)
16

  
17
if __name__ == "__main__":
18
    execute_manager(settings)
b/commissioning/servers/fscrud/fscrud_django/__init__.py
1

  
b/commissioning/servers/fscrud/fscrud_django/callpoint.py
1

  
2
from commissioning import ControlledCallpoint, get_callpoint, mkcallargs
3
from commissioning.controllers.django_controller \
4
    import Controller as DjangoController
5
from commissioning.specs.fscrud import API_Spec as FSCrudAPI
6
from commissioning.physicals.fscrud import FSCrudPhysical
7
from django.conf import settings
8

  
9

  
10
qh_callpoint = get_callpoint('clients.quotaholder', automake='http')
11
fscrud_api_spec = FSCrudAPI()
12

  
13
class FSCrudDjangoController(DjangoController):
14

  
15
    def controller_init(self):
16
        self.context = {}
17
        self.clientkey = 'fscrudck'
18
        self.entitykey = 'fscrudek'
19
        self.entityroot = 'fscrud'
20

  
21
    def get_commission_issue(self, commission_spec):
22
        call_data = commission_spec['call_data']
23
        path = call_data['path']
24
        args = mkcallargs (
25
                context     =   self.context,
26
                entity      =   path,
27
                key         =   self.entitykey,
28
                clientkey   =   self.clientkey,
29
                owner       =   self.entityroot,
30
                ownerkey    =   self.entitykey,
31
                provisions  =   [('access', 'path', 1)]
32
        )
33

  
34
        return args
35

  
36

  
37
class FSCrudControlled(ControlledCallpoint):
38

  
39
    api_spec = fscrud_api_spec
40

  
41
    def init_connection(self, connection):
42
	# ignore connection
43
	queuepath = settings.FSCRUD_QUEUE_PATH
44
	dataroot = settings.FSCRUD_DATA_ROOT
45
        physical = FSCrudPhysical(queuepath, dataroot)
46
        quotaholder = qh_callpoint('null://wherever/')
47
        self.controller = FSCrudDjangoController(quotaholder, physical)
48

  
49
    def commit(self):
50
        pass
51

  
52
    def rollback(self):
53
        pass
54

  
55
API_Callpoint = FSCrudControlled
56

  
b/commissioning/servers/fscrud/fscrud_django/fscrud-manage
1
#!/usr/bin/env python
2
from os import environ
3
from os.path import basename
4
from sys import argv
5

  
6

  
7
environ['COMMISSIONING_APP_NAME'] = 'fscrud'
8

  
9
from django.core.management import execute_manager
10
try:
11
    import commissioning.servers.fscrud.settings as settings
12
except ImportError:
13
    import sys
14
    sys.stderr.write("%s: Can't import settings." % __file__)
15
    sys.exit(1)
16

  
17
if __name__ == "__main__":
18
    execute_manager(settings)
b/commissioning/servers/fscrud/fscrud_django/settings.py
1

  
2
DEBUG = True
3
TEMPLATE_DEBUG = DEBUG
4

  
5
FSCRUD_QUEUE_PATH = '/var/lib/fscrude/queue'
6
FSCRUD_DATA_ROOT = '/var/lib/fscrude/data'
7

  
8
DATABASES = {
9
    'default': {
10
        # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
11
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
12
        'NAME': 'holder',               # Or path to database file if using sqlite3.
13
        'USER': 'holder',               # Not used with sqlite3.
14
        'PASSWORD': 'holder',           # Not used with sqlite3.
15
        'HOST': '127.0.0.1',            # Set to empty string for localhost. Not used with sqlite3.
16
        'PORT': '5432',                 # Set to empty string for default. Not used with sqlite3.
17
    }
18
}
19

  
20
from commissioning.utils.pyconf import pyconf_globals
21
pyconf_globals('/etc/fscrud/django.conf')
22

  
23
import sys
24
sys.stderr = sys.stdout
25

  
26
COMMISSIONING_APP_NAME = 'fscrud'
27

  
28
ADMINS = (
29
    # ('Your Name', 'your_email@domain.com'),
30
)
31

  
32
MANAGERS = ADMINS
33

  
34
TIME_ZONE = 'UTC'
35

  
36
# Language code for this installation. All choices can be found here:
37
# http://www.i18nguy.com/unicode/language-identifiers.html
38
LANGUAGE_CODE = 'en-us'
39

  
40
SITE_ID = 1
41

  
42
# If you set this to False, Django will make some optimizations so as not
43
# to load the internationalization machinery.
44
USE_I18N = False
45

  
46
# If you set this to False, Django will not format dates, numbers and
47
# calendars according to the current locale
48
USE_L10N = False
49

  
50
# Make this unique, and don't share it with anybody.
51
SECRET_KEY = 'ee=*x%x6sp=hcm7j4zzkvpam27g*7*d59fca-q!azaqma!jx*+'
52

  
53
# List of callables that know how to import templates from various sources.
54
TEMPLATE_LOADERS = (
55
    'django.template.loaders.filesystem.Loader',
56
    'django.template.loaders.app_directories.Loader',
57
#     'django.template.loaders.eggs.Loader',
58
)
59

  
60
MIDDLEWARE_CLASSES = (
61
    'django.middleware.common.CommonMiddleware',
62
    #'django.middleware.transaction.TransactionMiddleware',
63
    #'django.contrib.sessions.middleware.SessionMiddleware',
64
    #'django.middleware.csrf.CsrfViewMiddleware',
65
    #'django.contrib.auth.middleware.AuthenticationMiddleware',
66
    #'django.contrib.messages.middleware.MessageMiddleware',
67
)
68

  
69
ROOT_URLCONF = 'commissioning.servers.fscrud.urls'
70

  
71
TEMPLATE_DIRS = (
72
    # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
73
    # Always use forward slashes, even on Windows.
74
    # Don't forget to use absolute paths, not relative paths.
75
)
76

  
77

  
78
INSTALLED_APPS = (
79
    #'django.contrib.auth',
80
    'django.contrib.contenttypes',
81
    #'django.contrib.sessions',
82
    #'django.contrib.sites',
83
    #'django.contrib.messages',
84
    'commissioning.controllers.django_controller',
85
    'commissioning.servers.django_server.server_app',
86
    #'commissioning.servers.django_server.server_app',
87
    # Uncomment the next line to enable the admin:
88
    # 'django.contrib.admin',
89
    # Uncomment the next line to enable admin documentation:
90
    # 'django.contrib.admindocs',
91
)
92

  
93
names = COMMISSIONING_APP_NAME.split(',')
94
names = ('commissioning.servers.%s.django_backend' % (n,) for n in names)
95
from django.utils.importlib import import_module
96

  
97
applist = []
98
for name in names:
99
    try:
100
        import_module(name)
101
        applist.append(name)
102
    except ImportError:
103
        pass
104

  
105
INSTALLED_APPS += tuple(applist)
106

  
b/commissioning/servers/fscrud/fscrud_django/urls.py
1
from django.conf.urls.defaults import *
2

  
3
# Uncomment the next two lines to enable the admin:
4
# from django.contrib import admin
5
# admin.autodiscover()
6

  
7
urlpatterns = patterns('',
8
    # Example:
9
    # (r'^quota/', include('quota.foo.urls')),
10

  
11
    # Uncomment the admin/doc line below to enable admin documentation:
12
    # (r'^admin/doc/', include('django.contrib.admindocs.urls')),
13

  
14
    # Uncomment the next line to enable the admin:
15
    # (r'^admin/', include(admin.site.urls)),
16
    (r'^api/', include('commissioning.servers.django_server.server_app.urls')),
17
)
/dev/null
1

  
2
DEBUG = True
3
TEMPLATE_DEBUG = DEBUG
4

  
5
FSCRUD_QUEUE_PATH = '/var/lib/fscrude/queue'
6
FSCRUD_DATA_ROOT = '/var/lib/fscrude/data'
7

  
8
DATABASES = {
9
    'default': {
10
        # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
11
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
12
        'NAME': 'holder',               # Or path to database file if using sqlite3.
13
        'USER': 'holder',               # Not used with sqlite3.
14
        'PASSWORD': 'holder',           # Not used with sqlite3.
15
        'HOST': '127.0.0.1',            # Set to empty string for localhost. Not used with sqlite3.
16
        'PORT': '5432',                 # Set to empty string for default. Not used with sqlite3.
17
    }
18
}
19

  
20
from commissioning.utils.pyconf import pyconf_globals
21
pyconf_globals('/etc/fscrud/django.conf')
22

  
23
import sys
24
sys.stderr = sys.stdout
25

  
26
COMMISSIONING_APP_NAME = 'fscrud'
27

  
28
ADMINS = (
29
    # ('Your Name', 'your_email@domain.com'),
30
)
31

  
32
MANAGERS = ADMINS
33

  
34
TIME_ZONE = 'UTC'
35

  
36
# Language code for this installation. All choices can be found here:
37
# http://www.i18nguy.com/unicode/language-identifiers.html
38
LANGUAGE_CODE = 'en-us'
39

  
40
SITE_ID = 1
41

  
42
# If you set this to False, Django will make some optimizations so as not
43
# to load the internationalization machinery.
44
USE_I18N = False
45

  
46
# If you set this to False, Django will not format dates, numbers and
47
# calendars according to the current locale
48
USE_L10N = False
49

  
50
# Make this unique, and don't share it with anybody.
51
SECRET_KEY = 'ee=*x%x6sp=hcm7j4zzkvpam27g*7*d59fca-q!azaqma!jx*+'
52

  
53
# List of callables that know how to import templates from various sources.
54
TEMPLATE_LOADERS = (
55
    'django.template.loaders.filesystem.Loader',
56
    'django.template.loaders.app_directories.Loader',
57
#     'django.template.loaders.eggs.Loader',
58
)
59

  
60
MIDDLEWARE_CLASSES = (
61
    'django.middleware.common.CommonMiddleware',
62
    #'django.middleware.transaction.TransactionMiddleware',
63
    #'django.contrib.sessions.middleware.SessionMiddleware',
64
    #'django.middleware.csrf.CsrfViewMiddleware',
65
    #'django.contrib.auth.middleware.AuthenticationMiddleware',
66
    #'django.contrib.messages.middleware.MessageMiddleware',
67
)
68

  
69
ROOT_URLCONF = 'commissioning.servers.fscrud.urls'
70

  
71
TEMPLATE_DIRS = (
72
    # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
73
    # Always use forward slashes, even on Windows.
74
    # Don't forget to use absolute paths, not relative paths.
75
)
76

  
77

  
78
INSTALLED_APPS = (
79
    #'django.contrib.auth',
80
    'django.contrib.contenttypes',
81
    #'django.contrib.sessions',
82
    #'django.contrib.sites',
83
    #'django.contrib.messages',
84
    'commissioning.controllers.django_controller',
85
    'commissioning.servers.django_server.server_app',
86
    #'commissioning.servers.django_server.server_app',
87
    # Uncomment the next line to enable the admin:
88
    # 'django.contrib.admin',
89
    # Uncomment the next line to enable admin documentation:
90
    # 'django.contrib.admindocs',
91
)
92

  
93
names = COMMISSIONING_APP_NAME.split(',')
94
names = ('commissioning.servers.%s.django_backend' % (n,) for n in names)
95
from django.utils.importlib import import_module
96

  
97
applist = []
98
for name in names:
99
    try:
100
        import_module(name)
101
        applist.append(name)
102
    except ImportError:
103
        pass
104

  
105
INSTALLED_APPS += tuple(applist)
106

  
/dev/null
1
from django.conf.urls.defaults import *
2

  
3
# Uncomment the next two lines to enable the admin:
4
# from django.contrib import admin
5
# admin.autodiscover()
6

  
7
urlpatterns = patterns('',
8
    # Example:
9
    # (r'^quota/', include('quota.foo.urls')),
10

  
11
    # Uncomment the admin/doc line below to enable admin documentation:
12
    # (r'^admin/doc/', include('django.contrib.admindocs.urls')),
13

  
14
    # Uncomment the next line to enable the admin:
15
    # (r'^admin/', include(admin.site.urls)),
16
    (r'^api/', include('commissioning.servers.django_server.server_app.urls')),
17
)
b/commissioning/servers/quotaholder/__init__.py
1

  
b/commissioning/servers/quotaholder/django_backend/__init__.py
1
from .models import QuotaholderDjangoDBCallpoint
b/commissioning/servers/quotaholder/django_backend/fixtures/initial_data.json
1
[
2
    {
3
        "model": "quotaholder.backend.entity",
4
        "pk": "system",
5
        "fields": {
6
            "owner": "system",
7
            "key": ""
8
        }
9
    }
10
]
b/commissioning/servers/quotaholder/django_backend/models.py
1

  
2
from commissioning.quotaholder \
3
import (QuotaholderCallpoint,  QuotaholderException,
4
        QuotaholderController, QuotaholderPhysical,
5
        QuotaholderCorrupted,  QuotaholderInvalidData,
6
        QuotaholderInvalidKey, QuotaholderNoEntity,
7
        QuotaholderNoQuantity, QuotaholderNoCapacity)
8

  
9

  
10
from django.db.models import Model, BigIntegerField, CharField, ForeignKey
11
from django.db import transaction
12

  
13

  
14
class Holder(Model):
15

  
16
    attribute   =   CharField(max_length=72, primary_key=True)
17
    intval      =   BigIntegerField()
18
    strval      =   CharField(max_length=72)
19

  
20

  
21
def alloc_serial(nr=1):
22
    if nr < 0:
23
        m = "Can only receive a positive argument, not %d" % (nr,)
24
        raise QuotaholderCorrupted(m)
25

  
26
    try:
27
        holder = Holder.objects.get(attribute='serial')
28
    except Holder.DoesNotExist:
29
        holder = Holder(attribute='serial', inval=1)
30

  
31
    serial = holder.serial
32
    holder.serial += nr
33
    holder.save()
34

  
35
    return serial
36

  
37

  
38
class Entity(Model):
39

  
40
    entity      =   CharField(max_length=72, primary_key=True)
41
    owner       =   ForeignKey('self', to_field='entity',
42
                               related_name='entities')
43
    key         =   CharField(max_length=72, null=False)
44

  
45

  
46
class Policy(Model):
47

  
48
    policy          =   CharField(max_length=72, primary_key=True)
49
    quantity        =   BigIntegerField(null=False, default=0)
50
    capacity        =   BigIntegerField(null=False, default=0)
51
    import_limit    =   BigIntegerField(null=False, default=0)
52
    export_limit    =   BigIntegerField(null=False, default=0)
53

  
54

  
55
class Holding(Model):
56

  
57
    entity      =   ForeignKey(Entity, to_field='entity')
58
    resource    =   CharField(max_length=72, null=False)
59

  
60
    policy      =   ForeignKey(Policy, to_field='policy')
61
    flags       =   BigIntegerField(null=False, default=0)
62

  
63
    imported    =   BigIntegerField(null=False, default=0)
64
    importing   =   BigIntegerField(null=False, default=0)
65
    exported    =   BigIntegerField(null=False, default=0)
66
    exporting   =   BigIntegerField(null=False, default=0)
67

  
68
    class Meta:
69
        unique_together = (('entity', 'resource'),)
70

  
71

  
72
from datetime import datetime
73

  
74
def now():
75
    return datetime.now().strftime('%Y-%m-%dT:%H:%M:%S.%f')[:24]
76

  
77

  
78
class Commission(Model):
79

  
80
    serial      =   BigIntegerField(primary_key=True, default=alloc_serial)
81
    entity      =   ForeignKey(Entity, to_field='entity')
82
    clientkey   =   CharField(max_length=72, null=False)
83
    issue_time  =   CharField(max_length=24, default=now)
84

  
85

  
86
class Provision(Model):
87

  
88
    serial      =   ForeignKey( Commission,
89
                                to_field='serial',
90
                                related_name='provisions'   )
91

  
92
    entity      =   ForeignKey(Entity, to_field='entity')
93
    resource    =   CharField(max_length=72, null=False)
94
    quantity    =   BigIntegerField(null=False)
95

  
96

  
97

  
98
class QuotaholderDjangoDBCallpoint(QuotaholderCallpoint):
99

  
100
    http_exc_lookup = {
101
        QuotaholderCorrupted:   550,
102
        QuotaholderInvalidData: 400,
103
        QuotaholderInvalidKey:  401,
104
        QuotaholderNoEntity:    404,
105
        QuotaholderNoQuantity:  413,
106
        QuotaholderNoCapacity:  413,
107
    }
108

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

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

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

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

  
127
        return call_fn(**data)
128

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

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

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

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

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

  
150
        return rejected
151

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

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

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

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

  
173
            append((entity, key))
174

  
175
        return entities
176

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

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

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

  
193
        return limits
194

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

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

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

  
207
        return ()
208

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

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

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

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

  
225
        return holdings
226

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

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

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

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

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

  
257
        return rejected
258

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

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

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

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

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

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

  
287
            p = h.policy
288

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

  
293
        return quotas
294

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

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

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

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

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

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

  
327
        return rejected
328

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

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

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

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

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

  
361
            hp = h.policy
362

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

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

  
375
            tp = th.policy
376

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

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

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

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

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

  
395
        return serial
396

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

  
403
        t = c.entity
404

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

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

  
424
        return
425

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

  
432
        t = c.entity
433

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

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

  
453
        return
454

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

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

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

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

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

  
477
        return
478

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

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

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

  
497
            e.delete()
498

  
499
        return rejected
500

  
b/commissioning/servers/quotaholder/quotaholder_django/__init__.py
1

  
2

  
b/commissioning/servers/quotaholder/quotaholder_django/quotaholder-manage
1
#!/usr/bin/env python
2
from django.core.management import execute_manager
3
try:
4
    import commissioning.servers.quotaholder_django.settings as settings
5
except ImportError:
6
    import sys
7
    sys.stderr.write("%s: Can't import settings." % __file__)
8
    sys.exit(1)
9

  
10
if __name__ == "__main__":
11
    execute_manager(settings)
b/commissioning/servers/quotaholder/quotaholder_django/settings.py
1

  
2
DEBUG = True
3
TEMPLATE_DEBUG = DEBUG
4

  
5
DATABASES = {
6
    'default': {
7
        # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
8
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
9
        'NAME': 'holder',                       # Or path to database file if using sqlite3.
10
        'USER': 'holder',                       # Not used with sqlite3.
11
        'PASSWORD': 'holder',                   # Not used with sqlite3.
12
        'HOST': 'dev84.dev.grnet.gr',           # Set to empty string for localhost. Not used with sqlite3.
13
        'PORT': '5432',                         # Set to empty string for default. Not used with sqlite3.
14
    }
15
}
16

  
17
from commissioning.utils.pyconf import pyconf_globals
18
pyconf_globals('/etc/fscrud/django.conf')
19

  
20
COMMISSIONING_APP_NAME='quotaholder'
21

  
22
ADMINS = (
23
    # ('Your Name', 'your_email@domain.com'),
24
)
25

  
26
MANAGERS = ADMINS
27

  
28
# Local time zone for this installation. Choices can be found here:
29
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
30
# although not all choices may be available on all operating systems.
31
# On Unix systems, a value of None will cause Django to use the same
32
# timezone as the operating system.
33
# If running in a Windows environment this must be set to the same as your
34
# system time zone.
35
TIME_ZONE = 'Europe/Athens'
36

  
37
# Language code for this installation. All choices can be found here:
38
# http://www.i18nguy.com/unicode/language-identifiers.html
39
LANGUAGE_CODE = 'en-us'
40

  
41
SITE_ID = 1
42

  
43
# If you set this to False, Django will make some optimizations so as not
44
# to load the internationalization machinery.
45
USE_I18N = True
46

  
47
# If you set this to False, Django will not format dates, numbers and
48
# calendars according to the current locale
49
USE_L10N = True
50

  
51
# Absolute path to the directory that holds media.
52
# Example: "/home/media/media.lawrence.com/"
53
MEDIA_ROOT = ''
54

  
55
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
56
# trailing slash if there is a path component (optional in other cases).
57
# Examples: "http://media.lawrence.com", "http://example.com/media/"
58
MEDIA_URL = ''
59

  
60
# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
61
# trailing slash.
62
# Examples: "http://foo.com/media/", "/media/".
63
ADMIN_MEDIA_PREFIX = '/media/'
64

  
65
# Make this unique, and don't share it with anybody.
66
SECRET_KEY = 'ee=*x%x6sp=hcm7j4zzkvpam27g*7*d59fca-q!azaqma!jx*+'
67

  
68
# List of callables that know how to import templates from various sources.
69
TEMPLATE_LOADERS = (
70
    'django.template.loaders.filesystem.Loader',
71
    'django.template.loaders.app_directories.Loader',
72
#     'django.template.loaders.eggs.Loader',
73
)
74

  
75
MIDDLEWARE_CLASSES = (
76
    'django.middleware.common.CommonMiddleware',
77
    #'django.middleware.transaction.TransactionMiddleware',
78
    #'django.contrib.sessions.middleware.SessionMiddleware',
79
    #'django.middleware.csrf.CsrfViewMiddleware',
80
    #'django.contrib.auth.middleware.AuthenticationMiddleware',
81
    #'django.contrib.messages.middleware.MessageMiddleware',
82
)
83

  
84
ROOT_URLCONF = 'urls'
85

  
86
TEMPLATE_DIRS = (
87
    # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
88
    # Always use forward slashes, even on Windows.
89
    # Don't forget to use absolute paths, not relative paths.
90
)
91

  
92
INSTALLED_APPS = (
93
    #'django.contrib.auth',
94
    'django.contrib.contenttypes',
95
    #'django.contrib.sessions',
96
    #'django.contrib.sites',
97
    #'django.contrib.messages',
98
    #('commissioning.%s.backends.django_backend'
99
    #                    % (COMMISSIONING_APP_NAME,)),
100
    'commissioning.servers.django_server.server_app',
101
    # Uncomment the next line to enable the admin:
102
    # 'django.contrib.admin',
103
    # Uncomment the next line to enable admin documentation:
104
    # 'django.contrib.admindocs',
105
)
b/commissioning/servers/quotaholder/quotaholder_django/urls.py
1
from django.conf.urls.defaults import *
2

  
3
# Uncomment the next two lines to enable the admin:
4
# from django.contrib import admin
5
# admin.autodiscover()
6

  
7
urlpatterns = patterns('',
8
    # Example:
9
    # (r'^quota/', include('quota.foo.urls')),
10

  
11
    # Uncomment the admin/doc line below to enable admin documentation:
12
    # (r'^admin/doc/', include('django.contrib.admindocs.urls')),
13

  
14
    # Uncomment the next line to enable the admin:
15
    # (r'^admin/', include(admin.site.urls)),
16
    (r'^api/', include('server_app.urls')),
17
)
/dev/null
1

  
2

  
/dev/null
1
from .models import QuotaholderDjangoDBCallpoint
/dev/null
1
[
2
    {
3
        "model": "quotaholder.backend.entity",
4
        "pk": "system",
5
        "fields": {
6
            "owner": "system",
7
            "key": ""
8
        }
9
    }
10
]
/dev/null
1

  
2
from commissioning.quotaholder \
3
import (QuotaholderCallpoint,  QuotaholderException,
4
        QuotaholderController, QuotaholderPhysical,
5
        QuotaholderCorrupted,  QuotaholderInvalidData,
6
        QuotaholderInvalidKey, QuotaholderNoEntity,
7
        QuotaholderNoQuantity, QuotaholderNoCapacity)
8

  
9

  
10
from django.db.models import Model, BigIntegerField, CharField, ForeignKey
11
from django.db import transaction
12

  
13

  
14
class Holder(Model):
15

  
16
    attribute   =   CharField(max_length=72, primary_key=True)
17
    intval      =   BigIntegerField()
18
    strval      =   CharField(max_length=72)
19

  
20

  
21
def alloc_serial(nr=1):
22
    if nr < 0:
23
        m = "Can only receive a positive argument, not %d" % (nr,)
24
        raise QuotaholderCorrupted(m)
25

  
26
    try:
27
        holder = Holder.objects.get(attribute='serial')
28
    except Holder.DoesNotExist:
29
        holder = Holder(attribute='serial', inval=1)
30

  
31
    serial = holder.serial
32
    holder.serial += nr
33
    holder.save()
34

  
35
    return serial
36

  
37

  
38
class Entity(Model):
39

  
40
    entity      =   CharField(max_length=72, primary_key=True)
41
    owner       =   ForeignKey('self', to_field='entity',
42
                               related_name='entities')
43
    key         =   CharField(max_length=72, null=False)
44

  
45

  
46
class Policy(Model):
47

  
48
    policy          =   CharField(max_length=72, primary_key=True)
49
    quantity        =   BigIntegerField(null=False, default=0)
50
    capacity        =   BigIntegerField(null=False, default=0)
51
    import_limit    =   BigIntegerField(null=False, default=0)
52
    export_limit    =   BigIntegerField(null=False, default=0)
53

  
54

  
55
class Holding(Model):
56

  
57
    entity      =   ForeignKey(Entity, to_field='entity')
58
    resource    =   CharField(max_length=72, null=False)
59

  
60
    policy      =   ForeignKey(Policy, to_field='policy')
61
    flags       =   BigIntegerField(null=False, default=0)
62

  
63
    imported    =   BigIntegerField(null=False, default=0)
64
    importing   =   BigIntegerField(null=False, default=0)
65
    exported    =   BigIntegerField(null=False, default=0)
66
    exporting   =   BigIntegerField(null=False, default=0)
67

  
68
    class Meta:
69
        unique_together = (('entity', 'resource'),)
70

  
71

  
72
from datetime import datetime
73

  
74
def now():
75
    return datetime.now().strftime('%Y-%m-%dT:%H:%M:%S.%f')[:24]
76

  
77

  
78
class Commission(Model):
79

  
80
    serial      =   BigIntegerField(primary_key=True, default=alloc_serial)
81
    entity      =   ForeignKey(Entity, to_field='entity')
82
    clientkey   =   CharField(max_length=72, null=False)
83
    issue_time  =   CharField(max_length=24, default=now)
84

  
85

  
86
class Provision(Model):
87

  
88
    serial      =   ForeignKey( Commission,
89
                                to_field='serial',
90
                                related_name='provisions'   )
91

  
92
    entity      =   ForeignKey(Entity, to_field='entity')
93
    resource    =   CharField(max_length=72, null=False)
94
    quantity    =   BigIntegerField(null=False)
95

  
96

  
97

  
98
class QuotaholderDjangoDBCallpoint(QuotaholderCallpoint):
99

  
100
    http_exc_lookup = {
101
        QuotaholderCorrupted:   550,
102
        QuotaholderInvalidData: 400,
103
        QuotaholderInvalidKey:  401,
104
        QuotaholderNoEntity:    404,
105
        QuotaholderNoQuantity:  413,
106
        QuotaholderNoCapacity:  413,
107
    }
108

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

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

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

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

  
127
        return call_fn(**data)
128

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

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

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

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

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

  
150
        return rejected
151

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

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

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

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

  
173
            append((entity, key))
174

  
175
        return entities
176

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

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

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

  
193
        return limits
194

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

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

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

  
207
        return ()
208

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

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

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

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

  
225
        return holdings
226

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

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

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

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

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

  
257
        return rejected
258

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

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

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

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

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

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

  
287
            p = h.policy
288

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

  
293
        return quotas
294

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

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

  
303
                try:
304
                    h = Holding.objects.get(entity=entity, resource=resource)
305
                    if h.entity.key != key:
306
                        append((entity, resource))
307
                        continue
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff