Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (15.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 bd16bf3e Stratos Psomadakis
from base64 import urlsafe_b64encode, b64decode
35 bd16bf3e Stratos Psomadakis
from urllib import quote
36 c738c935 Giorgos Verigakis
from hashlib import sha256
37 2035039b Giorgos Verigakis
from logging import getLogger
38 d8e50a39 Giorgos Verigakis
from random import choice
39 dca2a31f Giorgos Verigakis
from string import digits, lowercase, uppercase
40 2035039b Giorgos Verigakis
41 c738c935 Giorgos Verigakis
from Crypto.Cipher import AES
42 529178b1 Giorgos Verigakis
43 d8e50a39 Giorgos Verigakis
from django.conf import settings
44 7e2f9d4b Giorgos Verigakis
from django.http import HttpResponse
45 7e2f9d4b Giorgos Verigakis
from django.template.loader import render_to_string
46 29a59bc1 Giorgos Verigakis
from django.utils import simplejson as json
47 d3406fbc Christos Stavrakakis
from django.db.models import Q
48 7e2f9d4b Giorgos Verigakis
49 bd40abfa Christos Stavrakakis
from snf_django.lib.api import faults
50 6ef51e9f Giorgos Verigakis
from synnefo.db.models import (Flavor, VirtualMachine, VirtualMachineMetadata,
51 a1713485 Marios Kogias
                               Network, NetworkInterface, SecurityGroup,
52 a1713485 Marios Kogias
                               BridgePoolTable, MacPrefixPoolTable, IPAddress,
53 495e2be8 Christos Stavrakakis
                               IPPoolTable)
54 b3fd98ae Christos Stavrakakis
from synnefo.plankton.utils import image_backend
55 9e98ba3c Giorgos Verigakis
56 1b696c26 Christos Stavrakakis
from synnefo.cyclades_settings import cyclades_services, BASE_HOST
57 1b696c26 Christos Stavrakakis
from synnefo.lib.services import get_service_path
58 1b696c26 Christos Stavrakakis
from synnefo.lib import join_urls
59 1b696c26 Christos Stavrakakis
60 1b696c26 Christos Stavrakakis
COMPUTE_URL = \
61 1b696c26 Christos Stavrakakis
    join_urls(BASE_HOST,
62 1b696c26 Christos Stavrakakis
              get_service_path(cyclades_services, "compute", version="v2.0"))
63 1b696c26 Christos Stavrakakis
SERVERS_URL = join_urls(COMPUTE_URL, "servers/")
64 1b696c26 Christos Stavrakakis
FLAVORS_URL = join_urls(COMPUTE_URL, "flavors/")
65 1b696c26 Christos Stavrakakis
IMAGES_URL = join_urls(COMPUTE_URL, "images/")
66 1b696c26 Christos Stavrakakis
PLANKTON_URL = \
67 1b696c26 Christos Stavrakakis
    join_urls(BASE_HOST,
68 1b696c26 Christos Stavrakakis
              get_service_path(cyclades_services, "image", version="v1.0"))
69 1b696c26 Christos Stavrakakis
IMAGES_PLANKTON_URL = join_urls(PLANKTON_URL, "images/")
70 1b696c26 Christos Stavrakakis
71 cdd6fc06 Christos Stavrakakis
NETWORK_URL = \
72 cdd6fc06 Christos Stavrakakis
    join_urls(BASE_HOST,
73 cdd6fc06 Christos Stavrakakis
              get_service_path(cyclades_services, "network", version="v2.0"))
74 cdd6fc06 Christos Stavrakakis
NETWORKS_URL = join_urls(NETWORK_URL, "networks/")
75 cdd6fc06 Christos Stavrakakis
PORTS_URL = join_urls(NETWORK_URL, "ports/")
76 cdd6fc06 Christos Stavrakakis
SUBNETS_URL = join_urls(NETWORK_URL, "subnets/")
77 cdd6fc06 Christos Stavrakakis
FLOATING_IPS_URL = join_urls(NETWORK_URL, "floatingips/")
78 cdd6fc06 Christos Stavrakakis
79 c172f4ab Christos Stavrakakis
PITHOSMAP_PREFIX = "pithosmap://"
80 9e98ba3c Giorgos Verigakis
81 9e98ba3c Giorgos Verigakis
log = getLogger('synnefo.api')
82 9e98ba3c Giorgos Verigakis
83 7e2f9d4b Giorgos Verigakis
84 dca2a31f Giorgos Verigakis
def random_password():
85 dca2a31f Giorgos Verigakis
    """Generates a random password
86 ce55f211 Kostas Papadimitriou

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

208 9dcb5b8a Christos Stavrakakis
    Provider for `ext` disk_template is encoded in the disk template
209 9dcb5b8a Christos Stavrakakis
    name, which is formed `ext_<provider_name>`. Provider is None
210 9dcb5b8a Christos Stavrakakis
    for all other disk templates.
211 9dcb5b8a Christos Stavrakakis

212 9dcb5b8a Christos Stavrakakis
    """
213 9dcb5b8a Christos Stavrakakis
    disk_template = flavor.disk_template
214 9dcb5b8a Christos Stavrakakis
    provider = None
215 9dcb5b8a Christos Stavrakakis
    if disk_template.startswith("ext"):
216 9dcb5b8a Christos Stavrakakis
        disk_template, provider = disk_template.split("_", 1)
217 9dcb5b8a Christos Stavrakakis
    return disk_template, provider
218 9dcb5b8a Christos Stavrakakis
219 95a213d4 Christos Stavrakakis
220 9e8be4fb Christos Stavrakakis
def get_network(network_id, user_id, for_update=False, non_deleted=False):
221 e2ee7808 Giorgos Verigakis
    """Return a Network instance or raise ItemNotFound."""
222 aa197ee4 Vangelis Koukis
223 e2ee7808 Giorgos Verigakis
    try:
224 7fede91e Christos Stavrakakis
        network_id = int(network_id)
225 a96e84cf Christos Stavrakakis
        objects = Network.objects.prefetch_related("subnets")
226 d2e73c0c Christos Stavrakakis
        if for_update:
227 d3406fbc Christos Stavrakakis
            objects = objects.select_for_update()
228 9e8be4fb Christos Stavrakakis
        network = objects.get(Q(userid=user_id) | Q(public=True),
229 9e8be4fb Christos Stavrakakis
                              id=network_id)
230 9e8be4fb Christos Stavrakakis
        if non_deleted and network.deleted:
231 f8675683 Christos Stavrakakis
            raise faults.BadRequest("Network has been deleted.")
232 9e8be4fb Christos Stavrakakis
        return network
233 8b7c2fc3 Christos Stavrakakis
    except (ValueError, TypeError):
234 8b7c2fc3 Christos Stavrakakis
        raise faults.BadRequest("Invalid network ID '%s'" % network_id)
235 8b7c2fc3 Christos Stavrakakis
    except Network.DoesNotExist:
236 710b1c43 Christos Stavrakakis
        raise faults.ItemNotFound('Network %s not found.' % network_id)
237 95a213d4 Christos Stavrakakis
238 95a213d4 Christos Stavrakakis
239 95a213d4 Christos Stavrakakis
def get_port(port_id, user_id, for_update=False):
240 0baa1e3d Buildbot
    """
241 95a213d4 Christos Stavrakakis
    Return a NetworkInteface instance or raise ItemNotFound.
242 0baa1e3d Buildbot
    """
243 0baa1e3d Buildbot
    try:
244 09b76b7e Christos Stavrakakis
        objects = NetworkInterface.objects.filter(userid=user_id)
245 593851e0 Buildbot
        if for_update:
246 593851e0 Buildbot
            objects = objects.select_for_update()
247 fae6e5f0 Christos Stavrakakis
        # if (port.device_owner != "vm") and for_update:
248 8d5795b4 Christos Stavrakakis
        #     raise faults.BadRequest('Cannot update non vm port')
249 09b76b7e Christos Stavrakakis
        return objects.get(id=port_id)
250 8b7c2fc3 Christos Stavrakakis
    except (ValueError, TypeError):
251 8b7c2fc3 Christos Stavrakakis
        raise faults.BadRequest("Invalid port ID '%s'" % port_id)
252 8b7c2fc3 Christos Stavrakakis
    except NetworkInterface.DoesNotExist:
253 09b76b7e Christos Stavrakakis
        raise faults.ItemNotFound("Port '%s' not found." % port_id)
254 95a213d4 Christos Stavrakakis
255 0711e5aa Christos Stavrakakis
256 a1713485 Marios Kogias
def get_security_group(sg_id):
257 a1713485 Marios Kogias
    try:
258 a1713485 Marios Kogias
        sg = SecurityGroup.objects.get(id=sg_id)
259 a1713485 Marios Kogias
        return sg
260 a1713485 Marios Kogias
    except (ValueError, SecurityGroup.DoesNotExist):
261 a1713485 Marios Kogias
        raise faults.ItemNotFound("Not valid security group")
262 a08e4270 Vangelis Koukis
263 0711e5aa Christos Stavrakakis
264 710b1c43 Christos Stavrakakis
def get_floating_ip_by_address(userid, address, for_update=False):
265 f8675683 Christos Stavrakakis
    try:
266 326c3ec8 Christos Stavrakakis
        objects = IPAddress.objects
267 f8675683 Christos Stavrakakis
        if for_update:
268 f8675683 Christos Stavrakakis
            objects = objects.select_for_update()
269 710b1c43 Christos Stavrakakis
        return objects.get(userid=userid, floating_ip=True,
270 710b1c43 Christos Stavrakakis
                           address=address, deleted=False)
271 326c3ec8 Christos Stavrakakis
    except IPAddress.DoesNotExist:
272 f8675683 Christos Stavrakakis
        raise faults.ItemNotFound("Floating IP does not exist.")
273 f8675683 Christos Stavrakakis
274 f8675683 Christos Stavrakakis
275 710b1c43 Christos Stavrakakis
def get_floating_ip_by_id(userid, floating_ip_id, for_update=False):
276 710b1c43 Christos Stavrakakis
    try:
277 710b1c43 Christos Stavrakakis
        objects = IPAddress.objects
278 710b1c43 Christos Stavrakakis
        if for_update:
279 710b1c43 Christos Stavrakakis
            objects = objects.select_for_update()
280 d9c36253 Marios Kogias
        return objects.get(id=floating_ip_id, floating_ip=True,
281 0711e5aa Christos Stavrakakis
                           userid=userid, deleted=False)
282 710b1c43 Christos Stavrakakis
    except IPAddress.DoesNotExist:
283 fae6e5f0 Christos Stavrakakis
        raise faults.ItemNotFound("Floating IP with ID %s does not exist." %
284 710b1c43 Christos Stavrakakis
                                  floating_ip_id)
285 dca7553e Christos Stavrakakis
286 dca7553e Christos Stavrakakis
287 710b1c43 Christos Stavrakakis
def backend_has_free_public_ip(backend):
288 710b1c43 Christos Stavrakakis
    """Check if a backend has a free public IPv4 address."""
289 710b1c43 Christos Stavrakakis
    ip_pool_rows = IPPoolTable.objects.select_for_update()\
290 710b1c43 Christos Stavrakakis
        .filter(subnet__network__public=True)\
291 710b1c43 Christos Stavrakakis
        .filter(subnet__network__drained=False)\
292 710b1c43 Christos Stavrakakis
        .filter(subnet__deleted=False)\
293 710b1c43 Christos Stavrakakis
        .filter(subnet__network__backend_networks__backend=backend)
294 710b1c43 Christos Stavrakakis
    for pool_row in ip_pool_rows:
295 710b1c43 Christos Stavrakakis
        pool = pool_row.pool
296 710b1c43 Christos Stavrakakis
        if pool.empty():
297 710b1c43 Christos Stavrakakis
            continue
298 710b1c43 Christos Stavrakakis
        else:
299 710b1c43 Christos Stavrakakis
            return True
300 710b1c43 Christos Stavrakakis
301 710b1c43 Christos Stavrakakis
302 710b1c43 Christos Stavrakakis
def backend_public_networks(backend):
303 710b1c43 Christos Stavrakakis
    return Network.objects.filter(deleted=False, public=True,
304 710b1c43 Christos Stavrakakis
                                  backend_networks__backend=backend)
305 7fede91e Christos Stavrakakis
306 7fede91e Christos Stavrakakis
307 c988fcca Christos Stavrakakis
def get_vm_nic(vm, nic_id):
308 d0545590 Christos Stavrakakis
    """Get a VMs NIC by its ID."""
309 d44c236b Giorgos Verigakis
    try:
310 7c714455 Christos Stavrakakis
        return vm.nics.get(id=nic_id)
311 d44c236b Giorgos Verigakis
    except NetworkInterface.DoesNotExist:
312 d0545590 Christos Stavrakakis
        raise faults.ItemNotFound("NIC '%s' not found" % nic_id)
313 d44c236b Giorgos Verigakis
314 7fede91e Christos Stavrakakis
315 c988fcca Christos Stavrakakis
def get_nic(nic_id):
316 c988fcca Christos Stavrakakis
    try:
317 c988fcca Christos Stavrakakis
        return NetworkInterface.objects.get(id=nic_id)
318 c988fcca Christos Stavrakakis
    except NetworkInterface.DoesNotExist:
319 c988fcca Christos Stavrakakis
        raise faults.ItemNotFound("NIC '%s' not found" % nic_id)
320 c988fcca Christos Stavrakakis
321 c988fcca Christos Stavrakakis
322 432fc8c3 Giorgos Verigakis
def render_metadata(request, metadata, use_values=False, status=200):
323 432fc8c3 Giorgos Verigakis
    if request.serialization == 'xml':
324 432fc8c3 Giorgos Verigakis
        data = render_to_string('metadata.xml', {'metadata': metadata})
325 432fc8c3 Giorgos Verigakis
    else:
326 b36f78fa Giorgos Verigakis
        if use_values:
327 b36f78fa Giorgos Verigakis
            d = {'metadata': {'values': metadata}}
328 b36f78fa Giorgos Verigakis
        else:
329 b36f78fa Giorgos Verigakis
            d = {'metadata': metadata}
330 432fc8c3 Giorgos Verigakis
        data = json.dumps(d)
331 432fc8c3 Giorgos Verigakis
    return HttpResponse(data, status=status)
332 432fc8c3 Giorgos Verigakis
333 a08e4270 Vangelis Koukis
334 432fc8c3 Giorgos Verigakis
def render_meta(request, meta, status=200):
335 432fc8c3 Giorgos Verigakis
    if request.serialization == 'xml':
336 32e4e343 Christos Stavrakakis
        key, val = meta.items()[0]
337 6ef51e9f Giorgos Verigakis
        data = render_to_string('meta.xml', dict(key=key, val=val))
338 432fc8c3 Giorgos Verigakis
    else:
339 6ef51e9f Giorgos Verigakis
        data = json.dumps(dict(meta=meta))
340 432fc8c3 Giorgos Verigakis
    return HttpResponse(data, status=status)
341 432fc8c3 Giorgos Verigakis
342 a08e4270 Vangelis Koukis
343 dca7553e Christos Stavrakakis
def verify_personality(personality):
344 6ec4694f Christos Stavrakakis
    """Verify that a a list of personalities is well formed"""
345 006c6249 Christos Stavrakakis
    if len(personality) > settings.MAX_PERSONALITY:
346 bd40abfa Christos Stavrakakis
        raise faults.OverLimit("Maximum number of personalities"
347 32e4e343 Christos Stavrakakis
                               " exceeded")
348 dca7553e Christos Stavrakakis
    for p in personality:
349 dca7553e Christos Stavrakakis
        # Verify that personalities are well-formed
350 dca7553e Christos Stavrakakis
        try:
351 dca7553e Christos Stavrakakis
            assert isinstance(p, dict)
352 dca7553e Christos Stavrakakis
            keys = set(p.keys())
353 dca7553e Christos Stavrakakis
            allowed = set(['contents', 'group', 'mode', 'owner', 'path'])
354 dca7553e Christos Stavrakakis
            assert keys.issubset(allowed)
355 dca7553e Christos Stavrakakis
            contents = p['contents']
356 dca7553e Christos Stavrakakis
            if len(contents) > settings.MAX_PERSONALITY_SIZE:
357 dca7553e Christos Stavrakakis
                # No need to decode if contents already exceed limit
358 bd40abfa Christos Stavrakakis
                raise faults.OverLimit("Maximum size of personality exceeded")
359 dca7553e Christos Stavrakakis
            if len(b64decode(contents)) > settings.MAX_PERSONALITY_SIZE:
360 bd40abfa Christos Stavrakakis
                raise faults.OverLimit("Maximum size of personality exceeded")
361 7bbe4333 Ilias Tsitsimpis
        except (AssertionError, TypeError):
362 bd40abfa Christos Stavrakakis
            raise faults.BadRequest("Malformed personality in request")
363 2a599282 Christos Stavrakakis
364 2a599282 Christos Stavrakakis
365 b7d38981 Dimitris Aragiorgis
def values_from_flavor(flavor):
366 b7d38981 Dimitris Aragiorgis
    """Get Ganeti connectivity info from flavor type.
367 b7d38981 Dimitris Aragiorgis

368 b7d38981 Dimitris Aragiorgis
    If link or mac_prefix equals to "pool", then the resources
369 b7d38981 Dimitris Aragiorgis
    are allocated from the corresponding Pools.
370 b7d38981 Dimitris Aragiorgis

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