Statistics
| Branch: | Tag: | Revision:

root / api / handlers.py @ ec06b07c

History | View | Annotate | Download (7.9 kB)

1
# vim: ts=4 sts=4 et ai sw=4 fileencoding=utf-8
2
#
3
# Copyright © 2010 Greek Research and Technology Network
4
#
5

    
6
from django.conf import settings
7
from piston.handler import BaseHandler, AnonymousBaseHandler
8
from synnefo.api.faults import fault, noContent, accepted, created
9
from synnefo.api.helpers import instance_to_server, paginator
10
from synnefo.util.rapi import GanetiRapiClient, GanetiApiError
11
from synnefo.vocabs import MOCK_SERVERS, MOCK_IMAGES
12

    
13
if settings.GANETI_CLUSTER_INFO:
14
    rapi = GanetiRapiClient(*settings.GANETI_CLUSTER_INFO)
15
else:
16
    rapi = None
17

    
18
VERSIONS = [
19
    {
20
        "status": "CURRENT",
21
        "id": "v1.0",
22
        "docURL" : "http://docs.rackspacecloud.com/servers/api/v1.0/cs-devguide-20090714.pdf ",
23
        "wadl" : "http://docs.rackspacecloud.com/servers/api/v1.0/application.wadl"
24
    },
25
]
26

    
27
class VersionHandler(AnonymousBaseHandler):
28
    allowed_methods = ('GET',)
29

    
30
    def read(self, request, number=None):
31
        if number is None:
32
            versions = map(lambda v: {
33
                        "status": v["status"],
34
                        "id": v["id"],
35
                    }, VERSIONS)
36
            return { "versions": versions }
37
        else:
38
            for version in VERSIONS:
39
                if version["id"] == number:
40
                    return { "version": version }
41
            raise fault.itemNotFound
42

    
43

    
44
class ServerHandler(BaseHandler):
45
    allowed_methods = ('GET', 'POST', 'PUT', 'DELETE')
46

    
47
    def read(self, request, id=None):
48
        if id is None:
49
            return self.read_all(request)
50
        elif id == "detail":
51
            return self.read_all(request, detail=True)
52
        else:
53
            return self.read_one(request, id)
54

    
55
    def read_one(self, request, id):
56
        if not rapi: # No ganeti backend. Return mock objects
57
            return { "server": MOCK_SERVERS[0] }
58
        try:
59
            instance = rapi.GetInstance(id)
60
            return { "server": instance_to_server(instance) }
61
        except GanetiApiError:
62
            raise fault.itemNotFound
63

    
64
    @paginator
65
    def read_all(self, request, detail=False):
66
        if not rapi: # No ganeti backend. Return mock objects
67
            if detail:
68
                return { "servers": MOCK_SERVERS }
69
            else:
70
                return { "servers": [ { "id": s['id'], "name": s['name'] } for s in MOCK_SERVERS ] }
71

    
72
        if not detail:
73
            instances = rapi.GetInstances(bulk=False)
74
            servers = [ { "id": id, "name": id } for id in instances ]
75
        else:
76
            instances = rapi.GetInstances(bulk=True)
77
            servers = []
78
            for instance in instances:
79
                servers.append(instance_to_server(instance))
80
        return { "servers": servers }
81

    
82
    def create(self, request):
83
        return accepted
84

    
85
    def update(self, request, id):
86
        return noContent
87

    
88
    def delete(self, request, id):
89
        return accepted
90

    
91

    
92
class ServerAddressHandler(BaseHandler):
93
    allowed_methods = ('GET', 'PUT', 'DELETE')
94

    
95
    def read(self, request, id, type=None):
96
        """List IP addresses for a server"""
97
        if type is None:
98
            pass
99
        elif type == "private":
100
            pass
101
        elif type == "public":
102
            pass
103
        return {}
104

    
105
    def update(self, request, id, address):
106
        """Share an IP address to another in the group"""
107
        return accepted
108

    
109
    def delete(self, request, id, address):
110
        """Unshare an IP address"""
111
        return accepted
112

    
113

    
114
class ServerActionHandler(BaseHandler):
115
    allowed_methods = ('POST',)
116

    
117
    def create(self, request, id):
118
        """Reboot, rebuild, resize, confirm resized, revert resized"""
119
        print ("server action %s" % id)
120
        return accepted
121

    
122

    
123
class ServerBackupHandler(BaseHandler):
124
    """ Backup Schedules are not implemented yet, return notImplemented """
125
    allowed_methods = ('GET', 'POST', 'DELETE')
126

    
127
    def read(self, request, id):
128
        raise fault.notImplemented
129

    
130
    def create(self, request, id):
