Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / api / util.py @ 03992c72

History | View | Annotate | Download (12.8 kB)

1 6ef51e9f Giorgos Verigakis
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2 d1387ed7 Christodoulos Psaltis
#
3 adee02b8 Giorgos Verigakis
# Redistribution and use in source and binary forms, with or
4 adee02b8 Giorgos Verigakis
# without modification, are permitted provided that the following
5 adee02b8 Giorgos Verigakis
# conditions are met:
6 d1387ed7 Christodoulos Psaltis
#
7 adee02b8 Giorgos Verigakis
#   1. Redistributions of source code must retain the above
8 adee02b8 Giorgos Verigakis
#      copyright notice, this list of conditions and the following
9 adee02b8 Giorgos Verigakis
#      disclaimer.
10 d1387ed7 Christodoulos Psaltis
#
11 adee02b8 Giorgos Verigakis
#   2. Redistributions in binary form must reproduce the above
12 adee02b8 Giorgos Verigakis
#      copyright notice, this list of conditions and the following
13 adee02b8 Giorgos Verigakis
#      disclaimer in the documentation and/or other materials
14 adee02b8 Giorgos Verigakis
#      provided with the distribution.
15 d1387ed7 Christodoulos Psaltis
#
16 adee02b8 Giorgos Verigakis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 adee02b8 Giorgos Verigakis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 adee02b8 Giorgos Verigakis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 adee02b8 Giorgos Verigakis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 adee02b8 Giorgos Verigakis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 adee02b8 Giorgos Verigakis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 adee02b8 Giorgos Verigakis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 adee02b8 Giorgos Verigakis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 adee02b8 Giorgos Verigakis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 adee02b8 Giorgos Verigakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 adee02b8 Giorgos Verigakis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 adee02b8 Giorgos Verigakis
# POSSIBILITY OF SUCH DAMAGE.
28 d1387ed7 Christodoulos Psaltis
#
29 adee02b8 Giorgos Verigakis
# The views and conclusions contained in the software and
30 adee02b8 Giorgos Verigakis
# documentation are those of the authors and should not be
31 adee02b8 Giorgos Verigakis
# interpreted as representing official policies, either expressed
32 adee02b8 Giorgos Verigakis
# or implied, of GRNET S.A.
33 7e2f9d4b Giorgos Verigakis
34 c738c935 Giorgos Verigakis
import datetime
35 c738c935 Giorgos Verigakis
36 c738c935 Giorgos Verigakis
from base64 import b64encode
37 d8e50a39 Giorgos Verigakis
from datetime import timedelta, tzinfo
38 d8e50a39 Giorgos Verigakis
from functools import wraps
39 c738c935 Giorgos Verigakis
from hashlib import sha256
40 2035039b Giorgos Verigakis
from logging import getLogger
41 d8e50a39 Giorgos Verigakis
from random import choice
42 dca2a31f Giorgos Verigakis
from string import digits, lowercase, uppercase
43 8b01f7f3 Giorgos Verigakis
from time import time
44 d8e50a39 Giorgos Verigakis
from traceback import format_exc
45 8b01f7f3 Giorgos Verigakis
from wsgiref.handlers import format_date_time
46 7e2f9d4b Giorgos Verigakis
47 2035039b Giorgos Verigakis
import dateutil.parser
48 2035039b Giorgos Verigakis
49 c738c935 Giorgos Verigakis
from Crypto.Cipher import AES
50 529178b1 Giorgos Verigakis
51 d8e50a39 Giorgos Verigakis
from django.conf import settings
52 7e2f9d4b Giorgos Verigakis
from django.http import HttpResponse
53 7e2f9d4b Giorgos Verigakis
from django.template.loader import render_to_string
54 29a59bc1 Giorgos Verigakis
from django.utils import simplejson as json
55 b75555e5 Giorgos Verigakis
from django.utils.cache import add_never_cache_headers
56 7e2f9d4b Giorgos Verigakis
57 b36f78fa Giorgos Verigakis
from synnefo.api.faults import (Fault, BadRequest, BuildInProgress,
58 6dd70a5c Christos Stavrakakis
                                ItemNotFound, ServiceUnavailable, Unauthorized,
59 7fede91e Christos Stavrakakis
                                BadMediaType)
