Commit bad78e66 authored by Iustin Pop's avatar Iustin Pop
Browse files

LUDiagnoseOS: add more fields, cleanup

This patch exports all the way from backend a new field ‘api_version’
which holds the list of support API versions, and exposes the (already
computed) ‘parameters’ field.

The patch also reworks (again) the field calculation in its Exec()
method. All callers of LUDiagnoseOS pass in the 'valid' and 'variants'
parameters, thus having the special casing of whether to compute or not
the validity seems overkill. We move to a model where we always compute
these across-nodes arguments, in order to simplify the code, and we also
change the parameters set to be intersection of all node's values (which
means a change in description will drop the parameter from the list of

Additionally, we update scripts/gnt-os, which was broken for multi-dir
OSes since the introduction of variants…
Signed-off-by: default avatarIustin Pop <>
Reviewed-by: default avatarGuido Trotter <>
parent 535b49cb
......@@ -1774,14 +1774,16 @@ def DiagnoseOS(top_dirs=None):
search (if not given defaults to
@rtype: list of L{objects.OS}
@return: a list of tuples (name, path, status, diagnose, variants)
for all (potential) OSes under all search paths, where:
@return: a list of tuples (name, path, status, diagnose, variants,
parameters, api_version) for all (potential) OSes under all
search paths, where:
- name is the (potential) OS name
- path is the full path to the OS
- status True/False is the validity of the OS
- diagnose is the error message for an invalid OS, otherwise empty
- variants is a list of supported OS variants, if any
- parameters is a list of (name, help) parameters, if any
- api_version is a list of support OS API versions
if top_dirs is None:
......@@ -1802,10 +1804,12 @@ def DiagnoseOS(top_dirs=None):
diagnose = ""
variants = os_inst.supported_variants
parameters = os_inst.supported_parameters
api_versions = os_inst.api_versions
diagnose = os_inst
variants = parameters = []
result.append((name, os_path, status, diagnose, variants, parameters))
variants = parameters = api_versions = []
result.append((name, os_path, status, diagnose, variants,
parameters, api_versions))
return result
......@@ -2738,9 +2738,8 @@ class LUDiagnoseOS(NoHooksLU):
_OP_REQP = ["output_fields", "names"]
REQ_BGL = False
_FIELDS_STATIC = utils.FieldSet()
_FIELDS_DYNAMIC = utils.FieldSet("name", "valid", "node_status", "variants")
# Fields that need calculation of global os validity
_FIELDS_NEEDVALID = frozenset(["valid", "variants"])
_FIELDS_DYNAMIC = utils.FieldSet("name", "valid", "node_status", "variants",
"parameters", "api_versions")
def ExpandNames(self):
if self.op.names:
......@@ -2772,7 +2771,7 @@ class LUDiagnoseOS(NoHooksLU):
@rtype: dict
@return: a dictionary with osnames as keys and as value another
map, with nodes as keys and tuples of (path, status, diagnose,
variants, parameters) as values, eg::
variants, parameters, api_versions) as values, eg::
{"debian-etch": {"node1": [(/usr/lib/..., True, "", [], []),
(/srv/..., False, "invalid api")],
......@@ -2789,15 +2788,18 @@ class LUDiagnoseOS(NoHooksLU):
for node_name, nr in rlist.items():
if nr.fail_msg or not nr.payload:
for name, path, status, diagnose, variants, params in nr.payload:
for (name, path, status, diagnose, variants,
params, api_versions) in nr.payload:
if name not in all_os:
# build a list of nodes for this os containing empty lists
# for each node in node_list
all_os[name] = {}
for nname in good_nodes:
all_os[name][nname] = []
# convert params from [name, help] to (name, help)
params = [tuple(v) for v in params]
all_os[name][node_name].append((path, status, diagnose,
variants, params))
variants, params, api_versions))
return all_os
def Exec(self, feedback_fn):
......@@ -2808,25 +2810,25 @@ class LUDiagnoseOS(NoHooksLU):
node_data = self.rpc.call_os_diagnose(valid_nodes)
pol = self._DiagnoseByOS(node_data)
output = []
calc_valid = self._FIELDS_NEEDVALID.intersection(self.op.output_fields)
calc_variants = "variants" in self.op.output_fields
for os_name, os_data in pol.items():
row = []
if calc_valid:
valid = True
variants = None
for osl in os_data.values():
valid = bool(valid and osl and osl[0][1])
if not valid:
variants = set()
if calc_variants:
node_variants = osl[0][3]
if variants is None:
variants = set(node_variants)
valid = True
(variants, params, api_versions) = null_state = (set(), set(), set())
for idx, osl in enumerate(os_data.values()):
valid = bool(valid and osl and osl[0][1])
if not valid:
(variants, params, api_versions) = null_state
node_variants, node_params, node_api = osl[0][3:6]
if idx == 0: # first entry
variants = set(node_variants)
params = set(node_params)
api_versions = set(node_api)
else: # keep consistency
for field in self.op.output_fields:
if field == "name":
......@@ -2840,6 +2842,10 @@ class LUDiagnoseOS(NoHooksLU):
val[node_name] = nos_list
elif field == "variants":
val = list(variants)
elif field == "parameters":
val = list(params)
elif field == "api_versions":
val = list(api_versions)
raise errors.ParameterError(field)
......@@ -114,17 +114,18 @@ def DiagnoseOS(opts, args):
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,
first_os_variants, _) = node_info.pop(0)
first_os_variants, _, first_os_api) = node_info.pop(0)
if not first_os_variants:
first_os_variants = []
first_os_msg = ("%s (path: %s) [variants: %s]" %
first_os_msg = ("%s (path: %s) [variants: %s] [api: %s]" %
(_OsStatus(first_os_status, first_os_msg),
first_os_path, utils.CommaJoin(first_os_variants)))
first_os_path, utils.CommaJoin(first_os_variants),
if first_os_status:
nodes_valid[node_name] = first_os_msg
nodes_bad[node_name] = first_os_msg
for hpath, hstatus, hmsg in node_info:
for hpath, hstatus, hmsg, _, _, _ in node_info:
nodes_hidden[node_name].append(" [hidden] path: %s, status: %s" %
(hpath, _OsStatus(hstatus, hmsg)))
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment