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):
opcodelist.append(opcodes.OpNodeSetParams(node_name=node, offline=True,
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)
......@@ -502,13 +503,22 @@ def PowerNode(opts, args):
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 % ""
(_, data_tuple) = result[0]
if data_tuple[0] != constants.RS_NORMAL:
if data_tuple[0] == constants.RS_UNAVAIL:
result = "OOB is not supported"
else:
result = text % "not "
ToStderr(result)
result = "RPC failed, look out for warning in the output"
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
......
......@@ -3192,31 +3192,33 @@ class LUOobCommand(NoHooksLU):
Any errors are signaled by raising errors.OpPrereqError.
"""
self.op.node_name = _ExpandNodeName(self.cfg, self.op.node_name)
node = self.cfg.GetNodeInfo(self.op.node_name)
if node is None:
raise errors.OpPrereqError("Node %s not found" % self.op.node_name)
self.nodes = []
for node_name in self.op.node_names:
node = self.cfg.GetNodeInfo(node_name)
self.oob_program = _SupportsOob(self.cfg, node)
if not self.oob_program:
raise errors.OpPrereqError("OOB is not supported for node %s" %
self.op.node_name)
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)
if node is None:
raise errors.OpPrereqError("Node %s not found" % node_name,
errors.ECODE_NOENT)
else:
self.nodes.append(node)
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):
"""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 = {
locking.LEVEL_NODE: [node_name],
locking.LEVEL_NODE: self.op.node_names,
}
def Exec(self, feedback_fn):
......@@ -3224,40 +3226,65 @@ class LUOobCommand(NoHooksLU):
"""
master_node = self.cfg.GetMasterNode()
node = self.node
ret = []
logging.info("Executing out-of-band command '%s' using '%s' on %s",
self.op.command, self.oob_program, self.op.node_name)
result = self.rpc.call_run_oob(master_node, self.oob_program,
self.op.command, self.op.node_name,
self.op.timeout)
for node in self.nodes:
node_entry = [(constants.RS_NORMAL, node.name)]
ret.append(node_entry)
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:
# For health we should log important events
for item, status in result.payload:
if status in [constants.OOB_STATUS_WARNING,
constants.OOB_STATUS_CRITICAL]:
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)
logging.info("Executing out-of-band command '%s' using '%s' on %s",
self.op.command, oob_program, node.name)
result = self.rpc.call_run_oob(master_node, oob_program,
self.op.command, node.name,
self.op.timeout)
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):
"""Checks if the payload is valid.
......
......@@ -590,7 +590,7 @@ class OpQueryFields(OpCode):
class OpOobCommand(OpCode):
"""Interact with OOB."""
OP_PARAMS = [
_PNodeName,
("node_names", ht.EmptyList, ht.TListOf(ht.TNonEmptyString)),
("command", None, ht.TElemOf(constants.OOB_COMMANDS)),
("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