Statistics
| Branch: | Tag: | Revision:

root / api / servers.py @ 5509b599

History | View | Annotate | Download (14 kB)

1 7e2f9d4b Giorgos Verigakis
#
2 7e2f9d4b Giorgos Verigakis
# Copyright (c) 2010 Greek Research and Technology Network
3 7e2f9d4b Giorgos Verigakis
#
4 7e2f9d4b Giorgos Verigakis
5 529178b1 Giorgos Verigakis
import logging
6 529178b1 Giorgos Verigakis
7 d8e50a39 Giorgos Verigakis
from django.conf.urls.defaults import patterns
8 7e2f9d4b Giorgos Verigakis
from django.http import HttpResponse
9 7e2f9d4b Giorgos Verigakis
from django.template.loader import render_to_string
10 29a59bc1 Giorgos Verigakis
from django.utils import simplejson as json
11 7e2f9d4b Giorgos Verigakis
12 0971fa71 Markos Gogoulos
from synnefo.api.actions import server_actions
13 d8e50a39 Giorgos Verigakis
from synnefo.api.common import method_not_allowed
14 529178b1 Giorgos Verigakis
from synnefo.api.faults import BadRequest, ItemNotFound, ServiceUnavailable
15 529178b1 Giorgos Verigakis
from synnefo.api.util import (isoformat, isoparse, random_password,
16 40777cc8 Giorgos Verigakis
                                get_vm, get_vm_meta, get_image, get_flavor,
17 529178b1 Giorgos Verigakis
                                get_request_dict, render_metadata, render_meta, api_method)
18 529178b1 Giorgos Verigakis
from synnefo.db.models import VirtualMachine, VirtualMachineMetadata
19 529178b1 Giorgos Verigakis
from synnefo.logic.backend import create_instance, delete_instance
20 d8e50a39 Giorgos Verigakis
from synnefo.logic.utils import get_rsapi_state
21 529178b1 Giorgos Verigakis
from synnefo.util.rapi import GanetiApiError
22 7e2f9d4b Giorgos Verigakis
23 7e2f9d4b Giorgos Verigakis
24 7e2f9d4b Giorgos Verigakis
urlpatterns = patterns('synnefo.api.servers',
25 7e2f9d4b Giorgos Verigakis
    (r'^(?:/|.json|.xml)?$', 'demux'),
26 7e2f9d4b Giorgos Verigakis
    (r'^/detail(?:.json|.xml)?$', 'list_servers', {'detail': True}),
27 7e2f9d4b Giorgos Verigakis
    (r'^/(\d+)(?:.json|.xml)?$', 'server_demux'),
28 b016b476 Giorgos Verigakis
    (r'^/(\d+)/action(?:.json|.xml)?$', 'server_action'),
29 b016b476 Giorgos Verigakis
    (r'^/(\d+)/ips(?:.json|.xml)?$', 'list_addresses'),
30 b016b476 Giorgos Verigakis
    (r'^/(\d+)/ips/(.+?)(?:.json|.xml)?$', 'list_addresses_by_network'),
31 d8e50a39 Giorgos Verigakis
    (r'^/(\d+)/meta(?:.json|.xml)?$', 'metadata_demux'),
32 d8e50a39 Giorgos Verigakis
    (r'^/(\d+)/meta/(.+?)(?:.json|.xml)?$', 'metadata_item_demux'),
33 7e2f9d4b Giorgos Verigakis
)
34 7e2f9d4b Giorgos Verigakis
35 7e2f9d4b Giorgos Verigakis
36 7e2f9d4b Giorgos Verigakis
def demux(request):
37 7e2f9d4b Giorgos Verigakis
    if request.method == 'GET':
38 7e2f9d4b Giorgos Verigakis
        return list_servers(request)
39 7e2f9d4b Giorgos Verigakis
    elif request.method == 'POST':
40 7e2f9d4b Giorgos Verigakis
        return create_server(request)
41 7e2f9d4b Giorgos Verigakis
    else:
42 d8e50a39 Giorgos Verigakis
        return method_not_allowed(request)
