Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / management / pprint.py @ db908bb1

History | View | Annotate | Download (11.6 kB)

1
#Copyright (C) 2013 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
import sys
35
from snf_django.management.utils import pprint_table
36
from synnefo.lib.ordereddict import OrderedDict
37
from snf_django.lib.astakos import UserCache
38
from synnefo.settings import (CYCLADES_SERVICE_TOKEN as ASTAKOS_TOKEN,
39
                              ASTAKOS_BASE_URL)
40
from synnefo.db.models import Backend, pooled_rapi_client
41
from synnefo.logic.rapi import GanetiApiError
42
from synnefo.logic.reconciliation import nics_from_instance
43
from synnefo.management.common import get_image
44

    
45

    
46
def pprint_network(network, display_mails=False, stdout=None, title=None):
47
    if stdout is None:
48
        stdout = sys.stdout
49
    if title is None:
50
        title = "State of Network %s in DB" % network.id
51

    
52
    ucache = UserCache(ASTAKOS_BASE_URL, ASTAKOS_TOKEN)
53
    userid = network.userid
54

    
55
    db_network = OrderedDict([
56
        ("name", network.name),
57
        ("backend-name", network.backend_id),
58
        ("state", network.state),
59
        ("userid", userid),
60
        ("username", ucache.get_name(userid) if display_mails else None),
61
        ("public", network.public),
62
        ("floating_ip_pool", network.floating_ip_pool),
63
        ("external_router", network.external_router),
64
        ("drained", network.drained),
65
        ("MAC prefix", network.mac_prefix),
66
        ("flavor", network.flavor),
67
        ("link", network.link),
68
        ("mode", network.mode),
69
        ("deleted", network.deleted),
70
        ("tags", "), ".join(network.backend_tag)),
71
        ("action", network.action)])
72

    
73
    pprint_table(stdout, db_network.items(), None, separator=" | ",
74
                 title=title)
75

    
76

    
77
def pprint_network_subnets(network, stdout=None, title=None):
78
    if stdout is None:
79
        stdout = sys.stdout
80
    if title is None:
81
        title = "Subnets of network %s" % network.id
82

    
83
    subnets = list(network.subnets.values_list("id", "name", "ipversion",
84
                                               "cidr", "gateway", "dhcp",
85
                                               "deleted"))
86
    headers = ["ID", "Name", "Version", "CIDR", "Gateway", "DHCP",
87
               "Deleted"]
88
    pprint_table(stdout, subnets, headers, separator=" | ",
89
                 title=title)
90

    
91

    
92
def pprint_network_backends(network, stdout=None, title=None):
93
    if stdout is None:
94
        stdout = sys.stdout
95
    if title is None:
96
        title = "State of Network %s in DB for each backend" % network.id
97
    bnets = list(network.backend_networks.values_list(
98
        "backend__clustername",
99
        "operstate", "deleted", "backendjobid",
100
        "backendopcode", "backendjobstatus"))
101
    headers = ["Backend", "State", "Deleted", "JobID", "Opcode",
102
               "JobStatus"]
103
    pprint_table(stdout, bnets, headers, separator=" | ",
104
                 title=title)
105

    
106

    
107
def pprint_network_in_ganeti(network, stdout=None):
108
    if stdout is None:
109
        stdout = sys.stdout
110
    for backend in Backend.objects.exclude(offline=True):
111
        with pooled_rapi_client(backend) as client:
112
            try:
113
                g_net = client.GetNetwork(network.backend_id)
114
                ip_map = g_net.pop("map")
115
                pprint_table(stdout, g_net.items(), None,
116
                             title="State of network in backend: %s" %
117
                                   backend.clustername)
118
                pprint_pool(None, ip_map, 80, stdout)
119
            except GanetiApiError as e:
120
                if e.code == 404:
121
                    stdout.write('Network does not exist in backend %s\n' %
122
                                 backend.clustername)
123
                else:
124
                    raise e
