Statistics
| Branch: | Tag: | Revision:

root / api / handlers.py @ 4e6f9904

History | View | Annotate | Download (37.4 kB)

1 00b4f1be Faidon Liambotis
# vim: ts=4 sts=4 et ai sw=4 fileencoding=utf-8
2 00b4f1be Faidon Liambotis
#
3 e9134601 Constantinos Venetsanopoulos
# Copyright © 2010 Greek Research and Technology Network
4 8b78d1a5 Markos Gogoulos
5 285a1fa8 Dimitris Moraitis
import simplejson as json
6 2c089b77 Faidon Liambotis
from django.conf import settings
7 285a1fa8 Dimitris Moraitis
from django.http import HttpResponse
8 00b4f1be Faidon Liambotis
from piston.handler import BaseHandler, AnonymousBaseHandler
9 1a49199e Dimitris Moraitis
from synnefo.api.faults import fault, noContent, accepted, created, notModified
10 2c089b77 Faidon Liambotis
from synnefo.api.helpers import instance_to_server, paginator
11 c18611c8 Markos Gogoulos
from synnefo.util.rapi import GanetiRapiClient, GanetiApiError, CertificateError
12 a31ff6cb Markos Gogoulos
from synnefo.db.models import *
13 285a1fa8 Dimitris Moraitis
from time import sleep
14 01199e0b Markos Gogoulos
import random
15 01199e0b Markos Gogoulos
import string
16 285a1fa8 Dimitris Moraitis
import logging
17 1a49199e Dimitris Moraitis
from datetime import datetime
18 285a1fa8 Dimitris Moraitis
19 285a1fa8 Dimitris Moraitis
log = logging.getLogger('synnefo.api.handlers')
20 253f0c82 Faidon Liambotis
21 c5e38339 Markos Gogoulos
try:
22 ec06b07c Dimitris Moraitis
    rapi = GanetiRapiClient(*settings.GANETI_CLUSTER_INFO)
23 c5e38339 Markos Gogoulos
    rapi.GetVersion()
24 c18611c8 Markos Gogoulos
except Exception, e:
25 6b83d46b Markos Gogoulos
    log.exception('Unexpected error: %s' % e)
26 c5e38339 Markos Gogoulos
    raise fault.serviceUnavailable
27 c5e38339 Markos Gogoulos
#If we can't connect to the rapi successfully, don't do anything
28 00b4f1be Faidon Liambotis
29 f5ad2956 Markos Gogoulos
backend_prefix_id = settings.BACKEND_PREFIX_ID
30 ccbd9f9b Markos Gogoulos
31 00b4f1be Faidon Liambotis
VERSIONS = [
32 00b4f1be Faidon Liambotis
    {
33 00b4f1be Faidon Liambotis
        "status": "CURRENT",
34 00b4f1be Faidon Liambotis
        "id": "v1.0",
35 ac7188e6 Markos Gogoulos
        "docURL" : "http://docs.rackspacecloud.com/servers/api/v1.0/cs-devguide-20110112.pdf",
36 00b4f1be Faidon Liambotis
        "wadl" : "http://docs.rackspacecloud.com/servers/api/v1.0/application.wadl"
37 00b4f1be Faidon Liambotis
    },
38 9071888e Constantinos Venetsanopoulos
    {
39 9071888e Constantinos Venetsanopoulos
        "status": "CURRENT",
40 60023e66 Constantinos Venetsanopoulos
        "id": "v1.1",
41 60023e66 Constantinos Venetsanopoulos
        "docURL" : "http://docs.openstack.org/openstack-compute/developer/content/",
42 60023e66 Constantinos Venetsanopoulos
        "wadl" : "None yet"
43 60023e66 Constantinos Venetsanopoulos
    },
44 60023e66 Constantinos Venetsanopoulos
    {
45 60023e66 Constantinos Venetsanopoulos
        "status": "CURRENT",
46 9071888e Constantinos Venetsanopoulos
        "id": "v1.0grnet1",
47 9071888e Constantinos Venetsanopoulos
        "docURL" : "None yet",
48 9071888e Constantinos Venetsanopoulos
        "wad1" : "None yet"
49 9071888e Constantinos Venetsanopoulos
    }
50 00b4f1be Faidon Liambotis
]
51 00b4f1be Faidon Liambotis
52 f5ea24a9 Markos Gogoulos
#read is called on GET requests
53 f5ea24a9 Markos Gogoulos
#create is called on POST, and creates new objects
54 f5ea24a9 Markos Gogoulos
#update is called on PUT, and should update an existing product
55 f5ea24a9 Markos Gogoulos
#delete is called on DELETE, and should delete an existing object
56 f5ea24a9 Markos Gogoulos
57 ccbd9f9b Markos Gogoulos
58 00b4f1be Faidon Liambotis
class VersionHandler(AnonymousBaseHandler):
59 00b4f1be Faidon Liambotis
    allowed_methods = ('GET',)
60 00b4f1be Faidon Liambotis
61 00b4f1be Faidon Liambotis
    def read(self, request, number=None):
62 ffffd5fe Markos Gogoulos
        try:
63 ffffd5fe Markos Gogoulos
            if number is None:
64 ffffd5fe Markos Gogoulos
                versions = map(lambda v: {
65 ffffd5fe Markos Gogoulos
                            "status": v["status"],
66 ffffd5fe Markos Gogoulos
                            "id": v["id"],
67 ffffd5fe Markos Gogoulos
                        }, VERSIONS)
68 ffffd5fe Markos Gogoulos
                return { "versions": versions }
69 ffffd5fe Markos Gogoulos
            else:
70 ffffd5fe Markos Gogoulos
                for version in VERSIONS:
71 ffffd5fe Markos Gogoulos
                    if version["id"] == number:
72 ffffd5fe Markos Gogoulos
                        return { "version": version }
73 ffffd5fe Markos Gogoulos
                raise fault.itemNotFound
74 ffffd5fe Markos Gogoulos
        except Exception, e:
75 6b83d46b Markos Gogoulos
            log.exception('Unexpected error: %s' % e)
76 ffffd5fe Markos Gogoulos
            raise fault.serviceUnavailable
77 00b4f1be Faidon Liambotis
78 00b4f1be Faidon Liambotis
79 00b4f1be Faidon Liambotis
class ServerHandler(BaseHandler):
80 f5ea24a9 Markos Gogoulos
    """Handler responsible for the Servers
81 f5ea24a9 Markos Gogoulos

82 f5ea24a9 Markos Gogoulos
     handles the listing of Virtual Machines, Creates and Destroys VM's
83 f5ea24a9 Markos Gogoulos

84 f5ea24a9 Markos Gogoulos
     @HTTP methods: POST, DELETE, PUT, GET
85 f5ea24a9 Markos Gogoulos
     @Parameters: POST data with the create data (cpu, ram, etc)
86 a788c7ab Markos Gogoulos
     @Responses: HTTP 200 if successfully call rapi, 304 if not modified, itemNotFound or serviceUnavailable otherwise
87 f5ea24a9 Markos Gogoulos

88 f5ea24a9 Markos Gogoulos
    """
89 fd4828ce Faidon Liambotis
    allowed_methods = ('GET', 'POST', 'PUT', 'DELETE')
90 fd4828ce Faidon Liambotis
91 00b4f1be Faidon Liambotis
    def read(self, request, id=None):
92 38e2c5ed Christodoulos Psaltis
        from time import sleep
93 dc8b976e Markos Gogoulos
        sleep(0.5)
94 ccbd9f9b Markos Gogoulos
        #TODO: delete the sleep once the mock objects are removed
95 00b4f1be Faidon Liambotis
        if id is None:
96 00b4f1be Faidon Liambotis
            return self.read_all(request)
97 253f0c82 Faidon Liambotis
        elif id == "detail":
98 00b4f1be Faidon Liambotis
            return self.read_all(request, detail=True)
99 00b4f1be Faidon Liambotis
        else:
100 00b4f1be Faidon Liambotis
            return self.read_one(request, id)
101 00b4f1be Faidon Liambotis
102 00b4f1be Faidon Liambotis
    def read_one(self, request, id):
103 909f415b Faidon Liambotis
        try:
104 37a57502 Markos Gogoulos
            server = VirtualMachine.objects.get(id=id)
105 ffffd5fe Markos Gogoulos
106 ffffd5fe Markos Gogoulos
            server = {'status': server.rsapi_state, 
107 b335768e Markos Gogoulos
                     'flavorRef': server.flavor.id, 
108 ffffd5fe Markos Gogoulos
                     'name': server.name, 
109 ffffd5fe Markos Gogoulos
                     'id': server.id, 
110 b335768e Markos Gogoulos
                     'imageRef': server.sourceimage.id,
111 b335768e Markos Gogoulos
                     'created': server.created, 
112 1a49199e Dimitris Moraitis
                     'updated': server.updated,
113 ffffd5fe Markos Gogoulos
                     'hostId': server.hostid, 
114 63597809 Markos Gogoulos
                     'progress': server.rsapi_state == 'ACTIVE' and 100 or 0, 
115 ffffd5fe Markos Gogoulos
                     #'metadata': {'Server_Label': server.description },
116 ffffd5fe Markos Gogoulos
                     'metadata':[{'meta': { 'key': {metadata.meta_key: metadata.meta_value}}} for metadata in server.virtualmachinemetadata_set.all()],                                    
117 ffffd5fe Markos Gogoulos
                     'addresses': {'public': { 'ip': {'addr': server.ipfour}, 'ip6': {'addr': server.ipsix}},'private': ''},      
118 ffffd5fe Markos Gogoulos
                    }
119 ffffd5fe Markos Gogoulos
            return { "server": server } 
120 c18611c8 Markos Gogoulos
        except VirtualMachine.DoesNotExist:
121 909f415b Faidon Liambotis
            raise fault.itemNotFound
122 c18611c8 Markos Gogoulos
        except VirtualMachine.MultipleObjectsReturned:
123 c18611c8 Markos Gogoulos
            raise fault.serviceUnavailable
124 c18611c8 Markos Gogoulos
        except Exception, e:
125 6b83d46b Markos Gogoulos
            log.exception('Unexpected error: %s' % e)
126 c18611c8 Markos Gogoulos
            raise fault.serviceUnavailable