43 7e2f9d4b Giorgos Verigakis
44 7e2f9d4b Giorgos Verigakis
def server_demux(request, server_id):
45 7e2f9d4b Giorgos Verigakis
    if request.method == 'GET':
46 7e2f9d4b Giorgos Verigakis
        return get_server_details(request, server_id)
47 7e2f9d4b Giorgos Verigakis
    elif request.method == 'PUT':
48 7e2f9d4b Giorgos Verigakis
        return update_server_name(request, server_id)
49 7e2f9d4b Giorgos Verigakis
    elif request.method == 'DELETE':
50 7e2f9d4b Giorgos Verigakis
        return delete_server(request, server_id)
51 7e2f9d4b Giorgos Verigakis
    else:
52 d8e50a39 Giorgos Verigakis
        return method_not_allowed(request)
53 d8e50a39 Giorgos Verigakis
54 d8e50a39 Giorgos Verigakis
def metadata_demux(request, server_id):
55 d8e50a39 Giorgos Verigakis
    if request.method == 'GET':
56 d8e50a39 Giorgos Verigakis
        return list_metadata(request, server_id)
57 d8e50a39 Giorgos Verigakis
    elif request.method == 'POST':
58 d8e50a39 Giorgos Verigakis
        return update_metadata(request, server_id)
59 d8e50a39 Giorgos Verigakis
    else:
60 d8e50a39 Giorgos Verigakis
        return method_not_allowed(request)
61 d8e50a39 Giorgos Verigakis
62 d8e50a39 Giorgos Verigakis
def metadata_item_demux(request, server_id, key):
63 d8e50a39 Giorgos Verigakis
    if request.method == 'GET':
64 d8e50a39 Giorgos Verigakis
        return get_metadata_item(request, server_id, key)
65 d8e50a39 Giorgos Verigakis
    elif request.method == 'PUT':
66 d8e50a39 Giorgos Verigakis
        return create_metadata_item(request, server_id, key)
67 d8e50a39 Giorgos Verigakis
    elif request.method == 'DELETE':
68 d8e50a39 Giorgos Verigakis
        return delete_metadata_item(request, server_id, key)
69 d8e50a39 Giorgos Verigakis
    else:
70 d8e50a39 Giorgos Verigakis
        return method_not_allowed(request)
71 7e2f9d4b Giorgos Verigakis
72 c36934a7 Giorgos Verigakis
73 b016b476 Giorgos Verigakis
def address_to_dict(ipfour, ipsix):
74 b016b476 Giorgos Verigakis
    return {'id': 'public',
75 b016b476 Giorgos Verigakis
            'values': [{'version': 4, 'addr': ipfour}, {'version': 6, 'addr': ipsix}]}
76 b016b476 Giorgos Verigakis
77 d8e50a39 Giorgos Verigakis
def metadata_to_dict(vm):
78 d8e50a39 Giorgos Verigakis
    vm_meta = vm.virtualmachinemetadata_set.all()
79 d8e50a39 Giorgos Verigakis
    return dict((meta.meta_key, meta.meta_value) for meta in vm_meta)
80 d8e50a39 Giorgos Verigakis
81 d8e50a39 Giorgos Verigakis
def vm_to_dict(vm, detail=False):
82 d8e50a39 Giorgos Verigakis
    d = dict(id=vm.id, name=vm.name)
83 7e2f9d4b Giorgos Verigakis
    if detail:
84 d8e50a39 Giorgos Verigakis
        d['status'] = get_rsapi_state(vm)
85 d8e50a39 Giorgos Verigakis
        d['progress'] = 100 if get_rsapi_state(vm) == 'ACTIVE' else 0
86 d8e50a39 Giorgos Verigakis
        d['hostId'] = vm.hostid
87 d8e50a39 Giorgos Verigakis
        d['updated'] = isoformat(vm.updated)
88 d8e50a39 Giorgos Verigakis
        d['created'] = isoformat(vm.created)
89 d8e50a39 Giorgos Verigakis
        d['flavorRef'] = vm.flavor.id
90 d8e50a39 Giorgos Verigakis
        d['imageRef'] = vm.sourceimage.id
