help="Separator between output fields"
" (defaults to one space)")
-USEUNITS_OPT = make_option("--human-readable", default=False,
- action="store_true", dest="human_readable",
- help="Print sizes in human readable format")
+USEUNITS_OPT = make_option("--units", default=None,
+ dest="units", choices=('h', 'm', 'g', 't'),
+ help="Specify units for output (one of hmgt)")
FIELDS_OPT = make_option("-o", "--output", dest="output", action="store",
type="string", help="Comma separated list of"
def GenerateTable(headers, fields, separator, data,
- numfields=None, unitfields=None):
+ numfields=None, unitfields=None,
+ units=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
+ @type headers: dict
+ @param headers: dictionary mapping field names to headers for
+ the table
+ @type fields: list
+ @param fields: the field names corresponding to each row in
+ the data field
+ @param separator: the separator to be used; if this is None,
+ the default 'smart' algorithm is used which computes optimal
+ field width, otherwise just the separator is used between
+ each field
+ @type data: list
+ @param data: a list of lists, each sublist being one row to be output
+ @type numfields: list
+ @param numfields: a list with the fields that hold numeric
+ values and thus should be right-aligned
+ @type unitfields: list
+ @param unitfields: a list with the fields that hold numeric
+ values that should be formatted with the units field
+ @type units: string or None
+ @param units: the units we should use for formatting, or None for
+ automatic choice (human-readable for non-separator usage, otherwise
+ megabytes); this is a one-letter string
"""
+ if units is None:
+ if separator:
+ units = "m"
+ else:
+ units = "h"
+
if numfields is None:
numfields = []
if unitfields is None:
except ValueError:
pass
else:
- val = row[idx] = utils.FormatUnit(val)
+ val = row[idx] = utils.FormatUnit(val, units)
val = row[idx] = str(val)
if separator is None:
mlens[idx] = max(mlens[idx], len(val))
return template % args
-def FormatUnit(value):
+def FormatUnit(value, units):
"""Formats an incoming number of MiB with the appropriate unit.
@type value: int
@param value: integer representing the value in MiB (1048576)
+ @type units: char
+ @param units: the type of formatting we should do:
+ - 'h' for automatic scaling
+ - 'm' for MiBs
+ - 'g' for GiBs
+ - 't' for TiBs
@rtype: str
@return: the formatted value (with suffix)
"""
- if value < 1024:
- return "%dM" % round(value, 0)
+ if units not in ('m', 'g', 't', 'h'):
+ raise errors.ProgrammerError("Invalid unit specified '%s'" % str(units))
- elif value < (1024 * 1024):
- return "%0.1fG" % round(float(value) / 1024, 1)
+ suffix = ''
+
+ if units == 'm' or (units == 'h' and value < 1024):
+ if units == 'h':
+ suffix = 'M'
+ return "%d%s" % (round(value, 0), suffix)
+
+ elif units == 'g' or (units == 'h' and value < (1024 * 1024)):
+ if units == 'h':
+ suffix = 'G'
+ return "%0.1f%s" % (round(float(value) / 1024, 1), suffix)
else:
- return "%0.1fT" % round(float(value) / 1024 / 1024, 1)
+ if units == 'h':
+ suffix = 'T'
+ return "%0.1f%s" % (round(float(value) / 1024 / 1024, 1), suffix)
def ParseUnit(input_string):
else:
headers = None
- if opts.human_readable:
- unitfields = ["be/memory", "oper_ram", "sd(a|b)_size", "disk\.size/.*"]
- else:
- unitfields = None
-
+ unitfields = ["be/memory", "oper_ram", "sd(a|b)_size", "disk\.size/.*"]
numfields = ["be/memory", "oper_ram", "sd(a|b)_size", "be/vcpus",
"serial_no", "(disk|nic)\.count", "disk\.size/.*"]
data = GenerateTable(separator=opts.separator, headers=headers,
fields=selected_fields, unitfields=unitfields,
- numfields=numfields, data=output)
+ numfields=numfields, data=output, units=opts.units)
for line in data:
ToStdout(line)
data = GenerateTable(separator=opts.separator, headers=headers,
fields=selected_fields, unitfields=unitfields,
- numfields=numfields, data=output)
+ numfields=numfields, data=output, units=opts.units)
for line in data:
ToStdout(line)
else:
headers = None
- if opts.human_readable:
- unitfields = ["dtotal", "dfree", "mtotal", "mnode", "mfree"]
- else:
- unitfields = None
+ unitfields = ["dtotal", "dfree", "mtotal", "mnode", "mfree"]
numfields = ["dtotal", "dfree",
"mtotal", "mnode", "mfree",
data = GenerateTable(separator=opts.separator, headers=headers,
fields=selected_fields, unitfields=unitfields,
- numfields=numfields, data=output)
+ numfields=numfields, data=output, units=opts.units)
for line in data:
ToStdout(line)
else:
headers = None
- if opts.human_readable:
- unitfields = ["size"]
- else:
- unitfields = None
+ unitfields = ["size"]
numfields = ["size"]
data = GenerateTable(separator=opts.separator, headers=headers,
fields=selected_fields, unitfields=unitfields,
- numfields=numfields, data=output)
+ numfields=numfields, data=output, units=opts.units)
for line in data:
ToStdout(line)
headers = None
data = GenerateTable(separator=None, headers=headers, fields=["name"],
- data=[[row[0]] for row in result if row[1]])
+ data=[[row[0]] for row in result if row[1]],
+ units=None)
for line in data:
ToStdout(line)
"""Test case for the FormatUnit function"""
def testMiB(self):
- self.assertEqual(FormatUnit(1), '1M')
- self.assertEqual(FormatUnit(100), '100M')
- self.assertEqual(FormatUnit(1023), '1023M')
+ self.assertEqual(FormatUnit(1, 'h'), '1M')
+ self.assertEqual(FormatUnit(100, 'h'), '100M')
+ self.assertEqual(FormatUnit(1023, 'h'), '1023M')
+
+ self.assertEqual(FormatUnit(1, 'm'), '1')
+ self.assertEqual(FormatUnit(100, 'm'), '100')
+ self.assertEqual(FormatUnit(1023, 'm'), '1023')
+
+ self.assertEqual(FormatUnit(1024, 'm'), '1024')
+ self.assertEqual(FormatUnit(1536, 'm'), '1536')
+ self.assertEqual(FormatUnit(17133, 'm'), '17133')
+ self.assertEqual(FormatUnit(1024 * 1024 - 1, 'm'), '1048575')
def testGiB(self):
- self.assertEqual(FormatUnit(1024), '1.0G')
- self.assertEqual(FormatUnit(1536), '1.5G')
- self.assertEqual(FormatUnit(17133), '16.7G')
- self.assertEqual(FormatUnit(1024 * 1024 - 1), '1024.0G')
+ self.assertEqual(FormatUnit(1024, 'h'), '1.0G')
+ self.assertEqual(FormatUnit(1536, 'h'), '1.5G')
+ self.assertEqual(FormatUnit(17133, 'h'), '16.7G')
+ self.assertEqual(FormatUnit(1024 * 1024 - 1, 'h'), '1024.0G')
+
+ self.assertEqual(FormatUnit(1024, 'g'), '1.0')
+ self.assertEqual(FormatUnit(1536, 'g'), '1.5')
+ self.assertEqual(FormatUnit(17133, 'g'), '16.7')
+ self.assertEqual(FormatUnit(1024 * 1024 - 1, 'g'), '1024.0')
+
+ self.assertEqual(FormatUnit(1024 * 1024, 'g'), '1024.0')
+ self.assertEqual(FormatUnit(5120 * 1024, 'g'), '5120.0')
+ self.assertEqual(FormatUnit(29829 * 1024, 'g'), '29829.0')
def testTiB(self):
- self.assertEqual(FormatUnit(1024 * 1024), '1.0T')
- self.assertEqual(FormatUnit(5120 * 1024), '5.0T')
- self.assertEqual(FormatUnit(29829 * 1024), '29.1T')
+ self.assertEqual(FormatUnit(1024 * 1024, 'h'), '1.0T')
+ self.assertEqual(FormatUnit(5120 * 1024, 'h'), '5.0T')
+ self.assertEqual(FormatUnit(29829 * 1024, 'h'), '29.1T')
+ self.assertEqual(FormatUnit(1024 * 1024, 't'), '1.0')
+ self.assertEqual(FormatUnit(5120 * 1024, 't'), '5.0')
+ self.assertEqual(FormatUnit(29829 * 1024, 't'), '29.1')
class TestParseUnit(unittest.TestCase):
"""Test case for the ParseUnit function"""