Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (14.7 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 dca7553e Christos Stavrakakis
from base64 import b64encode, b64decode
35 c738c935 Giorgos Verigakis
from hashlib import sha256
36 2035039b Giorgos Verigakis
from logging import getLogger
37 d8e50a39 Giorgos Verigakis
from random import choice
38 dca2a31f Giorgos Verigakis
from string import digits, lowercase, uppercase
39 2035039b Giorgos Verigakis
40 c738c935 Giorgos Verigakis
from Crypto.Cipher import AES
41 529178b1 Giorgos Verigakis
42 d8e50a39 Giorgos Verigakis
from django.conf import settings
43 7e2f9d4b Giorgos Verigakis
from django.http import HttpResponse
44 7e2f9d4b Giorgos Verigakis
from django.template.loader import render_to_string
45 29a59bc1 Giorgos Verigakis
from django.utils import simplejson as json
46 d3406fbc Christos Stavrakakis
from django.db.models import Q
47 7e2f9d4b Giorgos Verigakis
48 bd40abfa Christos Stavrakakis
from snf_django.lib.api import faults
49 6ef51e9f Giorgos Verigakis
from synnefo.db.models import (Flavor, VirtualMachine, VirtualMachineMetadata,
50 7fede91e Christos Stavrakakis
                               Network, BackendNetwork, NetworkInterface,
51 f8675683 Christos Stavrakakis
                               BridgePoolTable, MacPrefixPoolTable, Backend,
52 f8675683 Christos Stavrakakis
                               FloatingIP)
53 adc46059 Christos Stavrakakis
from synnefo.db.pools import EmptyPool
54 6dd70a5c Christos Stavrakakis
55 b3fd98ae Christos Stavrakakis
from synnefo.plankton.utils import image_backend
56 9e98ba3c Giorgos Verigakis
57 1b696c26 Christos Stavrakakis
from synnefo.cyclades_settings import cyclades_services, BASE_HOST
58 1b696c26 Christos Stavrakakis
from synnefo.lib.services import get_service_path
59 1b696c26 Christos Stavrakakis
from synnefo.lib import join_urls
60 1b696c26 Christos Stavrakakis
61 1b696c26 Christos Stavrakakis
COMPUTE_URL = \
62 1b696c26 Christos Stavrakakis
    join_urls(BASE_HOST,
63 1b696c26 Christos Stavrakakis
              get_service_path(cyclades_services, "compute", version="v2.0"))
64 1b696c26 Christos Stavrakakis
SERVERS_URL = join_urls(COMPUTE_URL, "servers/")
65 1b696c26 Christos Stavrakakis
NETWORKS_URL = join_urls(COMPUTE_URL, "networks/")
66 1b696c26 Christos Stavrakakis
FLAVORS_URL = join_urls(COMPUTE_URL, "flavors/")
67 1b696c26 Christos Stavrakakis
IMAGES_URL = join_urls(COMPUTE_URL, "images/")
68 1b696c26 Christos Stavrakakis
PLANKTON_URL = \
69 1b696c26 Christos Stavrakakis
    join_urls(BASE_HOST,
70 1b696c26 Christos Stavrakakis
              get_service_path(cyclades_services, "image", version="v1.0"))
71 1b696c26 Christos Stavrakakis
IMAGES_PLANKTON_URL = join_urls(PLANKTON_URL, "images/")
72 1b696c26 Christos Stavrakakis
73 9e98ba3c Giorgos Verigakis
74 9e98ba3c Giorgos Verigakis
log = getLogger('synnefo.api')
75 9e98ba3c Giorgos Verigakis
76 7e2f9d4b Giorgos Verigakis
77 dca2a31f Giorgos Verigakis
def random_password():
78 dca2a31f Giorgos Verigakis
    """Generates a random password
79 ce55f211 Kostas Papadimitriou

80 62eac5a6 Giorgos Verigakis
    We generate a windows compliant password: it must contain at least
81 dca2a31f Giorgos Verigakis
    one charachter from each of the groups: upper case, lower case, digits.
82 dca2a31f Giorgos Verigakis
    """
83 ce55f211 Kostas Papadimitriou
84 dca2a31f Giorgos Verigakis
    pool = lowercase + uppercase + digits
85 dca2a31f Giorgos Verigakis
    lowerset = set(lowercase)
86 dca2a31f Giorgos Verigakis
    upperset = set(uppercase)
87 dca2a31f Giorgos Verigakis
    digitset = set(digits)
88 dca2a31f Giorgos Verigakis
    length = 10
89 ce55f211 Kostas Papadimitriou
90 62eac5a6 Giorgos Verigakis
    password = ''.join(choice(pool) for i in range(length - 2))
91 ce55f211 Kostas Papadimitriou
92 62eac5a6 Giorgos Verigakis
    # Make sure the password is compliant
93 62eac5a6 Giorgos Verigakis
    chars = set(password)
94 62eac5a6 Giorgos Verigakis
    if not chars & lowerset:
95 62eac5a6 Giorgos Verigakis
        password += choice(lowercase)
96 62eac5a6 Giorgos Verigakis
    if not chars & upperset:
97 62eac5a6 Giorgos Verigakis
        password += choice(uppercase)
98 62eac5a6 Giorgos Verigakis
    if not chars & digitset:
99 62eac5a6 Giorgos Verigakis
        password += choice(digits)
100 ce55f211 Kostas Papadimitriou
101 62eac5a6 Giorgos Verigakis
    # Pad if necessary to reach required length
102 62eac5a6 Giorgos Verigakis
    password += ''.join(choice(pool) for i in range(length - len(password)))
103 ce55f211 Kostas Papadimitriou
104 dca2a31f Giorgos Verigakis
    return password
105 dca2a31f Giorgos Verigakis
106 d8e50a39 Giorgos Verigakis
107 c738c935 Giorgos Verigakis
def zeropad(s):
108 c738c935 Giorgos Verigakis
    """Add zeros at the end of a string in order to make its length
109 c738c935 Giorgos Verigakis
       a multiple of 16."""
110 d1387ed7 Christodoulos Psaltis
111 c738c935 Giorgos Verigakis
    npad = 16 - len(s) % 16
112 c738c935 Giorgos Verigakis
    return s + '\x00' * npad
113 c738c935 Giorgos Verigakis
114 a08e4270 Vangelis Koukis
115 c738c935 Giorgos Verigakis
def encrypt(plaintext):
116 c738c935 Giorgos Verigakis
    # Make sure key is 32 bytes long
117 c738c935 Giorgos Verigakis
    key = sha256(settings.SECRET_KEY).digest()
118 d1387ed7 Christodoulos Psaltis
119 c738c935 Giorgos Verigakis
    aes = AES.new(key)
120 c738c935 Giorgos Verigakis
    enc = aes.encrypt(zeropad(plaintext))
121 c738c935 Giorgos Verigakis
    return b64encode(enc)
122 c738c935 Giorgos Verigakis
123 7e2f9d4b Giorgos Verigakis
124 7f2dbcad Christos Stavrakakis
def get_vm(server_id, user_id, for_update=False, non_deleted=False,
125 7f2dbcad Christos Stavrakakis
           non_suspended=False):
126 e221ade2 Christos Stavrakakis
    """Find a VirtualMachine instance based on ID and owner."""
127 aa197ee4 Vangelis Koukis
128 d8e50a39 Giorgos Verigakis
    try:
129 d8e50a39 Giorgos Verigakis
        server_id = int(server_id)
130 7f2dbcad Christos Stavrakakis
        servers = VirtualMachine.objects
131 7f2dbcad Christos Stavrakakis
        if for_update:
132 7f2dbcad Christos Stavrakakis
            servers = servers.select_for_update()
133 7f2dbcad Christos Stavrakakis
        vm = servers.get(id=server_id, userid=user_id)
134 e221ade2 Christos Stavrakakis
        if non_deleted and vm.deleted:
135 5b0832fc Christos Stavrakakis
            raise faults.BadRequest("Server has been deleted.")
136 e221ade2 Christos Stavrakakis
        if non_suspended and vm.suspended:
137 bd40abfa Christos Stavrakakis
            raise faults.Forbidden("Administratively Suspended VM")
138 3a522cff Christos Stavrakakis
        return vm
139 d8e50a39 Giorgos Verigakis
    except ValueError:
140 bd40abfa Christos Stavrakakis
        raise faults.BadRequest('Invalid server ID.')
141 d8e50a39 Giorgos Verigakis
    except VirtualMachine.DoesNotExist:
142 bd40abfa Christos Stavrakakis
        raise faults.ItemNotFound('Server not found.')
143 d8e50a39 Giorgos Verigakis
144 7f2dbcad Christos Stavrakakis
145 40777cc8 Giorgos Verigakis
def get_vm_meta(vm, key):
146 d8e50a39 Giorgos Verigakis
    """Return a VirtualMachineMetadata instance or raise ItemNotFound."""
147 aa197ee4 Vangelis Koukis
148 d8e50a39 Giorgos Verigakis
    try:
149 40777cc8 Giorgos Verigakis
        return VirtualMachineMetadata.objects.get(meta_key=key, vm=vm)
150 d8e50a39 Giorgos Verigakis
    except VirtualMachineMetadata.DoesNotExist:
151 bd40abfa Christos Stavrakakis
        raise faults.ItemNotFound('Metadata key not found.')
152 d8e50a39 Giorgos Verigakis
153 a08e4270 Vangelis Koukis
154 6ef51e9f Giorgos Verigakis
def get_image(image_id, user_id):
155 d8e50a39 Giorgos Verigakis
    """Return an Image instance or raise ItemNotFound."""
156 aa197ee4 Vangelis Koukis
157 b3fd98ae Christos Stavrakakis
    with image_backend(user_id) as backend:
158 cda71050 Christos Stavrakakis
        return backend.get_image(image_id)
159 3a9b3cde Giorgos Verigakis
160 a08e4270 Vangelis Koukis
161 dca7553e Christos Stavrakakis
def get_image_dict(image_id, user_id):
162 dca7553e Christos Stavrakakis
    image = {}
163 dca7553e Christos Stavrakakis
    img = get_image(image_id, user_id)
164 dca7553e Christos Stavrakakis
    properties = img.get('properties', {})
165 bcd80cd9 Christos Stavrakakis
    image["id"] = img["id"]
166 bcd80cd9 Christos Stavrakakis
    image["name"] = img["name"]
167 dca7553e Christos Stavrakakis
    image['backend_id'] = img['location']
168 dca7553e Christos Stavrakakis
    image['format'] = img['disk_format']
169 e440e835 Christos Stavrakakis
    image['metadata'] = dict((key.upper(), val)
170 dca7553e Christos Stavrakakis
                             for key, val in properties.items())
171 2cb812be Christos Stavrakakis
    image['checksum'] = img['checksum']
172 2cb812be Christos Stavrakakis
173 dca7553e Christos Stavrakakis
    return image
174 dca7553e Christos Stavrakakis
175 dca7553e Christos Stavrakakis
176 aa8230bd Christos Stavrakakis
def get_flavor(flavor_id, include_deleted=False):
177 529178b1 Giorgos Verigakis
    """Return a Flavor instance or raise ItemNotFound."""
178 aa197ee4 Vangelis Koukis
179 529178b1 Giorgos Verigakis
    try:
180 529178b1 Giorgos Verigakis
        flavor_id = int(flavor_id)
181 aa8230bd Christos Stavrakakis
        if include_deleted:
182 aa8230bd Christos Stavrakakis
            return Flavor.objects.get(id=flavor_id)
183 aa8230bd Christos Stavrakakis
        else:
184 aa8230bd Christos Stavrakakis
            return Flavor.objects.get(id=flavor_id, deleted=include_deleted)
185 6ef51e9f Giorgos Verigakis
    except (ValueError, Flavor.DoesNotExist):
186 bd40abfa Christos Stavrakakis
        raise faults.ItemNotFound('Flavor not found.')
187 d8e50a39 Giorgos Verigakis
188 a08e4270 Vangelis Koukis
189 9dcb5b8a Christos Stavrakakis
def get_flavor_provider(flavor):
190 9dcb5b8a Christos Stavrakakis
    """Extract provider from disk template.
191 9dcb5b8a Christos Stavrakakis

192 9dcb5b8a Christos Stavrakakis
    Provider for `ext` disk_template is encoded in the disk template
193 9dcb5b8a Christos Stavrakakis
    name, which is formed `ext_<provider_name>`. Provider is None
194 9dcb5b8a Christos Stavrakakis
    for all other disk templates.
195 9dcb5b8a Christos Stavrakakis

196 9dcb5b8a Christos Stavrakakis
    """
197 9dcb5b8a Christos Stavrakakis
    disk_template = flavor.disk_template
198 9dcb5b8a Christos Stavrakakis
    provider = None
199 9dcb5b8a Christos Stavrakakis
    if disk_template.startswith("ext"):
200 9dcb5b8a Christos Stavrakakis
        disk_template, provider = disk_template.split("_", 1)
201 9dcb5b8a Christos Stavrakakis
    return disk_template, provider
202 9dcb5b8a Christos Stavrakakis
203 9dcb5b8a Christos Stavrakakis
204 9e8be4fb Christos Stavrakakis
def get_network(network_id, user_id, for_update=False, non_deleted=False):
205 e2ee7808 Giorgos Verigakis
    """Return a Network instance or raise ItemNotFound."""
206 aa197ee4 Vangelis Koukis
207 e2ee7808 Giorgos Verigakis
    try:
208 7fede91e Christos Stavrakakis
        network_id = int(network_id)
209 d3406fbc Christos Stavrakakis
        objects = Network.objects
210 d2e73c0c Christos Stavrakakis
        if for_update:
211 d3406fbc Christos Stavrakakis
            objects = objects.select_for_update()
212 9e8be4fb Christos Stavrakakis
        network = objects.get(Q(userid=user_id) | Q(public=True),
213 9e8be4fb Christos Stavrakakis
                              id=network_id)
214 9e8be4fb Christos Stavrakakis
        if non_deleted and network.deleted:
215 f8675683 Christos Stavrakakis
            raise faults.BadRequest("Network has been deleted.")
216 9e8be4fb Christos Stavrakakis
        return network
217 6ef51e9f Giorgos Verigakis
    except (ValueError, Network.DoesNotExist):
218 bd40abfa Christos Stavrakakis
        raise faults.ItemNotFound('Network not found.')
219 e2ee7808 Giorgos Verigakis
220 a08e4270 Vangelis Koukis
221 f8675683 Christos Stavrakakis
def get_floating_ip(user_id, ipv4, for_update=False):
222 f8675683 Christos Stavrakakis
    try:
223 f8675683 Christos Stavrakakis
        objects = FloatingIP.objects
224 f8675683 Christos Stavrakakis
        if for_update:
225 f8675683 Christos Stavrakakis
            objects = objects.select_for_update()
226 f8675683 Christos Stavrakakis
        return objects.get(userid=user_id, ipv4=ipv4, deleted=False)
227 f8675683 Christos Stavrakakis
    except FloatingIP.DoesNotExist:
228 f8675683 Christos Stavrakakis
        raise faults.ItemNotFound("Floating IP does not exist.")
229 f8675683 Christos Stavrakakis
230 f8675683 Christos Stavrakakis
231 adc46059 Christos Stavrakakis
def allocate_public_address(backend):
232 660b9f3b Christos Stavrakakis
    """Get a public IP for any available network of a backend."""
233 85919a0f Christos Stavrakakis
    # Guarantee exclusive access to backend, because accessing the IP pools of
234 85919a0f Christos Stavrakakis
    # the backend networks may result in a deadlock with backend allocator
235 85919a0f Christos Stavrakakis
    # which also checks that backend networks have a free IP.
236 85919a0f Christos Stavrakakis
    backend = Backend.objects.select_for_update().get(id=backend.id)
237 660b9f3b Christos Stavrakakis
    public_networks = backend_public_networks(backend)
238 660b9f3b Christos Stavrakakis
    return get_free_ip(public_networks)
239 dca7553e Christos Stavrakakis
240 dca7553e Christos Stavrakakis
241 7fede91e Christos Stavrakakis
def backend_public_networks(backend):
242 7fede91e Christos Stavrakakis
    """Return available public networks of the backend.
243 7fede91e Christos Stavrakakis

244 7fede91e Christos Stavrakakis
    Iterator for non-deleted public networks that are available
245 7fede91e Christos Stavrakakis
    to the specified backend.
246 7fede91e Christos Stavrakakis

247 7fede91e Christos Stavrakakis
    """
248 660b9f3b Christos Stavrakakis
    bnets = BackendNetwork.objects.filter(backend=backend,
249 660b9f3b Christos Stavrakakis
                                          network__public=True,
250 660b9f3b Christos Stavrakakis
                                          network__deleted=False,
251 12e539f0 Christos Stavrakakis
                                          network__floating_ip_pool=False,
252 12e539f0 Christos Stavrakakis
                                          network__subnet__isnull=False,
253 660b9f3b Christos Stavrakakis
                                          network__drained=False)
254 660b9f3b Christos Stavrakakis
    return [b.network for b in bnets]
255 660b9f3b Christos Stavrakakis
256 660b9f3b Christos Stavrakakis
257 660b9f3b Christos Stavrakakis
def get_free_ip(networks):
258 660b9f3b Christos Stavrakakis
    for network in networks:
259 660b9f3b Christos Stavrakakis
        try:
260 660b9f3b Christos Stavrakakis
            address = get_network_free_address(network)
261 660b9f3b Christos Stavrakakis
            return network, address
262 660b9f3b Christos Stavrakakis
        except faults.OverLimit:
263 660b9f3b Christos Stavrakakis
            pass
264 660b9f3b Christos Stavrakakis
    msg = "Can not allocate public IP. Public networks are full."
265 660b9f3b Christos Stavrakakis
    log.error(msg)
266 660b9f3b Christos Stavrakakis
    raise faults.OverLimit(msg)
267 7fede91e Christos Stavrakakis
268 7fede91e Christos Stavrakakis
269 7fede91e Christos Stavrakakis
def get_network_free_address(network):
270 34c03a51 Christos Stavrakakis
    """Reserve an IP address from the IP Pool of the network."""
271 7fede91e Christos Stavrakakis
272 fdc94944 Christos Stavrakakis
    pool = network.get_pool()
273 34c03a51 Christos Stavrakakis
    try:
274 34c03a51 Christos Stavrakakis
        address = pool.get()
275 34c03a51 Christos Stavrakakis
    except EmptyPool:
276 34c03a51 Christos Stavrakakis
        raise faults.OverLimit("Network %s is full." % network.backend_id)
277 7fede91e Christos Stavrakakis
    pool.save()
278 7fede91e Christos Stavrakakis
    return address
279 7fede91e Christos Stavrakakis
280 7fede91e Christos Stavrakakis
281 d44c236b Giorgos Verigakis
def get_nic(machine, network):
282 d44c236b Giorgos Verigakis
    try:
283 d44c236b Giorgos Verigakis
        return NetworkInterface.objects.get(machine=machine, network=network)
284 d44c236b Giorgos Verigakis
    except NetworkInterface.DoesNotExist:
285 bd40abfa Christos Stavrakakis
        raise faults.ItemNotFound('Server not connected to this network.')
286 d44c236b Giorgos Verigakis
287 7fede91e Christos Stavrakakis
288 08b079e2 Stavros Sachtouris
def get_nic_from_index(vm, nic_index):
289 08b079e2 Stavros Sachtouris
    """Returns the nic_index-th nic of a vm
290 08b079e2 Stavros Sachtouris
       Error Response Codes: itemNotFound (404), badMediaType (415)
291 08b079e2 Stavros Sachtouris
    """
292 08b079e2 Stavros Sachtouris
    matching_nics = vm.nics.filter(index=nic_index)
293 08b079e2 Stavros Sachtouris
    matching_nics_len = len(matching_nics)
294 08b079e2 Stavros Sachtouris
    if matching_nics_len < 1:
295 bd40abfa Christos Stavrakakis
        raise faults.ItemNotFound('NIC not found on VM')
296 08b079e2 Stavros Sachtouris
    elif matching_nics_len > 1:
297 bd40abfa Christos Stavrakakis
        raise faults.BadMediaType('NIC index conflict on VM')
298 08b079e2 Stavros Sachtouris
    nic = matching_nics[0]
299 08b079e2 Stavros Sachtouris
    return nic
300 e2ee7808 Giorgos Verigakis
301 7fede91e Christos Stavrakakis
302 432fc8c3 Giorgos Verigakis
def render_metadata(request, metadata, use_values=False, status=200):
303 432fc8c3 Giorgos Verigakis
    if request.serialization == 'xml':
304 432fc8c3 Giorgos Verigakis
        data = render_to_string('metadata.xml', {'metadata': metadata})
305 432fc8c3 Giorgos Verigakis
    else:
306 b36f78fa Giorgos Verigakis
        if use_values:
307 b36f78fa Giorgos Verigakis
            d = {'metadata': {'values': metadata}}
308 b36f78fa Giorgos Verigakis
        else:
309 b36f78fa Giorgos Verigakis
            d = {'metadata': metadata}
310 432fc8c3 Giorgos Verigakis
        data = json.dumps(d)
311 432fc8c3 Giorgos Verigakis
    return HttpResponse(data, status=status)
312 432fc8c3 Giorgos Verigakis
313 a08e4270 Vangelis Koukis
314 432fc8c3 Giorgos Verigakis
def render_meta(request, meta, status=200):
315 432fc8c3 Giorgos Verigakis
    if request.serialization == 'xml':
316 32e4e343 Christos Stavrakakis
        key, val = meta.items()[0]
317 6ef51e9f Giorgos Verigakis
        data = render_to_string('meta.xml', dict(key=key, val=val))
318 432fc8c3 Giorgos Verigakis
    else:
319 6ef51e9f Giorgos Verigakis
        data = json.dumps(dict(meta=meta))
320 432fc8c3 Giorgos Verigakis
    return HttpResponse(data, status=status)
321 432fc8c3 Giorgos Verigakis
322 a08e4270 Vangelis Koukis
323 08b079e2 Stavros Sachtouris
def construct_nic_id(nic):
324 08b079e2 Stavros Sachtouris
    return "-".join(["nic", unicode(nic.machine.id), unicode(nic.index)])
325 6dd70a5c Christos Stavrakakis
326 6dd70a5c Christos Stavrakakis
327 dca7553e Christos Stavrakakis
def verify_personality(personality):
328 6ec4694f Christos Stavrakakis
    """Verify that a a list of personalities is well formed"""
329 006c6249 Christos Stavrakakis
    if len(personality) > settings.MAX_PERSONALITY:
330 bd40abfa Christos Stavrakakis
        raise faults.OverLimit("Maximum number of personalities"
331 32e4e343 Christos Stavrakakis
                               " exceeded")
332 dca7553e Christos Stavrakakis
    for p in personality:
333 dca7553e Christos Stavrakakis
        # Verify that personalities are well-formed
334 dca7553e Christos Stavrakakis
        try:
335 dca7553e Christos Stavrakakis
            assert isinstance(p, dict)
336 dca7553e Christos Stavrakakis
            keys = set(p.keys())
337 dca7553e Christos Stavrakakis
            allowed = set(['contents', 'group', 'mode', 'owner', 'path'])
338 dca7553e Christos Stavrakakis
            assert keys.issubset(allowed)
339 dca7553e Christos Stavrakakis
            contents = p['contents']
340 dca7553e Christos Stavrakakis
            if len(contents) > settings.MAX_PERSONALITY_SIZE:
341 dca7553e Christos Stavrakakis
                # No need to decode if contents already exceed limit
342 bd40abfa Christos Stavrakakis
                raise faults.OverLimit("Maximum size of personality exceeded")
343 dca7553e Christos Stavrakakis
            if len(b64decode(contents)) > settings.MAX_PERSONALITY_SIZE:
344 bd40abfa Christos Stavrakakis
                raise faults.OverLimit("Maximum size of personality exceeded")
345 dca7553e Christos Stavrakakis
        except AssertionError:
346 bd40abfa Christos Stavrakakis
            raise faults.BadRequest("Malformed personality in request")
347 2a599282 Christos Stavrakakis
348 2a599282 Christos Stavrakakis
349 b7d38981 Dimitris Aragiorgis
def values_from_flavor(flavor):
350 b7d38981 Dimitris Aragiorgis
    """Get Ganeti connectivity info from flavor type.
351 b7d38981 Dimitris Aragiorgis

352 b7d38981 Dimitris Aragiorgis
    If link or mac_prefix equals to "pool", then the resources
353 b7d38981 Dimitris Aragiorgis
    are allocated from the corresponding Pools.
354 b7d38981 Dimitris Aragiorgis

355 b7d38981 Dimitris Aragiorgis
    """
356 b7d38981 Dimitris Aragiorgis
    try:
357 b7d38981 Dimitris Aragiorgis
        flavor = Network.FLAVORS[flavor]
358 b7d38981 Dimitris Aragiorgis
    except KeyError:
359 bd40abfa Christos Stavrakakis
        raise faults.BadRequest("Unknown network flavor")
360 b7d38981 Dimitris Aragiorgis
361 b7d38981 Dimitris Aragiorgis
    mode = flavor.get("mode")
362 b7d38981 Dimitris Aragiorgis
363 b7d38981 Dimitris Aragiorgis
    link = flavor.get("link")
364 b7d38981 Dimitris Aragiorgis
    if link == "pool":
365 b7d38981 Dimitris Aragiorgis
        link = allocate_resource("bridge")
366 b7d38981 Dimitris Aragiorgis
367 b7d38981 Dimitris Aragiorgis
    mac_prefix = flavor.get("mac_prefix")
368 b7d38981 Dimitris Aragiorgis
    if mac_prefix == "pool":
369 b7d38981 Dimitris Aragiorgis
        mac_prefix = allocate_resource("mac_prefix")
370 b7d38981 Dimitris Aragiorgis
371 b7d38981 Dimitris Aragiorgis
    tags = flavor.get("tags")
372 b7d38981 Dimitris Aragiorgis
373 b7d38981 Dimitris Aragiorgis
    return mode, link, mac_prefix, tags
374 b7d38981 Dimitris Aragiorgis
375 b7d38981 Dimitris Aragiorgis
376 b7d38981 Dimitris Aragiorgis
def allocate_resource(res_type):
377 b7d38981 Dimitris Aragiorgis
    table = get_pool_table(res_type)
378 b7d38981 Dimitris Aragiorgis
    pool = table.get_pool()
379 b7d38981 Dimitris Aragiorgis
    value = pool.get()
380 b7d38981 Dimitris Aragiorgis
    pool.save()
381 b7d38981 Dimitris Aragiorgis
    return value
382 b7d38981 Dimitris Aragiorgis
383 b7d38981 Dimitris Aragiorgis
384 b7d38981 Dimitris Aragiorgis
def release_resource(res_type, value):
385 b7d38981 Dimitris Aragiorgis
    table = get_pool_table(res_type)
386 b7d38981 Dimitris Aragiorgis
    pool = table.get_pool()
387 b7d38981 Dimitris Aragiorgis
    pool.put(value)
388 b7d38981 Dimitris Aragiorgis
    pool.save()
389 b7d38981 Dimitris Aragiorgis
390 b7d38981 Dimitris Aragiorgis
391 b7d38981 Dimitris Aragiorgis
def get_pool_table(res_type):
392 b7d38981 Dimitris Aragiorgis
    if res_type == "bridge":
393 b7d38981 Dimitris Aragiorgis
        return BridgePoolTable
394 b7d38981 Dimitris Aragiorgis
    elif res_type == "mac_prefix":
395 b7d38981 Dimitris Aragiorgis
        return MacPrefixPoolTable
396 b7d38981 Dimitris Aragiorgis
    else:
397 b7d38981 Dimitris Aragiorgis
        raise Exception("Unknown resource type")
398 55f562a4 Kostas Papadimitriou
399 55f562a4 Kostas Papadimitriou
400 55f562a4 Kostas Papadimitriou
def get_existing_users():
401 55f562a4 Kostas Papadimitriou
    """
402 55f562a4 Kostas Papadimitriou
    Retrieve user ids stored in cyclades user agnostic models.
403 55f562a4 Kostas Papadimitriou
    """
404 55f562a4 Kostas Papadimitriou
    # also check PublicKeys a user with no servers/networks exist
405 b47b110d Kostas Papadimitriou
    from synnefo.userdata.models import PublicKeyPair
406 55f562a4 Kostas Papadimitriou
    from synnefo.db.models import VirtualMachine, Network
407 55f562a4 Kostas Papadimitriou
408 55f562a4 Kostas Papadimitriou
    keypairusernames = PublicKeyPair.objects.filter().values_list('user',
409 e440e835 Christos Stavrakakis
                                                                  flat=True)
410 55f562a4 Kostas Papadimitriou
    serverusernames = VirtualMachine.objects.filter().values_list('userid',
411 e440e835 Christos Stavrakakis
                                                                  flat=True)
412 55f562a4 Kostas Papadimitriou
    networkusernames = Network.objects.filter().values_list('userid',
413 55f562a4 Kostas Papadimitriou
                                                            flat=True)
414 55f562a4 Kostas Papadimitriou
415 e440e835 Christos Stavrakakis
    return set(list(keypairusernames) + list(serverusernames) +
416 e440e835 Christos Stavrakakis
               list(networkusernames))
417 1b696c26 Christos Stavrakakis
418 1b696c26 Christos Stavrakakis
419 1b696c26 Christos Stavrakakis
def vm_to_links(vm_id):
420 73fbaad3 Christos Stavrakakis
    href = join_urls(SERVERS_URL, str(vm_id))
421 73fbaad3 Christos Stavrakakis
    return [{"rel": rel, "href": href} for rel in ("self", "bookmark")]
422 1b696c26 Christos Stavrakakis
423 1b696c26 Christos Stavrakakis
424 1b696c26 Christos Stavrakakis
def network_to_links(network_id):
425 73fbaad3 Christos Stavrakakis
    href = join_urls(NETWORKS_URL, str(network_id))
426 73fbaad3 Christos Stavrakakis
    return [{"rel": rel, "href": href} for rel in ("self", "bookmark")]
427 1b696c26 Christos Stavrakakis
428 1b696c26 Christos Stavrakakis
429 1b696c26 Christos Stavrakakis
def flavor_to_links(flavor_id):
430 73fbaad3 Christos Stavrakakis
    href = join_urls(FLAVORS_URL, str(flavor_id))
431 73fbaad3 Christos Stavrakakis
    return [{"rel": rel, "href": href} for rel in ("self", "bookmark")]
432 1b696c26 Christos Stavrakakis
433 1b696c26 Christos Stavrakakis
434 1b696c26 Christos Stavrakakis
def image_to_links(image_id):
435 73fbaad3 Christos Stavrakakis
    href = join_urls(IMAGES_URL, str(image_id))
436 73fbaad3 Christos Stavrakakis
    links = [{"rel": rel, "href": href} for rel in ("self", "bookmark")]
437 1b696c26 Christos Stavrakakis
    links.append({"rel": "alternate",
438 73fbaad3 Christos Stavrakakis
                  "href": join_urls(IMAGES_PLANKTON_URL, str(image_id))})
439 1b696c26 Christos Stavrakakis
    return links
440 41a7fae7 Christos Stavrakakis
441 32e4e343 Christos Stavrakakis
442 41a7fae7 Christos Stavrakakis
def start_action(vm, action, jobId):
443 41a7fae7 Christos Stavrakakis
    vm.action = action
444 41a7fae7 Christos Stavrakakis
    vm.backendjobid = jobId
445 41a7fae7 Christos Stavrakakis
    vm.backendopcode = None
446 41a7fae7 Christos Stavrakakis
    vm.backendjobstatus = None
447 41a7fae7 Christos Stavrakakis
    vm.backendlogmsg = None
448 41a7fae7 Christos Stavrakakis
    vm.save()