127 37a57502 Markos Gogoulos
128 00b4f1be Faidon Liambotis
129 2c089b77 Faidon Liambotis
    @paginator
130 00b4f1be Faidon Liambotis
    def read_all(self, request, detail=False):
131 ffffd5fe Markos Gogoulos
        try:
132 ab5282e4 Dimitris Moraitis
            changes_since = request.GET.get("changes-since", 0)
133 d19719cd Markos Gogoulos
            if changes_since:
134 1a49199e Dimitris Moraitis
                last_update = datetime.fromtimestamp(int(changes_since))
135 88854f35 Dimitris Moraitis
                virtual_servers = VirtualMachine.objects.filter(updated__gt=last_update)
136 1a49199e Dimitris Moraitis
                if not len(virtual_servers):
137 1a49199e Dimitris Moraitis
                    return notModified
138 d19719cd Markos Gogoulos
            else:
139 d19719cd Markos Gogoulos
                virtual_servers = VirtualMachine.objects.filter(deleted=False)
140 ffffd5fe Markos Gogoulos
            #get all VM's for now, FIX it to take the user's VMs only yet. also don't get deleted VM's
141 a3808aa8 Markos Gogoulos
        except Exception, e:
142 a3808aa8 Markos Gogoulos
            raise fault.badRequest        
143 a3808aa8 Markos Gogoulos
        try:
144 ffffd5fe Markos Gogoulos
            if not detail:
145 ffffd5fe Markos Gogoulos
                return { "servers": [ { "id": s.id, "name": s.name } for s in virtual_servers ] }
146 ffffd5fe Markos Gogoulos
            else:
147 0e1531b4 Markos Gogoulos
                virtual_servers_list = [{'status': server.deleted and "DELETED" or server.rsapi_state, 
148 b335768e Markos Gogoulos
                                         'flavorRef': server.flavor.id, 
149 ffffd5fe Markos Gogoulos
                                         'name': server.name, 
150 ffffd5fe Markos Gogoulos
                                         'id': server.id, 
151 b335768e Markos Gogoulos
                                         'created': server.created, 
152 1a49199e Dimitris Moraitis
                                         'updated': server.updated,
153 b335768e Markos Gogoulos
                                         'imageRef': server.sourceimage.id, 
154 ffffd5fe Markos Gogoulos
                                         'hostId': server.hostid, 
155 63597809 Markos Gogoulos
                                         'progress': server.rsapi_state == 'ACTIVE' and 100 or 0, 
156 ffffd5fe Markos Gogoulos
                                         #'metadata': {'Server_Label': server.description },
157 ffffd5fe Markos Gogoulos
                                         'metadata':[{'meta': { 'key': {metadata.meta_key: metadata.meta_value}}} for metadata in server.virtualmachinemetadata_set.all()],                                    
158 ffffd5fe Markos Gogoulos
                                         'addresses': {'public': { 'ip': {'addr': server.ipfour}, 'ip6': {'addr': server.ipsix}},'private': ''},      
159 ffffd5fe Markos Gogoulos
160 ffffd5fe Markos Gogoulos
                                        } for server in virtual_servers]
161 ffffd5fe Markos Gogoulos
                #pass some fake data regarding ip, since we don't have any such data            
162 ffffd5fe Markos Gogoulos
                return { "servers":  virtual_servers_list }                
163 ffffd5fe Markos Gogoulos
        except Exception, e:
164 6b83d46b Markos Gogoulos
            log.exception('Unexpected error: %s' % e)
165 ffffd5fe Markos Gogoulos
            raise fault.serviceUnavailable
166 e107ee57 Markos Gogoulos
167 00b4f1be Faidon Liambotis
168 00b4f1be Faidon Liambotis
    def create(self, request):
169 5ad45fcc Dimitris Moraitis
        """ Parse RackSpace API create request to generate rapi create request
170 285a1fa8 Dimitris Moraitis
        
171 285a1fa8 Dimitris Moraitis
            TODO: auto generate and set password
172 285a1fa8 Dimitris Moraitis
        """
173 34a619ae Vangelis Koukis
        # Check if we have all the necessary data in the JSON request       
174 debeeec9 Markos Gogoulos
        try:
175 285a1fa8 Dimitris Moraitis
            server = json.loads(request.raw_post_data)['server']
176 8714499d Markos Gogoulos
            name = server['name']
177 b335768e Markos Gogoulos
            flavorRef = server['flavorRef']
178 b335768e Markos Gogoulos
            flavor = Flavor.objects.get(id=flavorRef)
179 b335768e Markos Gogoulos
            imageRef = server['imageRef']
180 b335768e Markos Gogoulos
            image = Image.objects.get(id=imageRef)
181 285a1fa8 Dimitris Moraitis
            metadata = server['metadata']
182 285a1fa8 Dimitris Moraitis
            personality = server.get('personality', None)
183 2baac7ca Markos Gogoulos
        except (Flavor.DoesNotExist, Image.DoesNotExist):
184 2baac7ca Markos Gogoulos
            raise fault.itemNotFound
185 2baac7ca Markos Gogoulos
        except (Flavor.MultipleObjectsReturned, Image.MultipleObjectsReturned):
186 2baac7ca Markos Gogoulos
            raise fault.serviceUnavailable
187 285a1fa8 Dimitris Moraitis
        except Exception as e:
188 6b83d46b Markos Gogoulos
            log.exception('Malformed create request: %s - %s' % (e, request.raw_post_data))    
189 71008c92 Markos Gogoulos
            raise fault.badRequest
190 c18611c8 Markos Gogoulos
191 34a619ae Vangelis Koukis
        # TODO: Proper Authn, Authz
192 34a619ae Vangelis Koukis
        # Everything belongs to a single SynnefoUser for now.
193 34a619ae Vangelis Koukis
        try:          
194 34a619ae Vangelis Koukis
            owner = SynnefoUser.objects.all()[0]
195 34a619ae Vangelis Koukis
        except Exception as e:
196 6b83d46b Markos Gogoulos
            log.exception('Cannot find a single SynnefoUser in the DB: %s' % (e));
197 34a619ae Vangelis Koukis
            raise fault.unauthorized
198 34a619ae Vangelis Koukis
199 285a1fa8 Dimitris Moraitis
        # add the new VM to the local db
200 a43b7f70 Dimitris Moraitis
        try:
201 34a619ae Vangelis Koukis
            vm = VirtualMachine.objects.create(sourceimage=image, ipfour='0.0.0.0', ipsix='::1', flavor=flavor, owner=owner)
202 a43b7f70 Dimitris Moraitis
        except Exception as e:
203 6b83d46b Markos Gogoulos
            log.exception("Can't save vm: %s" % e)
204 a43b7f70 Dimitris Moraitis
            raise fault.serviceUnavailable
205 a43b7f70 Dimitris Moraitis
206 c18611c8 Markos Gogoulos
        try:
207 8714499d Markos Gogoulos
            vm.name = name
208 8714499d Markos Gogoulos
            #vm.description = descr
209 285a1fa8 Dimitris Moraitis
            vm.save()            
210 285a1fa8 Dimitris Moraitis
            jobId = rapi.CreateInstance(
211 285a1fa8 Dimitris Moraitis
                'create',
212 8714499d Markos Gogoulos
                request.META['SERVER_NAME'] == 'testserver' and 'test-server' or vm.backend_id,
213 285a1fa8 Dimitris Moraitis
                'plain',
214 9a6600f3 Vangelis Koukis
                # disk field of Flavor object is in GB, value specified here is in MB
215 9a6600f3 Vangelis Koukis
                # FIXME: Always ask for a 2GB disk, current LVM physical groups are too small:
216 9a6600f3 Vangelis Koukis
                # [{"size": flavor.disk * 1000}],
217 9a6600f3 Vangelis Koukis
                [{"size": 2000}],
218 285a1fa8 Dimitris Moraitis
                [{}],
219 b335768e Markos Gogoulos
                #TODO: select OS from imageRef
220 285a1fa8 Dimitris Moraitis
                os='debootstrap+default',
221 285a1fa8 Dimitris Moraitis
                ip_check=False,
222 285a1fa8 Dimitris Moraitis
                name_check=False,
223 285a1fa8 Dimitris Moraitis
                #TODO: verify if this is necessary
224 285a1fa8 Dimitris Moraitis
                pnode = rapi.GetNodes()[0],
225 285a1fa8 Dimitris Moraitis
                # Dry run when called by unit tests
226 285a1fa8 Dimitris Moraitis
                dry_run = request.META['SERVER_NAME'] == 'testserver',
227 285a1fa8 Dimitris Moraitis
                beparams={
228 285a1fa8 Dimitris Moraitis
                            'auto_balance': True,
229 285a1fa8 Dimitris Moraitis
                            'vcpus': flavor.cpu,
230 285a1fa8 Dimitris Moraitis
                            'memory': flavor.ram,
231 285a1fa8 Dimitris Moraitis
                        },
232 285a1fa8 Dimitris Moraitis
                )
233 71642965 Dimitris Moraitis
            log.info('created vm with %s cpus, %s ram and %s storage' % (flavor.cpu, flavor.ram, flavor.disk))
234 a43b7f70 Dimitris Moraitis
        except (GanetiApiError, CertificateError) as e:
235 6b83d46b Markos Gogoulos
            log.exception('CreateInstance failed: %s' % e)
236 285a1fa8 Dimitris Moraitis
            vm.deleted = True
237 285a1fa8 Dimitris Moraitis
            vm.save()
238 c18611c8 Markos Gogoulos
            raise fault.serviceUnavailable
239 a43b7f70 Dimitris Moraitis
        except Exception as e:
240 6b83d46b Markos Gogoulos
            log.exception('Unexpected error: %s' % e)
241 a43b7f70 Dimitris Moraitis
            vm.deleted = True
242 a43b7f70 Dimitris Moraitis
            vm.save()
243 01199e0b Markos Gogoulos
            raise fault.serviceUnavailable            
244 285a1fa8 Dimitris Moraitis
        
