Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / management / common.py @ 5112da27

History | View | Annotate | Download (9.2 kB)

1 11300d7b Giorgos Verigakis
# Copyright 2012 GRNET S.A. All rights reserved.
2 11300d7b Giorgos Verigakis
#
3 11300d7b Giorgos Verigakis
# Redistribution and use in source and binary forms, with or
4 11300d7b Giorgos Verigakis
# without modification, are permitted provided that the following
5 11300d7b Giorgos Verigakis
# conditions are met:
6 11300d7b Giorgos Verigakis
#
7 11300d7b Giorgos Verigakis
#   1. Redistributions of source code must retain the above
8 11300d7b Giorgos Verigakis
#      copyright notice, this list of conditions and the following
9 11300d7b Giorgos Verigakis
#      disclaimer.
10 11300d7b Giorgos Verigakis
#
11 11300d7b Giorgos Verigakis
#   2. Redistributions in binary form must reproduce the above
12 11300d7b Giorgos Verigakis
#      copyright notice, this list of conditions and the following
13 11300d7b Giorgos Verigakis
#      disclaimer in the documentation and/or other materials
14 11300d7b Giorgos Verigakis
#      provided with the distribution.
15 11300d7b Giorgos Verigakis
#
16 11300d7b Giorgos Verigakis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 11300d7b Giorgos Verigakis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 11300d7b Giorgos Verigakis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 11300d7b Giorgos Verigakis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 11300d7b Giorgos Verigakis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 11300d7b Giorgos Verigakis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 11300d7b Giorgos Verigakis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 11300d7b Giorgos Verigakis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 11300d7b Giorgos Verigakis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 11300d7b Giorgos Verigakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 11300d7b Giorgos Verigakis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 11300d7b Giorgos Verigakis
# POSSIBILITY OF SUCH DAMAGE.
28 11300d7b Giorgos Verigakis
#
29 11300d7b Giorgos Verigakis
# The views and conclusions contained in the software and
30 11300d7b Giorgos Verigakis
# documentation are those of the authors and should not be
31 11300d7b Giorgos Verigakis
# interpreted as representing official policies, either expressed
32 11300d7b Giorgos Verigakis
# or implied, of GRNET S.A.
33 11300d7b Giorgos Verigakis
34 b84ed662 Christos Stavrakakis
35 53b9ba10 Christos Stavrakakis
import ipaddr
36 11300d7b Giorgos Verigakis
from datetime import datetime
37 11300d7b Giorgos Verigakis
38 11300d7b Giorgos Verigakis
from django.utils.timesince import timesince, timeuntil
39 b84ed662 Christos Stavrakakis
40 53b9ba10 Christos Stavrakakis
from django.core.management import CommandError
41 b84ed662 Christos Stavrakakis
from synnefo.db.models import Backend, VirtualMachine, Network, Flavor
42 b84ed662 Christos Stavrakakis
from synnefo.api.util import get_image as backend_get_image
43 b84ed662 Christos Stavrakakis
from synnefo.api.faults import ItemNotFound
44 bad9404c Christos Stavrakakis
from django.core.exceptions import FieldError
45 bad9404c Christos Stavrakakis
46 53b9ba10 Christos Stavrakakis
from synnefo.api.util import validate_network_size
47 8814e07c Christos Stavrakakis
from synnefo.settings import (MAX_CIDR_BLOCK,
48 8814e07c Christos Stavrakakis
                              CYCLADES_ASTAKOS_SERVICE_TOKEN as ASTAKOS_TOKEN,
49 8814e07c Christos Stavrakakis
                              CYCLADES_USER_CATALOG_URL)
50 2333a2c4 Christos Stavrakakis
from synnefo.logic.rapi import GanetiApiError, GanetiRapiClient
51 3170076a Stratos Psomadakis
from synnefo.lib import astakos
52 11300d7b Giorgos Verigakis
53 8814e07c Christos Stavrakakis
import logging
54 8814e07c Christos Stavrakakis
log = logging.getLogger(__name__)
55 8814e07c Christos Stavrakakis
56 11300d7b Giorgos Verigakis
57 11300d7b Giorgos Verigakis
def format_bool(b):
58 11300d7b Giorgos Verigakis
    return 'YES' if b else 'NO'