60 6ef51e9f Giorgos Verigakis
from synnefo.db.models import (Flavor, VirtualMachine, VirtualMachineMetadata,
61 7fede91e Christos Stavrakakis
                               Network, BackendNetwork, NetworkInterface,
62 03992c72 Christos Stavrakakis
                               BridgePoolTable)
63 6dd70a5c Christos Stavrakakis
64 4b3b8688 Giorgos Verigakis
from synnefo.lib.astakos import get_user
65 3a9b3cde Giorgos Verigakis
from synnefo.plankton.backend import ImageBackend
66 03992c72 Christos Stavrakakis
from synnefo.db.pools import IPPool
67 b14725eb Christos Stavrakakis
from synnefo.settings import MAX_CIDR_BLOCK
68 9e98ba3c Giorgos Verigakis
69 9e98ba3c Giorgos Verigakis
70 9e98ba3c Giorgos Verigakis
log = getLogger('synnefo.api')
71 9e98ba3c Giorgos Verigakis
72 7e2f9d4b Giorgos Verigakis
73 d8e50a39 Giorgos Verigakis
class UTC(tzinfo):
74 d8e50a39 Giorgos Verigakis
    def utcoffset(self, dt):
75 d8e50a39 Giorgos Verigakis
        return timedelta(0)
76 aa197ee4 Vangelis Koukis
77 d8e50a39 Giorgos Verigakis
    def tzname(self, dt):
78 d8e50a39 Giorgos Verigakis
        return 'UTC'
79 aa197ee4 Vangelis Koukis
80 d8e50a39 Giorgos Verigakis
    def dst(self, dt):
81 d8e50a39 Giorgos Verigakis
        return timedelta(0)
82 7e2f9d4b Giorgos Verigakis
83 7e2f9d4b Giorgos Verigakis
84 d8e50a39 Giorgos Verigakis
def isoformat(d):
85 529178b1 Giorgos Verigakis
    """Return an ISO8601 date string that includes a timezone."""
86 aa197ee4 Vangelis Koukis
87 d8e50a39 Giorgos Verigakis
    return d.replace(tzinfo=UTC()).isoformat()
88 d8e50a39 Giorgos Verigakis
89 a08e4270 Vangelis Koukis
90 d8e50a39 Giorgos Verigakis
def isoparse(s):
91 d8e50a39 Giorgos Verigakis
    """Parse an ISO8601 date string into a datetime object."""
92 aa197ee4 Vangelis Koukis
93 d8e50a39 Giorgos Verigakis
    if not s:
94 d8e50a39 Giorgos Verigakis
        return None
95 aa197ee4 Vangelis Koukis
96 d8e50a39 Giorgos Verigakis
    try:
97 d8e50a39 Giorgos Verigakis
        since = dateutil.parser.parse(s)
98 e87d30f3 Giorgos Verigakis
        utc_since = since.astimezone(UTC()).replace(tzinfo=None)
99 d8e50a39 Giorgos Verigakis
    except ValueError:
100 d8e50a39 Giorgos Verigakis
        raise BadRequest('Invalid changes-since parameter.')
101 aa197ee4 Vangelis Koukis
102 e87d30f3 Giorgos Verigakis
    now = datetime.datetime.now()
103 e87d30f3 Giorgos Verigakis
    if utc_since > now:
104 d8e50a39 Giorgos Verigakis
        raise BadRequest('changes-since value set in the future.')
105 aa197ee4 Vangelis Koukis
106 e87d30f3 Giorgos Verigakis
    if now - utc_since > timedelta(seconds=settings.POLL_LIMIT):
107 d8e50a39 Giorgos Verigakis
        raise BadRequest('Too old changes-since value.')
