Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / management / common.py @ 1ec2f17e

History | View | Annotate | Download (6.2 kB)

1
# Copyright 2012-2014 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
from django.core.management import CommandError
35
from synnefo.db.models import (Backend, VirtualMachine, Network,
36
                               Flavor, IPAddress, Subnet,
37
                               BridgePoolTable, MacPrefixPoolTable,
38
                               NetworkInterface)
39
from functools import wraps
40

    
41
from django.conf import settings
42
from snf_django.lib.api import faults
43
from synnefo.api import util
44
from synnefo.logic import backend as backend_mod
45
from synnefo.logic.rapi import GanetiApiError, GanetiRapiClient
46
from synnefo.logic.utils import (id_from_instance_name,
47
                                 id_from_network_name,
48
                                 id_from_nic_name)
49
from django.core.exceptions import ObjectDoesNotExist
50
import logging
51
log = logging.getLogger(__name__)
52

    
53

    
54
def format_vm_state(vm):
55
    if vm.operstate == "BUILD":
56
        return "BUILD(" + str(vm.buildpercentage) + "%)"
57
    else:
58
        return vm.operstate
59

    
60
RESOURCE_MAP = {
61
    "backend": Backend.objects,
62
    "flavor": Flavor.objects,
63
    "server": VirtualMachine.objects,
64
    "network": Network.objects,
65
    "subnet": Subnet.objects,
66
    "port": NetworkInterface.objects,
67
    "floating-ip": IPAddress.objects.filter(floating_ip=True)}
68

    
69

    
70
def get_resource(name, value, for_update=False):
71
    """Get object from DB based by it's ID
72

73
    Helper function for getting an object from DB by it's DB and raising
74
    appropriate command line errors if the object does not exist or the
75
    ID is invalid.
76

77
    """
78
    objects = RESOURCE_MAP[name]
79
    if name == "floating-ip":
80
        capital_name = "Floating IP"
81
    else:
82
        capital_name = name.capitalize()
83

    
84
    if isinstance(value, basestring) and name in ["server", "network", "port"]:
85
        if value.startswith(settings.BACKEND_PREFIX_ID):
86
            try:
87
                if name == "server":
88
                    value = id_from_instance_name(value)
89
                elif name == "network":
90
                    value = id_from_network_name(value)
91
                elif name == "port":
92
                    value = id_from_nic_name(value)
93
            except ValueError:
94
                raise CommandError("Invalid {} ID: {}".format(capital_name,
95
                                                              value))
96

    
97
    if for_update:
98
        objects = objects.select_for_update()
99
    try:
100
        return objects.get(id=value)
101
    except ObjectDoesNotExist:
102
        msg = ("{0} with ID {1} does not exist. Use {2}-list to find out"
103
               " available {2} IDs.")
104
        raise CommandError(msg.format(capital_name, value, name))
105
    except (ValueError, TypeError):
106
        raise CommandError("Invalid {} ID: {}".format(capital_name, value))
107

    
108

    
109
def get_image(image_id, user_id):
110
    if image_id:
111
        try:
112
            return util.get_image_dict(image_id, user_id)
113
        except faults.ItemNotFound:
114
            raise CommandError("Image with ID %s not found."
115
                               " Use snf-manage image-list to find"
116
                               " out available image IDs." % image_id)
117
    else:
118
        raise CommandError("image-id is mandatory")
119

    
120

    
121
def check_backend_credentials(clustername, port, username, password):
122
    try:
123
        client = GanetiRapiClient(clustername, port, username, password)
124
        # This command will raise an exception if there is no
125
        # write-access
126
        client.ModifyCluster()
127
    except GanetiApiError as e:
128
        raise CommandError(e)
129

    
130
    info = client.GetInfo()
131
    info_name = info['name']
132
    if info_name != clustername:
133
        raise CommandError("Invalid clustername value. Please use the"
134
                           " Ganeti Cluster name: %s" % info_name)
135

    
136

    
137
def convert_api_faults(func):
138
    @wraps(func)
139
    def wrapper(*args, **kwargs):
140
        try:
141
            return func(*args, **kwargs)
142
        except faults.Fault as e:
143
            raise CommandError(e.message)
144
    return wrapper
145

    
146

    
147
class Omit(object):
148
    pass
149

    
150

    
151
def wait_server_task(server, wait, stdout):
152
    jobID = server.task_job_id
153
    if jobID is None:
154
        return
155
    if wait:
156
        msg = "Issued job '%s'. Waiting to complete...\n"
157
        stdout.write(msg % jobID)
158
        client = server.get_client()
159
        wait_ganeti_job(client, jobID, stdout)
160
    else:
161
        msg = "Issued job '%s'.\n"
162
        stdout.write(msg % jobID)
163

    
164

    
165
def wait_ganeti_job(client, jobID, stdout):
166
    status, error = backend_mod.wait_for_job(client, jobID)
167
    if status == "success":
168
        stdout.write("Job finished successfully.\n")
169
    else:
170
        raise CommandError("Job failed! Error: %s\n" % error)
171

    
172

    
173
def pool_table_from_type(type_):
174
    if type_ == "mac-prefix":
175
        return MacPrefixPoolTable
176
    elif type_ == "bridge":
177
        return BridgePoolTable
178
    # elif type == "ip":
179
    #     return IPPoolTable
180
    else:
181
        raise ValueError("Invalid pool type")