diff --git a/lib/client/gnt_node.py b/lib/client/gnt_node.py index 9b31df3be348a7b597b27d460e1009bc655e331a..1819a0de7305c22e4d6fdad83111efc6d97c22ee 100644 --- a/lib/client/gnt_node.py +++ b/lib/client/gnt_node.py @@ -31,7 +31,6 @@ from ganeti import bootstrap from ganeti import opcodes from ganeti import utils from ganeti import constants -from ganeti import compat from ganeti import errors from ganeti import netutils @@ -60,27 +59,6 @@ _LIST_STOR_DEF_FIELDS = [ ] -#: headers (and full field list) for L{ListNodes} -_LIST_HEADERS = { - "name": "Node", "pinst_cnt": "Pinst", "sinst_cnt": "Sinst", - "pinst_list": "PriInstances", "sinst_list": "SecInstances", - "pip": "PrimaryIP", "sip": "SecondaryIP", - "dtotal": "DTotal", "dfree": "DFree", - "mtotal": "MTotal", "mnode": "MNode", "mfree": "MFree", - "bootid": "BootID", - "ctotal": "CTotal", "cnodes": "CNodes", "csockets": "CSockets", - "tags": "Tags", - "serial_no": "SerialNo", - "master_candidate": "MasterC", - "master": "IsMaster", - "offline": "Offline", "drained": "Drained", - "role": "Role", - "ctime": "CTime", "mtime": "MTime", "uuid": "UUID", - "master_capable": "MasterCapable", "vm_capable": "VMCapable", - "group": "Group", "group.uuid": "GroupUUID", - } - - #: headers (and full field list) for L{ListStorage} _LIST_STOR_HEADERS = { constants.SF_NODE: "Node", @@ -232,48 +210,26 @@ def ListNodes(opts, args): """ selected_fields = ParseFields(opts.output, _LIST_DEF_FIELDS) - output = GetClient().QueryNodes(args, selected_fields, opts.do_locking) + fmtoverride = dict.fromkeys(["pinst_list", "sinst_list", "tags"], + (lambda value: ",".join(value), False)) - if not opts.no_headers: - headers = _LIST_HEADERS - else: - headers = None + return GenericList(constants.QR_NODE, selected_fields, args, opts.units, + opts.separator, not opts.no_headers, + format_override=fmtoverride) - unitfields = ["dtotal", "dfree", "mtotal", "mnode", "mfree"] - numfields = ["dtotal", "dfree", - "mtotal", "mnode", "mfree", - "pinst_cnt", "sinst_cnt", - "ctotal", "serial_no"] +def ListNodeFields(opts, args): + """List node fields. - list_type_fields = ("pinst_list", "sinst_list", "tags") - # change raw values to nicer strings - for row in output: - for idx, field in enumerate(selected_fields): - val = row[idx] - if field in list_type_fields: - val = ",".join(val) - elif field in ('master', 'master_candidate', 'offline', 'drained', - 'master_capable', 'vm_capable'): - if val: - val = 'Y' - else: - val = 'N' - elif field == "ctime" or field == "mtime": - val = utils.FormatTime(val) - elif val is None: - val = "?" - elif opts.roman_integers and isinstance(val, int): - val = compat.TryToRoman(val) - row[idx] = str(val) - - data = GenerateTable(separator=opts.separator, headers=headers, - fields=selected_fields, unitfields=unitfields, - numfields=numfields, data=output, units=opts.units) - for line in data: - ToStdout(line) + @param opts: the command line options selected by the user + @type args: list + @param args: fields to list, or empty for all + @rtype: int + @return: the desired exit code - return 0 + """ + return GenericListFields(constants.QR_NODE, args, opts.separator, + not opts.no_headers) def EvacuateNode(opts, args): @@ -716,11 +672,17 @@ commands = { "[<node_name>...]", "Show information about the node(s)"), 'list': ( ListNodes, ARGS_MANY_NODES, - [NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT, SYNC_OPT, ROMAN_OPT], + [NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT], "[nodes...]", - "Lists the nodes in the cluster. The available fields are (see the man" - " page for details): %s. The default field list is (in order): %s." % - (utils.CommaJoin(_LIST_HEADERS), utils.CommaJoin(_LIST_DEF_FIELDS))), + "Lists the nodes in the cluster. The available fields can be shown using" + " the \"list-fields\" command (see the man page for details)." + " The default field list is (in order): %s." % + utils.CommaJoin(_LIST_DEF_FIELDS)), + "list-fields": ( + ListNodeFields, [ArgUnknown()], + [NOHDR_OPT, SEP_OPT], + "[fields...]", + "Lists all available fields for nodes"), 'modify': ( SetNodeParams, ARGS_ONE_NODE, [FORCE_OPT, SUBMIT_OPT, MC_OPT, DRAINED_OPT, OFFLINE_OPT, diff --git a/man/gnt-node.rst b/man/gnt-node.rst index 5d288a6a995b13f3948e5bedbdb15d4bd637c896..0bb3c0791d137df6b9c988c78cb69253af22bd7e 100644 --- a/man/gnt-node.rst +++ b/man/gnt-node.rst @@ -143,10 +143,9 @@ output will be restricted to the given names. LIST ~~~~ -| **list** [--sync] +| **list** | [--no-headers] [--separator=*SEPARATOR*] | [--units=*UNITS*] [-o *[+]FIELD,...*] -| [--roman] | [node...] Lists the nodes in the cluster. @@ -163,15 +162,8 @@ option is given, then the values are shown in mebibytes to allow parsing by scripts. In both cases, the ``--units`` option can be used to enforce a given output unit. -By default, the query of nodes will be done in parallel with any -running jobs. This might give inconsistent results for the free -disk/memory. The ``--sync`` can be used to grab locks for all the -nodes and ensure consistent view of the cluster (but this might -stall the query for a long time). - -Passing the ``--roman`` option gnt-node list will try to output -some of its fields in a latin-friendly way. This is not the default -for backwards compatibility. +Queries of nodes will be done in parallel with any running jobs. This might +give inconsistent results for the free disk/memory. The ``-o`` option takes a comma-separated list of output fields. The available fields and their meaning are: @@ -319,6 +311,15 @@ memory for the node and for the instances (Xen). If no node names are given, then all nodes are queried. Otherwise, only the given nodes will be listed. + +LIST-FIELDS +~~~~~~~~~~~ + +**list-fields** [field...] + +Lists available fields for nodes. + + LIST-TAGS ~~~~~~~~~