245 285a1fa8 Dimitris Moraitis
246 01199e0b Markos Gogoulos
        ret = {'server': {
247 01199e0b Markos Gogoulos
                'id' : vm.id,
248 01199e0b Markos Gogoulos
                'name' : vm.name,
249 b335768e Markos Gogoulos
                "imageRef" : imageRef,
250 b335768e Markos Gogoulos
                "flavorRef" : flavorRef,
251 01199e0b Markos Gogoulos
                "hostId" : vm.hostid,
252 01199e0b Markos Gogoulos
                "progress" : 0,
253 01199e0b Markos Gogoulos
                "status" : 'BUILD',
254 01199e0b Markos Gogoulos
                "adminPass" : self.random_password(),
255 4e6f9904 Markos Gogoulos
                "metadata" : {"My Server Name" : vm.name},
256 01199e0b Markos Gogoulos
                "addresses" : {
257 01199e0b Markos Gogoulos
                    "public" : [  ],
258 01199e0b Markos Gogoulos
                    "private" : [  ],
259 285a1fa8 Dimitris Moraitis
                    },
260 01199e0b Markos Gogoulos
                },
261 01199e0b Markos Gogoulos
        }
262 01199e0b Markos Gogoulos
        return HttpResponse(json.dumps(ret), mimetype="application/json", status=202)
263 01199e0b Markos Gogoulos
264 01199e0b Markos Gogoulos
265 01199e0b Markos Gogoulos
    def random_password(self):
266 01199e0b Markos Gogoulos
        "return random password"
267 01199e0b Markos Gogoulos
        number_of_chars = 8
268 01199e0b Markos Gogoulos
        possible_chars = string.ascii_uppercase + string.ascii_lowercase + string.digits
269 01199e0b Markos Gogoulos
        return ''.join(random.choice(possible_chars) for x in range(number_of_chars))
270 01199e0b Markos Gogoulos
271 00b4f1be Faidon Liambotis
272 00b4f1be Faidon Liambotis
    def update(self, request, id):
273 73469364 Markos Gogoulos
        """Sets and updates Virtual Machine Metadata. 
274 73469364 Markos Gogoulos
 
275 73469364 Markos Gogoulos
        """
276 73469364 Markos Gogoulos
        try:
277 73469364 Markos Gogoulos
            metadata_request = json.loads(request.raw_post_data)['metadata']
278 73469364 Markos Gogoulos
            metadata_key = metadata_request.get('metadata_key')
279 73469364 Markos Gogoulos
            metadata_value = metadata_request.get('metadata_value')
280 73469364 Markos Gogoulos
 
281 73469364 Markos Gogoulos
            vm = VirtualMachine.objects.get(id=id)
282 73469364 Markos Gogoulos
            #we only update virtual machine's name atm
283 73469364 Markos Gogoulos
            if metadata_key == 'name':
284 73469364 Markos Gogoulos
                vm.name = metadata_value
285 73469364 Markos Gogoulos
                vm.save()
286 73469364 Markos Gogoulos
                return accepted
287 73469364 Markos Gogoulos
        except VirtualMachine.DoesNotExist:
288 73469364 Markos Gogoulos
            raise fault.itemNotFound
289 73469364 Markos Gogoulos
        except VirtualMachine.MultipleObjectsReturned:
290 73469364 Markos Gogoulos
            raise fault.serviceUnavailable
291 73469364 Markos Gogoulos
        except Exception, e:
292 6b83d46b Markos Gogoulos
            log.exception('Unexpected error: %s' % e)
293 73469364 Markos Gogoulos
            raise fault.serviceUnavailable
294 73469364 Markos Gogoulos
295 f0858246 Markos Gogoulos
        raise fault.itemNotFound
296 00b4f1be Faidon Liambotis
297 73469364 Markos Gogoulos
298 00b4f1be Faidon Liambotis
    def delete(self, request, id):
299 9eef701d Markos Gogoulos
        try:
300 c18611c8 Markos Gogoulos
            vm = VirtualMachine.objects.get(id=id)
301 ffffd5fe Markos Gogoulos
            #TODO: set the status to DESTROYED
302 ffffd5fe Markos Gogoulos
            vm.start_action('DESTROY')
303 ffffd5fe Markos Gogoulos
            rapi.DeleteInstance(vm.backend_id)
304 ffffd5fe Markos Gogoulos
            return accepted        
305 c18611c8 Markos Gogoulos
        except VirtualMachine.DoesNotExist:
306 9eef701d Markos Gogoulos
            raise fault.itemNotFound
307 c18611c8 Markos Gogoulos
        except VirtualMachine.MultipleObjectsReturned:
308 c18611c8 Markos Gogoulos
            raise fault.serviceUnavailable
309 c18611c8 Markos Gogoulos
        except GanetiApiError, CertificateError:
310 c18611c8 Markos Gogoulos
            raise fault.serviceUnavailable
311 c18611c8 Markos Gogoulos
        except Exception, e:
312 6b83d46b Markos Gogoulos
            log.exception('Unexpected error: %s' % e)
313 c18611c8 Markos Gogoulos
            raise fault.serviceUnavailable
314 00b4f1be Faidon Liambotis
315 ffffd5fe Markos Gogoulos
316 00b4f1be Faidon Liambotis
317 00b4f1be Faidon Liambotis
class ServerAddressHandler(BaseHandler):
318 d73d59e4 Markos Gogoulos
    """Handler responsible for Server Addresses
319 d73d59e4 Markos Gogoulos

320 d73d59e4 Markos Gogoulos
     handles Reboot, Shutdown and Start actions. 
321 d73d59e4 Markos Gogoulos

322 d73d59e4 Markos Gogoulos
     @HTTP methods: GET
323 d73d59e4 Markos Gogoulos
     @Parameters: Id of server and networkID (eg public, private)
324 d73d59e4 Markos Gogoulos
     @Responses: HTTP 200 if successfully call rapi, itemNotFound, serviceUnavailable otherwise
325 d73d59e4 Markos Gogoulos

326 d73d59e4 Markos Gogoulos
    """
327 d73d59e4 Markos Gogoulos
    allowed_methods = ('GET',)
328 00b4f1be Faidon Liambotis
329 76c8e33d Markos Gogoulos
    def read(self, request, id, networkID=None):
330 00b4f1be Faidon Liambotis
        """List IP addresses for a server"""
331 ccbd9f9b Markos Gogoulos
332 d73d59e4 Markos Gogoulos
        try:
333 d73d59e4 Markos Gogoulos
            server = VirtualMachine.objects.get(id=id)
334 d73d59e4 Markos Gogoulos
            address =  {'public': { 'ip': {'addr': server.ipfour}, 'ip6': {'addr': server.ipsix}},'private': ''}                                          
335 d73d59e4 Markos Gogoulos
        except VirtualMachine.DoesNotExist:
336 d73d59e4 Markos Gogoulos
            raise fault.itemNotFound
337 d73d59e4 Markos Gogoulos
        except VirtualMachine.MultipleObjectsReturned:
338 d73d59e4 Markos Gogoulos
            raise fault.serviceUnavailable
339 d73d59e4 Markos Gogoulos
        except Exception, e:
340 d73d59e4 Markos Gogoulos
            log.exception('Unexpected error: %s' % e)
341 d73d59e4 Markos Gogoulos
            raise fault.serviceUnavailable
342 00b4f1be Faidon Liambotis
343 d73d59e4 Markos Gogoulos
        if networkID == "public":
344 d73d59e4 Markos Gogoulos
            address = {'public': { 'ip': {'addr': server.ipfour}, 'ip6': {'addr': server.ipsix}}}                            
345 d73d59e4 Markos Gogoulos
        elif networkID == "private":
346 964185dd Markos Gogoulos
            address = {'private': ''}    
347 964185dd Markos Gogoulos
        elif networkID != None:
348 964185dd Markos Gogoulos
            raise fault.badRequest
349 d73d59e4 Markos Gogoulos
        return { "addresses": address } 
350 00b4f1be Faidon Liambotis
351 00b4f1be Faidon Liambotis
352 00b4f1be Faidon Liambotis
353 00b4f1be Faidon Liambotis
class ServerActionHandler(BaseHandler):
354 f5ea24a9 Markos Gogoulos
    """Handler responsible for Server Actions
355 f5ea24a9 Markos Gogoulos

356 f5ea24a9 Markos Gogoulos
     handles Reboot, Shutdown and Start actions. 
357 f5ea24a9 Markos Gogoulos

358 f5ea24a9 Markos Gogoulos
     @HTTP methods: POST, DELETE, PUT
359 f5ea24a9 Markos Gogoulos
     @Parameters: POST data with the action (reboot, shutdown, start)
360 f5ea24a9 Markos Gogoulos
     @Responses: HTTP 202 if successfully call rapi, itemNotFound, serviceUnavailable otherwise
361 f5ea24a9 Markos Gogoulos

362 f5ea24a9 Markos Gogoulos
    """
363 f5ea24a9 Markos Gogoulos
364 f5ea24a9 Markos Gogoulos
    allowed_methods = ('POST', 'DELETE',  'PUT')
365 00b4f1be Faidon Liambotis
366 00b4f1be Faidon Liambotis
    def create(self, request, id):
367 f5ea24a9 Markos Gogoulos
        """Reboot, Shutdown, Start virtual machine"""
368 aa6f51fd Markos Gogoulos
        
369 c18611c8 Markos Gogoulos
        try:
370 ffffd5fe Markos Gogoulos
            requested_action = json.loads(request.raw_post_data)
371 ffffd5fe Markos Gogoulos
            reboot_request = requested_action.get('reboot', None)
372 ffffd5fe Markos Gogoulos
            shutdown_request = requested_action.get('shutdown', None)
373 ffffd5fe Markos Gogoulos
            start_request = requested_action.get('start', None)
374 ffffd5fe Markos Gogoulos
            #action not implemented
375 6130effc Dimitris Moraitis
            action = reboot_request and 'REBOOT' or shutdown_request and 'STOP' or start_request and 'START'
376 ffffd5fe Markos Gogoulos
377 ffffd5fe Markos Gogoulos
            if not action:
378 ffffd5fe Markos Gogoulos
                raise fault.notImplemented 
379 ffffd5fe Markos Gogoulos
            #test if we can get the vm
380 c18611c8 Markos Gogoulos
            vm = VirtualMachine.objects.get(id=id)
381 c18611c8 Markos Gogoulos
            vm.start_action(action)
