Revision b04808ea

b/lib/client/gnt_node.py
491 491
    opcodelist.append(opcodes.OpNodeSetParams(node_name=node, offline=True,
492 492
                                              auto_promote=opts.auto_promote))
493 493

  
494
  opcodelist.append(opcodes.OpOobCommand(node_name=node, command=oob_command))
494
  opcodelist.append(opcodes.OpOobCommand(node_names=[node],
495
                                         command=oob_command))
495 496

  
496 497
  cli.SetGenericOpcodeOpts(opcodelist, opts)
497 498

  
......
502 503
  result = cli.PollJob(job_id)[-1]
503 504

  
504 505
  if result:
505
    if oob_command == constants.OOB_POWER_STATUS:
506
      text = "The machine is %spowered"
507
      if result[constants.OOB_POWER_STATUS_POWERED]:
508
        result = text % ""
506
    (_, data_tuple) = result[0]
507
    if data_tuple[0] != constants.RS_NORMAL:
508
      if data_tuple[0] == constants.RS_UNAVAIL:
509
        result = "OOB is not supported"
509 510
      else:
510
        result = text % "not "
511
    ToStderr(result)
511
        result = "RPC failed, look out for warning in the output"
512
      ToStderr(result)
513
      return constants.EXIT_FAILURE
514
    else:
515
      if oob_command == constants.OOB_POWER_STATUS:
516
        text = "The machine is %spowered"
517
        if data_tuple[1][constants.OOB_POWER_STATUS_POWERED]:
518
          result = text % ""
519
        else:
520
          result = text % "not "
521
        ToStdout(result)
512 522

  
513 523
  return constants.EXIT_SUCCESS
514 524

  
b/lib/cmdlib.py
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.
b/lib/opcodes.py
590 590
class OpOobCommand(OpCode):
591 591
  """Interact with OOB."""
592 592
  OP_PARAMS = [
593
    _PNodeName,
593
    ("node_names", ht.EmptyList, ht.TListOf(ht.TNonEmptyString)),
594 594
    ("command", None, ht.TElemOf(constants.OOB_COMMANDS)),
595 595
    ("timeout", constants.OOB_TIMEOUT, ht.TInt),
596 596
    ]

Also available in: Unified diff