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