108 aa197ee4 Vangelis Koukis
109 0140e54b Vangelis Koukis
    return utc_since
110 aa197ee4 Vangelis Koukis
111 dca2a31f Giorgos Verigakis
112 dca2a31f Giorgos Verigakis
def random_password():
113 dca2a31f Giorgos Verigakis
    """Generates a random password
114 ce55f211 Kostas Papadimitriou

115 62eac5a6 Giorgos Verigakis
    We generate a windows compliant password: it must contain at least
116 dca2a31f Giorgos Verigakis
    one charachter from each of the groups: upper case, lower case, digits.
117 dca2a31f Giorgos Verigakis
    """
118 ce55f211 Kostas Papadimitriou
119 dca2a31f Giorgos Verigakis
    pool = lowercase + uppercase + digits
120 dca2a31f Giorgos Verigakis
    lowerset = set(lowercase)
121 dca2a31f Giorgos Verigakis
    upperset = set(uppercase)
122 dca2a31f Giorgos Verigakis
    digitset = set(digits)
123 dca2a31f Giorgos Verigakis
    length = 10
124 ce55f211 Kostas Papadimitriou
125 62eac5a6 Giorgos Verigakis
    password = ''.join(choice(pool) for i in range(length - 2))
126 ce55f211 Kostas Papadimitriou
127 62eac5a6 Giorgos Verigakis
    # Make sure the password is compliant
128 62eac5a6 Giorgos Verigakis
    chars = set(password)
129 62eac5a6 Giorgos Verigakis
    if not chars & lowerset:
130 62eac5a6 Giorgos Verigakis
        password += choice(lowercase)
131 62eac5a6 Giorgos Verigakis
    if not chars & upperset:
132 62eac5a6 Giorgos Verigakis
        password += choice(uppercase)
133 62eac5a6 Giorgos Verigakis
    if not chars & digitset:
134 62eac5a6 Giorgos Verigakis
        password += choice(digits)
135 ce55f211 Kostas Papadimitriou
136 62eac5a6 Giorgos Verigakis
    # Pad if necessary to reach required length
137 62eac5a6 Giorgos Verigakis
    password += ''.join(choice(pool) for i in range(length - len(password)))
138 ce55f211 Kostas Papadimitriou
139 dca2a31f Giorgos Verigakis
    return password
140 dca2a31f Giorgos Verigakis
141 d8e50a39 Giorgos Verigakis
142 c738c935 Giorgos Verigakis
def zeropad(s):
143 c738c935 Giorgos Verigakis
    """Add zeros at the end of a string in order to make its length
144 c738c935 Giorgos Verigakis
       a multiple of 16."""
145 d1387ed7 Christodoulos Psaltis
146 c738c935 Giorgos Verigakis
    npad = 16 - len(s) % 16
147 c738c935 Giorgos Verigakis
    return s + '\x00' * npad
148 c738c935 Giorgos Verigakis
149 a08e4270 Vangelis Koukis
150 c738c935 Giorgos Verigakis
def encrypt(plaintext):
151 c738c935 Giorgos Verigakis
    # Make sure key is 32 bytes long
152 c738c935 Giorgos Verigakis
    key = sha256(settings.SECRET_KEY).digest()
153 d1387ed7 Christodoulos Psaltis
154 c738c935 Giorgos Verigakis
    aes = AES.new(key)
155 c738c935 Giorgos Verigakis
    enc = aes.encrypt(zeropad(plaintext))
156 c738c935 Giorgos Verigakis
    return b64encode(enc)
157 c738c935 Giorgos Verigakis
158 7e2f9d4b Giorgos Verigakis
159 6ef51e9f Giorgos Verigakis
def get_vm(server_id, user_id):
160 d8e50a39 Giorgos Verigakis
    """Return a VirtualMachine instance or raise ItemNotFound."""
161 aa197ee4 Vangelis Koukis
162 d8e50a39 Giorgos Verigakis
    try:
