diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index f8654d0e5aa662d66657eeab49e47c0f201d9bd7..dbeef5d0542fd6e6a72edb2b10916158d2724874 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -1163,7 +1163,7 @@ class LUDiagnoseOS(NoHooksLU):
   """Logical unit for OS diagnose/query.
 
   """
-  _OP_REQP = []
+  _OP_REQP = ["output_fields", "names"]
 
   def CheckPrereq(self):
     """Check prerequisites.
@@ -1171,7 +1171,44 @@ class LUDiagnoseOS(NoHooksLU):
     This always succeeds, since this is a pure query LU.
 
     """
-    return
+    if self.op.names:
+      raise errors.OpPrereqError("Selective OS query not supported")
+
+    self.dynamic_fields = frozenset(["name", "valid", "node_status"])
+    _CheckOutputFields(static=[],
+                       dynamic=self.dynamic_fields,
+                       selected=self.op.output_fields)
+
+  @staticmethod
+  def _DiagnoseByOS(node_list, rlist):
+    """Remaps a per-node return list into an a per-os per-node dictionary
+
+      Args:
+        node_list: a list with the names of all nodes
+        rlist: a map with node names as keys and OS objects as values
+
+      Returns:
+        map: a map with osnames as keys and as value another map, with
+             nodes as
+             keys and list of OS objects as values
+             e.g. {"debian-etch": {"node1": [<object>,...],
+                                   "node2": [<object>,]}
+                  }
+
+    """
+    all_os = {}
+    for node_name, nr in rlist.iteritems():
+      if not nr:
+        continue
+      for os in nr:
+        if os.name not in all_os:
+          # build a list of nodes for this os containing empty lists
+          # for each node in node_list
+          all_os[os.name] = {}
+          for nname in node_list:
+            all_os[os.name][nname] = []
+        all_os[os.name][node_name].append(os)
+    return all_os
 
   def Exec(self, feedback_fn):
     """Compute the list of OSes.
@@ -1181,7 +1218,25 @@ class LUDiagnoseOS(NoHooksLU):
     node_data = rpc.call_os_diagnose(node_list)
     if node_data == False:
       raise errors.OpExecError("Can't gather the list of OSes")
-    return node_data
+    pol = self._DiagnoseByOS(node_list, node_data)
+    output = []
+    for os_name, os_data in pol.iteritems():
+      row = []
+      for field in self.op.output_fields:
+        if field == "name":
+          val = os_name
+        elif field == "valid":
+          val = utils.all([osl and osl[0] for osl in os_data.values()])
+        elif field == "node_status":
+          val = {}
+          for node_name, nos_list in os_data.iteritems():
+            val[node_name] = [(v.status, v.path) for v in nos_list]
+        else:
+          raise errors.ParameterError(field)
+        row.append(val)
+      output.append(row)
+
+    return output
 
 
 class LURemoveNode(LogicalUnit):
diff --git a/lib/opcodes.py b/lib/opcodes.py
index a5d8dedfea446d4089958d7610690a1d877c1207..3d7a3b01e651ce4063ae279c5977288bccad565d 100644
--- a/lib/opcodes.py
+++ b/lib/opcodes.py
@@ -379,7 +379,7 @@ class OpSetInstanceParams(OpCode):
 class OpDiagnoseOS(OpCode):
   """Compute the list of guest operating systems."""
   OP_ID = "OP_OS_DIAGNOSE"
-  __slots__ = []
+  __slots__ = ["output_fields", "names"]
 
 
 # Exports opcodes
diff --git a/scripts/gnt-os b/scripts/gnt-os
index 5918769eb55925f6ea6657a61679406f96cb16d0..e4041c728d9b2d9d203aca30edcaa2ffbae3ddb3 100755
--- a/scripts/gnt-os
+++ b/scripts/gnt-os
@@ -28,64 +28,27 @@ from ganeti import logger
 from ganeti import objects
 from ganeti import utils
 from ganeti import errors
-
-
-def _DiagnoseByOS(rlist):
-  """Remap an OpDiagnoseOS() return list into an a per-os per-node dictionary
-
-    Args:
-      rlist: a map with nodes as keys and diagnoseobjects as values
-
-    Returns:
-      map: a map with osnames as keys and as value another map, with nodes as
-           keys and diagnoseobjects as values
-           e.g. {"debian-etch": {"node1": <object>, "node2": <object>}}
-
-  """
-  all_os = {}
-  for node_name, nr in rlist.iteritems():
-    if not nr:
-      continue
-    for os in nr:
-      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(os)
-
-  return all_os
+from ganeti import constants
 
 
 def ListOS(opts, args):
   """List the OSes existing on this node.
 
   """
-  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")
     return 1
 
-  node_data = result
-  num_nodes = len(node_data)
-  all_os = _DiagnoseByOS(node_data)
-
-  valid_os = []
-  for os_name, os_node_data in all_os.iteritems():
-    if len(os_node_data) != num_nodes:
-      continue
-
-    if utils.all(os_node_data.values(), lambda l: l[0]):
-      valid_os.append(os_name)
-
   if not opts.no_headers:
     headers = {"name": "Name"}
   else:
     headers = None
 
   data = GenerateTable(separator=None, headers=headers, fields=["name"],
-                       data=[[os] for os in valid_os])
+                       data=[[row[0]] for row in result if row[1]])
 
   for line in data:
     logger.ToStdout(line)
@@ -97,30 +60,33 @@ def DiagnoseOS(opts, args):
   """Analyse all OSes on this cluster.
 
   """
-  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")
     return 1
 
-  node_data = result
-  all_os = _DiagnoseByOS(node_data)
-
   has_bad = False
 
-  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)
+    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_status, first_os_path = node_info.pop(0)
         first_os_msg = ("%s (path: %s)" %
-                        (first_os.status, first_os.path))
-        if first_os:
+                        (first_os_status, first_os_path))
+        if first_os_status == constants.OS_VALID_STATUS:
           nodes_valid[node_name] = first_os_msg
         else:
           nodes_bad[node_name] = first_os_msg
+        for hstatus, hpath in node_info:
+          nodes_hidden[node_name].append("    [hidden] path: %s, status: %s" %
+                                         (hpath, hstatus))
       else:
         nodes_bad[node_name] = "OS not found"
 
@@ -133,18 +99,13 @@ def DiagnoseOS(opts, args):
       status = "partial valid"
       has_bad = True
 
-    def _OutputNodeHiddenOSStatus(dobj_list):
-      for dobj in dobj_list:
-        logger.ToStdout("    [hidden] path: %s, status: %s" %
-                        (dobj.path, dobj.status))
-
     def _OutputPerNodeOSStatus(msg_map):
       map_k = utils.NiceSort(msg_map.keys())
       for node_name in map_k:
         logger.ToStdout("  Node: %s, status: %s" %
                         (node_name, msg_map[node_name]))
-        if node_name in all_os[os_name]:
-          _OutputNodeHiddenOSStatus(all_os[os_name][node_name])
+        for msg in nodes_hidden[node_name]:
+          logger.ToStdout(msg)
 
     logger.ToStdout("OS: %s [global status: %s]" % (os_name, status))
     _OutputPerNodeOSStatus(nodes_valid)
diff --git a/tools/burnin b/tools/burnin
index 590cd15e102ba88a10552f4c4c510a7c949c56c3..0ecf11fd22b649888a6c02cd6e1ab6fa0c293c96 100755
--- a/tools/burnin
+++ b/tools/burnin
@@ -167,22 +167,15 @@ class Burner(object):
       sys.exit(err_code)
     self.nodes = [data[0] for data in result]
 
-    result = self.ExecOp(opcodes.OpDiagnoseOS())
+    result = self.ExecOp(opcodes.OpDiagnoseOS(output_fields=["name", "valid"],
+                                              names=[]))
 
     if not result:
       Log("Can't get the OS list")
       sys.exit(1)
 
     # filter non-valid OS-es
-    oses = {}
-    for node_name in result:
-      oses[node_name] = [obj for obj in result[node_name] if obj]
-
-    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]])
+    os_set = [val[0] for val in result if val[1]]
 
     if self.opts.os not in os_set:
       Log("OS '%s' not found" % self.opts.os)