Update scripts to pass 'opts' to SubmitOpCode
[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 """OS scripts related commands"""
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)
27 # C0103: Invalid name gnt-os
28
29 import sys
30
31 from ganeti.cli import *
32 from ganeti import opcodes
33 from ganeti import utils
34
35
36 def ListOS(opts, args):
37   """List the valid OSes in the cluster.
38
39   @param opts: the command line options selected by the user
40   @type args: list
41   @param args: should be an empty list
42   @rtype: int
43   @return: the desired exit code
44
45   """
46   op = opcodes.OpDiagnoseOS(output_fields=["name", "valid", "variants"],
47                             names=[])
48   result = SubmitOpCode(op, opts=opts)
49
50   if not result:
51     ToStderr("Can't get the OS list")
52     return 1
53
54   if not opts.no_headers:
55     headers = {"name": "Name"}
56   else:
57     headers = None
58
59   os_names = []
60   for (name, valid, variants) in result:
61     if valid:
62       os_names.extend([[n] for n in CalculateOSNames(name, variants)])
63
64   data = GenerateTable(separator=None, headers=headers, fields=["name"],
65                        data=os_names, units=None)
66
67   for line in data:
68     ToStdout(line)
69
70   return 0
71
72
73 def _OsStatus(status, diagnose):
74   """Beautifier function for OS status.
75
76   @type status: boolean
77   @param status: is the OS valid
78   @type diagnose: string
79   @param diagnose: the error message for invalid OSes
80   @rtype: string
81   @return: a formatted status
82
83   """
84   if status:
85     return "valid"
86   else:
87     return "invalid - %s" % diagnose
88
89 def DiagnoseOS(opts, args):
90   """Analyse all OSes on this cluster.
91
92   @param opts: the command line options selected by the user
93   @type args: list
94   @param args: should be an empty list
95   @rtype: int
96   @return: the desired exit code
97
98   """
99   op = opcodes.OpDiagnoseOS(output_fields=["name", "valid", "variants",
100                                            "node_status"], names=[])
101   result = SubmitOpCode(op, opts=opts)
102
103   if not result:
104     ToStderr("Can't get the OS list")
105     return 1
106
107   has_bad = False
108
109   for os_name, _, os_variants, node_data in result:
110     nodes_valid = {}
111     nodes_bad = {}
112     nodes_hidden = {}
113     for node_name, node_info in node_data.iteritems():
114       nodes_hidden[node_name] = []
115       if node_info: # at least one entry in the per-node list
116         (first_os_path, first_os_status, first_os_msg,
117          first_os_variants) = node_info.pop(0)
118         if not first_os_variants:
119           first_os_variants = []
120         first_os_msg = ("%s (path: %s) [variants: %s]" %
121                         (_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
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)))
130       else:
131         nodes_bad[node_name] = "OS not found"
132
133     if nodes_valid and not nodes_bad:
134       status = "valid"
135     elif not nodes_valid and nodes_bad:
136       status = "invalid"
137       has_bad = True
138     else:
139       status = "partial valid"
140       has_bad = True
141
142     def _OutputPerNodeOSStatus(msg_map):
143       map_k = utils.NiceSort(msg_map.keys())
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)
148
149     ToStdout("OS: %s [global status: %s]", os_name, status)
150     if os_variants:
151       ToStdout("  Variants: [%s]" % utils.CommaJoin(os_variants))
152     _OutputPerNodeOSStatus(nodes_valid)
153     _OutputPerNodeOSStatus(nodes_bad)
154     ToStdout("")
155
156   return int(has_bad)
157
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"),
164   }
165
166 if __name__ == '__main__':
167   sys.exit(GenericMain(commands))