163 d8e50a39 Giorgos Verigakis
        server_id = int(server_id)
164 6ef51e9f Giorgos Verigakis
        return VirtualMachine.objects.get(id=server_id, userid=user_id)
165 d8e50a39 Giorgos Verigakis
    except ValueError:
166 d8e50a39 Giorgos Verigakis
        raise BadRequest('Invalid server ID.')
167 d8e50a39 Giorgos Verigakis
    except VirtualMachine.DoesNotExist:
168 d8e50a39 Giorgos Verigakis
        raise ItemNotFound('Server not found.')
169 d8e50a39 Giorgos Verigakis
170 a08e4270 Vangelis Koukis
171 40777cc8 Giorgos Verigakis
def get_vm_meta(vm, key):
172 d8e50a39 Giorgos Verigakis
    """Return a VirtualMachineMetadata instance or raise ItemNotFound."""
173 aa197ee4 Vangelis Koukis
174 d8e50a39 Giorgos Verigakis
    try:
175 40777cc8 Giorgos Verigakis
        return VirtualMachineMetadata.objects.get(meta_key=key, vm=vm)
176 d8e50a39 Giorgos Verigakis
    except VirtualMachineMetadata.DoesNotExist:
177 d8e50a39 Giorgos Verigakis
        raise ItemNotFound('Metadata key not found.')
178 d8e50a39 Giorgos Verigakis
179 a08e4270 Vangelis Koukis
180 6ef51e9f Giorgos Verigakis
def get_image(image_id, user_id):
181 d8e50a39 Giorgos Verigakis
    """Return an Image instance or raise ItemNotFound."""
182 aa197ee4 Vangelis Koukis
183 6ef51e9f Giorgos Verigakis
    backend = ImageBackend(user_id)
184 d8e50a39 Giorgos Verigakis
    try:
185 6ef51e9f Giorgos Verigakis
        image = backend.get_image(image_id)
186 3a9b3cde Giorgos Verigakis
        if not image:
187 3a9b3cde Giorgos Verigakis
            raise ItemNotFound('Image not found.')
188 3a9b3cde Giorgos Verigakis
        return image
189 3a9b3cde Giorgos Verigakis
    finally:
190 3a9b3cde Giorgos Verigakis
        backend.close()
191 3a9b3cde Giorgos Verigakis
192 a08e4270 Vangelis Koukis
193 529178b1 Giorgos Verigakis
def get_flavor(flavor_id):
194 529178b1 Giorgos Verigakis
    """Return a Flavor instance or raise ItemNotFound."""
195 aa197ee4 Vangelis Koukis
196 529178b1 Giorgos Verigakis
    try:
197 529178b1 Giorgos Verigakis
        flavor_id = int(flavor_id)
198 529178b1 Giorgos Verigakis
        return Flavor.objects.get(id=flavor_id)
199 6ef51e9f Giorgos Verigakis
    except (ValueError, Flavor.DoesNotExist):
200 529178b1 Giorgos Verigakis
        raise ItemNotFound('Flavor not found.')
201 d8e50a39 Giorgos Verigakis
202 a08e4270 Vangelis Koukis
203 6ef51e9f Giorgos Verigakis
def get_network(network_id, user_id):
204 e2ee7808 Giorgos Verigakis
    """Return a Network instance or raise ItemNotFound."""
205 aa197ee4 Vangelis Koukis
206 e2ee7808 Giorgos Verigakis
    try:
207 7fede91e Christos Stavrakakis
        network_id = int(network_id)
208 7fede91e Christos Stavrakakis
        return Network.objects.get(id=network_id, userid=user_id)
209 6ef51e9f Giorgos Verigakis
    except (ValueError, Network.DoesNotExist):
210 e2ee7808 Giorgos Verigakis
        raise ItemNotFound('Network not found.')