382 c18611c8 Markos Gogoulos
383 c18611c8 Markos Gogoulos
            if reboot_request:
384 c18611c8 Markos Gogoulos
                rapi.RebootInstance(vm.backend_id)
385 c18611c8 Markos Gogoulos
            elif shutdown_request:
386 c18611c8 Markos Gogoulos
                rapi.ShutdownInstance(vm.backend_id)
387 c18611c8 Markos Gogoulos
            elif start_request:
388 c18611c8 Markos Gogoulos
                rapi.StartupInstance(vm.backend_id)
389 c18611c8 Markos Gogoulos
            return accepted
390 ffffd5fe Markos Gogoulos
        except VirtualMachine.DoesNotExist:
391 ffffd5fe Markos Gogoulos
            raise fault.itemNotFound
392 ffffd5fe Markos Gogoulos
        except VirtualMachine.MultipleObjectsReturned:
393 ffffd5fe Markos Gogoulos
            raise fault.serviceUnavailable
394 c18611c8 Markos Gogoulos
        except GanetiApiError, CertificateError:
395 c18611c8 Markos Gogoulos
            raise fault.serviceUnavailable
396 c18611c8 Markos Gogoulos
        except Exception, e:
397 6b83d46b Markos Gogoulos
            log.exception('Unexpected error: %s' % e)
398 c18611c8 Markos Gogoulos
            raise fault.serviceUnavailable
399 c18611c8 Markos Gogoulos
400 ccbd9f9b Markos Gogoulos
    def delete(self, request, id):
401 ccbd9f9b Markos Gogoulos
        """Delete an Instance"""
402 ccbd9f9b Markos Gogoulos
        return accepted
403 ccbd9f9b Markos Gogoulos
404 ccbd9f9b Markos Gogoulos
    def update(self, request, id):
405 f0858246 Markos Gogoulos
        raise fault.itemNotFound
406 ccbd9f9b Markos Gogoulos
407 ccbd9f9b Markos Gogoulos
408 c99adc90 Faidon Liambotis
class ServerBackupHandler(BaseHandler):
409 c99adc90 Faidon Liambotis
    """ Backup Schedules are not implemented yet, return notImplemented """
410 c99adc90 Faidon Liambotis
    allowed_methods = ('GET', 'POST', 'DELETE')
411 c99adc90 Faidon Liambotis
412 c99adc90 Faidon Liambotis
    def read(self, request, id):
413 635cfd6e Faidon Liambotis
        raise fault.notImplemented
414 c99adc90 Faidon Liambotis
415 c99adc90 Faidon Liambotis
    def create(self, request, id):
416 635cfd6e Faidon Liambotis
        raise fault.notImplemented
417 c99adc90 Faidon Liambotis
418 c99adc90 Faidon Liambotis
    def delete(self, request, id):
419 635cfd6e Faidon Liambotis
        raise fault.notImplemented
420 c99adc90 Faidon Liambotis
421 c99adc90 Faidon Liambotis
422 60023e66 Constantinos Venetsanopoulos
class ServerMetadataHandler(BaseHandler):
423 60023e66 Constantinos Venetsanopoulos
    """Handles Metadata of a specific Server
424 60023e66 Constantinos Venetsanopoulos

425 60023e66 Constantinos Venetsanopoulos
    the handler Lists, Creates, Updates and Deletes Metadata values
426 60023e66 Constantinos Venetsanopoulos

427 60023e66 Constantinos Venetsanopoulos
    @HTTP methods: POST, DELETE, PUT, GET
428 60023e66 Constantinos Venetsanopoulos
    @Parameters: POST data with key value pairs
429 60023e66 Constantinos Venetsanopoulos

430 60023e66 Constantinos Venetsanopoulos
    """
431 60023e66 Constantinos Venetsanopoulos
    allowed_methods = ('GET', 'POST', 'PUT', 'DELETE')
432 60023e66 Constantinos Venetsanopoulos
433 60023e66 Constantinos Venetsanopoulos
    def read(self, request, id, key=None):
434 60023e66 Constantinos Venetsanopoulos
        """List metadata of the specific server"""
435 60023e66 Constantinos Venetsanopoulos
        if key is None:
436 60023e66 Constantinos Venetsanopoulos
            return self.read_allkeys(request, id)
437 60023e66 Constantinos Venetsanopoulos
        else:
438 60023e66 Constantinos Venetsanopoulos
            return self.read_onekey(request, id, key)
439 60023e66 Constantinos Venetsanopoulos
440 60023e66 Constantinos Venetsanopoulos
    def read_allkeys(self, request, id):
441 60023e66 Constantinos Venetsanopoulos
        """Returns all the key value pairs of the specified server"""
442 60023e66 Constantinos Venetsanopoulos
        try:
443 60023e66 Constantinos Venetsanopoulos
            server = VirtualMachine.objects.get(pk=id)
444 60023e66 Constantinos Venetsanopoulos
            return {
445 60023e66 Constantinos Venetsanopoulos
                "metadata": {
446 60023e66 Constantinos Venetsanopoulos
                    "values": [
447 60023e66 Constantinos Venetsanopoulos
                        {m.meta_key: m.meta_value} for m in server.virtualmachinemetadata_set.all()
448 60023e66 Constantinos Venetsanopoulos
                    ]
449 60023e66 Constantinos Venetsanopoulos
                }
450 60023e66 Constantinos Venetsanopoulos
            }
451 60023e66 Constantinos Venetsanopoulos
        except VirtualMachine.DoesNotExist:
452 60023e66 Constantinos Venetsanopoulos
            raise fault.itemNotFound
453 60023e66 Constantinos Venetsanopoulos
        except VirtualMachine.MultipleObjectsReturned:
454 60023e66 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
455 60023e66 Constantinos Venetsanopoulos
        except Exception, e:
456 60023e66 Constantinos Venetsanopoulos
            log.exception('Unexpected error: %s' % e)
457 60023e66 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
458 60023e66 Constantinos Venetsanopoulos
        
459 60023e66 Constantinos Venetsanopoulos
    def read_onekey(self, request, id, key):
460 60023e66 Constantinos Venetsanopoulos
        """Returns the specified metadata key of the specified server"""
461 60023e66 Constantinos Venetsanopoulos
        try:
462 60023e66 Constantinos Venetsanopoulos
            server = VirtualMachine.objects.get(pk=id)
463 60023e66 Constantinos Venetsanopoulos
            return {
464 60023e66 Constantinos Venetsanopoulos
                "metadata": {
465 60023e66 Constantinos Venetsanopoulos
                    "values": [
466 60023e66 Constantinos Venetsanopoulos
                        {m.meta_key: m.meta_value} for m in server.virtualmachinemetadata_set.filter(meta_key=key)
467 60023e66 Constantinos Venetsanopoulos
                    ]
468 60023e66 Constantinos Venetsanopoulos
                }
469 60023e66 Constantinos Venetsanopoulos
            }
470 60023e66 Constantinos Venetsanopoulos
        except VirtualMachineMetadata.DoesNotExist:
471 60023e66 Constantinos Venetsanopoulos
            raise fault.itemNotFound            
472 60023e66 Constantinos Venetsanopoulos
        except VirtualMachine.DoesNotExist:
473 60023e66 Constantinos Venetsanopoulos
            raise fault.itemNotFound
474 60023e66 Constantinos Venetsanopoulos
        except VirtualMachine.MultipleObjectsReturned:
475 60023e66 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
476 60023e66 Constantinos Venetsanopoulos
        except Exception, e:
477 60023e66 Constantinos Venetsanopoulos
            log.exception('Unexpected error: %s' % e)
478 60023e66 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
479 60023e66 Constantinos Venetsanopoulos
480 13b4c540 Constantinos Venetsanopoulos
    def create(self, request, id, key=None):
481 13b4c540 Constantinos Venetsanopoulos
        """Create or Update all metadata for the specified VM"""
482 13b4c540 Constantinos Venetsanopoulos
        if key is not None:
483 13b4c540 Constantinos Venetsanopoulos
            log.exception('The POST request should not pass a key in the URL')
484 13b4c540 Constantinos Venetsanopoulos
            raise fault.badRequest
485 13b4c540 Constantinos Venetsanopoulos
        try:
486 13b4c540 Constantinos Venetsanopoulos
            metadata = json.loads(request.raw_post_data)['metadata']
487 13b4c540 Constantinos Venetsanopoulos
        except Exception as e:
488 13b4c540 Constantinos Venetsanopoulos
            log.exception('Malformed create request: %s - %s' % (e, request.raw_post_data))
489 13b4c540 Constantinos Venetsanopoulos
            raise fault.badRequest
490 13b4c540 Constantinos Venetsanopoulos
491 13b4c540 Constantinos Venetsanopoulos
        try:
492 13b4c540 Constantinos Venetsanopoulos
            vm = VirtualMachine.objects.get(pk=id)
493 13b4c540 Constantinos Venetsanopoulos
            for x in metadata.keys():
494 13b4c540 Constantinos Venetsanopoulos
                vm_meta, created = vm.virtualmachinemetadata_set.get_or_create(meta_key=x)
495 13b4c540 Constantinos Venetsanopoulos
                vm_meta.meta_value = metadata[x] 
496 13b4c540 Constantinos Venetsanopoulos
                vm_meta.save()
497 13b4c540 Constantinos Venetsanopoulos
            return {
498 13b4c540 Constantinos Venetsanopoulos
                "metadata": [{
499 13b4c540 Constantinos Venetsanopoulos
                    "meta": { 
500 13b4c540 Constantinos Venetsanopoulos
                        "key": {m.meta_key: m.meta_value}}} for m in vm.virtualmachinemetadata_set.all()]
501 13b4c540 Constantinos Venetsanopoulos
            }        
502 13b4c540 Constantinos Venetsanopoulos
        except VirtualMachine.DoesNotExist:
503 13b4c540 Constantinos Venetsanopoulos
            raise fault.itemNotFound
504 13b4c540 Constantinos Venetsanopoulos
        except VirtualMachine.MultipleObjectsReturned:
505 13b4c540 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
506 13b4c540 Constantinos Venetsanopoulos
        except VirtualMachineMetadata.DoesNotExist:
507 13b4c540 Constantinos Venetsanopoulos
            raise fault.itemNotFound
