Statistics
| Branch: | Tag: | Revision:

root / api / handlers.py @ 92c53da1

History | View | Annotate | Download (37 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 00b4f1be Faidon Liambotis
VERSIONS = [
30 00b4f1be Faidon Liambotis
    {
31 00b4f1be Faidon Liambotis
        "status": "CURRENT",
32 00b4f1be Faidon Liambotis
        "id": "v1.0",
33 ac7188e6 Markos Gogoulos
        "docURL" : "http://docs.rackspacecloud.com/servers/api/v1.0/cs-devguide-20110112.pdf",
34 00b4f1be Faidon Liambotis
        "wadl" : "http://docs.rackspacecloud.com/servers/api/v1.0/application.wadl"
35 00b4f1be Faidon Liambotis
    },
36 9071888e Constantinos Venetsanopoulos
    {
37 9071888e Constantinos Venetsanopoulos
        "status": "CURRENT",
38 60023e66 Constantinos Venetsanopoulos
        "id": "v1.1",
39 60023e66 Constantinos Venetsanopoulos
        "docURL" : "http://docs.openstack.org/openstack-compute/developer/content/",
40 60023e66 Constantinos Venetsanopoulos
        "wadl" : "None yet"
41 60023e66 Constantinos Venetsanopoulos
    },
42 60023e66 Constantinos Venetsanopoulos
    {
43 60023e66 Constantinos Venetsanopoulos
        "status": "CURRENT",
44 9071888e Constantinos Venetsanopoulos
        "id": "v1.0grnet1",
45 9071888e Constantinos Venetsanopoulos
        "docURL" : "None yet",
46 9071888e Constantinos Venetsanopoulos
        "wad1" : "None yet"
47 9071888e Constantinos Venetsanopoulos
    }
48 00b4f1be Faidon Liambotis
]
49 00b4f1be Faidon Liambotis
50 f5ea24a9 Markos Gogoulos
#read is called on GET requests
51 f5ea24a9 Markos Gogoulos
#create is called on POST, and creates new objects
52 f5ea24a9 Markos Gogoulos
#update is called on PUT, and should update an existing product
53 f5ea24a9 Markos Gogoulos
#delete is called on DELETE, and should delete an existing object
54 f5ea24a9 Markos Gogoulos
55 ccbd9f9b Markos Gogoulos
56 00b4f1be Faidon Liambotis
class VersionHandler(AnonymousBaseHandler):
57 00b4f1be Faidon Liambotis
    allowed_methods = ('GET',)
58 00b4f1be Faidon Liambotis
59 00b4f1be Faidon Liambotis
    def read(self, request, number=None):
60 ffffd5fe Markos Gogoulos
        try:
61 ffffd5fe Markos Gogoulos
            if number is None:
62 ffffd5fe Markos Gogoulos
                versions = map(lambda v: {
63 ffffd5fe Markos Gogoulos
                            "status": v["status"],
64 ffffd5fe Markos Gogoulos
                            "id": v["id"],
65 ffffd5fe Markos Gogoulos
                        }, VERSIONS)
66 ffffd5fe Markos Gogoulos
                return { "versions": versions }
67 ffffd5fe Markos Gogoulos
            else:
68 ffffd5fe Markos Gogoulos
                for version in VERSIONS:
69 ffffd5fe Markos Gogoulos
                    if version["id"] == number:
70 ffffd5fe Markos Gogoulos
                        return { "version": version }
71 ffffd5fe Markos Gogoulos
                raise fault.itemNotFound
72 ffffd5fe Markos Gogoulos
        except Exception, e:
73 6b83d46b Markos Gogoulos
            log.exception('Unexpected error: %s' % e)
74 ffffd5fe Markos Gogoulos
            raise fault.serviceUnavailable
75 00b4f1be Faidon Liambotis
76 00b4f1be Faidon Liambotis
77 00b4f1be Faidon Liambotis
class ServerHandler(BaseHandler):
78 f5ea24a9 Markos Gogoulos
    """Handler responsible for the Servers
79 f5ea24a9 Markos Gogoulos

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

82 f5ea24a9 Markos Gogoulos
     @HTTP methods: POST, DELETE, PUT, GET
83 f5ea24a9 Markos Gogoulos
     @Parameters: POST data with the create data (cpu, ram, etc)
84 f5ea24a9 Markos Gogoulos
     @Responses: HTTP 202 if successfully call rapi, itemNotFound, serviceUnavailable otherwise
85 f5ea24a9 Markos Gogoulos

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

678 60023e66 Constantinos Venetsanopoulos
    the handler Lists, Creates, Updates and Deletes Metadata values
679 60023e66 Constantinos Venetsanopoulos

680 60023e66 Constantinos Venetsanopoulos
    @HTTP methods: POST, DELETE, PUT, GET
681 60023e66 Constantinos Venetsanopoulos
    @Parameters: POST data with key value pairs
682 60023e66 Constantinos Venetsanopoulos

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

841 59cee068 Markos Gogoulos
     creates, lists, deletes virtual machine groups
842 59cee068 Markos Gogoulos

843 59cee068 Markos Gogoulos
     @HTTP methods: GET, POST, DELETE
844 59cee068 Markos Gogoulos
     @Parameters: POST data 
845 59cee068 Markos Gogoulos
     @Responses: HTTP 202 if successfully get the Groups list, itemNotFound, serviceUnavailable otherwise
846 59cee068 Markos Gogoulos

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