91 aa197ee4 Vangelis Koukis
92 d8e50a39 Giorgos Verigakis
        metadata = metadata_to_dict(vm)
93 7e2f9d4b Giorgos Verigakis
        if metadata:
94 b9a77976 Giorgos Verigakis
            d['metadata'] = {'values': metadata}
95 aa197ee4 Vangelis Koukis
96 d8e50a39 Giorgos Verigakis
        addresses = [address_to_dict(vm.ipfour, vm.ipsix)]
97 b19653d1 Giorgos Verigakis
        addresses.extend({'id': str(network.id), 'values': []} for network in vm.network_set.all())
98 b9a77976 Giorgos Verigakis
        d['addresses'] = {'values': addresses}
99 7e2f9d4b Giorgos Verigakis
    return d
100 7e2f9d4b Giorgos Verigakis
101 d8e50a39 Giorgos Verigakis
102 d8e50a39 Giorgos Verigakis
def render_server(request, server, status=200):
103 d8e50a39 Giorgos Verigakis
    if request.serialization == 'xml':
104 d8e50a39 Giorgos Verigakis
        data = render_to_string('server.xml', {'server': server, 'is_root': True})
105 7e2f9d4b Giorgos Verigakis
    else:
106 d8e50a39 Giorgos Verigakis
        data = json.dumps({'server': server})
107 c36934a7 Giorgos Verigakis
    return HttpResponse(data, status=status)
108 aa197ee4 Vangelis Koukis
109 7e2f9d4b Giorgos Verigakis
110 c36934a7 Giorgos Verigakis
@api_method('GET')
111 7e2f9d4b Giorgos Verigakis
def list_servers(request, detail=False):
112 7e2f9d4b Giorgos Verigakis
    # Normal Response Codes: 200, 203
113 7e2f9d4b Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
114 7e2f9d4b Giorgos Verigakis
    #                       serviceUnavailable (503),
115 7e2f9d4b Giorgos Verigakis
    #                       unauthorized (401),
116 7e2f9d4b Giorgos Verigakis
    #                       badRequest (400),
117 7e2f9d4b Giorgos Verigakis
    #                       overLimit (413)
118 aa197ee4 Vangelis Koukis
119 d8e50a39 Giorgos Verigakis
    since = isoparse(request.GET.get('changes-since'))
120 aa197ee4 Vangelis Koukis
121 d8e50a39 Giorgos Verigakis
    if since:
122 40777cc8 Giorgos Verigakis
        user_vms = VirtualMachine.objects.filter(owner=request.user, updated__gte=since)
123 d8e50a39 Giorgos Verigakis
        if not user_vms:
124 d8e50a39 Giorgos Verigakis
            return HttpResponse(status=304)
125 d8e50a39 Giorgos Verigakis
    else:
126 40777cc8 Giorgos Verigakis
        user_vms = VirtualMachine.objects.filter(owner=request.user, deleted=False)
127 d8e50a39 Giorgos Verigakis
    servers = [vm_to_dict(server, detail) for server in user_vms]
128 aa197ee4 Vangelis Koukis
129 d8e50a39 Giorgos Verigakis
    if request.serialization == 'xml':
130 d8e50a39 Giorgos Verigakis
        data = render_to_string('list_servers.xml', {'servers': servers, 'detail': detail})
131 7e2f9d4b Giorgos Verigakis
    else:
132 c36934a7 Giorgos Verigakis
        data = json.dumps({'servers': {'values': servers}})
133 aa197ee4 Vangelis Koukis
134 c36934a7 Giorgos Verigakis
    return HttpResponse(data, status=200)
135 7e2f9d4b Giorgos Verigakis
136 c36934a7 Giorgos Verigakis
@api_method('POST')
137 7e2f9d4b Giorgos Verigakis
def create_server(request):
138 7e2f9d4b Giorgos Verigakis
    # Normal Response Code: 202
139 7e2f9d4b Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
140 7e2f9d4b Giorgos Verigakis
    #                       serviceUnavailable (503),
141 7e2f9d4b Giorgos Verigakis
    #                       unauthorized (401),
142 7e2f9d4b Giorgos Verigakis
    #                       badMediaType(415),
