# C0103: Invalid name gnt-node
from ganeti.cli import *
+from ganeti import cli
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
]
-#: 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",
- }
+#: default list of power commands
+_LIST_POWER_COMMANDS = ["on", "off", "cycle", "status"]
-#: headers (and full field list for L{ListStorage}
+#: headers (and full field list) for L{ListStorage}
_LIST_STOR_HEADERS = {
constants.SF_NODE: "Node",
constants.SF_TYPE: "Type",
op = opcodes.OpAddNode(node_name=args[0], secondary_ip=sip,
readd=opts.readd, group=opts.nodegroup,
- vm_capable=opts.vm_capable,
+ vm_capable=opts.vm_capable, ndparams=opts.ndparams,
master_capable=opts.master_capable)
SubmitOpCode(op, opts=opts)
@param opts: the command line options selected by the user
@type args: list
- @param args: should be an empty list
+ @param args: nodes to list, or empty for all
@rtype: int
@return: the desired exit code
"""
selected_fields = ParseFields(opts.output, _LIST_DEF_FIELDS)
- output = GetClient().QueryNodes(args, selected_fields, opts.do_locking)
-
- if not opts.no_headers:
- headers = _LIST_HEADERS
- else:
- headers = None
+ fmtoverride = dict.fromkeys(["pinst_list", "sinst_list", "tags"],
+ (",".join, False))
- unitfields = ["dtotal", "dfree", "mtotal", "mnode", "mfree"]
+ return GenericList(constants.QR_NODE, selected_fields, args, opts.units,
+ opts.separator, not opts.no_headers,
+ format_override=fmtoverride)
- numfields = ["dtotal", "dfree",
- "mtotal", "mnode", "mfree",
- "pinst_cnt", "sinst_cnt",
- "ctotal", "serial_no"]
- 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)
+def ListNodeFields(opts, args):
+ """List node fields.
- 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):
return 0
+def PowerNode(opts, args):
+ """Change/ask power state of a node.
+
+ @param opts: the command line options selected by the user
+ @type args: list
+ @param args: should contain only one element, the name of
+ the node to be removed
+ @rtype: int
+ @return: the desired exit code
+
+ """
+ command = args[0]
+ node = args[1]
+
+ if command not in _LIST_POWER_COMMANDS:
+ ToStderr("power subcommand %s not supported." % command)
+ return constants.EXIT_FAILURE
+
+ oob_command = "power-%s" % command
+
+ opcodelist = []
+ if oob_command == constants.OOB_POWER_OFF:
+ opcodelist.append(opcodes.OpSetNodeParams(node_name=node, offline=True,
+ auto_promote=opts.auto_promote))
+
+ opcodelist.append(opcodes.OpOobCommand(node_name=node, command=oob_command))
+
+ cli.SetGenericOpcodeOpts(opcodelist, opts)
+
+ job_id = cli.SendJob(opcodelist)
+
+ # We just want the OOB Opcode status
+ # If it fails PollJob gives us the error message in it
+ result = cli.PollJob(job_id)[-1]
+
+ if result:
+ if oob_command == constants.OOB_POWER_STATUS:
+ text = "The machine is %spowered"
+ if result[constants.OOB_POWER_STATUS_POWERED]:
+ result = text % ""
+ else:
+ result = text % "not "
+ ToStderr(result)
+
+ return constants.EXIT_SUCCESS
+
+
def ListVolumes(opts, args):
"""List logical volumes on node(s).
"""
all_changes = [opts.master_candidate, opts.drained, opts.offline,
- opts.master_capable, opts.vm_capable]
+ opts.master_capable, opts.vm_capable, opts.secondary_ip,
+ opts.ndparams]
if all_changes.count(None) == len(all_changes):
ToStderr("Please give at least one of the parameters.")
return 1
drained=opts.drained,
master_capable=opts.master_capable,
vm_capable=opts.vm_capable,
+ secondary_ip=opts.secondary_ip,
force=opts.force,
- auto_promote=opts.auto_promote)
+ ndparams=opts.ndparams,
+ auto_promote=opts.auto_promote,
+ powered=opts.node_powered)
# even if here we process the result, we allow submit only
result = SubmitOrSend(op, opts)
AddNode, [ArgHost(min=1, max=1)],
[SECONDARY_IP_OPT, READD_OPT, NOSSH_KEYCHECK_OPT, NONODE_SETUP_OPT,
VERBOSE_OPT, NODEGROUP_OPT, PRIORITY_OPT, CAPAB_MASTER_OPT,
- CAPAB_VM_OPT],
+ CAPAB_VM_OPT, NODE_PARAMS_OPT],
"[-s ip] [--readd] [--no-ssh-key-check] [--no-node-setup] [--verbose] "
" <node_name>",
"Add a node to the cluster"),
"[<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,
- CAPAB_MASTER_OPT, CAPAB_VM_OPT,
- AUTO_PROMOTE_OPT, DRY_RUN_OPT, PRIORITY_OPT],
+ CAPAB_MASTER_OPT, CAPAB_VM_OPT, SECONDARY_IP_OPT,
+ AUTO_PROMOTE_OPT, DRY_RUN_OPT, PRIORITY_OPT, NODE_PARAMS_OPT,
+ NODE_POWERED_OPT],
"<node_name>", "Alters the parameters of a node"),
'powercycle': (
PowercycleNode, ARGS_ONE_NODE,
[FORCE_OPT, CONFIRM_OPT, DRY_RUN_OPT, PRIORITY_OPT],
"<node_name>", "Tries to forcefully powercycle a node"),
+ 'power': (
+ PowerNode,
+ [ArgChoice(min=1, max=1, choices=_LIST_POWER_COMMANDS),
+ ArgNode(min=1, max=1)],
+ [SUBMIT_OPT, AUTO_PROMOTE_OPT, PRIORITY_OPT],
+ "on|off|cycle|status <node>",
+ "Change power state of node by calling out-of-band helper."),
'remove': (
RemoveNode, ARGS_ONE_NODE, [DRY_RUN_OPT, PRIORITY_OPT],
"<node_name>", "Removes a node from the cluster"),