diff --git a/lib/client/gnt_node.py b/lib/client/gnt_node.py
index 55bbdf4b9283cf5d1e625f1eb3d55e78cab79659..1ac4f5acd85b74cdad36bb796c33b87a7fb5f04c 100644
--- a/lib/client/gnt_node.py
+++ b/lib/client/gnt_node.py
@@ -34,6 +34,7 @@ from ganeti import utils
 from ganeti import constants
 from ganeti import errors
 from ganeti import netutils
+from cStringIO import StringIO
 
 
 #: default list of field for L{ListNodes}
@@ -388,11 +389,13 @@ def ShowNodeConfig(opts, args):
   result = cl.QueryNodes(fields=["name", "pip", "sip",
                                  "pinst_list", "sinst_list",
                                  "master_candidate", "drained", "offline",
-                                 "master_capable", "vm_capable", "powered"],
+                                 "master_capable", "vm_capable", "powered",
+                                 "ndparams", "custom_ndparams"],
                          names=args, use_locking=False)
 
-  for (name, primary_ip, secondary_ip, pinst, sinst,
-       is_mc, drained, offline, master_capable, vm_capable, powered) in result:
+  for (name, primary_ip, secondary_ip, pinst, sinst, is_mc, drained, offline,
+       master_capable, vm_capable, powered, ndparams,
+       ndparams_custom) in result:
     ToStdout("Node name: %s", name)
     ToStdout("  primary ip: %s", primary_ip)
     ToStdout("  secondary ip: %s", secondary_ip)
@@ -416,6 +419,10 @@ def ShowNodeConfig(opts, args):
           ToStdout("    - %s", iname)
       else:
         ToStdout("  secondary for no instances")
+    ToStdout("  node parameters:")
+    buf = StringIO()
+    FormatParameterDict(buf, ndparams_custom, ndparams, level=2)
+    ToStdout(buf.getvalue().rstrip("\n"))
 
   return 0
 
diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index 97234d8eff13a036b8c88a2f873ce9d5a0a5583a..e989b2316f7927252bae43d732815c65d03c3e46 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -3595,7 +3595,7 @@ class _NodeQuery(_QueryBase):
     return query.NodeQueryData([all_info[name] for name in nodenames],
                                live_data, lu.cfg.GetMasterNode(),
                                node_to_primary, node_to_secondary, groups,
-                               oob_support)
+                               oob_support, lu.cfg.GetClusterInfo())
 
 
 class LUQueryNodes(NoHooksLU):
diff --git a/lib/query.py b/lib/query.py
index 55dc63f8e2be71d0059c995b078cf629071404c4..25263ce41eceb86203426ce93b9e1a435dab688a 100644
--- a/lib/query.py
+++ b/lib/query.py
@@ -358,7 +358,7 @@ class NodeQueryData:
 
   """
   def __init__(self, nodes, live_data, master_name, node_to_primary,
-               node_to_secondary, groups, oob_support):
+               node_to_secondary, groups, oob_support, cluster):
     """Initializes this class.
 
     """
@@ -369,6 +369,7 @@ class NodeQueryData:
     self.node_to_secondary = node_to_secondary
     self.groups = groups
     self.oob_support = oob_support
+    self.cluster = cluster
 
     # Used for individual rows
     self.curlive_data = None
@@ -415,19 +416,40 @@ _NODE_LIVE_FIELDS = {
   }
 
 
-def _GetNodeGroup(ctx, node):
+def _GetGroup(cb):
+  """Build function for calling another function with an node group.
+
+  @param cb: The callback to be called with the nodegroup
+
+  """
+  def fn(ctx, node):
+    """Get group data for a node.
+
+    @type ctx: L{NodeQueryData}
+    @type inst: L{objects.Node}
+    @param inst: Node object
+
+    """
+    ng = ctx.groups.get(node.group, None)
+    if ng is None:
+      # Nodes always have a group, or the configuration is corrupt
+      return (constants.QRFS_UNAVAIL, None)
+
+    return cb(ctx, node, ng)
+
+  return fn
+
+
+def _GetNodeGroup(ctx, node, ng): # pylint: disable-msg=W0613
   """Returns the name of a node's group.
 
   @type ctx: L{NodeQueryData}
   @type node: L{objects.Node}
   @param node: Node object
+  @type ng: L{objects.NodeGroup}
+  @param ng: The node group this node belongs to
 
   """
-  ng = ctx.groups.get(node.group, None)
-  if ng is None:
-    # Nodes always have a group, or the configuration is corrupt
-    return (constants.QRFS_UNAVAIL, None)
-
   return (constants.QRFS_NORMAL, ng.name)
 
 
@@ -445,6 +467,19 @@ def _GetNodePower(ctx, node):
   return (constants.QRFS_UNAVAIL, None)
 
 
+def _GetNdParams(ctx, node, ng):
+  """Returns the ndparams for this node.
+
+  @type ctx: L{NodeQueryData}
+  @type node: L{objects.Node}
+  @param node: Node object
+  @type ng: L{objects.NodeGroup}
+  @param ng: The node group this node belongs to
+
+  """
+  return (constants.QRFS_NORMAL, ctx.cluster.SimpleFillND(ng.FillND(node)))
+
+
 def _GetLiveNodeField(field, kind, ctx, node):
   """Gets the value of a "live" field from L{NodeQueryData}.
 