211 e2ee7808 Giorgos Verigakis
212 a08e4270 Vangelis Koukis
213 b14725eb Christos Stavrakakis
def validate_network_size(cidr_block):
214 b14725eb Christos Stavrakakis
    """Return True if network size is allowed."""
215 b14725eb Christos Stavrakakis
    return cidr_block <= 29 and cidr_block > MAX_CIDR_BLOCK
216 b14725eb Christos Stavrakakis
217 b14725eb Christos Stavrakakis
218 7fede91e Christos Stavrakakis
def backend_public_networks(backend):
219 7fede91e Christos Stavrakakis
    """Return available public networks of the backend.
220 7fede91e Christos Stavrakakis

221 7fede91e Christos Stavrakakis
    Iterator for non-deleted public networks that are available
222 7fede91e Christos Stavrakakis
    to the specified backend.
223 7fede91e Christos Stavrakakis

224 7fede91e Christos Stavrakakis
    """
225 7fede91e Christos Stavrakakis
    for network in Network.objects.filter(public=True, deleted=False):
226 7fede91e Christos Stavrakakis
        if BackendNetwork.objects.filter(network=network,
227 7fede91e Christos Stavrakakis
                                         backend=backend).exists():
228 7fede91e Christos Stavrakakis
            yield network
229 7fede91e Christos Stavrakakis
230 7fede91e Christos Stavrakakis
231 7fede91e Christos Stavrakakis
def get_network_free_address(network):
232 7fede91e Christos Stavrakakis
    """Reserve an IP address from the IP Pool of the network.
233 7fede91e Christos Stavrakakis

234 03992c72 Christos Stavrakakis
    Raises Network.DoesNotExist , IPPool.IPPoolExhausted
235 7fede91e Christos Stavrakakis

236 7fede91e Christos Stavrakakis
    """
237 7fede91e Christos Stavrakakis
238 7fede91e Christos Stavrakakis
    # Get the Network object in exclusive mode in order to
239 7fede91e Christos Stavrakakis
    # safely (isolated) reserve an IP address
240 7fede91e Christos Stavrakakis
    network = Network.objects.select_for_update().get(id=network.id)
241 03992c72 Christos Stavrakakis
    pool = IPPool(network)
242 7fede91e Christos Stavrakakis
    address = pool.get_free_address()
243 7fede91e Christos Stavrakakis
    pool.save()
244 7fede91e Christos Stavrakakis
    return address
245 7fede91e Christos Stavrakakis
246 7fede91e Christos Stavrakakis
247 d44c236b Giorgos Verigakis
def get_nic(machine, network):
248 d44c236b Giorgos Verigakis
    try:
249 d44c236b Giorgos Verigakis
        return NetworkInterface.objects.get(machine=machine, network=network)
250 d44c236b Giorgos Verigakis
    except NetworkInterface.DoesNotExist:
251 d44c236b Giorgos Verigakis
        raise ItemNotFound('Server not connected to this network.')
252 d44c236b Giorgos Verigakis
253 7fede91e Christos Stavrakakis
254 08b079e2 Stavros Sachtouris
def get_nic_from_index(vm, nic_index):
255 08b079e2 Stavros Sachtouris
    """Returns the nic_index-th nic of a vm
256 08b079e2 Stavros Sachtouris
       Error Response Codes: itemNotFound (404), badMediaType (415)
257 08b079e2 Stavros Sachtouris
    """
258 08b079e2 Stavros Sachtouris
    matching_nics = vm.nics.filter(index=nic_index)
259 08b079e2 Stavros Sachtouris
    matching_nics_len = len(matching_nics)
260 08b079e2 Stavros Sachtouris
    if matching_nics_len < 1:
261 08b079e2 Stavros Sachtouris
        raise  ItemNotFound('NIC not found on VM')
262 08b079e2 Stavros Sachtouris
    elif matching_nics_len > 1:
263 08b079e2 Stavros Sachtouris
        raise BadMediaType('NIC index conflict on VM')
264 08b079e2 Stavros Sachtouris
    nic = matching_nics[0]