508 13b4c540 Constantinos Venetsanopoulos
        except VirtualMachineMetadata.MultipleObjectsReturned:
509 13b4c540 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
510 13b4c540 Constantinos Venetsanopoulos
        except Exception, e:
511 13b4c540 Constantinos Venetsanopoulos
            log.exception('Unexpected error: %s' % e)
512 13b4c540 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
513 60023e66 Constantinos Venetsanopoulos
514 13b4c540 Constantinos Venetsanopoulos
    def update(self, request, id, key=None):
515 7abdaf78 Constantinos Venetsanopoulos
        """Update or Create the specified metadata key for the specified VM"""
516 13b4c540 Constantinos Venetsanopoulos
        if key is None:
517 13b4c540 Constantinos Venetsanopoulos
            log.exception('No metadata key specified in URL')
518 13b4c540 Constantinos Venetsanopoulos
            raise fault.badRequest
519 7abdaf78 Constantinos Venetsanopoulos
        try:
520 7abdaf78 Constantinos Venetsanopoulos
            metadata = json.loads(request.raw_post_data)['meta']
521 7abdaf78 Constantinos Venetsanopoulos
            metadata_value = metadata[key]
522 7abdaf78 Constantinos Venetsanopoulos
        except Exception as e:
523 7abdaf78 Constantinos Venetsanopoulos
            log.exception('Malformed create request: %s - %s' % (e, request.raw_post_data))
524 7abdaf78 Constantinos Venetsanopoulos
            raise fault.badRequest
525 7abdaf78 Constantinos Venetsanopoulos
526 7abdaf78 Constantinos Venetsanopoulos
        try:
527 7abdaf78 Constantinos Venetsanopoulos
            server = VirtualMachine.objects.get(pk=id)
528 7abdaf78 Constantinos Venetsanopoulos
            vm_meta, created = server.virtualmachinemetadata_set.get_or_create(meta_key=key)
529 7abdaf78 Constantinos Venetsanopoulos
            vm_meta.meta_value = metadata_value 
530 7abdaf78 Constantinos Venetsanopoulos
            vm_meta.save()
531 7abdaf78 Constantinos Venetsanopoulos
            return {"meta": {vm_meta.meta_key: vm_meta.meta_value}}
532 7abdaf78 Constantinos Venetsanopoulos
        
533 7abdaf78 Constantinos Venetsanopoulos
        except VirtualMachine.DoesNotExist:
534 7abdaf78 Constantinos Venetsanopoulos
            raise fault.itemNotFound
535 7abdaf78 Constantinos Venetsanopoulos
        except VirtualMachine.MultipleObjectsReturned:
536 7abdaf78 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
537 7abdaf78 Constantinos Venetsanopoulos
        except VirtualMachineMetadata.DoesNotExist:
538 7abdaf78 Constantinos Venetsanopoulos
            raise fault.itemNotFound
539 7abdaf78 Constantinos Venetsanopoulos
        except VirtualMachineMetadata.MultipleObjectsReturned:
540 7abdaf78 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
541 7abdaf78 Constantinos Venetsanopoulos
        except Exception, e:
542 7abdaf78 Constantinos Venetsanopoulos
            log.exception('Unexpected error: %s' % e)
543 7abdaf78 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
544 60023e66 Constantinos Venetsanopoulos
545 13b4c540 Constantinos Venetsanopoulos
    def delete(self, request, id, key=None):
546 13b4c540 Constantinos Venetsanopoulos
        """Delete the specified metadata key"""
547 13b4c540 Constantinos Venetsanopoulos
        if key is None:
548 13b4c540 Constantinos Venetsanopoulos
            log.exception('No metadata key specified in URL')
549 13b4c540 Constantinos Venetsanopoulos
            raise fault.badRequest
550 e9134601 Constantinos Venetsanopoulos
        try:
551 e9134601 Constantinos Venetsanopoulos
            server = VirtualMachine.objects.get(pk=id)
552 36d0df36 Constantinos Venetsanopoulos
            server.virtualmachinemetadata_set.get(meta_key=key).delete()
553 e9134601 Constantinos Venetsanopoulos
        except VirtualMachineMetadata.DoesNotExist:
554 e9134601 Constantinos Venetsanopoulos
            raise fault.itemNotFound
555 e9134601 Constantinos Venetsanopoulos
        except VirtualMachine.DoesNotExist:
556 e9134601 Constantinos Venetsanopoulos
            raise fault.itemNotFound
557 36d0df36 Constantinos Venetsanopoulos
        except VirtualMachineMetadata.MultipleObjectsReturned:
558 36d0df36 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
559 e9134601 Constantinos Venetsanopoulos
        except VirtualMachine.MultipleObjectsReturned:
560 e9134601 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
561 e9134601 Constantinos Venetsanopoulos
        except Exception, e:
562 e9134601 Constantinos Venetsanopoulos
            log.exception('Unexpected error: %s' % e)
563 e9134601 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
564 60023e66 Constantinos Venetsanopoulos
565 60023e66 Constantinos Venetsanopoulos
566 427a9220 Faidon Liambotis
class FlavorHandler(BaseHandler):
567 ffffd5fe Markos Gogoulos
    """Handler responsible for Flavors
568 ffffd5fe Markos Gogoulos

569 ffffd5fe Markos Gogoulos
    """
570 427a9220 Faidon Liambotis
    allowed_methods = ('GET',)
571 427a9220 Faidon Liambotis
572 427a9220 Faidon Liambotis
    def read(self, request, id=None):
573 dcc6a862 Faidon Liambotis
        """
574 dcc6a862 Faidon Liambotis
        List flavors or retrieve one
575 427a9220 Faidon Liambotis

576 427a9220 Faidon Liambotis
        Returns: OK
577 dcc6a862 Faidon Liambotis
        Faults: cloudServersFault, serviceUnavailable, unauthorized,
578 dcc6a862 Faidon Liambotis
                badRequest, itemNotFound
579 427a9220 Faidon Liambotis
        """
580 ffffd5fe Markos Gogoulos
        try:
581 ffffd5fe Markos Gogoulos
            flavors = Flavor.objects.all()
582 ffffd5fe Markos Gogoulos
            flavors = [ {'id': flavor.id, 'name': flavor.name, 'ram': flavor.ram, \
583 ffffd5fe Markos Gogoulos
                     'disk': flavor.disk, 'cpu': flavor.cpu} for flavor in flavors]
584 ffffd5fe Markos Gogoulos
585 ffffd5fe Markos Gogoulos
            if id is None:
586 ffffd5fe Markos Gogoulos
                simple = map(lambda v: {
587 ffffd5fe Markos Gogoulos
                            "id": v['id'],
588 ffffd5fe Markos Gogoulos
                            "name": v['name'],
589 ffffd5fe Markos Gogoulos
                        }, flavors)
590 ffffd5fe Markos Gogoulos
                return { "flavors": simple }
591 ffffd5fe Markos Gogoulos
            elif id == "detail":
592 ffffd5fe Markos Gogoulos
                return { "flavors": flavors }
593 ffffd5fe Markos Gogoulos
            else:
594 ffffd5fe Markos Gogoulos
                flavor = Flavor.objects.get(id=id)
595 ffffd5fe Markos Gogoulos
                return { "flavor":  {
596 ffffd5fe Markos Gogoulos
                    'id': flavor.id,
597 ffffd5fe Markos Gogoulos
                    'name': flavor.name,
598 ffffd5fe Markos Gogoulos
                    'ram': flavor.ram,
599 ffffd5fe Markos Gogoulos
                    'disk': flavor.disk,  
600 ffffd5fe Markos Gogoulos
                    'cpu': flavor.cpu,  
601 ffffd5fe Markos Gogoulos
                   } }
602 ffffd5fe Markos Gogoulos
603 ffffd5fe Markos Gogoulos
        except Flavor.DoesNotExist:
604 635cfd6e Faidon Liambotis
            raise fault.itemNotFound
605 ffffd5fe Markos Gogoulos
        except Flavor.MultipleObjectsReturned:
606 ffffd5fe Markos Gogoulos
            raise fault.serviceUnavailable
607 ffffd5fe Markos Gogoulos
        except Exception, e:
608 6b83d46b Markos Gogoulos
            log.exception('Unexpected error: %s' % e)
609 ffffd5fe Markos Gogoulos
            raise fault.serviceUnavailable
610 dcc6a862 Faidon Liambotis
611 dcc6a862 Faidon Liambotis
612 dcc6a862 Faidon Liambotis
class ImageHandler(BaseHandler):
613 f5ea24a9 Markos Gogoulos
    """Handler responsible for Images
614 f5ea24a9 Markos Gogoulos

615 f5ea24a9 Markos Gogoulos
     handles the listing, creation and delete of Images. 
616 f5ea24a9 Markos Gogoulos

617 f5ea24a9 Markos Gogoulos
     @HTTP methods: GET, POST
618 f5ea24a9 Markos Gogoulos
     @Parameters: POST data 
619 f5ea24a9 Markos Gogoulos
     @Responses: HTTP 202 if successfully create Image or get the Images list, itemNotFound, serviceUnavailable otherwise
620 f5ea24a9 Markos Gogoulos

621 f5ea24a9 Markos Gogoulos
    """
622 f5ea24a9 Markos Gogoulos
623 f5ea24a9 Markos Gogoulos
624 dcc6a862 Faidon Liambotis
    allowed_methods = ('GET', 'POST')
625 dcc6a862 Faidon Liambotis
626 dcc6a862 Faidon Liambotis
    def read(self, request, id=None):
627 dcc6a862 Faidon Liambotis
        """
628 dcc6a862 Faidon Liambotis
        List images or retrieve one
629 dcc6a862 Faidon Liambotis

630 dcc6a862 Faidon Liambotis
        Returns: OK
631 dcc6a862 Faidon Liambotis
        Faults: cloudServersFault, serviceUnavailable, unauthorized,
632 dcc6a862 Faidon Liambotis
                badRequest, itemNotFound
633 dcc6a862 Faidon Liambotis
        """
634 ffffd5fe Markos Gogoulos
        try:
635 ffffd5fe Markos Gogoulos
            images = Image.objects.all()