59 11300d7b Giorgos Verigakis
60 11300d7b Giorgos Verigakis
61 f83ebc98 Christos Stavrakakis
def parse_bool(string):
62 f83ebc98 Christos Stavrakakis
    if string == "True":
63 f83ebc98 Christos Stavrakakis
        return True
64 f83ebc98 Christos Stavrakakis
    elif string == "False":
65 f83ebc98 Christos Stavrakakis
        return False
66 f83ebc98 Christos Stavrakakis
    else:
67 f83ebc98 Christos Stavrakakis
        raise Exception("Can not parse string %s to bool" % string)
68 f83ebc98 Christos Stavrakakis
69 f83ebc98 Christos Stavrakakis
70 11300d7b Giorgos Verigakis
def format_date(d):
71 11300d7b Giorgos Verigakis
    if not d:
72 11300d7b Giorgos Verigakis
        return ''
73 11300d7b Giorgos Verigakis
74 11300d7b Giorgos Verigakis
    if d < datetime.now():
75 11300d7b Giorgos Verigakis
        return timesince(d) + ' ago'
76 11300d7b Giorgos Verigakis
    else:
77 11300d7b Giorgos Verigakis
        return 'in ' + timeuntil(d)
78 f66d8b04 Christos Stavrakakis
79 f66d8b04 Christos Stavrakakis
80 f66d8b04 Christos Stavrakakis
def format_vm_state(vm):
81 f66d8b04 Christos Stavrakakis
    if vm.operstate == "BUILD":
82 f66d8b04 Christos Stavrakakis
        return "BUILD(" + str(vm.buildpercentage) + "%)"
83 f66d8b04 Christos Stavrakakis
    else:
84 f66d8b04 Christos Stavrakakis
        return vm.operstate
85 53b9ba10 Christos Stavrakakis
86 53b9ba10 Christos Stavrakakis
87 53b9ba10 Christos Stavrakakis
def validate_network_info(options):
88 53b9ba10 Christos Stavrakakis
    subnet = options['subnet']
89 53b9ba10 Christos Stavrakakis
    gateway = options['gateway']
90 53b9ba10 Christos Stavrakakis
    subnet6 = options['subnet6']
91 53b9ba10 Christos Stavrakakis
    gateway6 = options['gateway6']
92 53b9ba10 Christos Stavrakakis
93 53b9ba10 Christos Stavrakakis
    try:
94 53b9ba10 Christos Stavrakakis
        net = ipaddr.IPv4Network(subnet)
95 53b9ba10 Christos Stavrakakis
        prefix = net.prefixlen
96 53b9ba10 Christos Stavrakakis
        if not validate_network_size(prefix):
97 53b9ba10 Christos Stavrakakis
            raise CommandError("Unsupport network mask %d."
98 53b9ba10 Christos Stavrakakis
                               " Must be in range (%s,29] "
99 53b9ba10 Christos Stavrakakis
                               % (prefix, MAX_CIDR_BLOCK))
100 53b9ba10 Christos Stavrakakis
    except ValueError:
101 53b9ba10 Christos Stavrakakis
        raise CommandError('Malformed subnet')
102 53b9ba10 Christos Stavrakakis
    try:
103 53b9ba10 Christos Stavrakakis
        gateway and ipaddr.IPv4Address(gateway) or None
104 53b9ba10 Christos Stavrakakis
    except ValueError:
105 53b9ba10 Christos Stavrakakis
        raise CommandError('Malformed gateway')
106 53b9ba10 Christos Stavrakakis
107 53b9ba10 Christos Stavrakakis
    try:
108 53b9ba10 Christos Stavrakakis
        subnet6 and ipaddr.IPv6Network(subnet6) or None
109 53b9ba10 Christos Stavrakakis
    except ValueError:
110 53b9ba10 Christos Stavrakakis
        raise CommandError('Malformed subnet6')
111 53b9ba10 Christos Stavrakakis
112 53b9ba10 Christos Stavrakakis
    try:
113 53b9ba10 Christos Stavrakakis
        gateway6 and ipaddr.IPv6Address(gateway6) or None
114 53b9ba10 Christos Stavrakakis
    except ValueError:
115 53b9ba10 Christos Stavrakakis
        raise CommandError('Malformed gateway6')
116 53b9ba10 Christos Stavrakakis
117 53b9ba10 Christos Stavrakakis
    return subnet, gateway, subnet6, gateway6