265 08b079e2 Stavros Sachtouris
    return nic
266 e2ee7808 Giorgos Verigakis
267 7fede91e Christos Stavrakakis
268 7e2f9d4b Giorgos Verigakis
def get_request_dict(request):
269 d8e50a39 Giorgos Verigakis
    """Returns data sent by the client as a python dict."""
270 aa197ee4 Vangelis Koukis
271 7e2f9d4b Giorgos Verigakis
    data = request.raw_post_data
272 7e45ddef Dimitris Moraitis
    if request.META.get('CONTENT_TYPE').startswith('application/json'):
273 7e2f9d4b Giorgos Verigakis
        try:
274 7e2f9d4b Giorgos Verigakis
            return json.loads(data)
275 7e2f9d4b Giorgos Verigakis
        except ValueError:
276 d8e50a39 Giorgos Verigakis
            raise BadRequest('Invalid JSON data.')
277 d8e50a39 Giorgos Verigakis
    else:
278 d8e50a39 Giorgos Verigakis
        raise BadRequest('Unsupported Content-Type.')
279 7e2f9d4b Giorgos Verigakis
280 a08e4270 Vangelis Koukis
281 8b01f7f3 Giorgos Verigakis
def update_response_headers(request, response):
282 8b01f7f3 Giorgos Verigakis
    if request.serialization == 'xml':
283 8b01f7f3 Giorgos Verigakis
        response['Content-Type'] = 'application/xml'
284 8b01f7f3 Giorgos Verigakis
    elif request.serialization == 'atom':
285 8b01f7f3 Giorgos Verigakis
        response['Content-Type'] = 'application/atom+xml'
286 8b01f7f3 Giorgos Verigakis
    else:
287 8b01f7f3 Giorgos Verigakis
        response['Content-Type'] = 'application/json'
288 aa197ee4 Vangelis Koukis
289 4cf8adf8 Vangelis Koukis
    if settings.TEST:
290 cdb65551 Giorgos Verigakis
        response['Date'] = format_date_time(time())
291 ce55f211 Kostas Papadimitriou
292 b75555e5 Giorgos Verigakis
    add_never_cache_headers(response)
293 b75555e5 Giorgos Verigakis
294 8b01f7f3 Giorgos Verigakis
295 432fc8c3 Giorgos Verigakis
def render_metadata(request, metadata, use_values=False, status=200):
296 432fc8c3 Giorgos Verigakis
    if request.serialization == 'xml':
297 432fc8c3 Giorgos Verigakis
        data = render_to_string('metadata.xml', {'metadata': metadata})
298 432fc8c3 Giorgos Verigakis
    else:
299 b36f78fa Giorgos Verigakis
        if use_values:
300 b36f78fa Giorgos Verigakis
            d = {'metadata': {'values': metadata}}
301 b36f78fa Giorgos Verigakis
        else:
302 b36f78fa Giorgos Verigakis
            d = {'metadata': metadata}
303 432fc8c3 Giorgos Verigakis
        data = json.dumps(d)
304 432fc8c3 Giorgos Verigakis
    return HttpResponse(data, status=status)
305 432fc8c3 Giorgos Verigakis
306 a08e4270 Vangelis Koukis
307 432fc8c3 Giorgos Verigakis
def render_meta(request, meta, status=200):
308 432fc8c3 Giorgos Verigakis
    if request.serialization == 'xml':
309 6ef51e9f Giorgos Verigakis
        data = render_to_string('meta.xml', dict(key=key, val=val))
310 432fc8c3 Giorgos Verigakis
    else:
311 6ef51e9f Giorgos Verigakis
        data = json.dumps(dict(meta=meta))
312 432fc8c3 Giorgos Verigakis
    return HttpResponse(data, status=status)
313 432fc8c3 Giorgos Verigakis
314 a08e4270 Vangelis Koukis
315 c36934a7 Giorgos Verigakis
def render_fault(request, fault):
316 4cf8adf8 Vangelis Koukis
    if settings.DEBUG or settings.TEST:
