# 02110-1301, USA.
+# pylint: disable-msg=W0401,W0614
+# W0401: Wildcard import ganeti.cli
+# W0614: Unused import %s from wildcard import (since we need cli)
+
import sys
-from optparse import make_option
from ganeti.cli import *
from ganeti import opcodes
-from ganeti import logger
-from ganeti import objects
from ganeti import utils
-from ganeti import errors
+from ganeti import constants
+
def ListOS(opts, args):
- """List the OSes existing on this node.
+ """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
"""
- op = opcodes.OpDiagnoseOS()
+ op = opcodes.OpDiagnoseOS(output_fields=["name", "valid"], names=[])
result = SubmitOpCode(op)
if not result:
- logger.ToStdout("Can't get the OS list")
+ ToStderr("Can't get the OS list")
return 1
- # filter non-valid OS-es
- oses = {}
- for node_name in result:
- oses[node_name] = [obj for obj in result[node_name]
- if isinstance(obj, objects.OS)]
-
- # Get intersection of all OSes
- fnode = oses.keys()[0]
- os_set = set([os_inst.name for os_inst in oses[fnode]])
- del oses[fnode]
- for node in oses:
- os_set &= set([os_inst.name for os_inst in oses[node]])
-
if not opts.no_headers:
headers = {"name": "Name"}
else:
headers = None
data = GenerateTable(separator=None, headers=headers, fields=["name"],
- data=[[os] for os in os_set])
+ data=[[row[0]] for row in result if row[1]],
+ units=None)
for line in data:
- logger.ToStdout(line)
+ ToStdout(line)
return 0
-def _DiagnoseOSValid(obj):
- """Verify whether an OS diagnose object represents a valid OS
-
- Args:
- obj: an diagnostic object as returned by OpDiagnoseOS
-
- Returns:
- bool: OS validity status
- """
-
- if isinstance(obj, objects.OS):
- return True
- elif isinstance(obj, errors.InvalidOS):
- return False
- else:
- raise errors.ProgrammerError('unknown OS diagnose type')
-def _DiagnoseOSStatus(obj):
- """Generate a status message for an OS diagnose object.
+def _OsStatus(status, diagnose):
+ """Beautifier function for OS status.
- Args:
- obj: an diagnostic object as returned by OpDiagnoseOS
+ @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
- Returns:
- string: a description of the OS status
"""
-
- if _DiagnoseOSValid(obj):
- return "valid (path: %s)" % obj.path
+ if status:
+ return "valid"
else:
- return "%s (path: %s)" % (obj.args[2], obj.args[1])
+ return "invalid - %s" % diagnose
def DiagnoseOS(opts, args):
"""Analyse all OSes on this 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
+
"""
- op = opcodes.OpDiagnoseOS()
+ op = opcodes.OpDiagnoseOS(output_fields=["name", "valid", "node_status"],
+ names=[])
result = SubmitOpCode(op)
if not result:
- logger.ToStdout("Can't get the OS list")
+ ToStderr("Can't get the OS list")
return 1
- format = "%-*s %-*s %s"
-
- node_data = result
- all_os = {}
- for node_name in node_data:
- nr = node_data[node_name]
- if nr:
- for obj in nr:
- if isinstance(obj, objects.OS):
- os_name = obj.name
- else:
- os_name = obj.args[0]
- if os_name not in all_os:
- all_os[os_name] = {}
- if node_name not in all_os[os_name]:
- all_os[os_name][node_name] = []
- all_os[os_name][node_name].append(obj)
-
- max_name = len('Name')
- if all_os:
- max_name = max(max_name, max([len(name) for name in all_os]))
+ has_bad = False
- max_node = len('Status/Node')
- max_node = max(max_node, max([len(name) for name in node_data]))
-
- logger.ToStdout(format % (max_name, 'Name', max_node, 'Status/Node',
- 'Details'))
-
- for os_name in all_os:
+ for os_name, os_valid, node_data in result:
nodes_valid = {}
nodes_bad = {}
- for node_name in node_data:
- if node_name in all_os[os_name]:
- first_os = all_os[os_name][node_name].pop(0)
- first_os_status = _DiagnoseOSStatus(first_os)
- if _DiagnoseOSValid(first_os):
- nodes_valid[node_name] = first_os_status
+ 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
+ first_os_path, first_os_status, first_os_msg = node_info.pop(0)
+ first_os_msg = ("%s (path: %s)" % (_OsStatus(first_os_status,
+ first_os_msg),
+ first_os_path))
+ if first_os_status:
+ nodes_valid[node_name] = first_os_msg
else:
- nodes_bad[node_name] = first_os_status
+ nodes_bad[node_name] = first_os_msg
+ for hpath, hstatus, hmsg in node_info:
+ nodes_hidden[node_name].append(" [hidden] path: %s, status: %s" %
+ (hpath, _OsStatus(hstatus, hmsg)))
else:
nodes_bad[node_name] = "OS not found"
status = "valid"
elif not nodes_valid and nodes_bad:
status = "invalid"
+ has_bad = True
else:
status = "partial valid"
+ has_bad = True
- def _OutputNodeHiddenOSStatus(dobj_list):
- for dobj in dobj_list:
- logger.ToStdout(format % (max_name, "", max_node, "",
- "[hidden] %s" %
- _DiagnoseOSStatus(dobj)))
-
- def _OutputPerNodeOSStatus(status_map):
- map_k = utils.NiceSort(status_map.keys())
+ def _OutputPerNodeOSStatus(msg_map):
+ map_k = utils.NiceSort(msg_map.keys())
for node_name in map_k:
- logger.ToStdout(format % (max_name, "", max_node,
- node_name, status_map[node_name]))
- if node_name in all_os[os_name]:
- _OutputNodeHiddenOSStatus(all_os[os_name][node_name])
+ ToStdout(" Node: %s, status: %s", node_name, msg_map[node_name])
+ for msg in nodes_hidden[node_name]:
+ ToStdout(msg)
- logger.ToStdout(format % (max_name, os_name, max_node, status, ""))
+ ToStdout("OS: %s [global status: %s]", os_name, status)
_OutputPerNodeOSStatus(nodes_valid)
_OutputPerNodeOSStatus(nodes_bad)
+ ToStdout("")
+
+ return int(has_bad)
commands = {