@@ -496,11 +531,16 @@ def _BuildNodeFields():
     (_MakeField("role", "Role", constants.QFT_TEXT), NQ_CONFIG,
      lambda ctx, node: (constants.QRFS_NORMAL,
                         _GetNodeRole(node, ctx.master_name))),
-    (_MakeField("group", "Group", constants.QFT_TEXT), NQ_GROUP, _GetNodeGroup),
+    (_MakeField("group", "Group", constants.QFT_TEXT), NQ_GROUP,
+     _GetGroup(_GetNodeGroup)),
     (_MakeField("group.uuid", "GroupUUID", constants.QFT_TEXT),
      NQ_CONFIG, lambda ctx, node: (constants.QRFS_NORMAL, node.group)),
     (_MakeField("powered", "Powered", constants.QFT_BOOL), NQ_OOB,
       _GetNodePower),
+    (_MakeField("ndparams", "NodeParameters", constants.QFT_OTHER), NQ_GROUP,
+      _GetGroup(_GetNdParams)),
+    (_MakeField("custom_ndparams", "CustomNodeParameters", constants.QFT_OTHER),
+      NQ_GROUP, lambda ctx, node: (constants.QRFS_NORMAL, node.ndparams)),
     ]
 
   def _GetLength(getter):
diff --git a/test/ganeti.query_unittest.py b/test/ganeti.query_unittest.py
index cb296a319d6e67826722db306fdc86d0a9dccf3b..baace67c1734793a7b7ea20a021dda247c5123a0 100755
--- a/test/ganeti.query_unittest.py
+++ b/test/ganeti.query_unittest.py
@@ -289,7 +289,8 @@ class TestNodeQuery(unittest.TestCase):
       objects.Node(name="node3", drained=False),
       ]
     for live_data in [None, dict.fromkeys([node.name for node in nodes], {})]:
-      nqd = query.NodeQueryData(nodes, live_data, None, None, None, None, None)
+      nqd = query.NodeQueryData(nodes, live_data, None, None, None, None, None,
+                                None)
 
       q = self._Create(["name", "drained"])
       self.assertEqual(q.RequestedData(), set([query.NQ_CONFIG]))
@@ -315,6 +316,17 @@ class TestNodeQuery(unittest.TestCase):
                      set([query.NQ_CONFIG, query.NQ_LIVE, query.NQ_INST,
                           query.NQ_GROUP, query.NQ_OOB]))
 
+    cluster = objects.Cluster(cluster_name="testcluster",
+      hvparams=constants.HVC_DEFAULTS,
+      beparams={
+        constants.PP_DEFAULT: constants.BEC_DEFAULTS,
+        },
+      nicparams={
+        constants.PP_DEFAULT: constants.NICC_DEFAULTS,
+        },
+      ndparams=constants.NDC_DEFAULTS,
+        )
+
     node_names = ["node%s" % i for i in range(20)]
     master_name = node_names[3]
     nodes = [
@@ -327,6 +339,7 @@ class TestNodeQuery(unittest.TestCase):
                    drained=False,
                    vm_capable=False,
                    master_capable=False,
+                   ndparams={},
                    group="default",
                    ctime=1290006900,
                    mtime=1290006913,
@@ -373,7 +386,7 @@ class TestNodeQuery(unittest.TestCase):
 
     ng_uuid = "492b4b74-8670-478a-b98d-4c53a76238e6"
     groups = {
-      ng_uuid: objects.NodeGroup(name="ng1", uuid=ng_uuid),
+      ng_uuid: objects.NodeGroup(name="ng1", uuid=ng_uuid, ndparams={}),
       }
 
     oob_support = dict((name, False) for name in node_names)
@@ -382,7 +395,7 @@ class TestNodeQuery(unittest.TestCase):
 
     nqd = query.NodeQueryData(nodes, live_data, master_name,
                               node_to_primary, node_to_secondary, groups,
-                              oob_support)
+                              oob_support, cluster)
     result = q.Query(nqd)
     self.assert_(compat.all(len(row) == len(selected) for row in result))
     self.assertEqual([row[field_index["name"]] for row in result],
@@ -445,7 +458,7 @@ class TestNodeQuery(unittest.TestCase):
     live_data = dict.fromkeys([node.name for node in nodes], {})
 
     # No data
-    nqd = query.NodeQueryData(None, None, None, None, None, None, None)
+    nqd = query.NodeQueryData(None, None, None, None, None, None, None, None)
     self.assertEqual(query._GetLiveNodeField("hello", constants.QFT_NUMBER,
                                              nqd, nodes[0]),
                      (constants.QRFS_NODATA, None))