Revision aafee533 lib/client/gnt_node.py

b/lib/client/gnt_node.py
26 26
# W0614: Unused import %s from wildcard import (since we need cli)
27 27
# C0103: Invalid name gnt-node
28 28

  
29
import itertools
30

  
29 31
from ganeti.cli import *
30 32
from ganeti import cli
31 33
from ganeti import bootstrap
......
263 265
  @return: the desired exit code
264 266

  
265 267
  """
266
  cl = GetClient()
267
  force = opts.force
268
  if opts.dst_node is not None:
269
    ToStderr("New secondary node given (disabling iallocator), hence evacuating"
270
             " secondary instances only.")
271
    opts.secondary_only = True
272
    opts.primary_only = False
273

  
274
  if opts.secondary_only and opts.primary_only:
275
    raise errors.OpPrereqError("Only one of the --primary-only and"
276
                               " --secondary-only options can be passed",
277
                               errors.ECODE_INVAL)
278
  elif opts.primary_only:
279
    mode = constants.IALLOCATOR_NEVAC_PRI
280
  elif opts.secondary_only:
281
    mode = constants.IALLOCATOR_NEVAC_SEC
282
  else:
283
    mode = constants.IALLOCATOR_NEVAC_ALL
268 284

  
269
  dst_node = opts.dst_node
270
  iallocator = opts.iallocator
285
  # Determine affected instances
286
  fields = []
271 287

  
272
  op = opcodes.OpNodeEvacStrategy(nodes=args,
273
                                  iallocator=iallocator,
274
                                  remote_node=dst_node)
288
  if not opts.secondary_only:
289
    fields.append("pinst_list")
290
  if not opts.primary_only:
291
    fields.append("sinst_list")
275 292

  
276
  result = SubmitOpCode(op, cl=cl, opts=opts)
277
  if not result:
278
    # no instances to migrate
279
    ToStderr("No secondary instances on node(s) %s, exiting.",
293
  cl = GetClient()
294

  
295
  result = cl.QueryNodes(names=args, fields=fields, use_locking=False)
296
  instances = set(itertools.chain(*itertools.chain(*itertools.chain(result))))
297

  
298
  if not instances:
299
    # No instances to evacuate
300
    ToStderr("No instances to evacuate on node(s) %s, exiting.",
280 301
             utils.CommaJoin(args))
281 302
    return constants.EXIT_SUCCESS
282 303

  
283
  if not force and not AskUser("Relocate instance(s) %s from node(s) %s?" %
284
                               (",".join("'%s'" % name[0] for name in result),
285
                               utils.CommaJoin(args))):
304
  if not (opts.force or
305
          AskUser("Relocate instance(s) %s from node(s) %s?" %
306
                  (utils.CommaJoin(utils.NiceSort(instances)),
307
                   utils.CommaJoin(args)))):
286 308
    return constants.EXIT_CONFIRMATION
287 309

  
310
  # Evacuate node
311
  op = opcodes.OpNodeEvacuate(node_name=args[0], mode=mode,
312
                              remote_node=opts.dst_node,
313
                              iallocator=opts.iallocator,
314
                              early_release=opts.early_release)
315
  result = SubmitOpCode(op, cl=cl, opts=opts)
316

  
317
  # Keep track of submitted jobs
288 318
  jex = JobExecutor(cl=cl, opts=opts)
289
  for row in result:
290
    iname = row[0]
291
    node = row[1]
292
    ToStdout("Will relocate instance %s to node %s", iname, node)
293
    op = opcodes.OpInstanceReplaceDisks(instance_name=iname,
294
                                        remote_node=node, disks=[],
295
                                        mode=constants.REPLACE_DISK_CHG,
296
                                        early_release=opts.early_release)
297
    jex.QueueJob(iname, op)
319

  
320
  for (status, job_id) in result[constants.JOB_IDS_KEY]:
321
    jex.AddJobId(None, status, job_id)
322

  
298 323
  results = jex.GetResults()
299 324
  bad_cnt = len([row for row in results if not row[0]])
300 325
  if bad_cnt == 0:
301
    ToStdout("All %d instance(s) failed over successfully.", len(results))
326
    ToStdout("All instances evacuated successfully.")
302 327
    rcode = constants.EXIT_SUCCESS
303 328
  else:
304
    ToStdout("There were errors during the failover:\n"
305
             "%d error(s) out of %d instance(s).", bad_cnt, len(results))
329
    ToStdout("There were %s errors during the evacuation.", bad_cnt)
306 330
    rcode = constants.EXIT_FAILURE
331

  
307 332
  return rcode
308 333

  
309 334

  
......
835 860
    " [--no-node-setup] [--verbose]"
836 861
    " <node_name>",
837 862
    "Add a node to the cluster"),
838
  'evacuate': (
839
    EvacuateNode, [ArgNode(min=1)],
863
  "evacuate": (
864
    EvacuateNode, ARGS_ONE_NODE,
840 865
    [FORCE_OPT, IALLOCATOR_OPT, NEW_SECONDARY_OPT, EARLY_RELEASE_OPT,
841
     PRIORITY_OPT],
866
     PRIORITY_OPT, PRIMARY_ONLY_OPT, SECONDARY_ONLY_OPT],
842 867
    "[-f] {-I <iallocator> | -n <dst>} <node>",
843 868
    "Relocate the secondary instances from a node"
844
    " to other nodes (only for instances with drbd disk template)"),
869
    " to other nodes"),
845 870
  'failover': (
846 871
    FailoverNode, ARGS_ONE_NODE, [FORCE_OPT, IGNORE_CONSIST_OPT,
847 872
                                  IALLOCATOR_OPT, PRIORITY_OPT],

Also available in: Unified diff