255 |
255 |
raise errors.OpPrereqError("One and only one of the -n and -I"
|
256 |
256 |
" options must be passed", errors.ECODE_INVAL)
|
257 |
257 |
|
258 |
|
selected_fields = ["name", "sinst_list"]
|
259 |
|
src_node = args[0]
|
260 |
|
|
261 |
|
result = cl.QueryNodes(names=[src_node], fields=selected_fields,
|
262 |
|
use_locking=False)
|
263 |
|
src_node, sinst = result[0]
|
264 |
|
|
265 |
|
if not sinst:
|
266 |
|
ToStderr("No secondary instances on node %s, exiting.", src_node)
|
|
258 |
op = opcodes.OpNodeEvacuationStrategy(nodes=args,
|
|
259 |
iallocator=iallocator,
|
|
260 |
remote_node=dst_node)
|
|
261 |
|
|
262 |
result = SubmitOpCode(op, cl=cl, opts=opts)
|
|
263 |
if not result:
|
|
264 |
# no instances to migrate
|
|
265 |
ToStderr("No secondary instances on node(s) %s, exiting.",
|
|
266 |
utils.CommaJoin(args))
|
267 |
267 |
return constants.EXIT_SUCCESS
|
268 |
268 |
|
269 |
|
if dst_node is not None:
|
270 |
|
result = cl.QueryNodes(names=[dst_node], fields=["name"],
|
271 |
|
use_locking=False)
|
272 |
|
dst_node = result[0][0]
|
273 |
|
|
274 |
|
if src_node == dst_node:
|
275 |
|
raise errors.OpPrereqError("Evacuate node needs different source and"
|
276 |
|
" target nodes (node %s given twice)" %
|
277 |
|
src_node, errors.ECODE_INVAL)
|
278 |
|
txt_msg = "to node %s" % dst_node
|
279 |
|
else:
|
280 |
|
txt_msg = "using iallocator %s" % iallocator
|
281 |
|
|
282 |
|
sinst = utils.NiceSort(sinst)
|
283 |
|
|
284 |
|
if not force and not AskUser("Relocate instance(s) %s from node\n"
|
285 |
|
" %s %s?" %
|
286 |
|
(",".join("'%s'" % name for name in sinst),
|
287 |
|
src_node, txt_msg)):
|
|
269 |
if not force and not AskUser("Relocate instance(s) %s from node(s) %s?" %
|
|
270 |
(",".join("'%s'" % name[0] for name in result),
|
|
271 |
utils.CommaJoin(args))):
|
288 |
272 |
return constants.EXIT_CONFIRMATION
|
289 |
273 |
|
290 |
|
op = opcodes.OpEvacuateNode(node_name=args[0], remote_node=dst_node,
|
291 |
|
iallocator=iallocator)
|
292 |
|
SubmitOpCode(op, cl=cl, opts=opts)
|
|
274 |
jex = JobExecutor(cl=cl, opts=opts)
|
|
275 |
for row in result:
|
|
276 |
iname = row[0]
|
|
277 |
node = row[1]
|
|
278 |
ToStdout("Will relocate instance %s to node %s", iname, node)
|
|
279 |
op = opcodes.OpReplaceDisks(instance_name=iname,
|
|
280 |
remote_node=node, disks=[],
|
|
281 |
mode=constants.REPLACE_DISK_CHG,
|
|
282 |
early_release=opts.early_release)
|
|
283 |
jex.QueueJob(iname, op)
|
|
284 |
results = jex.GetResults()
|
|
285 |
bad_cnt = len([row for row in results if not row[0]])
|
|
286 |
if bad_cnt == 0:
|
|
287 |
ToStdout("All %d instance(s) failed over successfully.", len(results))
|
|
288 |
rcode = constants.EXIT_SUCCESS
|
|
289 |
else:
|
|
290 |
ToStdout("There were errors during the failover:\n"
|
|
291 |
"%d error(s) out of %d instance(s).", bad_cnt, len(results))
|
|
292 |
rcode = constants.EXIT_FAILURE
|
|
293 |
return rcode
|
293 |
294 |
|
294 |
295 |
|
295 |
296 |
def FailoverNode(opts, args):
|
... | ... | |
653 |
654 |
"[-s ip] [--readd] [--no-ssh-key-check] <node_name>",
|
654 |
655 |
"Add a node to the cluster"),
|
655 |
656 |
'evacuate': (
|
656 |
|
EvacuateNode, ARGS_ONE_NODE,
|
657 |
|
[FORCE_OPT, IALLOCATOR_OPT, NEW_SECONDARY_OPT],
|
|
657 |
EvacuateNode, [ArgNode(min=1)],
|
|
658 |
[FORCE_OPT, IALLOCATOR_OPT, NEW_SECONDARY_OPT, EARLY_RELEASE_OPT],
|
658 |
659 |
"[-f] {-I <iallocator> | -n <dst>} <node>",
|
659 |
660 |
"Relocate the secondary instances from a node"
|
660 |
661 |
" to other nodes (only for instances with drbd disk template)"),
|