118 b84ed662 Christos Stavrakakis
119 b84ed662 Christos Stavrakakis
120 b84ed662 Christos Stavrakakis
def get_backend(backend_id):
121 b84ed662 Christos Stavrakakis
    try:
122 b84ed662 Christos Stavrakakis
        backend_id = int(backend_id)
123 b84ed662 Christos Stavrakakis
        return Backend.objects.get(id=backend_id)
124 b84ed662 Christos Stavrakakis
    except ValueError:
125 b84ed662 Christos Stavrakakis
        raise CommandError("Invalid Backend ID: %s" % backend_id)
126 b84ed662 Christos Stavrakakis
    except Backend.DoesNotExist:
127 b84ed662 Christos Stavrakakis
        raise CommandError("Backend with ID %s not found in DB. "
128 b84ed662 Christos Stavrakakis
                           " Use snf-manage backend-list to find"
129 b84ed662 Christos Stavrakakis
                           " out available backend IDs." % backend_id)
130 b84ed662 Christos Stavrakakis
131 b84ed662 Christos Stavrakakis
132 b84ed662 Christos Stavrakakis
def get_image(image_id, user_id):
133 b84ed662 Christos Stavrakakis
    if image_id:
134 b84ed662 Christos Stavrakakis
        try:
135 b84ed662 Christos Stavrakakis
            return backend_get_image(image_id, user_id)
136 b84ed662 Christos Stavrakakis
        except ItemNotFound:
137 b84ed662 Christos Stavrakakis
            raise CommandError("Image with ID %s not found."
138 b84ed662 Christos Stavrakakis
                               " Use snf-manage image-list to find"
139 b84ed662 Christos Stavrakakis
                               " out available image IDs." % image_id)
140 b84ed662 Christos Stavrakakis
    else:
141 b84ed662 Christos Stavrakakis
        raise CommandError("image-id is mandatory")
142 b84ed662 Christos Stavrakakis
143 b84ed662 Christos Stavrakakis
144 b84ed662 Christos Stavrakakis
def get_vm(server_id):
145 b84ed662 Christos Stavrakakis
    try:
146 b84ed662 Christos Stavrakakis
        server_id = int(server_id)
147 b84ed662 Christos Stavrakakis
        return VirtualMachine.objects.get(id=server_id)
148 b84ed662 Christos Stavrakakis
    except ValueError:
149 b84ed662 Christos Stavrakakis
        raise CommandError("Invalid server ID: %s", server_id)
150 b84ed662 Christos Stavrakakis
    except VirtualMachine.DoesNotExist:
151 b84ed662 Christos Stavrakakis
        raise CommandError("Server with ID %s not found in DB."
152 b84ed662 Christos Stavrakakis
                           " Use snf-manage server-list to find out"
153 b84ed662 Christos Stavrakakis
                           " available server IDs." % server_id)
154 b84ed662 Christos Stavrakakis
155 b84ed662 Christos Stavrakakis
156 b84ed662 Christos Stavrakakis
def get_network(network_id):
157 b84ed662 Christos Stavrakakis
    try:
158 b84ed662 Christos Stavrakakis
        network_id = int(network_id)
159 b84ed662 Christos Stavrakakis
        return Network.objects.get(id=network_id)
160 b84ed662 Christos Stavrakakis
    except ValueError:
161 b84ed662 Christos Stavrakakis
        raise CommandError("Invalid network ID: %s", network_id)
162 b84ed662 Christos Stavrakakis
    except Network.DoesNotExist:
163 b84ed662 Christos Stavrakakis
        raise CommandError("Network with ID %s not found in DB."
164 b84ed662 Christos Stavrakakis
                           " Use snf-manage network-list to find out"
165 b84ed662 Christos Stavrakakis
                           " available network IDs." % network_id)
166 b84ed662 Christos Stavrakakis
167 b84ed662 Christos Stavrakakis
168 b84ed662 Christos Stavrakakis
def get_flavor(flavor_id):
169 b84ed662 Christos Stavrakakis
    try:
170 b84ed662 Christos Stavrakakis
        flavor_id = int(flavor_id)
171 b84ed662 Christos Stavrakakis
        return Flavor.objects.get(id=flavor_id)
172 b84ed662 Christos Stavrakakis
    except ValueError:
173 b84ed662 Christos Stavrakakis
        raise CommandError("Invalid flavor ID: %s", flavor_id)
174 b84ed662 Christos Stavrakakis
    except Flavor.DoesNotExist:
175 b84ed662 Christos Stavrakakis
        raise CommandError("Flavor with ID %s not found in DB."
176 b84ed662 Christos Stavrakakis
                           " Use snf-manage flavor-list to find out"
177 b84ed662 Christos Stavrakakis
                           " available flavor IDs." % flavor_id)
178 bad9404c Christos Stavrakakis
179 bad9404c Christos Stavrakakis
180 bad9404c Christos Stavrakakis
def filter_results(objects, filter_by):
181 bad9404c Christos Stavrakakis
    filter_list = filter_by.split(",")
182 bad9404c Christos Stavrakakis
    filter_dict = {}
183 bad9404c Christos Stavrakakis
    exclude_dict = {}
184 bad9404c Christos Stavrakakis
185 bad9404c Christos Stavrakakis
    def map_field_type(query):
186 bad9404c Christos Stavrakakis
        def fix_bool(val):
187 bad9404c Christos Stavrakakis
            if val.lower() in ("yes", "true", "t"):
188 bad9404c Christos Stavrakakis
                return True
189 bad9404c Christos Stavrakakis
            if val.lower() in ("no", "false", "f"):
190 bad9404c Christos Stavrakakis
                return False
191 bad9404c Christos Stavrakakis
            return val
192 bad9404c Christos Stavrakakis
193 bad9404c Christos Stavrakakis
        if "!=" in query:
194 bad9404c Christos Stavrakakis
            key, val = query.split("!=")
195 bad9404c Christos Stavrakakis
            exclude_dict[key] = fix_bool(val)
196 bad9404c Christos Stavrakakis
            return
197 bad9404c Christos Stavrakakis
        OP_MAP = {
198 bad9404c Christos Stavrakakis
            ">=": "__gte",
199 bad9404c Christos Stavrakakis
            "=>": "__gte",
200 bad9404c Christos Stavrakakis
            ">":  "__gt",
201 bad9404c Christos Stavrakakis
            "<=": "__lte",
202 bad9404c Christos Stavrakakis
            "=<": "__lte",
203 bad9404c Christos Stavrakakis
            "<":  "__lt",
204 2d30ccdd Stratos Psomadakis
            "=":  "",
205 bad9404c Christos Stavrakakis
        }
206 bad9404c Christos Stavrakakis
        for op, new_op in OP_MAP.items():
207 bad9404c Christos Stavrakakis
            if op in query:
208 bad9404c Christos Stavrakakis
                key, val = query.split(op)
209 bad9404c Christos Stavrakakis
                filter_dict[key + new_op] = fix_bool(val)
210 bad9404c Christos Stavrakakis
                return
211 bad9404c Christos Stavrakakis
212 bad9404c Christos Stavrakakis
    map(lambda x: map_field_type(x), filter_list)
213 bad9404c Christos Stavrakakis
214 bad9404c Christos Stavrakakis
    try:
215 bad9404c Christos Stavrakakis
        objects = objects.filter(**filter_dict)
216 bad9404c Christos Stavrakakis
        return objects.exclude(**exclude_dict)
217 bad9404c Christos Stavrakakis
    except FieldError as e:
218 bad9404c Christos Stavrakakis
        raise CommandError(e)
219 8b3e98f8 Christos Stavrakakis
    except Exception as e:
220 8b3e98f8 Christos Stavrakakis
        raise CommandError("Can not filter results: %s" % e)
221 2333a2c4 Christos Stavrakakis
222 2333a2c4 Christos Stavrakakis
223 2333a2c4 Christos Stavrakakis
def check_backend_credentials(clustername, port, username, password):
224 2333a2c4 Christos Stavrakakis
    try:
225 2333a2c4 Christos Stavrakakis
        client = GanetiRapiClient(clustername, port, username, password)
226 2333a2c4 Christos Stavrakakis
        # This command will raise an exception if there is no
227 2333a2c4 Christos Stavrakakis
        # write-access
228 2333a2c4 Christos Stavrakakis
        client.ModifyCluster()
229 2333a2c4 Christos Stavrakakis
    except GanetiApiError as e:
230 2333a2c4 Christos Stavrakakis
        raise CommandError(e)