143 7e2f9d4b Giorgos Verigakis
    #                       itemNotFound (404),
144 7e2f9d4b Giorgos Verigakis
    #                       badRequest (400),
145 7e2f9d4b Giorgos Verigakis
    #                       serverCapacityUnavailable (503),
146 7e2f9d4b Giorgos Verigakis
    #                       overLimit (413)
147 aa197ee4 Vangelis Koukis
148 7e2f9d4b Giorgos Verigakis
    req = get_request_dict(request)
149 aa197ee4 Vangelis Koukis
150 7e2f9d4b Giorgos Verigakis
    try:
151 7e2f9d4b Giorgos Verigakis
        server = req['server']
152 7e2f9d4b Giorgos Verigakis
        name = server['name']
153 bc855ce7 Giorgos Verigakis
        metadata = server.get('metadata', {})
154 bc855ce7 Giorgos Verigakis
        assert isinstance(metadata, dict)
155 529178b1 Giorgos Verigakis
        image_id = server['imageRef']
156 529178b1 Giorgos Verigakis
        flavor_id = server['flavorRef']
157 bc855ce7 Giorgos Verigakis
    except (KeyError, AssertionError):
158 d8e50a39 Giorgos Verigakis
        raise BadRequest('Malformed request.')
159 aa197ee4 Vangelis Koukis
160 40777cc8 Giorgos Verigakis
    image = get_image(image_id, request.user)
161 529178b1 Giorgos Verigakis
    flavor = get_flavor(flavor_id)
162 aa197ee4 Vangelis Koukis
163 529178b1 Giorgos Verigakis
    # We must save the VM instance now, so that it gets a valid vm.backend_id.
164 529178b1 Giorgos Verigakis
    vm = VirtualMachine.objects.create(
165 7e2f9d4b Giorgos Verigakis
        name=name,
166 40777cc8 Giorgos Verigakis
        owner=request.user,
167 529178b1 Giorgos Verigakis
        sourceimage=image,
168 7e2f9d4b Giorgos Verigakis
        ipfour='0.0.0.0',
169 7e2f9d4b Giorgos Verigakis
        ipsix='::1',
170 7e2f9d4b Giorgos Verigakis
        flavor=flavor)
171 aa197ee4 Vangelis Koukis
172 529178b1 Giorgos Verigakis
    password = random_password()
173 aa197ee4 Vangelis Koukis
174 1c03e74e Vangelis Koukis
    try:
175 529178b1 Giorgos Verigakis
        create_instance(vm, flavor, password)
176 4f598167 Giorgos Verigakis
    except GanetiApiError:
177 1c03e74e Vangelis Koukis
        vm.delete()
178 4f598167 Giorgos Verigakis
        raise ServiceUnavailable('Could not create server.')
179 aa197ee4 Vangelis Koukis
180 bc855ce7 Giorgos Verigakis
    for key, val in metadata.items():
181 bc855ce7 Giorgos Verigakis
        VirtualMachineMetadata.objects.create(meta_key=key, meta_value=val, vm=vm)
182 aa197ee4 Vangelis Koukis
183 529178b1 Giorgos Verigakis
    logging.info('created vm with %s cpus, %s ram and %s storage',
184 529178b1 Giorgos Verigakis
                    flavor.cpu, flavor.ram, flavor.disk)
185 aa197ee4 Vangelis Koukis
186 d8e50a39 Giorgos Verigakis
    server = vm_to_dict(vm, detail=True)
187 d8e50a39 Giorgos Verigakis
    server['status'] = 'BUILD'
188 529178b1 Giorgos Verigakis
    server['adminPass'] = password
189 d8e50a39 Giorgos Verigakis
    return render_server(request, server, status=202)
190 7e2f9d4b Giorgos Verigakis
191 c36934a7 Giorgos Verigakis
@api_method('GET')
192 7e2f9d4b Giorgos Verigakis
def get_server_details(request, server_id):
193 c36934a7 Giorgos Verigakis
    # Normal Response Codes: 200, 203
194 c36934a7 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
195 c36934a7 Giorgos Verigakis
    #                       serviceUnavailable (503),
