gnt-os 4.75 KB
Newer Older
Iustin Pop's avatar
Iustin Pop committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/python
#

# Copyright (C) 2006, 2007 Google Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.

Iustin Pop's avatar
Iustin Pop committed
21
"""OS scripts related commands"""
Iustin Pop's avatar
Iustin Pop committed
22

23
# pylint: disable-msg=W0401,W0613,W0614,C0103
24
# W0401: Wildcard import ganeti.cli
25
# W0613: Unused argument, since all functions follow the same API
26
# W0614: Unused import %s from wildcard import (since we need cli)
Iustin Pop's avatar
Iustin Pop committed
27
# C0103: Invalid name gnt-os
28

Iustin Pop's avatar
Iustin Pop committed
29
30
31
32
33
import sys

from ganeti.cli import *
from ganeti import opcodes
from ganeti import utils
Guido Trotter's avatar
Guido Trotter committed
34

35

Iustin Pop's avatar
Iustin Pop committed
36
def ListOS(opts, args):
37
38
39
40
41
42
43
  """List the valid OSes in the cluster.

  @param opts: the command line options selected by the user
  @type args: list
  @param args: should be an empty list
  @rtype: int
  @return: the desired exit code
Iustin Pop's avatar
Iustin Pop committed
44
45

  """
46
47
  op = opcodes.OpDiagnoseOS(output_fields=["name", "valid", "variants"],
                            names=[])
48
  result = SubmitOpCode(op, opts=opts)
Iustin Pop's avatar
Iustin Pop committed
49
50

  if not result:
51
    ToStderr("Can't get the OS list")
Iustin Pop's avatar
Iustin Pop committed
52
53
54
    return 1

  if not opts.no_headers:
55
56
57
    headers = {"name": "Name"}
  else:
    headers = None
Iustin Pop's avatar
Iustin Pop committed
58

59
60
61
62
63
  os_names = []
  for (name, valid, variants) in result:
    if valid:
      os_names.extend([[n] for n in CalculateOSNames(name, variants)])

64
  data = GenerateTable(separator=None, headers=headers, fields=["name"],
65
                       data=os_names, units=None)
66
67

  for line in data:
68
    ToStdout(line)
Iustin Pop's avatar
Iustin Pop committed
69
70
71

  return 0

Guido Trotter's avatar
Guido Trotter committed
72

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
def _OsStatus(status, diagnose):
  """Beautifier function for OS status.

  @type status: boolean
  @param status: is the OS valid
  @type diagnose: string
  @param diagnose: the error message for invalid OSes
  @rtype: string
  @return: a formatted status

  """
  if status:
    return "valid"
  else:
    return "invalid - %s" % diagnose

Iustin Pop's avatar
Iustin Pop committed
89
90
91
def DiagnoseOS(opts, args):
  """Analyse all OSes on this cluster.

92
93
94
95
96
97
  @param opts: the command line options selected by the user
  @type args: list
  @param args: should be an empty list
  @rtype: int
  @return: the desired exit code

Iustin Pop's avatar
Iustin Pop committed
98
  """
99
100
  op = opcodes.OpDiagnoseOS(output_fields=["name", "valid", "variants",
                                           "node_status"], names=[])
101
  result = SubmitOpCode(op, opts=opts)
Iustin Pop's avatar
Iustin Pop committed
102
103

  if not result:
104
    ToStderr("Can't get the OS list")
Iustin Pop's avatar
Iustin Pop committed
105
106
    return 1

107
108
  has_bad = False

Iustin Pop's avatar
Iustin Pop committed
109
  for os_name, _, os_variants, node_data in result:
Guido Trotter's avatar
Guido Trotter committed
110
    nodes_valid = {}
Iustin Pop's avatar
Iustin Pop committed
111
    nodes_bad = {}
112
113
114
115
    nodes_hidden = {}
    for node_name, node_info in node_data.iteritems():
      nodes_hidden[node_name] = []
      if node_info: # at least one entry in the per-node list
116
117
118
119
120
121
        (first_os_path, first_os_status, first_os_msg,
         first_os_variants) = node_info.pop(0)
        if not first_os_variants:
          first_os_variants = []
        first_os_msg = ("%s (path: %s) [variants: %s]" %
                        (_OsStatus(first_os_status, first_os_msg),
122
                         first_os_path, utils.CommaJoin(first_os_variants)))
123
        if first_os_status:
124
          nodes_valid[node_name] = first_os_msg
Guido Trotter's avatar
Guido Trotter committed
125
        else:
126
          nodes_bad[node_name] = first_os_msg
127
        for hpath, hstatus, hmsg in node_info:
128
          nodes_hidden[node_name].append("    [hidden] path: %s, status: %s" %
129
                                         (hpath, _OsStatus(hstatus, hmsg)))
Iustin Pop's avatar
Iustin Pop committed
130
      else:
Guido Trotter's avatar
Guido Trotter committed
131
        nodes_bad[node_name] = "OS not found"
Iustin Pop's avatar
Iustin Pop committed
132
133
134
135
136

    if nodes_valid and not nodes_bad:
      status = "valid"
    elif not nodes_valid and nodes_bad:
      status = "invalid"
137
      has_bad = True
Iustin Pop's avatar
Iustin Pop committed
138
139
    else:
      status = "partial valid"
140
      has_bad = True
141

142
143
    def _OutputPerNodeOSStatus(msg_map):
      map_k = utils.NiceSort(msg_map.keys())
Guido Trotter's avatar
Guido Trotter committed
144
      for node_name in map_k:
145
        ToStdout("  Node: %s, status: %s", node_name, msg_map[node_name])
146
        for msg in nodes_hidden[node_name]:
147
          ToStdout(msg)
Guido Trotter's avatar
Guido Trotter committed
148

149
    ToStdout("OS: %s [global status: %s]", os_name, status)
150
    if os_variants:
151
      ToStdout("  Variants: [%s]" % utils.CommaJoin(os_variants))
Guido Trotter's avatar
Guido Trotter committed
152
153
    _OutputPerNodeOSStatus(nodes_valid)
    _OutputPerNodeOSStatus(nodes_bad)
154
    ToStdout("")
Iustin Pop's avatar
Iustin Pop committed
155

156
157
  return int(has_bad)

Iustin Pop's avatar
Iustin Pop committed
158
159

commands = {
160
  'list': (
161
    ListOS, ARGS_NONE, [NOHDR_OPT], "", "Lists all valid OSes on the master"),
162
  'diagnose': (
163
    DiagnoseOS, ARGS_NONE, [], "", "Diagnose all OSes"),
Iustin Pop's avatar
Iustin Pop committed
164
165
166
  }

if __name__ == '__main__':
167
  sys.exit(GenericMain(commands))