Statistics
| Branch: | Tag: | Revision:

root / api / handlers.py @ b9a77976

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

323 d73d59e4 Markos Gogoulos
     handles Reboot, Shutdown and Start actions. 
324 d73d59e4 Markos Gogoulos

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

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

359 f5ea24a9 Markos Gogoulos
     handles Reboot, Shutdown and Start actions. 
360 f5ea24a9 Markos Gogoulos

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

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

428 60023e66 Constantinos Venetsanopoulos
    the handler Lists, Creates, Updates and Deletes Metadata values
429 60023e66 Constantinos Venetsanopoulos

430 60023e66 Constantinos Venetsanopoulos
    @HTTP methods: POST, DELETE, PUT, GET
431 60023e66 Constantinos Venetsanopoulos
    @Parameters: POST data with key value pairs
432 60023e66 Constantinos Venetsanopoulos

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

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

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

618 f5ea24a9 Markos Gogoulos
     handles the listing, creation and delete of Images. 
619 f5ea24a9 Markos Gogoulos

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

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

633 dcc6a862 Faidon Liambotis
        Returns: OK
634 dcc6a862 Faidon Liambotis
        Faults: cloudServersFault, serviceUnavailable, unauthorized,
635 dcc6a862 Faidon Liambotis
                badRequest, itemNotFound
636 dcc6a862 Faidon Liambotis
        """
637 ffffd5fe Markos Gogoulos
        try:
638 ffffd5fe Markos Gogoulos
            images = Image.objects.all()
639 ffffd5fe Markos Gogoulos
            images_list = [ {'created': image.created.isoformat(), 
640 ffffd5fe Markos Gogoulos
                        'id': image.id,
641 ffffd5fe Markos Gogoulos
                        'name': image.name,
642 ffffd5fe Markos Gogoulos
                        'updated': image.updated.isoformat(),    
643 ffffd5fe Markos Gogoulos
                        'description': image.description, 
644 ffffd5fe Markos Gogoulos
                        'status': image.state, 
645 63597809 Markos Gogoulos
                        'progress': image.state == 'ACTIVE' and 100 or 0, 
646 ffffd5fe Markos Gogoulos
                        'size': image.size, 
647 ffffd5fe Markos Gogoulos
                        'serverId': image.sourcevm and image.sourcevm.id or ""
648 ffffd5fe Markos Gogoulos
                       } for image in images]
649 ffffd5fe Markos Gogoulos
            # Images info is stored in the DB. Ganeti is not aware of this
650 ffffd5fe Markos Gogoulos
            if id == "detail":
651 ffffd5fe Markos Gogoulos
                return { "images": images_list }
652 ffffd5fe Markos Gogoulos
            elif id is None:
653 ffffd5fe Markos Gogoulos
                return { "images": [ { "id": s['id'], "name": s['name'] } for s in images_list ] }
654 ffffd5fe Markos Gogoulos
            else:        
655 ffffd5fe Markos Gogoulos
                image = images.get(id=id)
656 ffffd5fe Markos Gogoulos
                return { "image":  {'created': image.created.isoformat(), 
657 12827073 Markos Gogoulos
                    'id': image.id,
658 12827073 Markos Gogoulos
                    'name': image.name,
659 12827073 Markos Gogoulos
                    'updated': image.updated.isoformat(),    
660 12827073 Markos Gogoulos
                    'description': image.description, 
661 b65b1281 Markos Gogoulos
                    'status': image.state, 
662 63597809 Markos Gogoulos
                    'progress': image.state == 'ACTIVE' and 100 or 0, 
663 d235fdd2 Markos Gogoulos
                    'size': image.size, 
664 d235fdd2 Markos Gogoulos
                    'serverId': image.sourcevm and image.sourcevm.id or ""
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