317 7e2f9d4b Giorgos Verigakis
        fault.details = format_exc(fault)
318 aa197ee4 Vangelis Koukis
319 d8e50a39 Giorgos Verigakis
    if request.serialization == 'xml':
320 d8e50a39 Giorgos Verigakis
        data = render_to_string('fault.xml', {'fault': fault})
321 7e2f9d4b Giorgos Verigakis
    else:
322 b36f78fa Giorgos Verigakis
        d = {fault.name: {
323 b36f78fa Giorgos Verigakis
                'code': fault.code,
324 b36f78fa Giorgos Verigakis
                'message': fault.message,
325 b36f78fa Giorgos Verigakis
                'details': fault.details}}
326 7e2f9d4b Giorgos Verigakis
        data = json.dumps(d)
327 aa197ee4 Vangelis Koukis
328 f0656db1 Giorgos Verigakis
    resp = HttpResponse(data, status=fault.code)
329 8b01f7f3 Giorgos Verigakis
    update_response_headers(request, resp)
330 f0656db1 Giorgos Verigakis
    return resp
331 d8e50a39 Giorgos Verigakis
332 432fc8c3 Giorgos Verigakis
333 d8e50a39 Giorgos Verigakis
def request_serialization(request, atom_allowed=False):
334 d8e50a39 Giorgos Verigakis
    """Return the serialization format requested.
335 aa197ee4 Vangelis Koukis

336 529178b1 Giorgos Verigakis
    Valid formats are 'json', 'xml' and 'atom' if `atom_allowed` is True.
337 d8e50a39 Giorgos Verigakis
    """
338 aa197ee4 Vangelis Koukis
339 d8e50a39 Giorgos Verigakis
    path = request.path
340 aa197ee4 Vangelis Koukis
341 d8e50a39 Giorgos Verigakis
    if path.endswith('.json'):
342 d8e50a39 Giorgos Verigakis
        return 'json'
343 d8e50a39 Giorgos Verigakis
    elif path.endswith('.xml'):
344 d8e50a39 Giorgos Verigakis
        return 'xml'
345 d8e50a39 Giorgos Verigakis
    elif atom_allowed and path.endswith('.atom'):
346 d8e50a39 Giorgos Verigakis
        return 'atom'
347 aa197ee4 Vangelis Koukis
348 d8e50a39 Giorgos Verigakis
    for item in request.META.get('HTTP_ACCEPT', '').split(','):
349 d8e50a39 Giorgos Verigakis
        accept, sep, rest = item.strip().partition(';')
350 d8e50a39 Giorgos Verigakis
        if accept == 'application/json':
351 d8e50a39 Giorgos Verigakis
            return 'json'
352 d8e50a39 Giorgos Verigakis
        elif accept == 'application/xml':
353 d8e50a39 Giorgos Verigakis
            return 'xml'
354 d8e50a39 Giorgos Verigakis
        elif atom_allowed and accept == 'application/atom+xml':
355 d8e50a39 Giorgos Verigakis
            return 'atom'
356 aa197ee4 Vangelis Koukis
357 d8e50a39 Giorgos Verigakis
    return 'json'
358 7e2f9d4b Giorgos Verigakis
359 a08e4270 Vangelis Koukis
360 d8e50a39 Giorgos Verigakis
def api_method(http_method=None, atom_allowed=False):
361 d8e50a39 Giorgos Verigakis
    """Decorator function for views that implement an API method."""
362 aa197ee4 Vangelis Koukis
363 c36934a7 Giorgos Verigakis
    def decorator(func):
364 c36934a7 Giorgos Verigakis
        @wraps(func)
365 c36934a7 Giorgos Verigakis
        def wrapper(request, *args, **kwargs):
366 c36934a7 Giorgos Verigakis
            try:
367 6ef51e9f Giorgos Verigakis
                request.serialization = request_serialization(request,
368 6ef51e9f Giorgos Verigakis
                                                              atom_allowed)
