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

>
>

Reply via email to