636 ffffd5fe Markos Gogoulos
            images_list = [ {'created': image.created.isoformat(), 
637 ffffd5fe Markos Gogoulos
                        'id': image.id,
638 ffffd5fe Markos Gogoulos
                        'name': image.name,
639 ffffd5fe Markos Gogoulos
                        'updated': image.updated.isoformat(),    
640 ffffd5fe Markos Gogoulos
                        'status': image.state, 
641 63597809 Markos Gogoulos
                        'progress': image.state == 'ACTIVE' and 100 or 0, 
642 ffffd5fe Markos Gogoulos
                        'size': image.size, 
643 4e6f9904 Markos Gogoulos
                        'serverId': image.sourcevm and image.sourcevm.id or "",
644 4e6f9904 Markos Gogoulos
                        #'metadata':[{'meta': { 'key': {metadata.meta_key: metadata.meta_value}}} for metadata in image.imagemetadata_set.all()]
645 4e6f9904 Markos Gogoulos
                        'metadata':{'meta': { 'key': {'description': image.description}}},
646 ffffd5fe Markos Gogoulos
                       } for image in images]
647 ffffd5fe Markos Gogoulos
            # Images info is stored in the DB. Ganeti is not aware of this
648 ffffd5fe Markos Gogoulos
            if id == "detail":
649 ffffd5fe Markos Gogoulos
                return { "images": images_list }
650 ffffd5fe Markos Gogoulos
            elif id is None:
651 ffffd5fe Markos Gogoulos
                return { "images": [ { "id": s['id'], "name": s['name'] } for s in images_list ] }
652 ffffd5fe Markos Gogoulos
            else:        
653 ffffd5fe Markos Gogoulos
                image = images.get(id=id)
654 ffffd5fe Markos Gogoulos
                return { "image":  {'created': image.created.isoformat(), 
655 12827073 Markos Gogoulos
                    'id': image.id,
656 12827073 Markos Gogoulos
                    'name': image.name,
657 12827073 Markos Gogoulos
                    'updated': image.updated.isoformat(),    
658 12827073 Markos Gogoulos
                    'description': image.description, 
659 b65b1281 Markos Gogoulos
                    'status': image.state, 
660 63597809 Markos Gogoulos
                    'progress': image.state == 'ACTIVE' and 100 or 0, 
661 d235fdd2 Markos Gogoulos
                    'size': image.size, 
662 4e6f9904 Markos Gogoulos
                    'serverId': image.sourcevm and image.sourcevm.id or "",
663 4e6f9904 Markos Gogoulos
                    #'metadata':[{'meta': { 'key': {metadata.meta_key: metadata.meta_value}}} for metadata in image.imagemetadata_set.all()]
664 4e6f9904 Markos Gogoulos
                    'metadata':{'meta': { 'key': {'description': image.description}}},
665 ffffd5fe Markos Gogoulos
                   } }
666 ffffd5fe Markos Gogoulos
        except Image.DoesNotExist:
667 ffffd5fe Markos Gogoulos
                    raise fault.itemNotFound
668 ffffd5fe Markos Gogoulos
        except Image.MultipleObjectsReturned:
669 ffffd5fe Markos Gogoulos
                    raise fault.serviceUnavailable
670 ffffd5fe Markos Gogoulos
        except Exception, e:
671 6b83d46b Markos Gogoulos
                    log.exception('Unexpected error: %s' % e)
672 ffffd5fe Markos Gogoulos
                    raise fault.serviceUnavailable
673 dcc6a862 Faidon Liambotis
674 dcc6a862 Faidon Liambotis
    def create(self, request):
675 dcc6a862 Faidon Liambotis
        """Create a new image"""
676 dcc6a862 Faidon Liambotis
        return accepted
677 ed66d976 Faidon Liambotis
678 ed66d976 Faidon Liambotis
679 60023e66 Constantinos Venetsanopoulos
class ImageMetadataHandler(BaseHandler):
680 60023e66 Constantinos Venetsanopoulos
    """Handles Metadata of a specific Image
681 60023e66 Constantinos Venetsanopoulos

682 60023e66 Constantinos Venetsanopoulos
    the handler Lists, Creates, Updates and Deletes Metadata values
683 60023e66 Constantinos Venetsanopoulos

684 60023e66 Constantinos Venetsanopoulos
    @HTTP methods: POST, DELETE, PUT, GET
685 60023e66 Constantinos Venetsanopoulos
    @Parameters: POST data with key value pairs
686 60023e66 Constantinos Venetsanopoulos

687 60023e66 Constantinos Venetsanopoulos
    """
688 60023e66 Constantinos Venetsanopoulos
    allowed_methods = ('GET', 'POST', 'PUT', 'DELETE')
689 60023e66 Constantinos Venetsanopoulos
690 60023e66 Constantinos Venetsanopoulos
    def read(self, request, id, key=None):
691 60023e66 Constantinos Venetsanopoulos
        """List metadata of the specific server"""
692 60023e66 Constantinos Venetsanopoulos
        if key is None:
693 60023e66 Constantinos Venetsanopoulos
            return self.read_allkeys(request, id)
694 60023e66 Constantinos Venetsanopoulos
        else:
695 60023e66 Constantinos Venetsanopoulos
            return self.read_onekey(request, id, key)
696 60023e66 Constantinos Venetsanopoulos
697 60023e66 Constantinos Venetsanopoulos
    def read_allkeys(self, request, id):
698 60023e66 Constantinos Venetsanopoulos
        """Returns all the key value pairs of the specified server"""
699 60023e66 Constantinos Venetsanopoulos
        try:
700 e9134601 Constantinos Venetsanopoulos
            image = Image.objects.get(pk=id)
701 60023e66 Constantinos Venetsanopoulos
            return {
702 60023e66 Constantinos Venetsanopoulos
                "metadata": [{
703 60023e66 Constantinos Venetsanopoulos
                    "meta": { 
704 e9134601 Constantinos Venetsanopoulos
                        "key": {m.meta_key: m.meta_value}}} for m in image.imagemetadata_set.all()]
705 60023e66 Constantinos Venetsanopoulos
            }
706 60023e66 Constantinos Venetsanopoulos
        except Image.DoesNotExist:
707 60023e66 Constantinos Venetsanopoulos
            raise fault.itemNotFound
708 60023e66 Constantinos Venetsanopoulos
        except Image.MultipleObjectsReturned:
709 60023e66 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
710 60023e66 Constantinos Venetsanopoulos
        except Exception, e:
711 60023e66 Constantinos Venetsanopoulos
            log.exception('Unexpected error: %s' % e)
712 60023e66 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
713 60023e66 Constantinos Venetsanopoulos
        
714 60023e66 Constantinos Venetsanopoulos
    def read_onekey(self, request, id, key):
715 60023e66 Constantinos Venetsanopoulos
        """Returns the specified metadata key of the specified server"""
716 60023e66 Constantinos Venetsanopoulos
        try:
717 60023e66 Constantinos Venetsanopoulos
            image = Image.objects.get(pk=id)
718 60023e66 Constantinos Venetsanopoulos
            return {
719 60023e66 Constantinos Venetsanopoulos
                "metadata": {
720 60023e66 Constantinos Venetsanopoulos
                    "values": [
721 60023e66 Constantinos Venetsanopoulos
                        {m.meta_key: m.meta_value} for m in image.imagemetadata_set.filter(meta_key=key)
722 60023e66 Constantinos Venetsanopoulos
                    ]
723 60023e66 Constantinos Venetsanopoulos
                }
724 60023e66 Constantinos Venetsanopoulos
            }
725 60023e66 Constantinos Venetsanopoulos
        except ImageMetadata.DoesNotExist:
726 60023e66 Constantinos Venetsanopoulos
            raise fault.itemNotFound            
727 60023e66 Constantinos Venetsanopoulos
        except Image.DoesNotExist:
728 60023e66 Constantinos Venetsanopoulos
            raise fault.itemNotFound
729 60023e66 Constantinos Venetsanopoulos
        except Image.MultipleObjectsReturned:
730 60023e66 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
731 60023e66 Constantinos Venetsanopoulos
        except Exception, e:
732 60023e66 Constantinos Venetsanopoulos
            log.exception('Unexpected error: %s' % e)
733 60023e66 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
734 60023e66 Constantinos Venetsanopoulos
735 13b4c540 Constantinos Venetsanopoulos
    def create(self, request, id, key=None):
736 13b4c540 Constantinos Venetsanopoulos
        """Create or Update all metadata for the specified Image"""
737 13b4c540 Constantinos Venetsanopoulos
        if key is not None:
738 13b4c540 Constantinos Venetsanopoulos
            log.exception('The POST request should not pass a key in the URL')
739 13b4c540 Constantinos Venetsanopoulos
            raise fault.badRequest
740 13b4c540 Constantinos Venetsanopoulos
        try:
741 13b4c540 Constantinos Venetsanopoulos
            metadata = json.loads(request.raw_post_data)['metadata']
742 13b4c540 Constantinos Venetsanopoulos
        except Exception as e:
743 13b4c540 Constantinos Venetsanopoulos
            log.exception('Malformed create request: %s - %s' % (e, request.raw_post_data))
744 13b4c540 Constantinos Venetsanopoulos
            raise fault.badRequest
745 13b4c540 Constantinos Venetsanopoulos
746 13b4c540 Constantinos Venetsanopoulos
        try:
747 13b4c540 Constantinos Venetsanopoulos
            image = Image.objects.get(pk=id)
748 13b4c540 Constantinos Venetsanopoulos
            for x in metadata.keys():
749 13b4c540 Constantinos Venetsanopoulos
                img_meta, created = image.imagemetadata_set.get_or_create(meta_key=x)
750 13b4c540 Constantinos Venetsanopoulos
                img_meta.meta_value = metadata[x] 
751 13b4c540 Constantinos Venetsanopoulos
                img_meta.save()
752 13b4c540 Constantinos Venetsanopoulos
            return {
753 13b4c540 Constantinos Venetsanopoulos
                "metadata": [{
754 13b4c540 Constantinos Venetsanopoulos
                    "meta": { 
755 13b4c540 Constantinos Venetsanopoulos
                        "key": {m.meta_key: m.meta_value}}} for m in image.imagemetadata_set.all()]
756 13b4c540 Constantinos Venetsanopoulos
            }        
