Revision 9fbfbb7b
b/lib/cli.py | ||
---|---|---|
171 | 171 |
help="Separator between output fields" |
172 | 172 |
" (defaults to one space)") |
173 | 173 |
|
174 |
USEUNITS_OPT = make_option("--human-readable", default=False,
|
|
175 |
action="store_true", dest="human_readable",
|
|
176 |
help="Print sizes in human readable format")
|
|
174 |
USEUNITS_OPT = make_option("--units", default=None,
|
|
175 |
dest="units", choices=('h', 'm', 'g', 't'),
|
|
176 |
help="Specify units for output (one of hmgt)")
|
|
177 | 177 |
|
178 | 178 |
FIELDS_OPT = make_option("-o", "--output", dest="output", action="store", |
179 | 179 |
type="string", help="Comma separated list of" |
... | ... | |
747 | 747 |
|
748 | 748 |
|
749 | 749 |
def GenerateTable(headers, fields, separator, data, |
750 |
numfields=None, unitfields=None): |
|
750 |
numfields=None, unitfields=None, |
|
751 |
units=None): |
|
751 | 752 |
"""Prints a table with headers and different fields. |
752 | 753 |
|
753 |
Args: |
|
754 |
headers: Dict of header titles or None if no headers should be shown |
|
755 |
fields: List of fields to show |
|
756 |
separator: String used to separate fields or None for spaces |
|
757 |
data: Data to be printed |
|
758 |
numfields: List of fields to be aligned to right |
|
759 |
unitfields: List of fields to be formatted as units |
|
754 |
@type headers: dict |
|
755 |
@param headers: dictionary mapping field names to headers for |
|
756 |
the table |
|
757 |
@type fields: list |
|
758 |
@param fields: the field names corresponding to each row in |
|
759 |
the data field |
|
760 |
@param separator: the separator to be used; if this is None, |
|
761 |
the default 'smart' algorithm is used which computes optimal |
|
762 |
field width, otherwise just the separator is used between |
|
763 |
each field |
|
764 |
@type data: list |
|
765 |
@param data: a list of lists, each sublist being one row to be output |
|
766 |
@type numfields: list |
|
767 |
@param numfields: a list with the fields that hold numeric |
|
768 |
values and thus should be right-aligned |
|
769 |
@type unitfields: list |
|
770 |
@param unitfields: a list with the fields that hold numeric |
|
771 |
values that should be formatted with the units field |
|
772 |
@type units: string or None |
|
773 |
@param units: the units we should use for formatting, or None for |
|
774 |
automatic choice (human-readable for non-separator usage, otherwise |
|
775 |
megabytes); this is a one-letter string |
|
760 | 776 |
|
761 | 777 |
""" |
778 |
if units is None: |
|
779 |
if separator: |
|
780 |
units = "m" |
|
781 |
else: |
|
782 |
units = "h" |
|
783 |
|
|
762 | 784 |
if numfields is None: |
763 | 785 |
numfields = [] |
764 | 786 |
if unitfields is None: |
... | ... | |
795 | 817 |
except ValueError: |
796 | 818 |
pass |
797 | 819 |
else: |
798 |
val = row[idx] = utils.FormatUnit(val) |
|
820 |
val = row[idx] = utils.FormatUnit(val, units)
|
|
799 | 821 |
val = row[idx] = str(val) |
800 | 822 |
if separator is None: |
801 | 823 |
mlens[idx] = max(mlens[idx], len(val)) |
b/lib/utils.py | ||
---|---|---|
638 | 638 |
return template % args |
639 | 639 |
|
640 | 640 |
|
641 |
def FormatUnit(value): |
|
641 |
def FormatUnit(value, units):
|
|
642 | 642 |
"""Formats an incoming number of MiB with the appropriate unit. |
643 | 643 |
|
644 | 644 |
@type value: int |
645 | 645 |
@param value: integer representing the value in MiB (1048576) |
646 |
@type units: char |
|
647 |
@param units: the type of formatting we should do: |
|
648 |
- 'h' for automatic scaling |
|
649 |
- 'm' for MiBs |
|
650 |
- 'g' for GiBs |
|
651 |
- 't' for TiBs |
|
646 | 652 |
@rtype: str |
647 | 653 |
@return: the formatted value (with suffix) |
648 | 654 |
|
649 | 655 |
""" |
650 |
if value < 1024:
|
|
651 |
return "%dM" % round(value, 0)
|
|
656 |
if units not in ('m', 'g', 't', 'h'):
|
|
657 |
raise errors.ProgrammerError("Invalid unit specified '%s'" % str(units))
|
|
652 | 658 |
|
653 |
elif value < (1024 * 1024): |
|
654 |
return "%0.1fG" % round(float(value) / 1024, 1) |
|
659 |
suffix = '' |
|
660 |
|
|
661 |
if units == 'm' or (units == 'h' and value < 1024): |
|
662 |
if units == 'h': |
|
663 |
suffix = 'M' |
|
664 |
return "%d%s" % (round(value, 0), suffix) |
|
665 |
|
|
666 |
elif units == 'g' or (units == 'h' and value < (1024 * 1024)): |
|
667 |
if units == 'h': |
|
668 |
suffix = 'G' |
|
669 |
return "%0.1f%s" % (round(float(value) / 1024, 1), suffix) |
|
655 | 670 |
|
656 | 671 |
else: |
657 |
return "%0.1fT" % round(float(value) / 1024 / 1024, 1) |
|
672 |
if units == 'h': |
|
673 |
suffix = 'T' |
|
674 |
return "%0.1f%s" % (round(float(value) / 1024 / 1024, 1), suffix) |
|
658 | 675 |
|
659 | 676 |
|
660 | 677 |
def ParseUnit(input_string): |
b/scripts/gnt-instance | ||
---|---|---|
228 | 228 |
else: |
229 | 229 |
headers = None |
230 | 230 |
|
231 |
if opts.human_readable: |
|
232 |
unitfields = ["be/memory", "oper_ram", "sd(a|b)_size", "disk\.size/.*"] |
|
233 |
else: |
|
234 |
unitfields = None |
|
235 |
|
|
231 |
unitfields = ["be/memory", "oper_ram", "sd(a|b)_size", "disk\.size/.*"] |
|
236 | 232 |
numfields = ["be/memory", "oper_ram", "sd(a|b)_size", "be/vcpus", |
237 | 233 |
"serial_no", "(disk|nic)\.count", "disk\.size/.*"] |
238 | 234 |
|
... | ... | |
270 | 266 |
|
271 | 267 |
data = GenerateTable(separator=opts.separator, headers=headers, |
272 | 268 |
fields=selected_fields, unitfields=unitfields, |
273 |
numfields=numfields, data=output) |
|
269 |
numfields=numfields, data=output, units=opts.units)
|
|
274 | 270 |
|
275 | 271 |
for line in data: |
276 | 272 |
ToStdout(line) |
b/scripts/gnt-job | ||
---|---|---|
106 | 106 |
|
107 | 107 |
data = GenerateTable(separator=opts.separator, headers=headers, |
108 | 108 |
fields=selected_fields, unitfields=unitfields, |
109 |
numfields=numfields, data=output) |
|
109 |
numfields=numfields, data=output, units=opts.units)
|
|
110 | 110 |
for line in data: |
111 | 111 |
ToStdout(line) |
112 | 112 |
|
b/scripts/gnt-node | ||
---|---|---|
115 | 115 |
else: |
116 | 116 |
headers = None |
117 | 117 |
|
118 |
if opts.human_readable: |
|
119 |
unitfields = ["dtotal", "dfree", "mtotal", "mnode", "mfree"] |
|
120 |
else: |
|
121 |
unitfields = None |
|
118 |
unitfields = ["dtotal", "dfree", "mtotal", "mnode", "mfree"] |
|
122 | 119 |
|
123 | 120 |
numfields = ["dtotal", "dfree", |
124 | 121 |
"mtotal", "mnode", "mfree", |
... | ... | |
138 | 135 |
|
139 | 136 |
data = GenerateTable(separator=opts.separator, headers=headers, |
140 | 137 |
fields=selected_fields, unitfields=unitfields, |
141 |
numfields=numfields, data=output) |
|
138 |
numfields=numfields, data=output, units=opts.units)
|
|
142 | 139 |
for line in data: |
143 | 140 |
ToStdout(line) |
144 | 141 |
|
... | ... | |
343 | 340 |
else: |
344 | 341 |
headers = None |
345 | 342 |
|
346 |
if opts.human_readable: |
|
347 |
unitfields = ["size"] |
|
348 |
else: |
|
349 |
unitfields = None |
|
343 |
unitfields = ["size"] |
|
350 | 344 |
|
351 | 345 |
numfields = ["size"] |
352 | 346 |
|
353 | 347 |
data = GenerateTable(separator=opts.separator, headers=headers, |
354 | 348 |
fields=selected_fields, unitfields=unitfields, |
355 |
numfields=numfields, data=output) |
|
349 |
numfields=numfields, data=output, units=opts.units)
|
|
356 | 350 |
|
357 | 351 |
for line in data: |
358 | 352 |
ToStdout(line) |
b/scripts/gnt-os | ||
---|---|---|
55 | 55 |
headers = None |
56 | 56 |
|
57 | 57 |
data = GenerateTable(separator=None, headers=headers, fields=["name"], |
58 |
data=[[row[0]] for row in result if row[1]]) |
|
58 |
data=[[row[0]] for row in result if row[1]], |
|
59 |
units=None) |
|
59 | 60 |
|
60 | 61 |
for line in data: |
61 | 62 |
ToStdout(line) |
b/test/ganeti.utils_unittest.py | ||
---|---|---|
324 | 324 |
"""Test case for the FormatUnit function""" |
325 | 325 |
|
326 | 326 |
def testMiB(self): |
327 |
self.assertEqual(FormatUnit(1), '1M') |
|
328 |
self.assertEqual(FormatUnit(100), '100M') |
|
329 |
self.assertEqual(FormatUnit(1023), '1023M') |
|
327 |
self.assertEqual(FormatUnit(1, 'h'), '1M') |
|
328 |
self.assertEqual(FormatUnit(100, 'h'), '100M') |
|
329 |
self.assertEqual(FormatUnit(1023, 'h'), '1023M') |
|
330 |
|
|
331 |
self.assertEqual(FormatUnit(1, 'm'), '1') |
|
332 |
self.assertEqual(FormatUnit(100, 'm'), '100') |
|
333 |
self.assertEqual(FormatUnit(1023, 'm'), '1023') |
|
334 |
|
|
335 |
self.assertEqual(FormatUnit(1024, 'm'), '1024') |
|
336 |
self.assertEqual(FormatUnit(1536, 'm'), '1536') |
|
337 |
self.assertEqual(FormatUnit(17133, 'm'), '17133') |
|
338 |
self.assertEqual(FormatUnit(1024 * 1024 - 1, 'm'), '1048575') |
|
330 | 339 |
|
331 | 340 |
def testGiB(self): |
332 |
self.assertEqual(FormatUnit(1024), '1.0G') |
|
333 |
self.assertEqual(FormatUnit(1536), '1.5G') |
|
334 |
self.assertEqual(FormatUnit(17133), '16.7G') |
|
335 |
self.assertEqual(FormatUnit(1024 * 1024 - 1), '1024.0G') |
|
341 |
self.assertEqual(FormatUnit(1024, 'h'), '1.0G') |
|
342 |
self.assertEqual(FormatUnit(1536, 'h'), '1.5G') |
|
343 |
self.assertEqual(FormatUnit(17133, 'h'), '16.7G') |
|
344 |
self.assertEqual(FormatUnit(1024 * 1024 - 1, 'h'), '1024.0G') |
|
345 |
|
|
346 |
self.assertEqual(FormatUnit(1024, 'g'), '1.0') |
|
347 |
self.assertEqual(FormatUnit(1536, 'g'), '1.5') |
|
348 |
self.assertEqual(FormatUnit(17133, 'g'), '16.7') |
|
349 |
self.assertEqual(FormatUnit(1024 * 1024 - 1, 'g'), '1024.0') |
|
350 |
|
|
351 |
self.assertEqual(FormatUnit(1024 * 1024, 'g'), '1024.0') |
|
352 |
self.assertEqual(FormatUnit(5120 * 1024, 'g'), '5120.0') |
|
353 |
self.assertEqual(FormatUnit(29829 * 1024, 'g'), '29829.0') |
|
336 | 354 |
|
337 | 355 |
def testTiB(self): |
338 |
self.assertEqual(FormatUnit(1024 * 1024), '1.0T') |
|
339 |
self.assertEqual(FormatUnit(5120 * 1024), '5.0T') |
|
340 |
self.assertEqual(FormatUnit(29829 * 1024), '29.1T') |
|
356 |
self.assertEqual(FormatUnit(1024 * 1024, 'h'), '1.0T')
|
|
357 |
self.assertEqual(FormatUnit(5120 * 1024, 'h'), '5.0T')
|
|
358 |
self.assertEqual(FormatUnit(29829 * 1024, 'h'), '29.1T')
|
|
341 | 359 |
|
360 |
self.assertEqual(FormatUnit(1024 * 1024, 't'), '1.0') |
|
361 |
self.assertEqual(FormatUnit(5120 * 1024, 't'), '5.0') |
|
362 |
self.assertEqual(FormatUnit(29829 * 1024, 't'), '29.1') |
|
342 | 363 |
|
343 | 364 |
class TestParseUnit(unittest.TestCase): |
344 | 365 |
"""Test case for the ParseUnit function""" |
Also available in: Unified diff