Revision 3a5ba66a

b/lib/cmdlib.py
2123 2123
    if node_name is None:
2124 2124
      raise errors.OpPrereqError("Invalid node name '%s'" % self.op.node_name)
2125 2125
    self.op.node_name = node_name
2126
    if not hasattr(self.op, 'master_candidate'):
2126
    _CheckBooleanOpField(self.op, 'master_candidate')
2127
    _CheckBooleanOpField(self.op, 'offline')
2128
    if self.op.master_candidate is None and self.op.offline is None:
2127 2129
      raise errors.OpPrereqError("Please pass at least one modification")
2128
    self.op.master_candidate = bool(self.op.master_candidate)
2130
    if self.op.offline == True and self.op.master_candidate == True:
2131
      raise errors.OpPrereqError("Can't set the node into offline and"
2132
                                 " master_candidate at the same time")
2129 2133

  
2130 2134
  def ExpandNames(self):
2131 2135
    self.needed_locks = {locking.LEVEL_NODE: self.op.node_name}
......
2139 2143
    env = {
2140 2144
      "OP_TARGET": self.op.node_name,
2141 2145
      "MASTER_CANDIDATE": str(self.op.master_candidate),
2146
      "OFFLINE": str(self.op.offline),
2142 2147
      }
2143 2148
    nl = [self.cfg.GetMasterNode(),
2144 2149
          self.op.node_name]
......
2150 2155
    This only checks the instance list against the existing names.
2151 2156

  
2152 2157
    """
2153
    force = self.force = self.op.force
2158
    node = self.node = self.cfg.GetNodeInfo(self.op.node_name)
2154 2159

  
2155
    if self.op.master_candidate == False:
2160
    if ((self.op.master_candidate == False or self.op.offline == True)
2161
        and node.master_candidate):
2162
      # we will demote the node from master_candidate
2156 2163
      if self.op.node_name == self.cfg.GetMasterNode():
2157 2164
        raise errors.OpPrereqError("The master node has to be a"
2158
                                   " master candidate")
2165
                                   " master candidate and online")
2159 2166
      cp_size = self.cfg.GetClusterInfo().candidate_pool_size
2160 2167
      node_info = self.cfg.GetAllNodesInfo().values()
2161
      num_candidates = len([node for node in node_info
2162
                            if node.master_candidate])
2168
      num_candidates, _ = self.cfg.GetMasterCandidateStats()
2163 2169
      if num_candidates <= cp_size:
2164 2170
        msg = ("Not enough master candidates (desired"
2165 2171
               " %d, new value will be %d)" % (cp_size, num_candidates-1))
2166
        if force:
2172
        if self.op.force:
2167 2173
          self.LogWarning(msg)
2168 2174
        else:
2169 2175
          raise errors.OpPrereqError(msg)
2170 2176

  
2177
    if (self.op.master_candidate == True and node.offline and
2178
        not self.op.offline == False):
2179
      raise errors.OpPrereqError("Can't set an offline node to"
2180
                                 " master_candidate")
2181

  
2171 2182
    return
2172 2183

  
2173 2184
  def Exec(self, feedback_fn):
2174 2185
    """Modifies a node.
2175 2186

  
2176 2187
    """
2177
    node = self.cfg.GetNodeInfo(self.op.node_name)
2188
    node = self.node
2178 2189

  
2179 2190
    result = []
2180 2191

  
2192
    if self.op.offline is not None:
2193
      node.offline = self.op.offline
2194
      result.append(("offline", str(self.op.offline)))
2195
      if self.op.offline == True and node.master_candidate:
2196
        node.master_candidate = False
2197
        result.append(("master_candidate", "auto-demotion due to offline"))
2198

  
2181 2199
    if self.op.master_candidate is not None:
2182 2200
      node.master_candidate = self.op.master_candidate
2183 2201
      result.append(("master_candidate", str(self.op.master_candidate)))
b/lib/opcodes.py
326 326
    "node_name",
327 327
    "force",
328 328
    "master_candidate",
329
    "offline",
329 330
    ]
330 331

  
331 332
# instance opcodes
b/scripts/gnt-node
379 379
  @return: the desired exit code
380 380

  
381 381
  """
382
  if opts.master_candidate is None:
382
  if opts.master_candidate is None and opts.offline is None:
383 383
    ToStderr("Please give at least one of the parameters.")
384 384
    return 1
385 385

  
386
  candidate = opts.master_candidate == 'yes'
386
  if opts.master_candidate is not None:
387
    candidate = opts.master_candidate == 'yes'
388
  else:
389
    candidate = None
390
  if opts.offline is not None:
391
    offline = opts.offline == 'yes'
392
  else:
393
    offline = None
387 394
  op = opcodes.OpSetNodeParams(node_name=args[0],
388
                              master_candidate=candidate,
389
                              force=opts.force)
395
                               master_candidate=candidate,
396
                               offline=offline,
397
                               force=opts.force)
390 398

  
391 399
  # even if here we process the result, we allow submit only
392 400
  result = SubmitOrSend(op, opts)
......
444 452
              make_option("-C", "--master-candidate", dest="master_candidate",
445 453
                          choices=('yes', 'no'), default=None,
446 454
                          help="Set the master_candidate flag on the node"),
455
              make_option("-O", "--offline", dest="offline",
456
                          choices=('yes', 'no'), default=None,
457
                          help="Set the offline flag on the node"),
447 458
              ],
448 459
             "<instance>", "Alters the parameters of an instance"),
449 460
  'remove': (RemoveNode, ARGS_ONE, [DEBUG_OPT],

Also available in: Unified diff