Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (16.2 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["location"] = img["location"]
177 8e057ed0 Christos Stavrakakis
    image["is_snapshot"] = img["is_snapshot"]
178 c172f4ab Christos Stavrakakis
    size = image["size"] = img["size"]
179 4944a1f8 Christos Stavrakakis
180 4944a1f8 Christos Stavrakakis
    checksum = img["checksum"]
181 4944a1f8 Christos Stavrakakis
    if checksum.startswith("archip:"):
182 4944a1f8 Christos Stavrakakis
        unprefixed_checksum, _ = checksum.split("archip:")
183 4944a1f8 Christos Stavrakakis
        checksum = unprefixed_checksum
184 4944a1f8 Christos Stavrakakis
    else:
185 4944a1f8 Christos Stavrakakis
        unprefixed_checksum = checksum
186 4944a1f8 Christos Stavrakakis
        checksum = "pithos:" + checksum
187 4944a1f8 Christos Stavrakakis
188 4944a1f8 Christos Stavrakakis
    image["backend_id"] = PITHOSMAP_PREFIX + "/".join([unprefixed_checksum,
189 4944a1f8 Christos Stavrakakis
                                                       str(size)])
190 4944a1f8 Christos Stavrakakis
    image["checksum"] = checksum
191 c172f4ab Christos Stavrakakis
192 c172f4ab Christos Stavrakakis
    properties = img.get("properties", {})
193 c172f4ab Christos Stavrakakis
    image["metadata"] = dict((key.upper(), val)
194 dca7553e Christos Stavrakakis
                             for key, val in properties.items())
195 c172f4ab Christos Stavrakakis
196 dca7553e Christos Stavrakakis
    return image
197 dca7553e Christos Stavrakakis
198 dca7553e Christos Stavrakakis
199 aa8230bd Christos Stavrakakis
def get_flavor(flavor_id, include_deleted=False):
200 529178b1 Giorgos Verigakis
    """Return a Flavor instance or raise ItemNotFound."""
201 aa197ee4 Vangelis Koukis
202 529178b1 Giorgos Verigakis
    try:
203 529178b1 Giorgos Verigakis
        flavor_id = int(flavor_id)
204 aa8230bd Christos Stavrakakis
        if include_deleted:
205 aa8230bd Christos Stavrakakis
            return Flavor.objects.get(id=flavor_id)
206 aa8230bd Christos Stavrakakis
        else:
207 aa8230bd Christos Stavrakakis
            return Flavor.objects.get(id=flavor_id, deleted=include_deleted)
208 8b7c2fc3 Christos Stavrakakis
    except (ValueError, TypeError):
209 8b7c2fc3 Christos Stavrakakis
        raise faults.BadRequest("Invalid flavor ID '%s'" % flavor_id)
210 8b7c2fc3 Christos Stavrakakis
    except Flavor.DoesNotExist:
211 bd40abfa Christos Stavrakakis
        raise faults.ItemNotFound('Flavor not found.')
212 d8e50a39 Giorgos Verigakis
213 a08e4270 Vangelis Koukis
214 9dcb5b8a Christos Stavrakakis
def get_flavor_provider(flavor):
215 9dcb5b8a Christos Stavrakakis
    """Extract provider from disk template.
216 9dcb5b8a Christos Stavrakakis

217 9dcb5b8a Christos Stavrakakis
    Provider for `ext` disk_template is encoded in the disk template
218 9dcb5b8a Christos Stavrakakis
    name, which is formed `ext_<provider_name>`. Provider is None
219 9dcb5b8a Christos Stavrakakis
    for all other disk templates.
220 9dcb5b8a Christos Stavrakakis

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

380 b7d38981 Dimitris Aragiorgis
    If link or mac_prefix equals to "pool", then the resources
381 b7d38981 Dimitris Aragiorgis
    are allocated from the corresponding Pools.
382 b7d38981 Dimitris Aragiorgis

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