757 13b4c540 Constantinos Venetsanopoulos
        except Image.DoesNotExist:
758 13b4c540 Constantinos Venetsanopoulos
            raise fault.itemNotFound
759 13b4c540 Constantinos Venetsanopoulos
        except Image.MultipleObjectsReturned:
760 13b4c540 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
761 13b4c540 Constantinos Venetsanopoulos
        except ImageMetadata.DoesNotExist:
762 13b4c540 Constantinos Venetsanopoulos
            raise fault.itemNotFound
763 13b4c540 Constantinos Venetsanopoulos
        except ImageMetadata.MultipleObjectsReturned:
764 13b4c540 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
765 13b4c540 Constantinos Venetsanopoulos
        except Exception, e:
766 13b4c540 Constantinos Venetsanopoulos
            log.exception('Unexpected error: %s' % e)
767 13b4c540 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
768 60023e66 Constantinos Venetsanopoulos
769 13b4c540 Constantinos Venetsanopoulos
    def update(self, request, id, key=None):
770 7abdaf78 Constantinos Venetsanopoulos
        """Update or Create the specified metadata key for the specified Image"""
771 13b4c540 Constantinos Venetsanopoulos
        if key is None:
772 13b4c540 Constantinos Venetsanopoulos
            log.exception('No metadata key specified in URL')
773 13b4c540 Constantinos Venetsanopoulos
            raise fault.badRequest
774 7abdaf78 Constantinos Venetsanopoulos
        try:
775 7abdaf78 Constantinos Venetsanopoulos
            metadata = json.loads(request.raw_post_data)['meta']
776 7abdaf78 Constantinos Venetsanopoulos
            metadata_value = metadata[key]
777 7abdaf78 Constantinos Venetsanopoulos
        except Exception as e:
778 7abdaf78 Constantinos Venetsanopoulos
            log.exception('Malformed create request: %s - %s' % (e, request.raw_post_data))
779 7abdaf78 Constantinos Venetsanopoulos
            raise fault.badRequest
780 7abdaf78 Constantinos Venetsanopoulos
781 7abdaf78 Constantinos Venetsanopoulos
        try:
782 7abdaf78 Constantinos Venetsanopoulos
            image = Image.objects.get(pk=id)
783 7abdaf78 Constantinos Venetsanopoulos
            img_meta, created = image.imagemetadata_set.get_or_create(meta_key=key)
784 7abdaf78 Constantinos Venetsanopoulos
            img_meta.meta_value = metadata_value 
785 7abdaf78 Constantinos Venetsanopoulos
            img_meta.save()
786 7abdaf78 Constantinos Venetsanopoulos
            return {"meta": {img_meta.meta_key: img_meta.meta_value}}
787 7abdaf78 Constantinos Venetsanopoulos
        
788 7abdaf78 Constantinos Venetsanopoulos
        except Image.DoesNotExist:
789 7abdaf78 Constantinos Venetsanopoulos
            raise fault.itemNotFound
790 7abdaf78 Constantinos Venetsanopoulos
        except Image.MultipleObjectsReturned:
791 7abdaf78 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
792 7abdaf78 Constantinos Venetsanopoulos
        except ImageMetadata.DoesNotExist:
793 7abdaf78 Constantinos Venetsanopoulos
            raise fault.itemNotFound
794 7abdaf78 Constantinos Venetsanopoulos
        except ImageMetadata.MultipleObjectsReturned:
795 7abdaf78 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
796 7abdaf78 Constantinos Venetsanopoulos
        except Exception, e:
797 7abdaf78 Constantinos Venetsanopoulos
            log.exception('Unexpected error: %s' % e)
798 7abdaf78 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
799 60023e66 Constantinos Venetsanopoulos
800 13b4c540 Constantinos Venetsanopoulos
    def delete(self, request, id, key=None):
801 13b4c540 Constantinos Venetsanopoulos
        """Delete the specified metadata key"""
802 13b4c540 Constantinos Venetsanopoulos
        if key is None:
803 13b4c540 Constantinos Venetsanopoulos
            log.exception('No metadata key specified in URL')
804 13b4c540 Constantinos Venetsanopoulos
            raise fault.badRequest
805 e9134601 Constantinos Venetsanopoulos
        try:
806 e9134601 Constantinos Venetsanopoulos
            image = Image.objects.get(pk=id)
807 36d0df36 Constantinos Venetsanopoulos
            image.imagemetadata_set.get(meta_key=key).delete()
808 e9134601 Constantinos Venetsanopoulos
        except ImageMetadata.DoesNotExist:
809 e9134601 Constantinos Venetsanopoulos
            raise fault.itemNotFound
810 e9134601 Constantinos Venetsanopoulos
        except Image.DoesNotExist:
811 e9134601 Constantinos Venetsanopoulos
            raise fault.itemNotFound
812 36d0df36 Constantinos Venetsanopoulos
        except ImageMetadata.MultipleObjectsReturned:
813 36d0df36 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
814 e9134601 Constantinos Venetsanopoulos
        except Image.MultipleObjectsReturned:
815 e9134601 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
816 e9134601 Constantinos Venetsanopoulos
        except Exception, e:
817 e9134601 Constantinos Venetsanopoulos
            log.exception('Unexpected error: %s' % e)
818 e9134601 Constantinos Venetsanopoulos
            raise fault.serviceUnavailable
819 60023e66 Constantinos Venetsanopoulos
820 60023e66 Constantinos Venetsanopoulos
821 ed66d976 Faidon Liambotis
class SharedIPGroupHandler(BaseHandler):
822 ed66d976 Faidon Liambotis
    allowed_methods = ('GET', 'POST', 'DELETE')
823 ed66d976 Faidon Liambotis
824 ed66d976 Faidon Liambotis
    def read(self, request, id=None):
825 ed66d976 Faidon Liambotis
        """List Shared IP Groups"""
826 ed66d976 Faidon Liambotis
        if id is None:
827 ed66d976 Faidon Liambotis
            return {}
828 ed66d976 Faidon Liambotis
        elif id == "detail":
829 ed66d976 Faidon Liambotis
            return {}
830 ed66d976 Faidon Liambotis
        else:
831 635cfd6e Faidon Liambotis
            raise fault.itemNotFound
832 ed66d976 Faidon Liambotis
833 ed66d976 Faidon Liambotis
    def create(self, request, id):
834 ed66d976 Faidon Liambotis
        """Creates a new Shared IP Group"""
835 ed66d976 Faidon Liambotis
        return created
836 ed66d976 Faidon Liambotis
837 ed66d976 Faidon Liambotis
    def delete(self, request, id):
838 ed66d976 Faidon Liambotis
        """Deletes a Shared IP Group"""
839 f0858246 Markos Gogoulos
        raise fault.itemNotFound
840 beb79c95 Faidon Liambotis
841 beb79c95 Faidon Liambotis
842 a31ff6cb Markos Gogoulos
class VirtualMachineGroupHandler(BaseHandler):
843 59cee068 Markos Gogoulos
    """Handler responsible for Virtual Machine Groups
844 59cee068 Markos Gogoulos

845 59cee068 Markos Gogoulos
     creates, lists, deletes virtual machine groups
846 59cee068 Markos Gogoulos

847 59cee068 Markos Gogoulos
     @HTTP methods: GET, POST, DELETE
848 59cee068 Markos Gogoulos
     @Parameters: POST data 
849 59cee068 Markos Gogoulos
     @Responses: HTTP 202 if successfully get the Groups list, itemNotFound, serviceUnavailable otherwise
850 59cee068 Markos Gogoulos

851 59cee068 Markos Gogoulos
    """
852 59cee068 Markos Gogoulos
853 a31ff6cb Markos Gogoulos
    allowed_methods = ('GET', 'POST', 'DELETE')
854 a31ff6cb Markos Gogoulos
855 a31ff6cb Markos Gogoulos
    def read(self, request, id=None):
856 a31ff6cb Markos Gogoulos
        """List Groups"""
857 ffffd5fe Markos Gogoulos
        try:
858 ffffd5fe Markos Gogoulos
            vmgroups = VirtualMachineGroup.objects.all() 
859 59cee068 Markos Gogoulos
            vmgroups_list = [ {'id': vmgroup.id, \
860 ffffd5fe Markos Gogoulos
                  'name': vmgroup.name,  \
861 ffffd5fe Markos Gogoulos
                   'server_id': [machine.id for machine in vmgroup.machines.all()] \
862 ffffd5fe Markos Gogoulos
                   } for vmgroup in vmgroups]
863 ffffd5fe Markos Gogoulos
            # Group info is stored in the DB. Ganeti is not aware of this
864 ffffd5fe Markos Gogoulos
            if id == "detail":
865 59cee068 Markos Gogoulos
                return { "groups": vmgroups_list }
866 ffffd5fe Markos Gogoulos
            elif id is None:
867 59cee068 Markos Gogoulos
                return { "groups": [ { "id": s['id'], "name": s['name'] } for s in vmgroups_list ] }
868 ffffd5fe Markos Gogoulos
            else:
869 a8acbbac Markos Gogoulos
                vmgroup = vmgroups.get(id=id)
870 59cee068 Markos Gogoulos
871 59cee068 Markos Gogoulos
                return { "group":  {'id': vmgroup.id, \
872 59cee068 Markos Gogoulos
                  'name': vmgroup.name,  \
873 59cee068 Markos Gogoulos
                   'server_id': [machine.id for machine in vmgroup.machines.all()] \
874 59cee068 Markos Gogoulos
                   } }
875 59cee068 Markos Gogoulos
876 59cee068 Markos Gogoulos
877 59cee068 Markos Gogoulos
        except VirtualMachineGroup.DoesNotExist:
878 59cee068 Markos Gogoulos
                    raise fault.itemNotFound
879 59cee068 Markos Gogoulos
        except VirtualMachineGroup.MultipleObjectsReturned:
880 59cee068 Markos Gogoulos
                    raise fault.serviceUnavailable
881 ffffd5fe Markos Gogoulos
        except Exception, e:
882 6b83d46b Markos Gogoulos
                    log.exception('Unexpected error: %s' % e)
883 ffffd5fe Markos Gogoulos
                    raise fault.serviceUnavailable