125

    
126

    
127
def pool_map_chunks(smap, step=64):
128
    for i in xrange(0, len(smap), step):
129
        yield smap[i:i + step]
130

    
131

    
132
def splitPoolMap(s, count):
133
    chunks = pool_map_chunks(s, count)
134
    acc = []
135
    count = 0
136
    for chunk in chunks:
137
        chunk_len = len(chunk)
138
        acc.append(str(count).rjust(3) + ' ' + chunk + ' ' +
139
                   str(count + chunk_len - 1).ljust(4))
140
        count += chunk_len
141
    return '\n' + '\n'.join(acc)
142

    
143

    
144
def pprint_pool(name, pool_map, step=80, stdout=None):
145
    if stdout is None:
146
        stdout = sys.stdout
147
    if name is not None:
148
        stdout.write("Pool: %s\n" % name)
149
    stdout.write(splitPoolMap(pool_map, count=step))
150
    stdout.write("\n")
151

    
152

    
153
def pprint_port(port, stdout=None, title=None):
154
    if stdout is None:
155
        stdout = sys.stdout
156
    if title is None:
157
        title = "State of Port %s in DB" % port.id
158
    port = OrderedDict([
159
        ("id", port.id),
160
        ("name", port.name),
161
        ("userid", port.userid),
162
        ("server", port.machine_id),
163
        ("network", port.network_id),
164
        ("device_owner", port.device_owner),
165
        ("mac", port.mac),
166
        ("state", port.state)])
167

    
168
    pprint_table(stdout, port.items(), None, separator=" | ",
169
                 title=title)
170

    
171

    
172
def pprint_port_ips(port, stdout=None, title=None):
173
    if stdout is None:
174
        stdout = sys.stdout
175
    if title is None:
176
        title = "IP Addresses of Port %s" % port.id
177
    ips = list(port.ips.values_list("address", "network_id", "subnet_id",
178
                                    "subnet__cidr", "floating_ip"))
179
    headers = ["Address", "Network", "Subnet", "CIDR", "is_floating"]
180
    pprint_table(stdout, ips, headers, separator=" | ",
181
                 title=title)
182

    
183

    
184
def pprint_port_in_ganeti(port, stdout=None, title=None):
185
    if stdout is None:
186
        stdout = sys.stdout
187
    if title is None:
188
        title = "State of Port %s in Ganeti" % port.id
189

    
190
    vm = port.machine
191
    if vm is None:
192
        stdout.write("Port is not attached to any instance.\n")
193
        return
194

    
195
    client = vm.get_client()
196
    try:
197
        vm_info = client.GetInstance(vm.backend_vm_id)
198
    except GanetiApiError as e:
199
        if e.code == 404:
200
            stdout.write("NIC seems attached to server %s, but"
201
                         " server does not exist in backend.\n"
202
                         % vm)
203
            return
204
        raise e
205

    
206
    nics = nics_from_instance(vm_info)
207
    try:
208
        gnt_nic = filter(lambda nic: nic.get("name") == port.backend_uuid,
209
                         nics)[0]
210
        gnt_nic["instance"] = vm_info["name"]
211
    except IndexError:
212
        stdout.write("NIC %s is not attached to instance %s" % (port, vm))
213
        return
214
    pprint_table(stdout, gnt_nic.items(), None, separator=" | ",
215
                 title=title)
216

    
217
    vm.put_client(client)
218

    
219

    
220
def pprint_server(server, display_mails=False, stdout=None, title=None):
221
    if stdout is None:
222
        stdout = sys.stdout
223
    if title is None:
224
        title = "State of Server %s in DB" % server.id
225

    
226
    ucache = UserCache(ASTAKOS_BASE_URL, ASTAKOS_TOKEN)
227
    userid = server.userid
228

    
229
    try:
230
        image = get_image(server.imageid, server.userid)['name']
231
    except:
232
        image = server.imageid
