Statistics
| Branch: | Tag: | Revision:

root / api / handlers.py @ 6f6bd1a2

History | View | Annotate | Download (8.8 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
from synnefo.db.models import VirtualMachine, User
13

    
14

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

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

    
29
class VersionHandler(AnonymousBaseHandler):
30
    allowed_methods = ('GET',)
31

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

    
45

    
46
class ServerHandler(BaseHandler):
47
    allowed_methods = ('GET', 'POST', 'PUT', 'DELETE')
48

    
49
    def read(self, request, id=None):
50
        from time import sleep
51
        sleep(1)
52
        if id is None:
53
            return self.read_all(request)
54
        elif id == "detail":
55
            return self.read_all(request, detail=True)
56
        else:
57
            return self.read_one(request, id)
58

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

    
68
    @paginator
69
    def read_all(self, request, detail=False):
70
        if not rapi: # No ganeti backend. Return mock objects
71
            if detail:
72
                return { "servers":  MOCK_SERVERS }
73
                virtual_servers = VirtualMachine.objects.filter(owner=User.objects.all()[0])
74
                #get the first user, since we don't have any user data yet
75
                virtual_servers_list = [{'status': server.state, 'flavorId': server.flavor, \
76
                    'name': server.name, 'id': server.id, 'imageId': server.imageid, 
77
                    'metadata': {'Server_Label': server.server_label, \
78
                    'Image_Version': server.image_version}, \
79
                    'hostId': '9e107d9d372bb6826bd81d3542a419d6',  \
80
                    'addresses': {'public': ['67.23.10.133'], 'private': ['10.176.42.17']}} \
81
                        for server in virtual_servers]
82
                #pass some fake data regarding ip, since we don't have any such data
83
                return { "servers":  virtual_servers_list }                
84
            else:
85
                return { "servers": [ { "id": s['id'], "name": s['name'] } for s in MOCK_SERVERS ] }
86

    
87
        if not detail:
88
            instances = rapi.GetInstances(bulk=False)
89
            servers = [ { "id": id, "name": id } for id in instances ]
90
        else:
91
            instances = rapi.GetInstances(bulk=True)
92
            servers = []
93
            for instance in instances:
94
                servers.append(instance_to_server(instance))
95
        return { "servers": servers }
96

    
97
    def create(self, request):
98
        return accepted
99

    
100
    def update(self, request, id):
101
        return noContent
102

    
103
    def delete(self, request, id):
104
        return accepted
105

    
106

    
107
class ServerAddressHandler(BaseHandler):
108
    allowed_methods = ('GET', 'PUT', 'DELETE')
109

    
110
    def read(self, request, id, type=None):
111
        """List IP addresses for a server"""
112
        if type is None:
113
            pass
114
        elif type == "private":
115
            pass
116
        elif type == "public":
117
            pass
118
        return {}
119

    
120
    def update(self, request, id, address):
121
        """Share an IP address to another in the group"""
122
        return accepted
123

    
124
    def delete(self, request, id, address):
125
        """Unshare an IP address"""
126
        return accepted
127

    
128

    
129
class ServerActionHandler(BaseHandler):
130
    allowed_methods = ('POST',)
131

    
132
    def create(self, request, id):
133
        """Reboot, rebuild, resize, confirm resized, revert resized"""
134
        print ("server action %s" % id)
135
        return accepted
136

    
137

    
138
class ServerBackupHandler(BaseHandler):
139
    """ Backup Schedules are not implemented yet, return notImplemented """
140
    allowed_methods = ('GET', 'POST', 'DELETE')
141

    
142
    def read(self, request, id):
143
        raise fault.notImplemented
144

    
145
    def create(self, request, id):
146
        raise fault.notImplemented
147

    
148
    def delete(self, request, id):
149
        raise fault.notImplemented
150

    
151

    
152
class FlavorHandler(BaseHandler):
153
    allowed_methods = ('GET',)
154
    flavors = [
155
          {
156
            "id" : 1,
157
            "name" : "256 MB Server",
158
            "ram" : 256,
159
            "disk" : 10
160
          },
161
          {
162
            "id" : 2,
163
            "name" : "512 MB Server",
164
            "ram" : 512,
165
            "disk" : 20
166
          }
167
        ]
168

    
169
    def read(self, request, id=None):
170
        """
171
        List flavors or retrieve one
172

173
        Returns: OK
174
        Faults: cloudServersFault, serviceUnavailable, unauthorized,
175
                badRequest, itemNotFound
176
        """
177
        if id is None:
178
            simple = map(lambda v: {
179
                        "id": v["id"],
180
                        "name": v["name"],
181
                    }, self.flavors)
182
            return { "flavors": simple }
183
        elif id == "detail":
184
            return { "flavors": self.flavors }
185
        else:
186
            for flavor in self.flavors:
187
                if str(flavor["id"]) == id:
188
                    return { "flavor": flavor }
189
            raise fault.itemNotFound
190

    
191

    
192
class ImageHandler(BaseHandler):
193
    allowed_methods = ('GET', 'POST')
194

    
195
    def read(self, request, id=None):
196
        """
197
        List images or retrieve one
198

199
        Returns: OK
200
        Faults: cloudServersFault, serviceUnavailable, unauthorized,
201
                badRequest, itemNotFound
202
        """
203
        if not rapi: # No ganeti backend. Return mock objects
204
            if id == "detail":
205
                return { "images": MOCK_IMAGES }
206
            elif id is None:
207
                return { "images": [ { "id": s['id'], "name": s['name'] } for s in MOCK_IMAGES ] }
208
            else:
209
                return { "image": MOCK_IMAGES[0] }
210
        if id is None:
211
            return {}
212
        elif id == "detail":
213
            return {}
214
        else:
215
            raise fault.itemNotFound
216

    
217
    def create(self, request):
218
        """Create a new image"""
219
        return accepted
220

    
221

    
222
class SharedIPGroupHandler(BaseHandler):
223
    allowed_methods = ('GET', 'POST', 'DELETE')
224

    
225
    def read(self, request, id=None):
226
        """List Shared IP Groups"""
227
        if id is None:
228
            return {}
229
        elif id == "detail":
230
            return {}
231
        else:
232
            raise fault.itemNotFound
233

    
234
    def create(self, request, id):
235
        """Creates a new Shared IP Group"""
236
        return created
237

    
238
    def delete(self, request, id):
239
        """Deletes a Shared IP Group"""
240
        return noContent
241

    
242

    
243
class LimitHandler(BaseHandler):
244
    allowed_methods = ('GET',)
245

    
246
    # XXX: hookup with @throttle
247

    
248
    rate = [
249
        {
250
           "verb" : "POST",
251
           "URI" : "*",
252
           "regex" : ".*",
253
           "value" : 10,
254
           "remaining" : 2,
255
           "unit" : "MINUTE",
256
           "resetTime" : 1244425439
257
        },
258
        {
259
           "verb" : "POST",
260
           "URI" : "*/servers",
261
           "regex" : "^/servers",
262
           "value" : 25,
263
           "remaining" : 24,
264
           "unit" : "DAY",
265
           "resetTime" : 1244511839
266
        },
267
        {
268
           "verb" : "PUT",
269
           "URI" : "*",
270
           "regex" : ".*",
271
           "value" : 10,
272
           "remaining" : 2,
273
           "unit" : "MINUTE",
274
           "resetTime" : 1244425439
275
        },
276
        {
277
           "verb" : "GET",
278
           "URI" : "*",
279
           "regex" : ".*",
280
           "value" : 3,
281
           "remaining" : 3,
282
           "unit" : "MINUTE",
283
           "resetTime" : 1244425439
284
        },
285
        {
286
           "verb" : "DELETE",
287
           "URI" : "*",
288
           "regex" : ".*",
289
           "value" : 100,
290
           "remaining" : 100,
291
           "unit" : "MINUTE",
292
           "resetTime" : 1244425439
293
        }
294
    ]
295

    
296
    absolute = {
297
        "maxTotalRAMSize" : 51200,
298
        "maxIPGroups" : 50,
299
        "maxIPGroupMembers" : 25
300
    }
301

    
302
    def read(self, request):
303
        return { "limits": {
304
                "rate": self.rate,
305
                "absolute": self.absolute,
306
               }
307
            }