raise errors.OpPrereqError("One and only one of the -n and -I"
" options must be passed", errors.ECODE_INVAL)
- selected_fields = ["name", "sinst_list"]
- src_node = args[0]
-
- result = cl.QueryNodes(names=[src_node], fields=selected_fields,
- use_locking=False)
- src_node, sinst = result[0]
-
- if not sinst:
- ToStderr("No secondary instances on node %s, exiting.", src_node)
+ op = opcodes.OpNodeEvacuationStrategy(nodes=args,
+ iallocator=iallocator,
+ remote_node=dst_node)
+
+ result = SubmitOpCode(op, cl=cl, opts=opts)
+ if not result:
+ # no instances to migrate
+ ToStderr("No secondary instances on node(s) %s, exiting.",
+ utils.CommaJoin(args))
return constants.EXIT_SUCCESS
- if dst_node is not None:
- result = cl.QueryNodes(names=[dst_node], fields=["name"],
- use_locking=False)
- dst_node = result[0][0]
-
- if src_node == dst_node:
- raise errors.OpPrereqError("Evacuate node needs different source and"
- " target nodes (node %s given twice)" %
- src_node, errors.ECODE_INVAL)
- txt_msg = "to node %s" % dst_node
- else:
- txt_msg = "using iallocator %s" % iallocator
-
- sinst = utils.NiceSort(sinst)
-
- if not force and not AskUser("Relocate instance(s) %s from node\n"
- " %s %s?" %
- (",".join("'%s'" % name for name in sinst),
- src_node, txt_msg)):
+ if not force and not AskUser("Relocate instance(s) %s from node(s) %s?" %
+ (",".join("'%s'" % name[0] for name in result),
+ utils.CommaJoin(args))):
return constants.EXIT_CONFIRMATION
- op = opcodes.OpEvacuateNode(node_name=args[0], remote_node=dst_node,
- iallocator=iallocator)
- SubmitOpCode(op, cl=cl, opts=opts)
+ jex = JobExecutor(cl=cl, opts=opts)
+ for row in result:
+ iname = row[0]
+ node = row[1]
+ ToStdout("Will relocate instance %s to node %s", iname, node)
+ op = opcodes.OpReplaceDisks(instance_name=iname,
+ remote_node=node, disks=[],
+ mode=constants.REPLACE_DISK_CHG,
+ early_release=opts.early_release)
+ jex.QueueJob(iname, op)
+ results = jex.GetResults()
+ bad_cnt = len([row for row in results if not row[0]])
+ if bad_cnt == 0:
+ ToStdout("All %d instance(s) failed over successfully.", len(results))
+ rcode = constants.EXIT_SUCCESS
+ else:
+ ToStdout("There were errors during the failover:\n"
+ "%d error(s) out of %d instance(s).", bad_cnt, len(results))
+ rcode = constants.EXIT_FAILURE
+ return rcode
def FailoverNode(opts, args):
"[-s ip] [--readd] [--no-ssh-key-check] <node_name>",
"Add a node to the cluster"),
'evacuate': (
- EvacuateNode, ARGS_ONE_NODE,
- [FORCE_OPT, IALLOCATOR_OPT, NEW_SECONDARY_OPT],
+ EvacuateNode, [ArgNode(min=1)],
+ [FORCE_OPT, IALLOCATOR_OPT, NEW_SECONDARY_OPT, EARLY_RELEASE_OPT],
"[-f] {-I <iallocator> | -n <dst>} <node>",
"Relocate the secondary instances from a node"
" to other nodes (only for instances with drbd disk template)"),