Change indentation style in commands definitions
[ganeti-local] / scripts / gnt-os
1 #!/usr/bin/python
2 #
3
4 # Copyright (C) 2006, 2007 Google Inc.
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 # General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 # 02110-1301, USA.
20
21
22 # pylint: disable-msg=W0401,W0614
23 # W0401: Wildcard import ganeti.cli
24 # W0614: Unused import %s from wildcard import (since we need cli)
25
26 import sys
27
28 from ganeti.cli import *
29 from ganeti import opcodes
30 from ganeti import utils
31 from ganeti import constants
32
33
34 def ListOS(opts, args):
35   """List the valid OSes in the cluster.
36
37   @param opts: the command line options selected by the user
38   @type args: list
39   @param args: should be an empty list
40   @rtype: int
41   @return: the desired exit code
42
43   """
44   op = opcodes.OpDiagnoseOS(output_fields=["name", "valid"], names=[])
45   result = SubmitOpCode(op)
46
47   if not result:
48     ToStderr("Can't get the OS list")
49     return 1
50
51   if not opts.no_headers:
52     headers = {"name": "Name"}
53   else:
54     headers = None
55
56   data = GenerateTable(separator=None, headers=headers, fields=["name"],
57                        data=[[row[0]] for row in result if row[1]],
58                        units=None)
59
60   for line in data:
61     ToStdout(line)
62
63   return 0
64
65
66 def _OsStatus(status, diagnose):
67   """Beautifier function for OS status.
68
69   @type status: boolean
70   @param status: is the OS valid
71   @type diagnose: string
72   @param diagnose: the error message for invalid OSes
73   @rtype: string
74   @return: a formatted status
75
76   """
77   if status:
78     return "valid"
79   else:
80     return "invalid - %s" % diagnose
81
82 def DiagnoseOS(opts, args):
83   """Analyse all OSes on this cluster.
84
85   @param opts: the command line options selected by the user
86   @type args: list
87   @param args: should be an empty list
88   @rtype: int
89   @return: the desired exit code
90
91   """
92   op = opcodes.OpDiagnoseOS(output_fields=["name", "valid", "node_status"],
93                             names=[])
94   result = SubmitOpCode(op)
95
96   if not result:
97     ToStderr("Can't get the OS list")
98     return 1
99
100   has_bad = False
101
102   for os_name, os_valid, node_data in result:
103     nodes_valid = {}
104     nodes_bad = {}
105     nodes_hidden = {}
106     for node_name, node_info in node_data.iteritems():
107       nodes_hidden[node_name] = []
108       if node_info: # at least one entry in the per-node list
109         first_os_path, first_os_status, first_os_msg = node_info.pop(0)
110         first_os_msg = ("%s (path: %s)" % (_OsStatus(first_os_status,
111                                                      first_os_msg),
112                                            first_os_path))
113         if first_os_status:
114           nodes_valid[node_name] = first_os_msg
115         else:
116           nodes_bad[node_name] = first_os_msg
117         for hpath, hstatus, hmsg in node_info:
118           nodes_hidden[node_name].append("    [hidden] path: %s, status: %s" %
119                                          (hpath, _OsStatus(hstatus, hmsg)))
120       else:
121         nodes_bad[node_name] = "OS not found"
122
123     if nodes_valid and not nodes_bad:
124       status = "valid"
125     elif not nodes_valid and nodes_bad:
126       status = "invalid"
127       has_bad = True
128     else:
129       status = "partial valid"
130       has_bad = True
131
132     def _OutputPerNodeOSStatus(msg_map):
133       map_k = utils.NiceSort(msg_map.keys())
134       for node_name in map_k:
135         ToStdout("  Node: %s, status: %s", node_name, msg_map[node_name])
136         for msg in nodes_hidden[node_name]:
137           ToStdout(msg)
138
139     ToStdout("OS: %s [global status: %s]", os_name, status)
140     _OutputPerNodeOSStatus(nodes_valid)
141     _OutputPerNodeOSStatus(nodes_bad)
142     ToStdout("")
143
144   return int(has_bad)
145
146
147 commands = {
148   'list': (
149     ListOS, ARGS_NONE, [DEBUG_OPT, NOHDR_OPT],
150     "", "Lists all valid OSes on the master"),
151   'diagnose': (
152     DiagnoseOS, ARGS_NONE, [DEBUG_OPT], "", "Diagnose all OSes"),
153   }
154
155 if __name__ == '__main__':
156   sys.exit(GenericMain(commands))