gnt-os 4.76 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
34
from ganeti import constants
Guido Trotter's avatar
Guido Trotter committed
35

36

Iustin Pop's avatar
Iustin Pop committed
37
def ListOS(opts, args):
38
39
40
41
42
43
44
  """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
45
46

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

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

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

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

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

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

  return 0

Guido Trotter's avatar
Guido Trotter committed
73

74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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
90
91
92
def DiagnoseOS(opts, args):
  """Analyse all OSes on this cluster.

93
94
95
96
97
98
  @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
99
  """
100
101
  op = opcodes.OpDiagnoseOS(output_fields=["name", "valid", "variants",
                                           "node_status"], names=[])
Iustin Pop's avatar
Iustin Pop committed
102
103
104
  result = SubmitOpCode(op)

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

108
109
  has_bad = False

Iustin Pop's avatar
Iustin Pop committed
110
  for os_name, _, os_variants, node_data in result:
Guido Trotter's avatar
Guido Trotter committed
111
    nodes_valid = {}
Iustin Pop's avatar
Iustin Pop committed
112
    nodes_bad = {}
113
114
115
116
    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
117
118
119
120
121
122
        (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),
123
                         first_os_path, utils.CommaJoin(first_os_variants)))
124
        if first_os_status:
125
          nodes_valid[node_name] = first_os_msg
Guido Trotter's avatar
Guido Trotter committed
126
        else:
127
          nodes_bad[node_name] = first_os_msg
128
        for hpath, hstatus, hmsg in node_info:
129
          nodes_hidden[node_name].append("    [hidden] path: %s, status: %s" %
130
                                         (hpath, _OsStatus(hstatus, hmsg)))
Iustin Pop's avatar
Iustin Pop committed
131
      else:
Guido Trotter's avatar
Guido Trotter committed
132
        nodes_bad[node_name] = "OS not found"
Iustin Pop's avatar
Iustin Pop committed
133
134
135
136
137

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

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

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

157
158
  return int(has_bad)

Iustin Pop's avatar
Iustin Pop committed
159
160

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

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