Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / management / common.py @ 35f2fc07

History | View | Annotate | Download (6.4 kB)

1
# Copyright 2012 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, Flavor
36
from functools import wraps
37

    
38
from snf_django.lib.api import faults
39
from synnefo.api import util
40
from synnefo.logic import backend as backend_mod
41
from synnefo.logic.rapi import GanetiApiError, GanetiRapiClient
42
from synnefo.logic.utils import (id_from_instance_name,
43
                                 id_from_network_name)
44

    
45
import logging
46
log = logging.getLogger(__name__)
47

    
48

    
49
def format_vm_state(vm):
50
    if vm.operstate == "BUILD":
51
        return "BUILD(" + str(vm.buildpercentage) + "%)"
52
    else:
53
        return vm.operstate
54

    
55

    
56
def get_backend(backend_id):
57
    try:
58
        backend_id = int(backend_id)
59
        return Backend.objects.get(id=backend_id)
60
    except ValueError:
61
        raise CommandError("Invalid Backend ID: %s" % backend_id)
62
    except Backend.DoesNotExist:
63
        raise CommandError("Backend with ID %s not found in DB. "
64
                           " Use snf-manage backend-list to find"
65
                           " out available backend IDs." % backend_id)
66

    
67

    
68
def get_image(image_id, user_id):
69
    if image_id:
70
        try:
71
            return util.get_image_dict(image_id, user_id)
72
        except faults.ItemNotFound:
73
            raise CommandError("Image with ID %s not found."
74
                               " Use snf-manage image-list to find"
75
                               " out available image IDs." % image_id)
76
    else:
77
        raise CommandError("image-id is mandatory")
78

    
79

    
80
def get_vm(server_id):
81
    """Get a VirtualMachine object by its ID.
82

83
    @type server_id: int or string
84
    @param server_id: The server's DB id or the Ganeti name
85

86
    """
87
    try:
88
        server_id = int(server_id)
89
    except (ValueError, TypeError):
90
        try:
91
            server_id = id_from_instance_name(server_id)
92
        except VirtualMachine.InvalidBackendIdError:
93
            raise CommandError("Invalid server ID: %s" % server_id)
94

    
95
    try:
96
        return VirtualMachine.objects.get(id=server_id)
97
    except VirtualMachine.DoesNotExist:
98
        raise CommandError("Server with ID %s not found in DB."
99
                           " Use snf-manage server-list to find out"
100
                           " available server IDs." % server_id)
101

    
102

    
103
def get_network(network_id, for_update=True):
104
    """Get a Network object by its ID.
105

106
    @type network_id: int or string
107
    @param network_id: The networks DB id or the Ganeti name
108

109
    """
110

    
111
    try:
112
        network_id = int(network_id)
113
    except (ValueError, TypeError):
114
        try:
115
            network_id = id_from_network_name(network_id)
116
        except Network.InvalidBackendIdError:
117
            raise CommandError("Invalid network ID: %s" % network_id)
118

    
119
    networks = Network.objects
120
    if for_update:
121
        networks = networks.select_for_update()
122
    try:
123
        return networks.get(id=network_id)
124
    except Network.DoesNotExist:
125
        raise CommandError("Network with ID %s not found in DB."
126
                           " Use snf-manage network-list to find out"
127
                           " available network IDs." % network_id)
128

    
129

    
130
def get_flavor(flavor_id):
131
    try:
132
        flavor_id = int(flavor_id)
133
        return Flavor.objects.get(id=flavor_id)
134
    except ValueError:
135
        raise CommandError("Invalid flavor ID: %s", flavor_id)
136
    except Flavor.DoesNotExist:
137
        raise CommandError("Flavor with ID %s not found in DB."
138
                           " Use snf-manage flavor-list to find out"
139
                           " available flavor IDs." % flavor_id)
140

    
141

    
142
def check_backend_credentials(clustername, port, username, password):
143
    try:
144
        client = GanetiRapiClient(clustername, port, username, password)
145
        # This command will raise an exception if there is no
146
        # write-access
147
        client.ModifyCluster()
148
    except GanetiApiError as e:
149
        raise CommandError(e)
150

    
151
    info = client.GetInfo()
152
    info_name = info['name']
153
    if info_name != clustername:
154
        raise CommandError("Invalid clustername value. Please use the"
155
                           " Ganeti Cluster name: %s" % info_name)
156

    
157

    
158
def convert_api_faults(func):
159
    @wraps(func)
160
    def wrapper(*args, **kwargs):
161
        try:
162
            return func(*args, **kwargs)
163
        except faults.Fault as e:
164
            raise CommandError(e.message)
165
    return wrapper
166

    
167

    
168
class Omit(object):
169
    pass
170

    
171

    
172
def wait_server_task(server, wait, stdout):
173
    jobID = server.task_job_id
174
    if wait:
175
        msg = "Issued job '%s'. Waiting to complete...\n"
176
        stdout.write(msg % jobID)
177
        client = server.get_client()
178
        wait_ganeti_job(client, jobID, stdout)
179
    else:
180
        msg = "Issued job '%s'.\n"
181
        stdout.write(msg % jobID)
182

    
183

    
184
def wait_ganeti_job(client, jobID, stdout):
185
    status, error = backend_mod.wait_for_job(client, jobID)
186
    if status == "success":
187
        stdout.write("Job finished successfully.\n")
188
    else:
189
        raise CommandError("Job failed! Error: %s\n" % error)