196 c36934a7 Giorgos Verigakis
    #                       unauthorized (401),
197 c36934a7 Giorgos Verigakis
    #                       badRequest (400),
198 c36934a7 Giorgos Verigakis
    #                       itemNotFound (404),
199 c36934a7 Giorgos Verigakis
    #                       overLimit (413)
200 aa197ee4 Vangelis Koukis
201 40777cc8 Giorgos Verigakis
    vm = get_vm(server_id, request.user)
202 d8e50a39 Giorgos Verigakis
    server = vm_to_dict(vm, detail=True)
203 d8e50a39 Giorgos Verigakis
    return render_server(request, server)
204 7e2f9d4b Giorgos Verigakis
205 c36934a7 Giorgos Verigakis
@api_method('PUT')
206 c36934a7 Giorgos Verigakis
def update_server_name(request, server_id):
207 c36934a7 Giorgos Verigakis
    # Normal Response Code: 204
208 c36934a7 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
209 c36934a7 Giorgos Verigakis
    #                       serviceUnavailable (503),
210 c36934a7 Giorgos Verigakis
    #                       unauthorized (401),
211 c36934a7 Giorgos Verigakis
    #                       badRequest (400),
212 c36934a7 Giorgos Verigakis
    #                       badMediaType(415),
213 c36934a7 Giorgos Verigakis
    #                       itemNotFound (404),
214 c36934a7 Giorgos Verigakis
    #                       buildInProgress (409),
215 c36934a7 Giorgos Verigakis
    #                       overLimit (413)
216 aa197ee4 Vangelis Koukis
217 7e2f9d4b Giorgos Verigakis
    req = get_request_dict(request)
218 aa197ee4 Vangelis Koukis
219 7e2f9d4b Giorgos Verigakis
    try:
220 7e2f9d4b Giorgos Verigakis
        name = req['server']['name']
221 529178b1 Giorgos Verigakis
    except (TypeError, KeyError):
222 d8e50a39 Giorgos Verigakis
        raise BadRequest('Malformed request.')
223 aa197ee4 Vangelis Koukis
224 40777cc8 Giorgos Verigakis
    vm = get_vm(server_id, request.user)
225 d8e50a39 Giorgos Verigakis
    vm.name = name
226 d8e50a39 Giorgos Verigakis
    vm.save()
227 aa197ee4 Vangelis Koukis
228 7e2f9d4b Giorgos Verigakis
    return HttpResponse(status=204)
229 7e2f9d4b Giorgos Verigakis
230 c36934a7 Giorgos Verigakis
@api_method('DELETE')
231 7e2f9d4b Giorgos Verigakis
def delete_server(request, server_id):
232 c36934a7 Giorgos Verigakis
    # Normal Response Codes: 204
233 c36934a7 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
234 c36934a7 Giorgos Verigakis
    #                       serviceUnavailable (503),
235 c36934a7 Giorgos Verigakis
    #                       unauthorized (401),
236 c36934a7 Giorgos Verigakis
    #                       itemNotFound (404),
237 c36934a7 Giorgos Verigakis
    #                       unauthorized (401),
238 c36934a7 Giorgos Verigakis
    #                       buildInProgress (409),
239 c36934a7 Giorgos Verigakis
    #                       overLimit (413)
240 aa197ee4 Vangelis Koukis
241 40777cc8 Giorgos Verigakis
    vm = get_vm(server_id, request.user)
242 529178b1 Giorgos Verigakis
    delete_instance(vm)
243 7e2f9d4b Giorgos Verigakis
    return HttpResponse(status=204)
244 b016b476 Giorgos Verigakis
245 b016b476 Giorgos Verigakis
@api_method('POST')
246 b016b476 Giorgos Verigakis
def server_action(request, server_id):
247 40777cc8 Giorgos Verigakis
    vm = get_vm(server_id, request.user)
248 b016b476 Giorgos Verigakis
    req = get_request_dict(request)
249 b016b476 Giorgos Verigakis
    if len(req) != 1:
250 d8e50a39 Giorgos Verigakis
        raise BadRequest('Malformed request.')
