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 |