Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / management / common.py @ 0252fb8b

History | View | Annotate | Download (7.9 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 synnefo.api.util import get_image as backend_get_image
37
from synnefo.api.faults import ItemNotFound, BadRequest, OverLimit
38

    
39
from synnefo.api.util import validate_network_params
40
from synnefo.settings import (CYCLADES_ASTAKOS_SERVICE_TOKEN as ASTAKOS_TOKEN,
41
                              ASTAKOS_URL)
42
from synnefo.logic.rapi import GanetiApiError, GanetiRapiClient
43
from synnefo.logic.utils import (id_from_instance_name,
44
                                 id_from_network_name)
45
from synnefo.lib import astakos
46

    
47
import logging
48
log = logging.getLogger(__name__)
49

    
50

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

    
57

    
58
def validate_network_info(options):
59
    subnet = options['subnet']
60
    gateway = options['gateway']
61
    subnet6 = options['subnet6']
62
    gateway6 = options['gateway6']
63

    
64
    try:
65
        validate_network_params(subnet, gateway)
66
    except (BadRequest, OverLimit) as e:
67
        raise CommandError(e)
68

    
69
    return subnet, gateway, subnet6, gateway6
70

    
71

    
72
def get_backend(backend_id):
73
    try:
74
        backend_id = int(backend_id)
75
        return Backend.objects.get(id=backend_id)
76
    except ValueError:
77
        raise CommandError("Invalid Backend ID: %s" % backend_id)
78
    except Backend.DoesNotExist:
79
        raise CommandError("Backend with ID %s not found in DB. "
80
                           " Use snf-manage backend-list to find"
81
                           " out available backend IDs." % backend_id)
82

    
83

    
84
def get_image(image_id, user_id):
85
    if image_id:
86
        try:
87
            return backend_get_image(image_id, user_id)
88
        except ItemNotFound:
89
            raise CommandError("Image with ID %s not found."
90
                               " Use snf-manage image-list to find"
91
                               " out available image IDs." % image_id)
92
    else:
93
        raise CommandError("image-id is mandatory")
94

    
95

    
96
def get_vm(server_id):
97
    """Get a VirtualMachine object by its ID.
98

99
    @type server_id: int or string
100
    @param server_id: The server's DB id or the Ganeti name
101

102
    """
103
    try:
104
        server_id = int(server_id)
105
    except (ValueError, TypeError):
106
        try:
107
            server_id = id_from_instance_name(server_id)
108
        except VirtualMachine.InvalidBackendIdError:
109
            raise CommandError("Invalid server ID: %s" % server_id)
110

    
111
    try:
112
        return VirtualMachine.objects.get(id=server_id)
113
    except VirtualMachine.DoesNotExist:
114
        raise CommandError("Server with ID %s not found in DB."
115
                           " Use snf-manage server-list to find out"
116
                           " available server IDs." % server_id)
117

    
118

    
119
def get_network(network_id):
120
    """Get a Network object by its ID.
121

122
    @type network_id: int or string
123
    @param network_id: The networks DB id or the Ganeti name
124

125
    """
126

    
127
    try:
128
        network_id = int(network_id)
129
    except (ValueError, TypeError):
130
        try:
131
            network_id = id_from_network_name(network_id)
132
        except Network.InvalidBackendIdError:
133
            raise CommandError("Invalid network ID: %s" % network_id)
134

    
135
    try:
136
        return Network.objects.get(id=network_id)
137
    except Network.DoesNotExist:
138
        raise CommandError("Network with ID %s not found in DB."
139
                           " Use snf-manage network-list to find out"
140
                           " available network IDs." % network_id)
141

    
142

    
143
def get_flavor(flavor_id):
144
    try:
145
        flavor_id = int(flavor_id)
146
        return Flavor.objects.get(id=flavor_id)
147
    except ValueError:
148
        raise CommandError("Invalid flavor ID: %s", flavor_id)
149
    except Flavor.DoesNotExist:
150
        raise CommandError("Flavor with ID %s not found in DB."
151
                           " Use snf-manage flavor-list to find out"
152
                           " available flavor IDs." % flavor_id)
153

    
154

    
155
def check_backend_credentials(clustername, port, username, password):
156
    try:
157
        client = GanetiRapiClient(clustername, port, username, password)
158
        # This command will raise an exception if there is no
159
        # write-access
160
        client.ModifyCluster()
161
    except GanetiApiError as e:
162
        raise CommandError(e)
163

    
164
    info = client.GetInfo()
165
    info_name = info['name']
166
    if info_name != clustername:
167
        raise CommandError("Invalid clustername value. Please use the"
168
                           " Ganeti Cluster name: %s" % info_name)
169

    
170

    
171
class UserCache(object):
172
    """uuid<->displayname user 'cache'"""
173

    
174
    user_catalogs_url = ASTAKOS_URL.replace("im/authenticate",
175
                                            "service/api/user_catalogs")
176

    
177
    def __init__(self, split=100):
178
        self.users = {}
179

    
180
        self.split = split
181
        assert(self.split > 0), "split must be positive"
182

    
183
    def fetch_names(self, uuid_list):
184
        total = len(uuid_list)
185
        split = self.split
186

    
187
        for start in range(0, total, split):
188
            end = start + split
189
            try:
190
                names = \
191
                    astakos.get_displaynames(token=ASTAKOS_TOKEN,
192
                                             url=UserCache.user_catalogs_url,
193
                                             uuids=uuid_list[start:end])
194
                self.users.update(names)
195
            except Exception as e:
196
                log.error("Failed to fetch names: %s",  e)
197

    
198
    def get_uuid(self, name):
199
        if not name in self.users:
200
            try:
201
                self.users[name] = \
202
                    astakos.get_user_uuid(token=ASTAKOS_TOKEN,
203
                                          url=UserCache.user_catalogs_url,
204
                                          displayname=name)
205
            except Exception as e:
206
                log.error("Can not get uuid for name %s: %s", name, e)
207
                self.users[name] = name
208

    
209
        return self.users[name]
210

    
211
    def get_name(self, uuid):
212
        """Do the uuid-to-email resolving"""
213

    
214
        if not uuid in self.users:
215
            try:
216
                self.users[uuid] = \
217
                    astakos.get_displayname(token=ASTAKOS_TOKEN,
218
                                            url=UserCache.user_catalogs_url,
219
                                            uuid=uuid)
220
            except Exception as e:
221
                log.error("Can not get display name for uuid %s: %s", uuid, e)
222
                self.users[uuid] = "-"
223

    
224
        return self.users[uuid]
225

    
226

    
227
class Omit(object):
228
    pass