+def EvacuateNode(opts, args):
+ """Relocate all secondary instance from a node.
+
+ @param opts: the command line options selected by the user
+ @type args: list
+ @param args: should be an empty list
+ @rtype: int
+ @return: the desired exit code
+
+ """
+ cl = GetClient()
+ force = opts.force
+
+ dst_node = opts.dst_node
+ iallocator = opts.iallocator
+
+ cnt = [dst_node, iallocator].count(None)
+ if cnt != 1:
+ raise errors.OpPrereqError("One and only one of the -n and -i"
+ " options must be passed")
+
+ 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)
+ 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)
+ 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)):
+ return constants.EXIT_CONFIRMATION
+
+ ops = []
+ for iname in sinst:
+ op = opcodes.OpReplaceDisks(instance_name=iname,
+ remote_node=dst_node,
+ mode=constants.REPLACE_DISK_CHG,
+ iallocator=iallocator,
+ disks=[])
+ ops.append(op)
+
+ job_id = cli.SendJob(ops, cl=cl)
+ cli.PollJob(job_id, cl=cl)
+
+
+def FailoverNode(opts, args):
+ """Failover all primary instance on a node.
+
+ @param opts: the command line options selected by the user
+ @type args: list
+ @param args: should be an empty list
+ @rtype: int
+ @return: the desired exit code
+
+ """
+ cl = GetClient()
+ force = opts.force
+ selected_fields = ["name", "pinst_list"]
+
+ # these fields are static data anyway, so it doesn't matter, but
+ # locking=True should be safer
+ result = cl.QueryNodes(names=args, fields=selected_fields,
+ use_locking=False)
+ node, pinst = result[0]
+
+ if not pinst:
+ ToStderr("No primary instances on node %s, exiting.", node)
+ return 0
+
+ pinst = utils.NiceSort(pinst)
+
+ retcode = 0
+
+ if not force and not AskUser("Fail over instance(s) %s?" %
+ (",".join("'%s'" % name for name in pinst))):
+ return 2
+
+ jex = JobExecutor(cl=cl)
+ for iname in pinst:
+ op = opcodes.OpFailoverInstance(instance_name=iname,
+ ignore_consistency=opts.ignore_consistency)
+ 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))
+ else:
+ ToStdout("There were errors during the failover:\n"
+ "%d error(s) out of %d instance(s).", bad_cnt, len(results))
+ return retcode
+
+
+def MigrateNode(opts, args):
+ """Migrate all primary instance on a node.
+
+ """
+ cl = GetClient()
+ force = opts.force
+ selected_fields = ["name", "pinst_list"]
+
+ result = cl.QueryNodes(names=args, fields=selected_fields, use_locking=False)
+ node, pinst = result[0]
+
+ if not pinst:
+ ToStdout("No primary instances on node %s, exiting." % node)
+ return 0
+
+ pinst = utils.NiceSort(pinst)
+
+ retcode = 0
+
+ if not force and not AskUser("Migrate instance(s) %s?" %
+ (",".join("'%s'" % name for name in pinst))):
+ return 2
+
+ jex = JobExecutor(cl=cl)
+ for iname in pinst:
+ op = opcodes.OpMigrateInstance(instance_name=iname, live=opts.live,
+ cleanup=False)
+ 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) migrated successfully.", len(results))
+ else:
+ ToStdout("There were errors during the migration:\n"
+ "%d error(s) out of %d instance(s).", bad_cnt, len(results))
+ return retcode
+
+