3192 |
3192 |
Any errors are signaled by raising errors.OpPrereqError.
|
3193 |
3193 |
|
3194 |
3194 |
"""
|
3195 |
|
self.op.node_name = _ExpandNodeName(self.cfg, self.op.node_name)
|
3196 |
|
node = self.cfg.GetNodeInfo(self.op.node_name)
|
3197 |
|
|
3198 |
|
if node is None:
|
3199 |
|
raise errors.OpPrereqError("Node %s not found" % self.op.node_name)
|
|
3195 |
self.nodes = []
|
|
3196 |
for node_name in self.op.node_names:
|
|
3197 |
node = self.cfg.GetNodeInfo(node_name)
|
3200 |
3198 |
|
3201 |
|
self.oob_program = _SupportsOob(self.cfg, node)
|
3202 |
|
|
3203 |
|
if not self.oob_program:
|
3204 |
|
raise errors.OpPrereqError("OOB is not supported for node %s" %
|
3205 |
|
self.op.node_name)
|
3206 |
|
|
3207 |
|
if self.op.command == constants.OOB_POWER_OFF and not node.offline:
|
3208 |
|
raise errors.OpPrereqError(("Cannot power off node %s because it is"
|
3209 |
|
" not marked offline") % self.op.node_name)
|
|
3199 |
if node is None:
|
|
3200 |
raise errors.OpPrereqError("Node %s not found" % node_name,
|
|
3201 |
errors.ECODE_NOENT)
|
|
3202 |
else:
|
|
3203 |
self.nodes.append(node)
|
3210 |
3204 |
|
3211 |
|
self.node = node
|
|
3205 |
if (self.op.command == constants.OOB_POWER_OFF and not node.offline):
|
|
3206 |
raise errors.OpPrereqError(("Cannot power off node %s because it is"
|
|
3207 |
" not marked offline") % node_name,
|
|
3208 |
errors.ECODE_STATE)
|
3212 |
3209 |
|
3213 |
3210 |
def ExpandNames(self):
|
3214 |
3211 |
"""Gather locks we need.
|
3215 |
3212 |
|
3216 |
3213 |
"""
|
3217 |
|
node_name = _ExpandNodeName(self.cfg, self.op.node_name)
|
|
3214 |
if self.op.node_names:
|
|
3215 |
self.op.node_names = [_ExpandNodeName(self.cfg, name)
|
|
3216 |
for name in self.op.node_names]
|
|
3217 |
else:
|
|
3218 |
self.op.node_names = self.cfg.GetNodeList()
|
|
3219 |
|
3218 |
3220 |
self.needed_locks = {
|
3219 |
|
locking.LEVEL_NODE: [node_name],
|
|
3221 |
locking.LEVEL_NODE: self.op.node_names,
|
3220 |
3222 |
}
|
3221 |
3223 |
|
3222 |
3224 |
def Exec(self, feedback_fn):
|
... | ... | |
3224 |
3226 |
|
3225 |
3227 |
"""
|
3226 |
3228 |
master_node = self.cfg.GetMasterNode()
|
3227 |
|
node = self.node
|
|
3229 |
ret = []
|
3228 |
3230 |
|
3229 |
|
logging.info("Executing out-of-band command '%s' using '%s' on %s",
|
3230 |
|
self.op.command, self.oob_program, self.op.node_name)
|
3231 |
|
result = self.rpc.call_run_oob(master_node, self.oob_program,
|
3232 |
|
self.op.command, self.op.node_name,
|
3233 |
|
self.op.timeout)
|
|
3231 |
for node in self.nodes:
|
|
3232 |
node_entry = [(constants.RS_NORMAL, node.name)]
|
|
3233 |
ret.append(node_entry)
|
3234 |
3234 |
|
3235 |
|
result.Raise("An error occurred on execution of OOB helper")
|
|
3235 |
oob_program = _SupportsOob(self.cfg, node)
|
3236 |
3236 |
|
3237 |
|
self._CheckPayload(result)
|
|
3237 |
if not oob_program:
|
|
3238 |
node_entry.append((constants.RS_UNAVAIL, None))
|
|
3239 |
continue
|
3238 |
3240 |
|
3239 |
|
if self.op.command == constants.OOB_HEALTH:
|
3240 |
|
# For health we should log important events
|
3241 |
|
for item, status in result.payload:
|
3242 |
|
if status in [constants.OOB_STATUS_WARNING,
|
3243 |
|
constants.OOB_STATUS_CRITICAL]:
|
3244 |
|
logging.warning("On node '%s' item '%s' has status '%s'",
|
3245 |
|
self.op.node_name, item, status)
|
3246 |
|
|
3247 |
|
if self.op.command == constants.OOB_POWER_ON:
|
3248 |
|
node.powered = True
|
3249 |
|
elif self.op.command == constants.OOB_POWER_OFF:
|
3250 |
|
node.powered = False
|
3251 |
|
elif self.op.command == constants.OOB_POWER_STATUS:
|
3252 |
|
powered = result.payload[constants.OOB_POWER_STATUS_POWERED]
|
3253 |
|
if powered != self.node.powered:
|
3254 |
|
logging.warning(("Recorded power state (%s) of node '%s' does not match"
|
3255 |
|
" actual power state (%s)"), node.powered,
|
3256 |
|
self.op.node_name, powered)
|
|
3241 |
logging.info("Executing out-of-band command '%s' using '%s' on %s",
|
|
3242 |
self.op.command, oob_program, node.name)
|
|
3243 |
result = self.rpc.call_run_oob(master_node, oob_program,
|
|
3244 |
self.op.command, node.name,
|
|
3245 |
self.op.timeout)
|
3257 |
3246 |
|
3258 |
|
self.cfg.Update(node, feedback_fn)
|
|
3247 |
result.Raise("An error occurred on execution of OOB helper")
|
3259 |
3248 |
|
3260 |
|
return result.payload
|
|
3249 |
if result.fail_msg:
|
|
3250 |
self.LogWarning("On node '%s' out-of-band RPC failed with: %s",
|
|
3251 |
node.name, result.fail_msg)
|
|
3252 |
node_entry.append((constants.RS_NODATA, None))
|
|
3253 |
else:
|
|
3254 |
try:
|
|
3255 |
self._CheckPayload(result)
|
|
3256 |
except errors.OpExecError, err:
|
|
3257 |
self.LogWarning("The payload returned by '%s' is not valid: %s",
|
|
3258 |
node.name, err)
|
|
3259 |
node_entry.append((constants.RS_NODATA, None))
|
|
3260 |
else:
|
|
3261 |
if self.op.command == constants.OOB_HEALTH:
|
|
3262 |
# For health we should log important events
|
|
3263 |
for item, status in result.payload:
|
|
3264 |
if status in [constants.OOB_STATUS_WARNING,
|
|
3265 |
constants.OOB_STATUS_CRITICAL]:
|
|
3266 |
self.LogWarning("On node '%s' item '%s' has status '%s'",
|
|
3267 |
node.name, item, status)
|
|
3268 |
|
|
3269 |
if self.op.command == constants.OOB_POWER_ON:
|
|
3270 |
node.powered = True
|
|
3271 |
elif self.op.command == constants.OOB_POWER_OFF:
|
|
3272 |
node.powered = False
|
|
3273 |
elif self.op.command == constants.OOB_POWER_STATUS:
|
|
3274 |
powered = result.payload[constants.OOB_POWER_STATUS_POWERED]
|
|
3275 |
if powered != node.powered:
|
|
3276 |
logging.warning(("Recorded power state (%s) of node '%s' does not"
|
|
3277 |
" match actual power state (%s)"), node.powered,
|
|
3278 |
node.name, powered)
|
|
3279 |
|
|
3280 |
# For configuration changing commands we should update the node
|
|
3281 |
if self.op.command in (constants.OOB_POWER_ON,
|
|
3282 |
constants.OOB_POWER_OFF):
|
|
3283 |
self.cfg.Update(node, feedback_fn)
|
|
3284 |
|
|
3285 |
node_entry.append((constants.RS_NORMAL, result.payload))
|
|
3286 |
|
|
3287 |
return ret
|
3261 |
3288 |
|
3262 |
3289 |
def _CheckPayload(self, result):
|
3263 |
3290 |
"""Checks if the payload is valid.
|