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 |