On Mon, May 30, 2011 at 5:14 PM, Michael Hanselmann <[email protected]> wrote: > By default it'll now evacuate all instances from the node, not > just secondaries. > --- > lib/cli.py | 13 ++++++++ > lib/client/gnt_node.py | 73 > +++++++++++++++++++++++++++++++----------------- > man/gnt-node.rst | 11 ++++-- > 3 files changed, 67 insertions(+), 30 deletions(-) > > diff --git a/lib/cli.py b/lib/cli.py > index aba1f1b..6d260ed 100644 > --- a/lib/cli.py > +++ b/lib/cli.py > @@ -143,6 +143,7 @@ __all__ = [ > "POWER_DELAY_OPT", > "PREALLOC_WIPE_DISKS_OPT", > "PRIMARY_IP_VERSION_OPT", > + "PRIMARY_ONLY_OPT", > "PRIORITY_OPT", > "RAPI_CERT_OPT", > "READD_OPT", > @@ -152,6 +153,7 @@ __all__ = [ > "RESERVED_LVS_OPT", > "ROMAN_OPT", > "SECONDARY_IP_OPT", > + "SECONDARY_ONLY_OPT", > "SELECT_OS_OPT", > "SEP_OPT", > "SHOWCMD_OPT", > @@ -1205,6 +1207,17 @@ NO_REMEMBER_OPT = cli_option("--no-remember", > help="Perform but do not record the change" > " in the configuration") > > +PRIMARY_ONLY_OPT = cli_option("-p", "--primary-only", > + default=False, action="store_true", > + help="Evacuate primary instances only") > + > +SECONDARY_ONLY_OPT = cli_option("-s", "--secondary-only", > + default=False, action="store_true", > + help="Evacuate secondary instances only" > + " (applies only to internally mirrored" > + " disk templates, e.g. %s)" % > + > utils.CommaJoin(constants.DTS_INT_MIRROR)) > + > > #: Options provided by all commands > COMMON_OPTS = [DEBUG_OPT] > diff --git a/lib/client/gnt_node.py b/lib/client/gnt_node.py > index a56e449..7da4e66 100644 > --- a/lib/client/gnt_node.py > +++ b/lib/client/gnt_node.py > @@ -26,6 +26,8 @@ > # W0614: Unused import %s from wildcard import (since we need cli) > # C0103: Invalid name gnt-node > > +import itertools > + > from ganeti.cli import * > from ganeti import cli > from ganeti import bootstrap > @@ -263,47 +265,66 @@ def EvacuateNode(opts, args): > @return: the desired exit code > > """ > + if opts.dst_node is not None: > + ToStderr("New secondary node given (disabling iallocator), hence > evacuating" > + " secondary instances only.") > + opts.secondary_only = True > + opts.primary_only = False > + > + if opts.secondary_only and opts.primary_only: > + raise errors.OpPrereqError("Only one of the --primary-only and" > + " --secondary-only options can be passed", > + errors.ECODE_INVAL) > + > cl = GetClient() > - force = opts.force > > - dst_node = opts.dst_node > - iallocator = opts.iallocator > + # Determine affected instances > + fields = [] > > - op = opcodes.OpNodeEvacStrategy(nodes=args, > - iallocator=iallocator, > - remote_node=dst_node) > + if not opts.secondary_only: > + fields.append("pinst_list") > + if not opts.primary_only: > + fields.append("sinst_list") > > - result = SubmitOpCode(op, cl=cl, opts=opts) > - if not result: > - # no instances to migrate > - ToStderr("No secondary instances on node(s) %s, exiting.", > + result = cl.QueryNodes(names=args, fields=fields, use_locking=False) > + instances = > set(itertools.chain(*itertools.chain(*itertools.chain(result)))) > + > + if not instances: > + # No instances to evacuate > + ToStderr("No instances to evacuate on node(s) %s, exiting.", > utils.CommaJoin(args)) > return constants.EXIT_SUCCESS > > - 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))): > + if not (opts.force or > + AskUser("Relocate instance(s) %s from node(s) %s?" % > + (utils.CommaJoin(utils.NiceSort(instances)), > + utils.CommaJoin(args)))): > return constants.EXIT_CONFIRMATION > > + # Evacuate node > + op = opcodes.OpNodeEvacuate(nodes=args, > + remote_node=opts.dst_node, > + iallocator=opts.iallocator, > + primary=not opts.secondary_only, > + secondary=not opts.primary_only, > + early_release=opts.early_release) > + result = SubmitOpCode(op, cl=cl, opts=opts) > + > + # Keep track of submitted jobs > 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.OpInstanceReplaceDisks(instance_name=iname, > - remote_node=node, disks=[], > - mode=constants.REPLACE_DISK_CHG, > - early_release=opts.early_release) > - jex.QueueJob(iname, op) > + > + for (status, job_id) in result[constants.JOB_IDS_KEY]: > + jex.AddJobId(None, status, job_id) > + > 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)) > + ToStdout("All instances evacuated successfully.") > 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)) > + ToStdout("There were %s errors during the evacuation.", bad_cnt) > rcode = constants.EXIT_FAILURE > + > return rcode > > > @@ -838,7 +859,7 @@ commands = { > 'evacuate': ( > EvacuateNode, [ArgNode(min=1)], > [FORCE_OPT, IALLOCATOR_OPT, NEW_SECONDARY_OPT, EARLY_RELEASE_OPT, > - PRIORITY_OPT], > + PRIORITY_OPT, PRIMARY_ONLY_OPT, SECONDARY_ONLY_OPT], > "[-f] {-I <iallocator> | -n <dst>} <node>", > "Relocate the secondary instances from a node" > " to other nodes (only for instances with drbd disk template)"), > diff --git a/man/gnt-node.rst b/man/gnt-node.rst > index aa3a9f5..86683e9 100644 > --- a/man/gnt-node.rst > +++ b/man/gnt-node.rst > @@ -87,10 +87,14 @@ EVACUATE > ~~~~~~~~ > > **evacuate** [-f] [--early-release] [--iallocator *NAME* \| > ---new-secondary *destination\_node*] {*node*...} > +--new-secondary *destination\_node*] > +[--primary-only \| --secondary-only] [--early-release] {*node*...} > > -This command will move all secondary instances away from the given > -node(s). It works only for instances having a drbd disk template. > +This command will move instances away from the given node(s). If > +``--primary-only`` is given, only primary instances are evacuated, with > +``--secondary-only`` only secondaries. If neither is given, all > +instances are evacuated. It works only for instances having a drbd disk > +template. > > The new location for the instances can be specified in two ways: > > @@ -101,7 +105,6 @@ The new location for the instances can be specified in > two ways: > parameter, so each instance will be in turn placed on the (per the > script) optimal node > > - > The ``--early-release`` changes the code so that the old storage on > node being evacuated is removed early (before the resync is > completed) and the internal Ganeti locks are also released for both > -- > 1.7.3.5
LGTM > >