231 2333a2c4 Christos Stavrakakis
232 2333a2c4 Christos Stavrakakis
    info = client.GetInfo()
233 2333a2c4 Christos Stavrakakis
    info_name = info['name']
234 2333a2c4 Christos Stavrakakis
    if info_name != clustername:
235 2333a2c4 Christos Stavrakakis
        raise CommandError("Invalid clustername value. Please use the"
236 2333a2c4 Christos Stavrakakis
                           " Ganeti Cluster name: %s" % info_name)
237 7a0aa449 Christos Stavrakakis
238 7a0aa449 Christos Stavrakakis
239 7a0aa449 Christos Stavrakakis
def pprint_table(out, table, headers=None, separator=None):
240 7a0aa449 Christos Stavrakakis
    """Print a pretty, aligned string representation of table.
241 7a0aa449 Christos Stavrakakis

242 7a0aa449 Christos Stavrakakis
    Works by finding out the max width of each column and padding to data
243 7a0aa449 Christos Stavrakakis
    to this value.
244 7a0aa449 Christos Stavrakakis
    """
245 7a0aa449 Christos Stavrakakis
246 7a0aa449 Christos Stavrakakis
    sep = separator if separator else "  "
247 7a0aa449 Christos Stavrakakis
248 7a0aa449 Christos Stavrakakis
    if headers:
249 7a0aa449 Christos Stavrakakis
        table.insert(0, headers)
250 7a0aa449 Christos Stavrakakis
251 7a0aa449 Christos Stavrakakis
    # Find out the max width of each column
252 7a0aa449 Christos Stavrakakis
    widths = [max(map(len, col)) for col in zip(*table)]
253 7a0aa449 Christos Stavrakakis
254 7a0aa449 Christos Stavrakakis
    t_length = sum(widths) + len(sep) * (len(widths) - 1)
255 7a0aa449 Christos Stavrakakis
    if headers:
256 7a0aa449 Christos Stavrakakis
        # pretty print the headers
257 5112da27 Christos Stavrakakis
        print >> out, sep.join((val.rjust(width)
258 5112da27 Christos Stavrakakis
                               for val, width in zip(headers, widths)))
259 7a0aa449 Christos Stavrakakis
        print >> out, "-" * t_length
260 7a0aa449 Christos Stavrakakis
        # remove headers
261 7a0aa449 Christos Stavrakakis
        table = table[1:]
262 7a0aa449 Christos Stavrakakis
263 7a0aa449 Christos Stavrakakis
    # print the rest table
264 7a0aa449 Christos Stavrakakis
    for row in table:
265 5112da27 Christos Stavrakakis
        print >> out, sep.join((val.rjust(width).encode('utf8')
266 5112da27 Christos Stavrakakis
                               for val, width in zip(row, widths)))
267 3170076a Stratos Psomadakis
268 3170076a Stratos Psomadakis
269 3170076a Stratos Psomadakis
class UUIDCache(object):
270 8814e07c Christos Stavrakakis
    """UUID-to-email cache"""
271 3fa01ebd Stratos Psomadakis
272 3170076a Stratos Psomadakis
    def __init__(self):
273 3170076a Stratos Psomadakis
        self.users = {}
274 3170076a Stratos Psomadakis
275 3170076a Stratos Psomadakis
    def get_user(self, uuid):
276 8814e07c Christos Stavrakakis
        """Do the uuid-to-email resolving"""
277 3fa01ebd Stratos Psomadakis
278 3170076a Stratos Psomadakis
        if not uuid in self.users:
279 3fa01ebd Stratos Psomadakis
            try:
280 8814e07c Christos Stavrakakis
                self.users[uuid] =\
281 8814e07c Christos Stavrakakis
                    astakos.get_displayname(token=ASTAKOS_TOKEN,
282 8814e07c Christos Stavrakakis
                                            url=CYCLADES_USER_CATALOG_URL,
283 8814e07c Christos Stavrakakis
                                            uuid=uuid)
284 8814e07c Christos Stavrakakis
            except Exception as e:
285 8814e07c Christos Stavrakakis
                log.error("Can not get display name for uuid %s: %s", uuid, e)
286 3fa01ebd Stratos Psomadakis
                return uuid
287 3170076a Stratos Psomadakis
288 3170076a Stratos Psomadakis
        return self.users[uuid]