+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.pop(0)
+
+ if opts.no_headers:
+ headers = None
+ else:
+ headers = {"node": "Node", "status": "Status"}
+
+ if command not in _LIST_POWER_COMMANDS:
+ ToStderr("power subcommand %s not supported." % command)
+ return constants.EXIT_FAILURE
+
+ oob_command = "power-%s" % command
+
+ if oob_command in _OOB_COMMAND_ASK:
+ if not args:
+ ToStderr("Please provide at least one node for this command")
+ return constants.EXIT_FAILURE
+ elif not opts.force and not ConfirmOperation(args, "nodes",
+ "power %s" % command):
+ return constants.EXIT_FAILURE
+ assert len(args) > 0
+
+ opcodelist = []
+ if not opts.ignore_status and oob_command == constants.OOB_POWER_OFF:
+ # TODO: This is a little ugly as we can't catch and revert
+ for node in args:
+ opcodelist.append(opcodes.OpNodeSetParams(node_name=node, offline=True,
+ auto_promote=opts.auto_promote))
+
+ opcodelist.append(opcodes.OpOobCommand(node_names=args,
+ command=oob_command,
+ ignore_status=opts.ignore_status,
+ timeout=opts.oob_timeout,
+ power_delay=opts.power_delay))
+
+ 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]
+
+ errs = 0
+ data = []
+ for node_result in result:
+ (node_tuple, data_tuple) = node_result
+ (_, node_name) = node_tuple
+ (data_status, data_node) = data_tuple
+ if data_status == constants.RS_NORMAL:
+ if oob_command == constants.OOB_POWER_STATUS:
+ if data_node[constants.OOB_POWER_STATUS_POWERED]:
+ text = "powered"
+ else:
+ text = "unpowered"
+ data.append([node_name, text])
+ else:
+ # We don't expect data here, so we just say, it was successfully invoked
+ data.append([node_name, "invoked"])
+ else:
+ errs += 1
+ data.append([node_name, cli.FormatResultError(data_status, True)])
+
+ data = GenerateTable(separator=opts.separator, headers=headers,
+ fields=["node", "status"], data=data)
+
+ for line in data:
+ ToStdout(line)
+
+ if errs:
+ return constants.EXIT_FAILURE
+ else:
+ return constants.EXIT_SUCCESS
+
+
+def Health(opts, args):
+ """Show health of a node using OOB.
+
+ @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
+
+ """
+ op = opcodes.OpOobCommand(node_names=args, command=constants.OOB_HEALTH,
+ timeout=opts.oob_timeout)
+ result = SubmitOpCode(op, opts=opts)
+
+ if opts.no_headers:
+ headers = None
+ else:
+ headers = {"node": "Node", "status": "Status"}
+
+ errs = 0
+ data = []
+ for node_result in result:
+ (node_tuple, data_tuple) = node_result
+ (_, node_name) = node_tuple
+ (data_status, data_node) = data_tuple
+ if data_status == constants.RS_NORMAL:
+ data.append([node_name, "%s=%s" % tuple(data_node[0])])
+ for item, status in data_node[1:]:
+ data.append(["", "%s=%s" % (item, status)])
+ else:
+ errs += 1
+ data.append([node_name, cli.FormatResultError(data_status, True)])
+
+ data = GenerateTable(separator=opts.separator, headers=headers,
+ fields=["node", "status"], data=data)
+
+ for line in data:
+ ToStdout(line)
+
+ if errs:
+ return constants.EXIT_FAILURE
+ else:
+ return constants.EXIT_SUCCESS
+
+