251 aa197ee4 Vangelis Koukis
252 b016b476 Giorgos Verigakis
    key = req.keys()[0]
253 d8e50a39 Giorgos Verigakis
    val = req[key]
254 aa197ee4 Vangelis Koukis
255 d8e50a39 Giorgos Verigakis
    try:
256 d8e50a39 Giorgos Verigakis
        assert isinstance(val, dict)
257 20a51b1e Giorgos Verigakis
        return server_actions[key](request, vm, req[key])
258 d8e50a39 Giorgos Verigakis
    except KeyError:
259 d8e50a39 Giorgos Verigakis
        raise BadRequest('Unknown action.')
260 d8e50a39 Giorgos Verigakis
    except AssertionError:
261 d8e50a39 Giorgos Verigakis
        raise BadRequest('Invalid argument.')
262 b016b476 Giorgos Verigakis
263 b016b476 Giorgos Verigakis
@api_method('GET')
264 b016b476 Giorgos Verigakis
def list_addresses(request, server_id):
265 b016b476 Giorgos Verigakis
    # Normal Response Codes: 200, 203
266 b016b476 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
267 b016b476 Giorgos Verigakis
    #                       serviceUnavailable (503),
268 b016b476 Giorgos Verigakis
    #                       unauthorized (401),
269 b016b476 Giorgos Verigakis
    #                       badRequest (400),
270 b016b476 Giorgos Verigakis
    #                       overLimit (413)
271 aa197ee4 Vangelis Koukis
272 40777cc8 Giorgos Verigakis
    vm = get_vm(server_id, request.user)
273 d8e50a39 Giorgos Verigakis
    addresses = [address_to_dict(vm.ipfour, vm.ipsix)]
274 aa197ee4 Vangelis Koukis
275 d8e50a39 Giorgos Verigakis
    if request.serialization == 'xml':
276 b016b476 Giorgos Verigakis
        data = render_to_string('list_addresses.xml', {'addresses': addresses})
277 b016b476 Giorgos Verigakis
    else:
278 b016b476 Giorgos Verigakis
        data = json.dumps({'addresses': {'values': addresses}})
279 aa197ee4 Vangelis Koukis
280 b016b476 Giorgos Verigakis
    return HttpResponse(data, status=200)
281 b016b476 Giorgos Verigakis
282 b016b476 Giorgos Verigakis
@api_method('GET')
283 b016b476 Giorgos Verigakis
def list_addresses_by_network(request, server_id, network_id):
284 b016b476 Giorgos Verigakis
    # Normal Response Codes: 200, 203
285 b016b476 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
286 b016b476 Giorgos Verigakis
    #                       serviceUnavailable (503),
287 b016b476 Giorgos Verigakis
    #                       unauthorized (401),
288 b016b476 Giorgos Verigakis
    #                       badRequest (400),
289 b016b476 Giorgos Verigakis
    #                       itemNotFound (404),
290 b016b476 Giorgos Verigakis
    #                       overLimit (413)
291 aa197ee4 Vangelis Koukis
292 40777cc8 Giorgos Verigakis
    vm = get_vm(server_id, request.user)
293 b016b476 Giorgos Verigakis
    if network_id != 'public':
294 d8e50a39 Giorgos Verigakis
        raise ItemNotFound('Unknown network.')
295 aa197ee4 Vangelis Koukis
296 d8e50a39 Giorgos Verigakis
    address = address_to_dict(vm.ipfour, vm.ipsix)
297 aa197ee4 Vangelis Koukis
298 d8e50a39 Giorgos Verigakis
    if request.serialization == 'xml':
299 b016b476 Giorgos Verigakis
        data = render_to_string('address.xml', {'address': address})
300 b016b476 Giorgos Verigakis
    else:
301 b016b476 Giorgos Verigakis
        data = json.dumps({'network': address})
302 aa197ee4 Vangelis Koukis
303 b016b476 Giorgos Verigakis
    return HttpResponse(data, status=200)
304 d8e50a39 Giorgos Verigakis
305 d8e50a39 Giorgos Verigakis
@api_method('GET')
306 d8e50a39 Giorgos Verigakis
def list_metadata(request, server_id):
307 d8e50a39 Giorgos Verigakis
    # Normal Response Codes: 200, 203
