Commit b04808ea authored by René Nussbaumer's avatar René Nussbaumer

Modify LUOobCommand to support multiple nodes

This will change the result of this LU to a query like result. A list of
tuples with information about the state of the data.

It also includes the modification to the commands calling this opcode.
Signed-off-by: default avatarRené Nussbaumer <rn@google.com>
Reviewed-by: default avatarIustin Pop <iustin@google.com>
parent e18c6c47
...@@ -491,7 +491,8 @@ def PowerNode(opts, args): ...@@ -491,7 +491,8 @@ def PowerNode(opts, args):
opcodelist.append(opcodes.OpNodeSetParams(node_name=node, offline=True, opcodelist.append(opcodes.OpNodeSetParams(node_name=node, offline=True,
auto_promote=opts.auto_promote)) auto_promote=opts.auto_promote))
opcodelist.append(opcodes.OpOobCommand(node_name=node, command=oob_command)) opcodelist.append(opcodes.OpOobCommand(node_names=[node],
command=oob_command))
cli.SetGenericOpcodeOpts(opcodelist, opts) cli.SetGenericOpcodeOpts(opcodelist, opts)
...@@ -502,13 +503,22 @@ def PowerNode(opts, args): ...@@ -502,13 +503,22 @@ def PowerNode(opts, args):
result = cli.PollJob(job_id)[-1] result = cli.PollJob(job_id)[-1]
if result: if result:
if oob_command == constants.OOB_POWER_STATUS: (_, data_tuple) = result[0]
text = "The machine is %spowered" if data_tuple[0] != constants.RS_NORMAL:
if result[constants.OOB_POWER_STATUS_POWERED]: if data_tuple[0] == constants.RS_UNAVAIL:
result = text % "" result = "OOB is not supported"
else: else:
result = text % "not " result = "RPC failed, look out for warning in the output"
ToStderr(result) ToStderr(result)
return constants.EXIT_FAILURE
else:
if oob_command == constants.OOB_POWER_STATUS:
text = "The machine is %spowered"
if data_tuple[1][constants.OOB_POWER_STATUS_POWERED]:
result = text % ""
else:
result = text % "not "
ToStdout(result)
return constants.EXIT_SUCCESS return constants.EXIT_SUCCESS
......
...@@ -3192,31 +3192,33 @@ class LUOobCommand(NoHooksLU): ...@@ -3192,31 +3192,33 @@ class LUOobCommand(NoHooksLU):
Any errors are signaled by raising errors.OpPrereqError. Any errors are signaled by raising errors.OpPrereqError.
""" """
self.op.node_name = _ExpandNodeName(self.cfg, self.op.node_name) self.nodes = []
node = self.cfg.GetNodeInfo(self.op.node_name) for node_name in self.op.node_names:
node = self.cfg.GetNodeInfo(node_name)
if node is None:
raise errors.OpPrereqError("Node %s not found" % self.op.node_name)
self.oob_program = _SupportsOob(self.cfg, node) if node is None:
raise errors.OpPrereqError("Node %s not found" % node_name,
if not self.oob_program: errors.ECODE_NOENT)
raise errors.OpPrereqError("OOB is not supported for node %s" % else:
self.op.node_name) self.nodes.append(node)
if self.op.command == constants.OOB_POWER_OFF and not node.offline:
raise errors.OpPrereqError(("Cannot power off node %s because it is"
" not marked offline") % self.op.node_name)
self.node = node if (self.op.command == constants.OOB_POWER_OFF and not node.offline):
raise errors.OpPrereqError(("Cannot power off node %s because it is"
" not marked offline") % node_name,
errors.ECODE_STATE)
def ExpandNames(self): def ExpandNames(self):
"""Gather locks we need. """Gather locks we need.
""" """
node_name = _ExpandNodeName(self.cfg, self.op.node_name) if self.op.node_names:
self.op.node_names = [_ExpandNodeName(self.cfg, name)
for name in self.op.node_names]
else:
self.op.node_names = self.cfg.GetNodeList()
self.needed_locks = { self.needed_locks = {
locking.LEVEL_NODE: [node_name], locking.LEVEL_NODE: self.op.node_names,
} }
def Exec(self, feedback_fn): def Exec(self, feedback_fn):
...@@ -3224,40 +3226,65 @@ class LUOobCommand(NoHooksLU): ...@@ -3224,40 +3226,65 @@ class LUOobCommand(NoHooksLU):
""" """
master_node = self.cfg.GetMasterNode() master_node = self.cfg.GetMasterNode()
node = self.node ret = []
logging.info("Executing out-of-band command '%s' using '%s' on %s", for node in self.nodes:
self.op.command, self.oob_program, self.op.node_name) node_entry = [(constants.RS_NORMAL, node.name)]
result = self.rpc.call_run_oob(master_node, self.oob_program, ret.append(node_entry)
self.op.command, self.op.node_name,
self.op.timeout)
result.Raise("An error occurred on execution of OOB helper") oob_program = _SupportsOob(self.cfg, node)
self._CheckPayload(result) if not oob_program:
node_entry.append((constants.RS_UNAVAIL, None))
continue
if self.op.command == constants.OOB_HEALTH: logging.info("Executing out-of-band command '%s' using '%s' on %s",
# For health we should log important events self.op.command, oob_program, node.name)
for item, status in result.payload: result = self.rpc.call_run_oob(master_node, oob_program,
if status in [constants.OOB_STATUS_WARNING, self.op.command, node.name,
constants.OOB_STATUS_CRITICAL]: self.op.timeout)
logging.warning("On node '%s' item '%s' has status '%s'",
self.op.node_name, item, status)
if self.op.command == constants.OOB_POWER_ON:
node.powered = True
elif self.op.command == constants.OOB_POWER_OFF:
node.powered = False
elif self.op.command == constants.OOB_POWER_STATUS:
powered = result.payload[constants.OOB_POWER_STATUS_POWERED]
if powered != self.node.powered:
logging.warning(("Recorded power state (%s) of node '%s' does not match"
" actual power state (%s)"), node.powered,
self.op.node_name, powered)
self.cfg.Update(node, feedback_fn) result.Raise("An error occurred on execution of OOB helper")
return result.payload if result.fail_msg:
self.LogWarning("On node '%s' out-of-band RPC failed with: %s",
node.name, result.fail_msg)
node_entry.append((constants.RS_NODATA, None))
else:
try:
self._CheckPayload(result)
except errors.OpExecError, err:
self.LogWarning("The payload returned by '%s' is not valid: %s",
node.name, err)
node_entry.append((constants.RS_NODATA, None))
else:
if self.op.command == constants.OOB_HEALTH:
# For health we should log important events
for item, status in result.payload:
if status in [constants.OOB_STATUS_WARNING,
constants.OOB_STATUS_CRITICAL]:
self.LogWarning("On node '%s' item '%s' has status '%s'",
node.name, item, status)
if self.op.command == constants.OOB_POWER_ON:
node.powered = True
elif self.op.command == constants.OOB_POWER_OFF:
node.powered = False
elif self.op.command == constants.OOB_POWER_STATUS:
powered = result.payload[constants.OOB_POWER_STATUS_POWERED]
if powered != node.powered:
logging.warning(("Recorded power state (%s) of node '%s' does not"
" match actual power state (%s)"), node.powered,
node.name, powered)
# For configuration changing commands we should update the node
if self.op.command in (constants.OOB_POWER_ON,
constants.OOB_POWER_OFF):
self.cfg.Update(node, feedback_fn)
node_entry.append((constants.RS_NORMAL, result.payload))
return ret
def _CheckPayload(self, result): def _CheckPayload(self, result):
"""Checks if the payload is valid. """Checks if the payload is valid.
......
...@@ -590,7 +590,7 @@ class OpQueryFields(OpCode): ...@@ -590,7 +590,7 @@ class OpQueryFields(OpCode):
class OpOobCommand(OpCode): class OpOobCommand(OpCode):
"""Interact with OOB.""" """Interact with OOB."""
OP_PARAMS = [ OP_PARAMS = [
_PNodeName, ("node_names", ht.EmptyList, ht.TListOf(ht.TNonEmptyString)),
("command", None, ht.TElemOf(constants.OOB_COMMANDS)), ("command", None, ht.TElemOf(constants.OOB_COMMANDS)),
("timeout", constants.OOB_TIMEOUT, ht.TInt), ("timeout", constants.OOB_TIMEOUT, ht.TInt),
] ]
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment