commit 137161c9012de37aecd28a38667bfa200c9c1edb
Author: Michael Hanselmann <hansmi@google.com>
Date:   Tue Jul 24 13:29:43 2007 +0000

    Use generic function to output tables.
    
    Reviewed-by: iustinp

diff --git a/lib/cli.py b/lib/cli.py
index 5508fbd..45644db 100644
--- a/lib/cli.py
+++ b/lib/cli.py
@@ -37,7 +37,7 @@ from optparse import (OptionParser, make_option, TitledHelpFormatter,
                       Option, OptionValueError, SUPPRESS_HELP)
 
 __all__ = ["DEBUG_OPT", "NOHDR_OPT", "SEP_OPT", "GenericMain", "SubmitOpCode",
-           "cli_option",
+           "cli_option", "OutputTable",
            "ARGS_NONE", "ARGS_FIXED", "ARGS_ATLEAST", "ARGS_ANY", "ARGS_ONE",
            "USEUNITS_OPT", "FIELDS_OPT"]
 
@@ -49,7 +49,7 @@ NOHDR_OPT = make_option("--no-headers", default=False,
                         action="store_true", dest="no_headers",
                         help="Don't display column headers")
 
-SEP_OPT = make_option("--separator", default=" ",
+SEP_OPT = make_option("--separator", default=None,
                       action="store", dest="separator",
                       help="Separator between output fields"
                       " (defaults to one space)")
@@ -274,3 +274,67 @@ def GenericMain(commands):
     utils.LockCleanup()
 
   return result
+
+
+def OutputTable(headers, fields, separator, data,
+                numfields=None, unitfields=None):
+  """Prints a table with headers and different fields.
+
+  Args:
+    headers: Dict of header titles or None if no headers should be shown
+    fields: List of fields to show
+    separator: String used to separate fields or None for spaces
+    data: Data to be printed
+    numfields: List of fields to be aligned to right
+    unitfields: List of fields to be formatted as units
+
+  """
+  if numfields is None:
+    numfields = []
+  if unitfields is None:
+    unitfields = []
+
+  format_fields = []
+  for field in fields:
+    if separator is not None:
+      format_fields.append("%s")
+    elif field in numfields:
+      format_fields.append("%*s")
+    else:
+      format_fields.append("%-*s")
+
+  if separator is None:
+    mlens = [0 for name in fields]
+    format = ' '.join(format_fields)
+  else:
+    format = separator.replace("%", "%%").join(format_fields)
+
+  for row in data:
+    for idx, val in enumerate(row):
+      if fields[idx] in unitfields:
+        try:
+          val = int(val)
+        except ValueError:
+          pass
+        else:
+          val = row[idx] = utils.FormatUnit(val)
+      if separator is None:
+        mlens[idx] = max(mlens[idx], len(val))
+
+  if headers:
+    args = []
+    for idx, name in enumerate(fields):
+      hdr = headers[name]
+      if separator is None:
+        mlens[idx] = max(mlens[idx], len(hdr))
+        args.append(mlens[idx])
+      args.append(hdr)
+    logger.ToStdout(format % tuple(args))
+
+  for line in data:
+    args = []
+    for idx in xrange(len(fields)):
+      if separator is None:
+        args.append(mlens[idx])
+      args.append(line[idx])
+    logger.ToStdout(format % tuple(args))
diff --git a/scripts/gnt-instance b/scripts/gnt-instance
index 45f6795..5ef3966 100755
--- a/scripts/gnt-instance
+++ b/scripts/gnt-instance
@@ -45,52 +45,26 @@ def ListInstances(opts, args):
   op = opcodes.OpQueryInstances(output_fields=selected_fields)
   output = SubmitOpCode(op)
 
-  mlens = [0 for name in selected_fields]
+  if not opts.no_headers:
+    headers = {"name": "Instance", "os": "OS", "pnode": "Primary_node",
+               "snodes": "Secondary_Nodes", "admin_state": "Autostart",
+               "oper_state": "Status", "admin_ram": "Configured_memory",
+               "oper_ram": "Memory", "disk_template": "Disk_template",
+               "ip": "IP Address", "mac": "MAC Address",
+               "bridge": "Bridge"}
+  else:
+    headers = None
 
-  format_fields = []
-  unitformat_fields = ("admin_ram", "oper_ram")
-  for field in selected_fields:
-    if field in ("admin_ram", "oper_ram"):
-      format_fields.append("%*s")
-    else:
-      format_fields.append("%-*s")
-  separator = opts.separator
-  if "%" in separator:
-    separator = separator.replace("%", "%%")
-  format = separator.join(format_fields)
-
-  for row in output:
-    for idx, val in enumerate(row):
-      if opts.human_readable and selected_fields[idx] in unitformat_fields:
-        try:
-          val = int(val)
-        except ValueError:
-          pass
-        else:
-          val = row[idx] = utils.FormatUnit(val)
-      mlens[idx] = max(mlens[idx], len(val))
+  if opts.human_readable:
+    unitfields = ["admin_ram", "oper_ram"]
+  else:
+    unitfields = None
 
-  if not opts.no_headers:
-    header_list = {"name": "Instance", "os": "OS", "pnode": "Primary_node",
-                   "snodes": "Secondary_Nodes", "admin_state": "Autostart",
-                   "oper_state": "Status", "admin_ram": "Configured_memory",
-                   "oper_ram": "Memory", "disk_template": "Disk_template",
-                   "ip": "IP Address", "mac": "MAC Address",
-                   "bridge": "Bridge"}
-    args = []
-    for idx, name in enumerate(selected_fields):
-      hdr = header_list[name]
-      mlens[idx] = max(mlens[idx], len(hdr))
-      args.append(mlens[idx])
-      args.append(hdr)
-    logger.ToStdout(format % tuple(args))
-
-  for line in output:
-    args = []
-    for idx in range(len(selected_fields)):
-      args.append(mlens[idx])
-      args.append(line[idx])
-    logger.ToStdout(format % tuple(args))
+  numfields = ["admin_ram", "oper_ram"]
+
+  OutputTable(separator=opts.separator, headers=headers,
+      fields=selected_fields, unitfields=unitfields,
+      numfields=numfields, data=output)
 
   return 0
 
diff --git a/scripts/gnt-node b/scripts/gnt-node
index 7593f89..34e4214 100755
--- a/scripts/gnt-node
+++ b/scripts/gnt-node
@@ -48,51 +48,24 @@ def ListNodes(opts, args):
   op = opcodes.OpQueryNodes(output_fields=selected_fields)
   output = SubmitOpCode(op)
 
-  mlens = [0 for name in selected_fields]
-  format_fields = []
-  unitformat_fields = ("dtotal", "dfree", "mtotal", "mnode", "mfree")
-  for field in selected_fields:
-    if field in ("dtotal", "dfree", "mtotal", "mnode",
-                 "mfree", "pinst", "sinst"):
-      format_fields.append("%*s")
-    else:
-      format_fields.append("%-*s")
-
-  separator = opts.separator
-  if "%" in separator:
-    separator = separator.replace("%", "%%")
-  format = separator.join(format_fields)
-
-  for row in output:
-    for idx, val in enumerate(row):
-      if opts.human_readable and selected_fields[idx] in unitformat_fields:
-        try:
-          val = int(val)
-        except ValueError:
-          pass
-        else:
-          val = row[idx] = utils.FormatUnit(val)
-      mlens[idx] = max(mlens[idx], len(val))
-
   if not opts.no_headers:
-    header_list = {"name": "Node", "pinst": "Pinst", "sinst": "Sinst",
-                   "pip": "PrimaryIP", "sip": "SecondaryIP",
-                   "dtotal": "DTotal", "dfree": "DFree",
-                   "mtotal": "MTotal", "mnode": "MNode", "mfree": "MFree"}
-    args = []
-    for idx, name in enumerate(selected_fields):
-      hdr = header_list[name]
-      mlens[idx] = max(mlens[idx], len(hdr))
-      args.append(mlens[idx])
-      args.append(hdr)
-    logger.ToStdout(format % tuple(args))
-
-  for row in output:
-    args = []
-    for idx, val in enumerate(row):
-      args.append(mlens[idx])
-      args.append(val)
-    logger.ToStdout(format % tuple(args))
+    headers = {"name": "Node", "pinst": "Pinst", "sinst": "Sinst",
+               "pip": "PrimaryIP", "sip": "SecondaryIP",
+               "dtotal": "DTotal", "dfree": "DFree",
+               "mtotal": "MTotal", "mnode": "MNode", "mfree": "MFree"}
+  else:
+    headers = None
+
+  if opts.human_readable:
+    unitfields = ["dtotal", "dfree", "mtotal", "mnode", "mfree"]
+  else:
+    unitfields = None
+
+  numfields = ["dtotal", "dfree", "mtotal", "mnode", "mfree", "pinst", "sinst"]
+
+  OutputTable(separator=opts.separator, headers=headers,
+      fields=selected_fields, unitfields=unitfields,
+      numfields=numfields, data=output)
 
   return 0
 
@@ -143,49 +116,23 @@ def ListVolumes(opts, args):
   op = opcodes.OpQueryNodeVolumes(nodes=args, output_fields=selected_fields)
   output = SubmitOpCode(op)
 
-  mlens = [0 for name in selected_fields]
-  format_fields = []
-  unitformat_fields = ("size",)
-  for field in selected_fields:
-    if field in unitformat_fields:
-      format_fields.append("%*s")
-    else:
-      format_fields.append("%-*s")
-
-  separator = opts.separator
-  if "%" in separator:
-    separator = separator.replace("%", "%%")
-  format = separator.join(format_fields)
-
-  for row in output:
-    for idx, val in enumerate(row):
-      if opts.human_readable and selected_fields[idx] in unitformat_fields:
-        try:
-          val = int(val)
-        except ValueError:
-          pass
-        else:
-          val = row[idx] = utils.FormatUnit(val)
-      mlens[idx] = max(mlens[idx], len(val))
-
   if not opts.no_headers:
-    header_list = {"node": "Node", "phys": "PhysDev",
-                   "vg": "VG", "name": "Name",
-                   "size": "Size", "instance": "Instance"}
-    args = []
-    for idx, name in enumerate(selected_fields):
-      hdr = header_list[name]
-      mlens[idx] = max(mlens[idx], len(hdr))
-      args.append(mlens[idx])
-      args.append(hdr)
-    logger.ToStdout(format % tuple(args))
-
-  for row in output:
-    args = []
-    for idx, val in enumerate(row):
-      args.append(mlens[idx])
-      args.append(val)
-    logger.ToStdout(format % tuple(args))
+    headers = {"node": "Node", "phys": "PhysDev",
+               "vg": "VG", "name": "Name",
+               "size": "Size", "instance": "Instance"}
+  else:
+    headers = None
+
+  if opts.human_readable:
+    unitfields = ["size"]
+  else:
+    unitfields = None
+
+  numfields = ["size"]
+
+  OutputTable(separator=opts.separator, headers=headers,
+      fields=selected_fields, unitfields=unitfields,
+      numfields=numfields, data=output)
 
   return 0
 