131
        raise fault.notImplemented
132

    
133
    def delete(self, request, id):
134
        raise fault.notImplemented
135

    
136

    
137
class FlavorHandler(BaseHandler):
138
    allowed_methods = ('GET',)
139
    flavors = [
140
          {
141
            "id" : 1,
142
            "name" : "256 MB Server",
143
            "ram" : 256,
144
            "disk" : 10
145
          },
146
          {
147
            "id" : 2,
148
            "name" : "512 MB Server",
149
            "ram" : 512,
150
            "disk" : 20
151
          }
152
        ]
153

    
154
    def read(self, request, id=None):
155
        """
156
        List flavors or retrieve one
157

158
        Returns: OK
159
        Faults: cloudServersFault, serviceUnavailable, unauthorized,
160
                badRequest, itemNotFound
161
        """
162
        if id is None:
163
            simple = map(lambda v: {
164
                        "id": v["id"],
165
                        "name": v["name"],
166
                    }, self.flavors)
167
            return { "flavors": simple }
168
        elif id == "detail":
169
            return { "flavors": self.flavors }
170
        else:
171
            for flavor in self.flavors:
172
                if str(flavor["id"]) == id:
173
                    return { "flavor": flavor }
174
            raise fault.itemNotFound
175

    
176

    
177
class ImageHandler(BaseHandler):
178
    allowed_methods = ('GET', 'POST')
179

    
180
    def read(self, request, id=None):
181
        """
182
        List images or retrieve one
183

184
        Returns: OK
185
        Faults: cloudServersFault, serviceUnavailable, unauthorized,
186
                badRequest, itemNotFound
187
        """
188
        if not rapi: # No ganeti backend. Return mock objects
189
            if id == "detail":
190
                return { "images": MOCK_IMAGES }
191
            elif id is None:
192
                return { "images": [ { "id": s['id'], "name": s['name'] } for s in MOCK_IMAGES ] }
193
            else:
194
                return { "image": MOCK_IMAGES[0] }
195
        if id is None:
196
            return {}
197
        elif id == "detail":
198
            return {}
199
        else:
200
            raise fault.itemNotFound
201

    
202
    def create(self, request):
203
        """Create a new image"""
204
        return accepted
205

    
206

    
207
class SharedIPGroupHandler(BaseHandler):
208
    allowed_methods = ('GET', 'POST', 'DELETE')
209

    
210
    def read(self, request, id=None):
211
        """List Shared IP Groups"""
212
        if id is None:
213
            return {}
214
        elif id == "detail":
215
            return {}
216
        else:
217
            raise fault.itemNotFound
218

    
219
    def create(self, request, id):
220
        """Creates a new Shared IP Group"""
221
        return created
222

    
223
    def delete(self, request, id):
224
        """Deletes a Shared IP Group"""
225
        return noContent
226

    
227

    
228
class LimitHandler(BaseHandler):
229
    allowed_methods = ('GET',)
230

    
231
    # XXX: hookup with @throttle
232

    
233
    rate = [
234
        {
235
           "verb" : "POST",
236
           "URI" : "*",
237
           "regex" : ".*",
238
           "value" : 10,
239
           "remaining" : 2,
240
           "unit" : "MINUTE",
241
           "resetTime" : 1244425439
242
        },
243
        {
244
           "verb" : "POST",
245
           "URI" : "*/servers",
246
           "regex" : "^/servers",
247
           "value" : 25,
248
           "remaining" : 24,
249
           "unit" : "DAY",
250
           "resetTime" : 1244511839
251
        },
252
        {
253
           "verb" : "PUT",
254
           "URI" : "*",
255
           "regex" : ".*",
256
           "value" : 10,
257
           "remaining" : 2,
258
           "unit" : "MINUTE",
259
           "resetTime" : 1244425439
260
        },
261
        {
262
           "verb" : "GET",
263
           "URI" : "*",
264
           "regex" : ".*",
265
           "value" : 3,
266
           "remaining" : 3,
267
           "unit" : "MINUTE",
268
           "resetTime" : 1244425439
269
        },
270
        {
271
           "verb" : "DELETE",
272
           "URI" : "*",
273
           "regex" : ".*",
274
           "value" : 100,
275
           "remaining" : 100,
276
           "unit" : "MINUTE",
277
           "resetTime" : 1244425439
278
        }
279
    ]
280

    
281
    absolute = {
282
        "maxTotalRAMSize" : 51200,
283
        "maxIPGroups" : 50,
284
        "maxIPGroupMembers" : 25
285
    }
286

    
287
    def read(self, request):
288
        return { "limits": {
289
                "rate": self.rate,
290
                "absolute": self.absolute,
291
               }
292
            }