233

    
234
    server_dict = OrderedDict([
235
        ("id", server.id),
236
        ("name", server.name),
237
        ("userid", server.userid),
238
        ("username", ucache.get_name(userid) if display_mails else None),
239
        ("flavor_id", server.flavor_id),
240
        ("flavor_name", server.flavor.name),
241
        ("imageid", server.imageid),
242
        ("image_name", image),
243
        ("state", server.operstate),
244
        ("backend", server.backend),
245
        ("deleted", server.deleted),
246
        ("action", server.action),
247
        ("task", server.task),
248
        ("task_job_id", server.task_job_id),
249
        ("backendjobid", server.backendjobid),
250
        ("backendopcode", server.backendopcode),
251
        ("backendjobstatus", server.backendjobstatus),
252
        ("backend_time", server.backendtime),
253
        ])
254

    
255
    pprint_table(stdout, server_dict.items(), None, separator=" | ",
256
                 title=title)
257

    
258

    
259
def pprint_server_nics(server, stdout=None, title=None):
260
    if title is None:
261
        title = "NICs of Server %s" % server.id
262
    if stdout is None:
263
        stdout = sys.stdout
264

    
265
    nics = []
266
    for nic in server.nics.all():
267
        nics.append((nic.id, nic.name, nic.index, nic.mac, nic.ipv4_address,
268
                     nic.ipv6_address, nic.network, nic.firewall_profile,
269
                     nic.state))
270

    
271
    headers = ["ID", "Name", "Index", "MAC", "IPv4 Address", "IPv6 Address",
272
               "Network", "Firewall", "State"]
273
    pprint_table(stdout, nics, headers, separator=" | ",
274
                 title=title)
275

    
276

    
277
def pprint_server_in_ganeti(server, print_jobs=False, stdout=None, title=None):
278
    if stdout is None:
279
        stdout = sys.stdout
280
    if title is None:
281
        title = "State of Server %s in Ganeti" % server.id
282

    
283
    client = server.get_client()
284
    try:
285
        server_info = client.GetInstance(server.backend_vm_id)
286
    except GanetiApiError as e:
287
        if e.code == 404:
288
            stdout.write("NIC seems attached to server %s, but"
289
                         " server does not exist in backend.\n"
290
                         % server)
291
            return
292
        raise e
293
    server.put_client(client)
294

    
295
    GANETI_INSTANCE_FIELDS = ('name', 'oper_state', 'admin_state', 'status',
296
                              'pnode', 'snode', 'network_port',
297
                              'disk_template', 'disk_usage',
298
                              'oper_ram', 'oper_vcpus', 'mtime')
299
    server_dict = OrderedDict([(k, server_info.get(k))
300
                              for k in GANETI_INSTANCE_FIELDS])
301

    
302
    pprint_table(stdout, server_dict.items(), None, separator=" | ",
303
                 title="NICs of Server %s in Ganeti" % server.id)
304
    stdout.write("\n")
305

    
306
    nics = nics_from_instance(server_info)
307
    nics_keys = ["ip", "mac", "name", "network"]
308
    nics_values = [[nic[key] for key in nics_keys] for nic in nics]
309
    pprint_table(stdout, nics_values, nics_keys, separator=" | ",
310
                 title=title)
311

    
312
    if not print_jobs:
313
        return
314

    
315
    client = server.get_client()
316
    jobs = client.GetJobs(bulk=True)
317
    server_jobs = filter(
318
        lambda x: server.backend_vm_id in (" ".join(x.get("summary"))), jobs)
319

    
320
    GANETI_JOB_FIELDS = ('id', 'status', 'summary', 'opresult', 'opstatus',
321
                         'oplog', 'start_ts', 'end_ts')
322
    for server_job in server_jobs:
323
        stdout.write("\n")
324
        values = [server_job.get(k) for k in GANETI_JOB_FIELDS]
325
        pprint_table(stdout, zip(GANETI_JOB_FIELDS, values), None,
326
                     separator=" | ",
327
                     title="Ganeti Job %s" % server_job["id"])
328
    server.put_client(client)