308 d8e50a39 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
309 d8e50a39 Giorgos Verigakis
    #                       serviceUnavailable (503),
310 d8e50a39 Giorgos Verigakis
    #                       unauthorized (401),
311 d8e50a39 Giorgos Verigakis
    #                       badRequest (400),
312 d8e50a39 Giorgos Verigakis
    #                       overLimit (413)
313 d8e50a39 Giorgos Verigakis
314 40777cc8 Giorgos Verigakis
    vm = get_vm(server_id, request.user)
315 d8e50a39 Giorgos Verigakis
    metadata = metadata_to_dict(vm)
316 432fc8c3 Giorgos Verigakis
    return render_metadata(request, metadata, use_values=True, status=200)
317 d8e50a39 Giorgos Verigakis
318 d8e50a39 Giorgos Verigakis
@api_method('POST')
319 d8e50a39 Giorgos Verigakis
def update_metadata(request, server_id):
320 d8e50a39 Giorgos Verigakis
    # Normal Response Code: 201
321 d8e50a39 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
322 d8e50a39 Giorgos Verigakis
    #                       serviceUnavailable (503),
323 d8e50a39 Giorgos Verigakis
    #                       unauthorized (401),
324 d8e50a39 Giorgos Verigakis
    #                       badRequest (400),
325 d8e50a39 Giorgos Verigakis
    #                       buildInProgress (409),
326 d8e50a39 Giorgos Verigakis
    #                       badMediaType(415),
327 d8e50a39 Giorgos Verigakis
    #                       overLimit (413)
328 d8e50a39 Giorgos Verigakis
329 40777cc8 Giorgos Verigakis
    vm = get_vm(server_id, request.user)
330 d8e50a39 Giorgos Verigakis
    req = get_request_dict(request)
331 d8e50a39 Giorgos Verigakis
    try:
332 d8e50a39 Giorgos Verigakis
        metadata = req['metadata']
333 d8e50a39 Giorgos Verigakis
        assert isinstance(metadata, dict)
334 d8e50a39 Giorgos Verigakis
    except (KeyError, AssertionError):
335 d8e50a39 Giorgos Verigakis
        raise BadRequest('Malformed request.')
336 aa197ee4 Vangelis Koukis
337 d8e50a39 Giorgos Verigakis
    updated = {}
338 aa197ee4 Vangelis Koukis
339 d8e50a39 Giorgos Verigakis
    for key, val in metadata.items():
340 d8e50a39 Giorgos Verigakis
        try:
341 d8e50a39 Giorgos Verigakis
            meta = VirtualMachineMetadata.objects.get(meta_key=key, vm=vm)
342 d8e50a39 Giorgos Verigakis
            meta.meta_value = val
343 d8e50a39 Giorgos Verigakis
            meta.save()
344 d8e50a39 Giorgos Verigakis
            updated[key] = val
345 d8e50a39 Giorgos Verigakis
        except VirtualMachineMetadata.DoesNotExist:
346 d8e50a39 Giorgos Verigakis
            pass    # Ignore non-existent metadata
347 5509b599 Giorgos Verigakis
    
348 5509b599 Giorgos Verigakis
    if updated:
349 5509b599 Giorgos Verigakis
        vm.save()
350 5509b599 Giorgos Verigakis
    
351 d115929c Giorgos Verigakis
    return render_metadata(request, updated, status=201)
352 d8e50a39 Giorgos Verigakis
353 d8e50a39 Giorgos Verigakis
@api_method('GET')
354 d8e50a39 Giorgos Verigakis
def get_metadata_item(request, server_id, key):
355 d8e50a39 Giorgos Verigakis
    # Normal Response Codes: 200, 203
356 d8e50a39 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
357 d8e50a39 Giorgos Verigakis
    #                       serviceUnavailable (503),
358 d8e50a39 Giorgos Verigakis
    #                       unauthorized (401),
359 d8e50a39 Giorgos Verigakis
    #                       itemNotFound (404),
360 d8e50a39 Giorgos Verigakis
    #                       badRequest (400),