369 4b3b8688 Giorgos Verigakis
                get_user(request, settings.ASTAKOS_URL)
370 4b3b8688 Giorgos Verigakis
                if not request.user_uniq:
371 40777cc8 Giorgos Verigakis
                    raise Unauthorized('No user found.')
372 d8e50a39 Giorgos Verigakis
                if http_method and request.method != http_method:
373 d8e50a39 Giorgos Verigakis
                    raise BadRequest('Method not allowed.')
374 7fede91e Christos Stavrakakis
375 c36934a7 Giorgos Verigakis
                resp = func(request, *args, **kwargs)
376 8b01f7f3 Giorgos Verigakis
                update_response_headers(request, resp)
377 c36934a7 Giorgos Verigakis
                return resp
378 5231a38a Giorgos Verigakis
            except VirtualMachine.DeletedError:
379 5231a38a Giorgos Verigakis
                fault = BadRequest('Server has been deleted.')
380 5231a38a Giorgos Verigakis
                return render_fault(request, fault)
381 5231a38a Giorgos Verigakis
            except VirtualMachine.BuildingError:
382 5231a38a Giorgos Verigakis
                fault = BuildInProgress('Server is being built.')
383 5231a38a Giorgos Verigakis
                return render_fault(request, fault)
384 c36934a7 Giorgos Verigakis
            except Fault, fault:
385 c36934a7 Giorgos Verigakis
                return render_fault(request, fault)
386 7fede91e Christos Stavrakakis
            except BaseException:
387 9e98ba3c Giorgos Verigakis
                log.exception('Unexpected error')
388 529178b1 Giorgos Verigakis
                fault = ServiceUnavailable('Unexpected error.')
389 c36934a7 Giorgos Verigakis
                return render_fault(request, fault)
390 c36934a7 Giorgos Verigakis
        return wrapper
391 c36934a7 Giorgos Verigakis
    return decorator
392 08b079e2 Stavros Sachtouris
393 3165f027 Christos Stavrakakis
394 08b079e2 Stavros Sachtouris
def construct_nic_id(nic):
395 08b079e2 Stavros Sachtouris
    return "-".join(["nic", unicode(nic.machine.id), unicode(nic.index)])
396 6dd70a5c Christos Stavrakakis
397 6dd70a5c Christos Stavrakakis
398 3165f027 Christos Stavrakakis
def network_link_from_type(network_type):
399 3165f027 Christos Stavrakakis
    if network_type == 'PRIVATE_MAC_FILTERED':
400 3165f027 Christos Stavrakakis
        link = settings.PRIVATE_MAC_FILTERED_BRIDGE
401 3165f027 Christos Stavrakakis
    elif network_type == 'PRIVATE_PHYSICAL_VLAN':
402 03992c72 Christos Stavrakakis
        pool = BridgePoolTable.get_pool()
403 03992c72 Christos Stavrakakis
        link = pool.get()
404 03992c72 Christos Stavrakakis
        pool.save()
405 3165f027 Christos Stavrakakis
    elif network_type == 'CUSTOM_ROUTED':
406 3165f027 Christos Stavrakakis
        link = settings.CUSTOM_ROUTED_ROUTING_TABLE
407 3165f027 Christos Stavrakakis
    elif network_type == 'CUSTOM_BRIDGED':
408 3165f027 Christos Stavrakakis
        link = settings.CUSTOM_BRIDGED_BRIDGE
409 3165f027 Christos Stavrakakis
    elif network_type == 'PUBLIC_ROUTED':
410 3165f027 Christos Stavrakakis
        link = settings.PUBLIC_ROUTED_ROUTING_TABLE
411 3165f027 Christos Stavrakakis
    else:
412 3165f027 Christos Stavrakakis
        raise BadRequest('Unknown network network_type')
413 6dd70a5c Christos Stavrakakis
414 3165f027 Christos Stavrakakis
    return link