diff --git a/lib/client/gnt_node.py b/lib/client/gnt_node.py index 618629596e43d8862c722d261ae2a43ceb6f7f9a..6956839ceab5628b8a9150cd0251500ca2a1d274 100644 --- a/lib/client/gnt_node.py +++ b/lib/client/gnt_node.py @@ -105,6 +105,16 @@ NONODE_SETUP_OPT = cli_option("--no-node-setup", default=True, help=("Do not make initial SSH setup on remote" " node (needs to be done manually)")) +IGNORE_STATUS_OPT = cli_option("--ignore-status", default=False, + action="store_true", dest="ignore_status", + help=("Ignore the Node(s) offline status" + " (potentially DANGEROUS)")) + +FORCE_MASTER_OPT = cli_option("--force-master", default=False, + action="store_true", dest="force_master", + help=("Operate on the master node too" + " (potentially DANGEROUS)")) + def ConvertStorageType(user_storage_type): """Converts a user storage type to its internal name. @@ -487,12 +497,14 @@ def PowerNode(opts, args): oob_command = "power-%s" % command opcodelist = [] - if oob_command == constants.OOB_POWER_OFF: + if not opts.ignore_status and oob_command == constants.OOB_POWER_OFF: opcodelist.append(opcodes.OpNodeSetParams(node_name=node, offline=True, auto_promote=opts.auto_promote)) opcodelist.append(opcodes.OpOobCommand(node_names=[node], - command=oob_command)) + command=oob_command, + ignore_status=opts.ignore_status, + force_master=opts.force_master)) cli.SetGenericOpcodeOpts(opcodelist, opts) @@ -815,7 +827,8 @@ commands = { PowerNode, [ArgChoice(min=1, max=1, choices=_LIST_POWER_COMMANDS), ArgNode(min=1, max=1)], - [SUBMIT_OPT, AUTO_PROMOTE_OPT, PRIORITY_OPT], + [SUBMIT_OPT, AUTO_PROMOTE_OPT, PRIORITY_OPT, IGNORE_STATUS_OPT, + FORCE_MASTER_OPT], "on|off|cycle|status <node>", "Change power state of node by calling out-of-band helper."), 'remove': ( diff --git a/qa/qa_node.py b/qa/qa_node.py index 30e5853e4da338ce8ef1f50935b2d93bbabc9a24..fb3495a773735d0d71bde4aa103aee42b33c0dc6 100644 --- a/qa/qa_node.py +++ b/qa/qa_node.py @@ -251,6 +251,8 @@ def TestOutOfBand(): node = qa_config.AcquireNode(exclude=master) + master_name = master["primary"] + full_master_name = qa_utils.ResolveNodeName(master) node_name = node["primary"] full_node_name = qa_utils.ResolveNodeName(node) @@ -270,6 +272,18 @@ def TestOutOfBand(): AssertCommand(["gnt-node", "power", "off", node_name]) _AssertOobCall(verify_path, "power-off %s" % full_node_name) + # Power off on master without options should fail + AssertCommand(["gnt-node", "power", "off", master_name], fail=True) + # With force master it should still fail + AssertCommand(["gnt-node", "power", "--force-master", "off", master_name], + fail=True) + AssertCommand(["gnt-node", "power", "--ignore-status", "off", master_name], + fail=True) + # This should work again + AssertCommand(["gnt-node", "power", "--ignore-status", "--force-master", + "off", master_name]) + _AssertOobCall(verify_path, "power-off %s" % full_master_name) + # Verify we can't transform back to online when not yet powered on AssertCommand(["gnt-node", "modify", "-O", "no", node_name], fail=True)