361 d8e50a39 Giorgos Verigakis
    #                       overLimit (413)
362 aa197ee4 Vangelis Koukis
363 40777cc8 Giorgos Verigakis
    vm = get_vm(server_id, request.user)
364 40777cc8 Giorgos Verigakis
    meta = get_vm_meta(vm, key)
365 432fc8c3 Giorgos Verigakis
    return render_meta(request, meta, status=200)
366 d8e50a39 Giorgos Verigakis
367 d8e50a39 Giorgos Verigakis
@api_method('PUT')
368 d8e50a39 Giorgos Verigakis
def create_metadata_item(request, server_id, key):
369 d8e50a39 Giorgos Verigakis
    # Normal Response Code: 201
370 d8e50a39 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
371 d8e50a39 Giorgos Verigakis
    #                       serviceUnavailable (503),
372 d8e50a39 Giorgos Verigakis
    #                       unauthorized (401),
373 d8e50a39 Giorgos Verigakis
    #                       itemNotFound (404),
374 d8e50a39 Giorgos Verigakis
    #                       badRequest (400),
375 d8e50a39 Giorgos Verigakis
    #                       buildInProgress (409),
376 d8e50a39 Giorgos Verigakis
    #                       badMediaType(415),
377 d8e50a39 Giorgos Verigakis
    #                       overLimit (413)
378 d8e50a39 Giorgos Verigakis
379 40777cc8 Giorgos Verigakis
    vm = get_vm(server_id, request.user)
380 d8e50a39 Giorgos Verigakis
    req = get_request_dict(request)
381 d8e50a39 Giorgos Verigakis
    try:
382 d8e50a39 Giorgos Verigakis
        metadict = req['meta']
383 d8e50a39 Giorgos Verigakis
        assert isinstance(metadict, dict)
384 d8e50a39 Giorgos Verigakis
        assert len(metadict) == 1
385 d8e50a39 Giorgos Verigakis
        assert key in metadict
386 d8e50a39 Giorgos Verigakis
    except (KeyError, AssertionError):
387 d8e50a39 Giorgos Verigakis
        raise BadRequest('Malformed request.')
388 aa197ee4 Vangelis Koukis
389 d8e50a39 Giorgos Verigakis
    meta, created = VirtualMachineMetadata.objects.get_or_create(meta_key=key, vm=vm)
390 d8e50a39 Giorgos Verigakis
    meta.meta_value = metadict[key]
391 d8e50a39 Giorgos Verigakis
    meta.save()
392 5509b599 Giorgos Verigakis
    vm.save()
393 432fc8c3 Giorgos Verigakis
    return render_meta(request, meta, status=201)
394 d8e50a39 Giorgos Verigakis
395 d8e50a39 Giorgos Verigakis
@api_method('DELETE')
396 d8e50a39 Giorgos Verigakis
def delete_metadata_item(request, server_id, key):
397 d8e50a39 Giorgos Verigakis
    # Normal Response Code: 204
398 d8e50a39 Giorgos Verigakis
    # Error Response Codes: computeFault (400, 500),
399 d8e50a39 Giorgos Verigakis
    #                       serviceUnavailable (503),
400 d8e50a39 Giorgos Verigakis
    #                       unauthorized (401),
401 d8e50a39 Giorgos Verigakis
    #                       itemNotFound (404),
402 d8e50a39 Giorgos Verigakis
    #                       badRequest (400),
403 d8e50a39 Giorgos Verigakis
    #                       buildInProgress (409),
404 d8e50a39 Giorgos Verigakis
    #                       badMediaType(415),
405 d8e50a39 Giorgos Verigakis
    #                       overLimit (413),
406 aa197ee4 Vangelis Koukis
407 40777cc8 Giorgos Verigakis
    vm = get_vm(server_id, request.user)
408 40777cc8 Giorgos Verigakis
    meta = get_vm_meta(vm, key)
409 d8e50a39 Giorgos Verigakis
    meta.delete()
410 5509b599 Giorgos Verigakis
    vm.save()
411 d8e50a39 Giorgos Verigakis
    return HttpResponse(status=204)