install.rst: note about the default parameters
[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", "variants"],
45                             names=[])
46   result = SubmitOpCode(op)
47
48   if not result:
49     ToStderr("Can't get the OS list")
50     return 1
51
52   if not opts.no_headers:
53     headers = {"name": "Name"}
54   else:
55     headers = None
56
57   os_names = []
58   for (name, valid, variants) in result:
59     if valid:
60       os_names.extend([[n] for n in CalculateOSNames(name, variants)])
61
62   data = GenerateTable(separator=None, headers=headers, fields=["name"],
63                        data=os_names, units=None)
64
65   for line in data:
66     ToStdout(line)
67
68   return 0
69
70
71 def _OsStatus(status, diagnose):
72   """Beautifier function for OS status.
73
74   @type status: boolean
75   @param status: is the OS valid
76   @type diagnose: string
77   @param diagnose: the error message for invalid OSes
78   @rtype: string
79   @return: a formatted status
80
81   """
82   if status:
83     return "valid"
84   else:
85     return "invalid - %s" % diagnose
86
87 def DiagnoseOS(opts, args):
88   """Analyse all OSes on this cluster.
89
90   @param opts: the command line options selected by the user
91   @type args: list
92   @param args: should be an empty list
93   @rtype: int
94   @return: the desired exit code
95
96   """
97   op = opcodes.OpDiagnoseOS(output_fields=["name", "valid", "variants",
98                                            "node_status"], names=[])
99   result = SubmitOpCode(op)
100
101   if not result:
102     ToStderr("Can't get the OS list")
103     return 1
104
105   has_bad = False
106
107   for os_name, os_valid, os_variants, node_data in result:
108     nodes_valid = {}
109     nodes_bad = {}
110     nodes_hidden = {}
111     for node_name, node_info in node_data.iteritems():
112       nodes_hidden[node_name] = []
113       if node_info: # at least one entry in the per-node list
114         (first_os_path, first_os_status, first_os_msg,
115          first_os_variants) = node_info.pop(0)
116         if not first_os_variants:
117           first_os_variants = []
118         first_os_msg = ("%s (path: %s) [variants: %s]" %
119                         (_OsStatus(first_os_status, first_os_msg),
120                          first_os_path, utils.CommaJoin(first_os_variants)))
121         if first_os_status:
122           nodes_valid[node_name] = first_os_msg
123         else:
124           nodes_bad[node_name] = first_os_msg
125         for hpath, hstatus, hmsg in node_info:
126           nodes_hidden[node_name].append("    [hidden] path: %s, status: %s" %
127                                          (hpath, _OsStatus(hstatus, hmsg)))
128       else:
129         nodes_bad[node_name] = "OS not found"
130
131     if nodes_valid and not nodes_bad:
132       status = "valid"
133     elif not nodes_valid and nodes_bad:
134       status = "invalid"
135       has_bad = True
136     else:
137       status = "partial valid"
138       has_bad = True
139
140     def _OutputPerNodeOSStatus(msg_map):
141       map_k = utils.NiceSort(msg_map.keys())
142       for node_name in map_k:
143         ToStdout("  Node: %s, status: %s", node_name, msg_map[node_name])
144         for msg in nodes_hidden[node_name]:
145           ToStdout(msg)
146
147     ToStdout("OS: %s [global status: %s]", os_name, status)
148     if os_variants:
149       ToStdout("  Variants: [%s]" % utils.CommaJoin(os_variants))
150     _OutputPerNodeOSStatus(nodes_valid)
151     _OutputPerNodeOSStatus(nodes_bad)
152     ToStdout("")
153
154   return int(has_bad)
155
156
157 commands = {
158   'list': (
159     ListOS, ARGS_NONE, [NOHDR_OPT], "", "Lists all valid OSes on the master"),
160   'diagnose': (
161     DiagnoseOS, ARGS_NONE, [], "", "Diagnose all OSes"),
162   }
163
164 if __name__ == '__main__':
165   sys.exit(GenericMain(commands))