884 a31ff6cb Markos Gogoulos
885 a31ff6cb Markos Gogoulos
886 59cee068 Markos Gogoulos
887 a31ff6cb Markos Gogoulos
    def create(self, request, id):
888 a31ff6cb Markos Gogoulos
        """Creates a Group"""
889 a31ff6cb Markos Gogoulos
        return created
890 a31ff6cb Markos Gogoulos
891 a31ff6cb Markos Gogoulos
    def delete(self, request, id):
892 a31ff6cb Markos Gogoulos
        """Deletes a  Group"""
893 f0858246 Markos Gogoulos
        raise fault.itemNotFound
894 a31ff6cb Markos Gogoulos
895 a31ff6cb Markos Gogoulos
896 beb79c95 Faidon Liambotis
class LimitHandler(BaseHandler):
897 beb79c95 Faidon Liambotis
    allowed_methods = ('GET',)
898 beb79c95 Faidon Liambotis
899 beb79c95 Faidon Liambotis
    # XXX: hookup with @throttle
900 beb79c95 Faidon Liambotis
901 beb79c95 Faidon Liambotis
    rate = [
902 beb79c95 Faidon Liambotis
        {
903 beb79c95 Faidon Liambotis
           "verb" : "POST",
904 beb79c95 Faidon Liambotis
           "URI" : "*",
905 beb79c95 Faidon Liambotis
           "regex" : ".*",
906 beb79c95 Faidon Liambotis
           "value" : 10,
907 beb79c95 Faidon Liambotis
           "remaining" : 2,
908 beb79c95 Faidon Liambotis
           "unit" : "MINUTE",
909 beb79c95 Faidon Liambotis
           "resetTime" : 1244425439
910 beb79c95 Faidon Liambotis
        },
911 beb79c95 Faidon Liambotis
        {
912 beb79c95 Faidon Liambotis
           "verb" : "POST",
913 beb79c95 Faidon Liambotis
           "URI" : "*/servers",
914 beb79c95 Faidon Liambotis
           "regex" : "^/servers",
915 beb79c95 Faidon Liambotis
           "value" : 25,
916 beb79c95 Faidon Liambotis
           "remaining" : 24,
917 beb79c95 Faidon Liambotis
           "unit" : "DAY",
918 beb79c95 Faidon Liambotis
           "resetTime" : 1244511839
919 beb79c95 Faidon Liambotis
        },
920 beb79c95 Faidon Liambotis
        {
921 beb79c95 Faidon Liambotis
           "verb" : "PUT",
922 beb79c95 Faidon Liambotis
           "URI" : "*",
923 beb79c95 Faidon Liambotis
           "regex" : ".*",
924 beb79c95 Faidon Liambotis
           "value" : 10,
925 beb79c95 Faidon Liambotis
           "remaining" : 2,
926 beb79c95 Faidon Liambotis
           "unit" : "MINUTE",
927 beb79c95 Faidon Liambotis
           "resetTime" : 1244425439
928 beb79c95 Faidon Liambotis
        },
929 beb79c95 Faidon Liambotis
        {
930 beb79c95 Faidon Liambotis
           "verb" : "GET",
931 beb79c95 Faidon Liambotis
           "URI" : "*",
932 beb79c95 Faidon Liambotis
           "regex" : ".*",
933 beb79c95 Faidon Liambotis
           "value" : 3,
934 beb79c95 Faidon Liambotis
           "remaining" : 3,
935 beb79c95 Faidon Liambotis
           "unit" : "MINUTE",
936 beb79c95 Faidon Liambotis
           "resetTime" : 1244425439
937 beb79c95 Faidon Liambotis
        },
938 beb79c95 Faidon Liambotis
        {
939 beb79c95 Faidon Liambotis
           "verb" : "DELETE",
940 beb79c95 Faidon Liambotis
           "URI" : "*",
941 beb79c95 Faidon Liambotis
           "regex" : ".*",
942 beb79c95 Faidon Liambotis
           "value" : 100,
943 beb79c95 Faidon Liambotis
           "remaining" : 100,
944 beb79c95 Faidon Liambotis
           "unit" : "MINUTE",
945 beb79c95 Faidon Liambotis
           "resetTime" : 1244425439
946 beb79c95 Faidon Liambotis
        }
947 beb79c95 Faidon Liambotis
    ]
948 beb79c95 Faidon Liambotis
949 beb79c95 Faidon Liambotis
    absolute = {
950 beb79c95 Faidon Liambotis
        "maxTotalRAMSize" : 51200,
951 beb79c95 Faidon Liambotis
        "maxIPGroups" : 50,
952 beb79c95 Faidon Liambotis
        "maxIPGroupMembers" : 25
953 beb79c95 Faidon Liambotis
    }
954 beb79c95 Faidon Liambotis
955 beb79c95 Faidon Liambotis
    def read(self, request):
956 beb79c95 Faidon Liambotis
        return { "limits": {
957 beb79c95 Faidon Liambotis
                "rate": self.rate,
958 beb79c95 Faidon Liambotis
                "absolute": self.absolute,
959 beb79c95 Faidon Liambotis
               }
960 beb79c95 Faidon Liambotis
            }
961 9071888e Constantinos Venetsanopoulos
962 9071888e Constantinos Venetsanopoulos
963 9071888e Constantinos Venetsanopoulos
class DiskHandler(BaseHandler):
964 9071888e Constantinos Venetsanopoulos
    allowed_methods = ('GET', 'POST', 'PUT', 'DELETE')
965 9071888e Constantinos Venetsanopoulos
966 9071888e Constantinos Venetsanopoulos
    def read(self, request, id=None):
967 9071888e Constantinos Venetsanopoulos
        """List Disks"""
968 9071888e Constantinos Venetsanopoulos
        if id is None:
969 9071888e Constantinos Venetsanopoulos
            return self.read_all(request)
970 9071888e Constantinos Venetsanopoulos
        elif id == "detail":
971 9071888e Constantinos Venetsanopoulos
            return self.read_all(request, detail=True)
972 9071888e Constantinos Venetsanopoulos
        else:
973 9071888e Constantinos Venetsanopoulos
            return self.read_one(request, id)
974 9071888e Constantinos Venetsanopoulos
975 9071888e Constantinos Venetsanopoulos
    def read_one(self, request, id):
976 9071888e Constantinos Venetsanopoulos
        """List one Disk with the specified id with all details"""
977 9071888e Constantinos Venetsanopoulos
        # FIXME Get detailed info from the DB 
978 9071888e Constantinos Venetsanopoulos
        # for the Disk with the specified id
979 9071888e Constantinos Venetsanopoulos
        try:
980 9071888e Constantinos Venetsanopoulos
            disk = Disk.objects.get(pk=id)
981 9071888e Constantinos Venetsanopoulos
            disk_details = {
982 9071888e Constantinos Venetsanopoulos
                "id" : disk.id, 
983 9071888e Constantinos Venetsanopoulos
                "name" : disk.name, 
984 9071888e Constantinos Venetsanopoulos
                "size" : disk.size,
985 9071888e Constantinos Venetsanopoulos
                "created" : disk.created, 
986 9071888e Constantinos Venetsanopoulos
                "serverId" : disk.vm.id
987 9071888e Constantinos Venetsanopoulos
            }
988 9071888e Constantinos Venetsanopoulos
            return { "disks" : disk_details }
989 9071888e Constantinos Venetsanopoulos
        except:
990 9071888e Constantinos Venetsanopoulos
            raise fault.itemNotFound
991 9071888e Constantinos Venetsanopoulos
992 9071888e Constantinos Venetsanopoulos
    @paginator
993 9071888e Constantinos Venetsanopoulos
    def read_all(self, request, detail=False):
994 9071888e Constantinos Venetsanopoulos
        """List all Disks. If -detail- is set list them with all details"""
995 9071888e Constantinos Venetsanopoulos
        if not detail:
996 9071888e Constantinos Venetsanopoulos
            disks = Disk.objects.filter(owner=SynnefoUser.objects.all()[0])
997 9071888e Constantinos Venetsanopoulos
            return { "disks": [ { "id": disk.id, "name": disk.name } for disk in disks ] }
998 9071888e Constantinos Venetsanopoulos
        else:
999 9071888e Constantinos Venetsanopoulos
            disks = Disk.objects.filter(owner=SynnefoUser.objects.all()[0])
1000 9071888e Constantinos Venetsanopoulos
            disks_details = [ {
1001 9071888e Constantinos Venetsanopoulos
                "id" : disk.id, 
1002 9071888e Constantinos Venetsanopoulos
                "name" : disk.name,
1003 9071888e Constantinos Venetsanopoulos
                "size" : disk.size,
1004 9071888e Constantinos Venetsanopoulos
                "created" : disk.created, 
1005 9071888e Constantinos Venetsanopoulos
                "serverId" : disk.vm.id,
1006 9071888e Constantinos Venetsanopoulos
            } for disk in disks ]
1007 9071888e Constantinos Venetsanopoulos
            return { "disks":  disks_details }                
1008 9071888e Constantinos Venetsanopoulos
1009 9071888e Constantinos Venetsanopoulos
    def create(self, request):
1010 9071888e Constantinos Venetsanopoulos
        """Create a new Disk"""
1011 9071888e Constantinos Venetsanopoulos
        # FIXME Create a partial DB entry, 
1012 9071888e Constantinos Venetsanopoulos
        # then call the backend for actual creation
1013 9071888e Constantinos Venetsanopoulos
        pass
1014 9071888e Constantinos Venetsanopoulos
1015 9071888e Constantinos Venetsanopoulos
    def update(self, request, id):
1016 9071888e Constantinos Venetsanopoulos
        """Rename the Disk with the specified id"""
1017 9071888e Constantinos Venetsanopoulos
        # FIXME Change the Disk's name in the DB
1018 9071888e Constantinos Venetsanopoulos
        pass
1019 9071888e Constantinos Venetsanopoulos
1020 9071888e Constantinos Venetsanopoulos
    def delete(self, request, id):
1021 9071888e Constantinos Venetsanopoulos
        """Destroy the Disk with the specified id"""
1022 9071888e Constantinos Venetsanopoulos
        # Call the backend for actual destruction
1023 9071888e Constantinos Venetsanopoulos
        pass