#
#

# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2014 Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""Instance related commands"""

# pylint: disable=W0401,W0614,C0103
# W0401: Wildcard import ganeti.cli
# W0614: Unused import %s from wildcard import (since we need cli)
# C0103: Invalid name gnt-instance

import copy
import itertools
import simplejson
import logging

from ganeti.cli import *
from ganeti import opcodes
from ganeti import constants
from ganeti import compat
from ganeti import utils
from ganeti import errors
from ganeti import netutils
from ganeti import ssh
from ganeti import objects
from ganeti import ht


_EXPAND_CLUSTER = "cluster"
_EXPAND_NODES_BOTH = "nodes"
_EXPAND_NODES_PRI = "nodes-pri"
_EXPAND_NODES_SEC = "nodes-sec"
_EXPAND_NODES_BOTH_BY_TAGS = "nodes-by-tags"
_EXPAND_NODES_PRI_BY_TAGS = "nodes-pri-by-tags"
_EXPAND_NODES_SEC_BY_TAGS = "nodes-sec-by-tags"
_EXPAND_INSTANCES = "instances"
_EXPAND_INSTANCES_BY_TAGS = "instances-by-tags"

_EXPAND_NODES_TAGS_MODES = compat.UniqueFrozenset([
  _EXPAND_NODES_BOTH_BY_TAGS,
  _EXPAND_NODES_PRI_BY_TAGS,
  _EXPAND_NODES_SEC_BY_TAGS,
  ])

#: default list of options for L{ListInstances}
_LIST_DEF_FIELDS = [
  "name", "hypervisor", "os", "pnode", "status", "oper_ram",
  ]

_MISSING = object()
_ENV_OVERRIDE = compat.UniqueFrozenset(["list"])

_INST_DATA_VAL = ht.TListOf(ht.TDict)


def _ExpandMultiNames(mode, names, client=None):
  """Expand the given names using the passed mode.

  For _EXPAND_CLUSTER, all instances will be returned. For
  _EXPAND_NODES_PRI/SEC, all instances having those nodes as
  primary/secondary will be returned. For _EXPAND_NODES_BOTH, all
  instances having those nodes as either primary or secondary will be
  returned. For _EXPAND_INSTANCES, the given instances will be
  returned.

  @param mode: one of L{_EXPAND_CLUSTER}, L{_EXPAND_NODES_BOTH},
      L{_EXPAND_NODES_PRI}, L{_EXPAND_NODES_SEC} or
      L{_EXPAND_INSTANCES}
  @param names: a list of names; for cluster, it must be empty,
      and for node and instance it must be a list of valid item
      names (short names are valid as usual, e.g. node1 instead of
      node1.example.com)
  @rtype: list
  @return: the list of names after the expansion
  @raise errors.ProgrammerError: for unknown selection type
  @raise errors.OpPrereqError: for invalid input parameters

  """
  # pylint: disable=W0142

  if client is None:
    client = GetClient()
  if mode == _EXPAND_CLUSTER:
    if names:
      raise errors.OpPrereqError("Cluster filter mode takes no arguments",
                                 errors.ECODE_INVAL)
    idata = client.QueryInstances([], ["name"], False)
    inames = [row[0] for row in idata]

  elif (mode in _EXPAND_NODES_TAGS_MODES or
        mode in (_EXPAND_NODES_BOTH, _EXPAND_NODES_PRI, _EXPAND_NODES_SEC)):
    if mode in _EXPAND_NODES_TAGS_MODES:
      if not names:
        raise errors.OpPrereqError("No node tags passed", errors.ECODE_INVAL)
      ndata = client.QueryNodes([], ["name", "pinst_list",
                                     "sinst_list", "tags"], False)
      ndata = [row for row in ndata if set(row[3]).intersection(names)]
    else:
      if not names:
        raise errors.OpPrereqError("No node names passed", errors.ECODE_INVAL)
      ndata = client.QueryNodes(names, ["name", "pinst_list", "sinst_list"],
                                False)

    ipri = [row[1] for row in ndata]
    pri_names = list(itertools.chain(*ipri))
    isec = [row[2] for row in ndata]
    sec_names = list(itertools.chain(*isec))
    if mode in (_EXPAND_NODES_BOTH, _EXPAND_NODES_BOTH_BY_TAGS):
      inames = pri_names + sec_names
    elif mode in (_EXPAND_NODES_PRI, _EXPAND_NODES_PRI_BY_TAGS):
      inames = pri_names
    elif mode in (_EXPAND_NODES_SEC, _EXPAND_NODES_SEC_BY_TAGS):
      inames = sec_names
    else:
      raise errors.ProgrammerError("Unhandled shutdown type")
  elif mode == _EXPAND_INSTANCES:
    if not names:
      raise errors.OpPrereqError("No instance names passed",
                                 errors.ECODE_INVAL)
    idata = client.QueryInstances(names, ["name"], False)
    inames = [row[0] for row in idata]
  elif mode == _EXPAND_INSTANCES_BY_TAGS:
    if not names:
      raise errors.OpPrereqError("No instance tags passed",
                                 errors.ECODE_INVAL)
    idata = client.QueryInstances([], ["name", "tags"], False)
    inames = [row[0] for row in idata if set(row[1]).intersection(names)]
  else:
    raise errors.OpPrereqError("Unknown mode '%s'" % mode, errors.ECODE_INVAL)

  return inames


def _EnsureInstancesExist(client, names):
  """Check for and ensure the given instance names exist.

  This function will raise an OpPrereqError in case they don't
  exist. Otherwise it will exit cleanly.

  @type client: L{ganeti.luxi.Client}
  @param client: the client to use for the query
  @type names: list
  @param names: the list of instance names to query
  @raise errors.OpPrereqError: in case any instance is missing

  """
  # TODO: change LUInstanceQuery to that it actually returns None
  # instead of raising an exception, or devise a better mechanism
  result = client.QueryInstances(names, ["name"], False)
  for orig_name, row in zip(names, result):
    if row[0] is None:
      raise errors.OpPrereqError("Instance '%s' does not exist" % orig_name,
                                 errors.ECODE_NOENT)


def GenericManyOps(operation, fn):
  """Generic multi-instance operations.

  The will return a wrapper that processes the options and arguments
  given, and uses the passed function to build the opcode needed for
  the specific operation. Thus all the generic loop/confirmation code
  is abstracted into this function.

  """
  def realfn(opts, args):
    if opts.multi_mode is None:
      opts.multi_mode = _EXPAND_INSTANCES
    cl = GetClient()
    inames = _ExpandMultiNames(opts.multi_mode, args, client=cl)
    if not inames:
      if opts.multi_mode == _EXPAND_CLUSTER:
        ToStdout("Cluster is empty, no instances to shutdown")
        return 0
      raise errors.OpPrereqError("Selection filter does not match"
                                 " any instances", errors.ECODE_INVAL)
    multi_on = opts.multi_mode != _EXPAND_INSTANCES or len(inames) > 1
    if not (opts.force_multi or not multi_on
            or ConfirmOperation(inames, "instances", operation)):
      return 1
    jex = JobExecutor(verbose=multi_on, cl=cl, opts=opts)
    for name in inames:
      op = fn(name, opts)
      jex.QueueJob(name, op)
    results = jex.WaitOrShow(not opts.submit_only)
    rcode = compat.all(row[0] for row in results)
    return int(not rcode)
  return realfn


def ListInstances(opts, args):
  """List instances and their properties.

  @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

  """
  selected_fields = ParseFields(opts.output, _LIST_DEF_FIELDS)

  fmtoverride = dict.fromkeys(["tags", "disk.sizes", "nic.macs", "nic.ips",
                               "nic.modes", "nic.links", "nic.bridges",
                               "nic.networks",
                               "snodes", "snodes.group", "snodes.group.uuid"],
                              (lambda value: ",".join(str(item)
                                                      for item in value),
                               False))

  cl = GetClient()

  return GenericList(constants.QR_INSTANCE, selected_fields, args, opts.units,
                     opts.separator, not opts.no_headers,
                     format_override=fmtoverride, verbose=opts.verbose,
                     force_filter=opts.force_filter, cl=cl)


def ListInstanceFields(opts, args):
  """List instance fields.

  @param opts: the command line options selected by the user
  @type args: list
  @param args: fields to list, or empty for all
  @rtype: int
  @return: the desired exit code

  """
  return GenericListFields(constants.QR_INSTANCE, args, opts.separator,
                           not opts.no_headers)


def AddInstance(opts, args):
  """Add an instance to the cluster.

  This is just a wrapper over L{GenericInstanceCreate}.

  """
  return GenericInstanceCreate(constants.INSTANCE_CREATE, opts, args)


def BatchCreate(opts, args):
  """Create instances using a definition file.

  This function reads a json file with L{opcodes.OpInstanceCreate}
  serialisations.

  @param opts: the command line options selected by the user
  @type args: list
  @param args: should contain one element, the json filename
  @rtype: int
  @return: the desired exit code

  """
  (json_filename,) = args
  cl = GetClient()

  try:
    instance_data = simplejson.loads(utils.ReadFile(json_filename))
  except Exception, err: # pylint: disable=W0703
    ToStderr("Can't parse the instance definition file: %s" % str(err))
    return 1

  if not _INST_DATA_VAL(instance_data):
    ToStderr("The instance definition file is not %s" % _INST_DATA_VAL)
    return 1

  instances = []
  possible_params = set(opcodes.OpInstanceCreate.GetAllSlots())
  for (idx, inst) in enumerate(instance_data):
    unknown = set(inst.keys()) - possible_params

    if unknown:
      # TODO: Suggest closest match for more user friendly experience
      raise errors.OpPrereqError("Unknown fields in definition %s: %s" %
                                 (idx, utils.CommaJoin(unknown)),
                                 errors.ECODE_INVAL)

    op = opcodes.OpInstanceCreate(**inst) # pylint: disable=W0142
    op.Validate(False)
    instances.append(op)

  op = opcodes.OpInstanceMultiAlloc(iallocator=opts.iallocator,
                                    instances=instances)
  result = SubmitOrSend(op, opts, cl=cl)

  # Keep track of submitted jobs
  jex = JobExecutor(cl=cl, opts=opts)

  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 instances created successfully.")
    rcode = constants.EXIT_SUCCESS
  else:
    ToStdout("There were %s errors during the creation.", bad_cnt)
    rcode = constants.EXIT_FAILURE

  return rcode


def ReinstallInstance(opts, args):
  """Reinstall an instance.

  @param opts: the command line options selected by the user
  @type args: list
  @param args: should contain only one element, the name of the
      instance to be reinstalled
  @rtype: int
  @return: the desired exit code

  """
  # first, compute the desired name list
  if opts.multi_mode is None:
    opts.multi_mode = _EXPAND_INSTANCES

  inames = _ExpandMultiNames(opts.multi_mode, args)
  if not inames:
    raise errors.OpPrereqError("Selection filter does not match any instances",
                               errors.ECODE_INVAL)

  # second, if requested, ask for an OS
  if opts.select_os is True:
    op = opcodes.OpOsDiagnose(output_fields=["name", "variants"], names=[])
    result = SubmitOpCode(op, opts=opts)

    if not result:
      ToStdout("Can't get the OS list")
      return 1

    ToStdout("Available OS templates:")
    number = 0
    choices = []
    for (name, variants) in result:
      for entry in CalculateOSNames(name, variants):
        ToStdout("%3s: %s", number, entry)
        choices.append(("%s" % number, entry, entry))
        number += 1

    choices.append(("x", "exit", "Exit gnt-instance reinstall"))
    selected = AskUser("Enter OS template number (or x to abort):",
                       choices)

    if selected == "exit":
      ToStderr("User aborted reinstall, exiting")
      return 1

    os_name = selected
    os_msg = "change the OS to '%s'" % selected
  else:
    os_name = opts.os
    if opts.os is not None:
      os_msg = "change the OS to '%s'" % os_name
    else:
      os_msg = "keep the same OS"

  # third, get confirmation: multi-reinstall requires --force-multi,
  # single-reinstall either --force or --force-multi (--force-multi is
  # a stronger --force)
  multi_on = opts.multi_mode != _EXPAND_INSTANCES or len(inames) > 1
  if multi_on:
    warn_msg = ("Note: this will remove *all* data for the"
                " below instances! It will %s.\n" % os_msg)
    if not (opts.force_multi or
            ConfirmOperation(inames, "instances", "reinstall", extra=warn_msg)):
      return 1
  else:
    if not (opts.force or opts.force_multi):
      usertext = ("This will reinstall the instance '%s' (and %s) which"
                  " removes all data. Continue?") % (inames[0], os_msg)
      if not AskUser(usertext):
        return 1

  jex = JobExecutor(verbose=multi_on, opts=opts)
  for instance_name in inames:
    op = opcodes.OpInstanceReinstall(instance_name=instance_name,
                                     os_type=os_name,
                                     force_variant=opts.force_variant,
                                     osparams=opts.osparams,
                                     osparams_private=opts.osparams_private,
                                     osparams_secret=opts.osparams_secret)
    jex.QueueJob(instance_name, op)

  results = jex.WaitOrShow(not opts.submit_only)

  if compat.all(map(compat.fst, results)):
    return constants.EXIT_SUCCESS
  else:
    return constants.EXIT_FAILURE


def RemoveInstance(opts, args):
  """Remove an instance.

  @param opts: the command line options selected by the user
  @type args: list
  @param args: should contain only one element, the name of
      the instance to be removed
  @rtype: int
  @return: the desired exit code

  """
  instance_name = args[0]
  force = opts.force
  cl = GetClient()

  if not force:
    _EnsureInstancesExist(cl, [instance_name])

    usertext = ("This will remove the volumes of the instance %s"
                " (including mirrors), thus removing all the data"
                " of the instance. Continue?") % instance_name
    if not AskUser(usertext):
      return 1

  op = opcodes.OpInstanceRemove(instance_name=instance_name,
                                ignore_failures=opts.ignore_failures,
                                shutdown_timeout=opts.shutdown_timeout)
  SubmitOrSend(op, opts, cl=cl)
  return 0


def RenameInstance(opts, args):
  """Rename an instance.

  @param opts: the command line options selected by the user
  @type args: list
  @param args: should contain two elements, the old and the
      new instance names
  @rtype: int
  @return: the desired exit code

  """
  if not opts.name_check:
    if not AskUser("As you disabled the check of the DNS entry, please verify"
                   " that '%s' is a FQDN. Continue?" % args[1]):
      return 1

  op = opcodes.OpInstanceRename(instance_name=args[0],
                                new_name=args[1],
                                ip_check=opts.ip_check,
                                name_check=opts.name_check)
  result = SubmitOrSend(op, opts)

  if result:
    ToStdout("Instance '%s' renamed to '%s'", args[0], result)

  return 0


def ActivateDisks(opts, args):
  """Activate an instance's disks.

  This serves two purposes:
    - it allows (as long as the instance is not running)
      mounting the disks and modifying them from the node
    - it repairs inactive secondary drbds

  @param opts: the command line options selected by the user
  @type args: list
  @param args: should contain only one element, the instance name
  @rtype: int
  @return: the desired exit code

  """
  instance_name = args[0]
  op = opcodes.OpInstanceActivateDisks(instance_name=instance_name,
                                       ignore_size=opts.ignore_size,
                                       wait_for_sync=opts.wait_for_sync)
  disks_info = SubmitOrSend(op, opts)
  for host, iname, nname in disks_info:
    ToStdout("%s:%s:%s", host, iname, nname)
  return 0


def DeactivateDisks(opts, args):
  """Deactivate an instance's disks.

  This function takes the instance name, looks for its primary node
  and the tries to shutdown its block devices on that node.

  @param opts: the command line options selected by the user
  @type args: list
  @param args: should contain only one element, the instance name
  @rtype: int
  @return: the desired exit code

  """
  instance_name = args[0]
  op = opcodes.OpInstanceDeactivateDisks(instance_name=instance_name,
                                         force=opts.force)
  SubmitOrSend(op, opts)
  return 0


def RecreateDisks(opts, args):
  """Recreate an instance's disks.

  @param opts: the command line options selected by the user
  @type args: list
  @param args: should contain only one element, the instance name
  @rtype: int
  @return: the desired exit code

  """
  instance_name = args[0]

  disks = []

  if opts.disks:
    for didx, ddict in opts.disks:
      didx = int(didx)

      if not ht.TDict(ddict):
        msg = "Invalid disk/%d value: expected dict, got %s" % (didx, ddict)
        raise errors.OpPrereqError(msg, errors.ECODE_INVAL)

      if constants.IDISK_SIZE in ddict:
        try:
          ddict[constants.IDISK_SIZE] = \
            utils.ParseUnit(ddict[constants.IDISK_SIZE])
        except ValueError, err:
          raise errors.OpPrereqError("Invalid disk size for disk %d: %s" %
                                     (didx, err), errors.ECODE_INVAL)

      if constants.IDISK_SPINDLES in ddict:
        try:
          ddict[constants.IDISK_SPINDLES] = \
              int(ddict[constants.IDISK_SPINDLES])
        except ValueError, err:
          raise errors.OpPrereqError("Invalid spindles for disk %d: %s" %
                                     (didx, err), errors.ECODE_INVAL)

      disks.append((didx, ddict))

    # TODO: Verify modifyable parameters (already done in
    # LUInstanceRecreateDisks, but it'd be nice to have in the client)

  if opts.node:
    if opts.iallocator:
      msg = "At most one of either --nodes or --iallocator can be passed"
      raise errors.OpPrereqError(msg, errors.ECODE_INVAL)
    pnode, snode = SplitNodeOption(opts.node)
    nodes = [pnode]
    if snode is not None:
      nodes.append(snode)
  else:
    nodes = []

  op = opcodes.OpInstanceRecreateDisks(instance_name=instance_name,
                                       disks=disks, nodes=nodes,
                                       iallocator=opts.iallocator)
  SubmitOrSend(op, opts)

  return 0


def GrowDisk(opts, args):
  """Grow an instance's disks.

  @param opts: the command line options selected by the user
  @type args: list
  @param args: should contain three elements, the target instance name,
      the target disk id, and the target growth
  @rtype: int
  @return: the desired exit code

  """
  instance = args[0]
  disk = args[1]
  try:
    disk = int(disk)
  except (TypeError, ValueError), err:
    raise errors.OpPrereqError("Invalid disk index: %s" % str(err),
                               errors.ECODE_INVAL)
  try:
    amount = utils.ParseUnit(args[2])
  except errors.UnitParseError:
    raise errors.OpPrereqError("Can't parse the given amount '%s'" % args[2],
                               errors.ECODE_INVAL)
  op = opcodes.OpInstanceGrowDisk(instance_name=instance,
                                  disk=disk, amount=amount,
                                  wait_for_sync=opts.wait_for_sync,
                                  absolute=opts.absolute,
                                  ignore_ipolicy=opts.ignore_ipolicy
                                  )
  SubmitOrSend(op, opts)
  return 0


def _StartupInstance(name, opts):
  """Startup instances.

  This returns the opcode to start an instance, and its decorator will
  wrap this into a loop starting all desired instances.

  @param name: the name of the instance to act on
  @param opts: the command line options selected by the user
  @return: the opcode needed for the operation

  """
  op = opcodes.OpInstanceStartup(instance_name=name,
                                 force=opts.force,
                                 ignore_offline_nodes=opts.ignore_offline,
                                 no_remember=opts.no_remember,
                                 startup_paused=opts.startup_paused)
  # do not add these parameters to the opcode unless they're defined
  if opts.hvparams:
    op.hvparams = opts.hvparams
  if opts.beparams:
    op.beparams = opts.beparams
  return op


def _RebootInstance(name, opts):
  """Reboot instance(s).

  This returns the opcode to reboot an instance, and its decorator
  will wrap this into a loop rebooting all desired instances.

  @param name: the name of the instance to act on
  @param opts: the command line options selected by the user
  @return: the opcode needed for the operation

  """
  return opcodes.OpInstanceReboot(instance_name=name,
                                  reboot_type=opts.reboot_type,
                                  ignore_secondaries=opts.ignore_secondaries,
                                  shutdown_timeout=opts.shutdown_timeout)


def _ShutdownInstance(name, opts):
  """Shutdown an instance.

  This returns the opcode to shutdown an instance, and its decorator
  will wrap this into a loop shutting down all desired instances.

  @param name: the name of the instance to act on
  @param opts: the command line options selected by the user
  @return: the opcode needed for the operation

  """
  return opcodes.OpInstanceShutdown(instance_name=name,
                                    force=opts.force,
                                    timeout=opts.timeout,
                                    ignore_offline_nodes=opts.ignore_offline,
                                    no_remember=opts.no_remember)


def ReplaceDisks(opts, args):
  """Replace the disks of an instance

  @param opts: the command line options selected by the user
  @type args: list
  @param args: should contain only one element, the instance name
  @rtype: int
  @return: the desired exit code

  """
  new_2ndary = opts.dst_node
  iallocator = opts.iallocator
  if opts.disks is None:
    disks = []
  else:
    try:
      disks = [int(i) for i in opts.disks.split(",")]
    except (TypeError, ValueError), err:
      raise errors.OpPrereqError("Invalid disk index passed: %s" % str(err),
                                 errors.ECODE_INVAL)
  cnt = [opts.on_primary, opts.on_secondary, opts.auto,
         new_2ndary is not None, iallocator is not None].count(True)
  if cnt != 1:
    raise errors.OpPrereqError("One and only one of the -p, -s, -a, -n and -I"
                               " options must be passed", errors.ECODE_INVAL)
  elif opts.on_primary:
    mode = constants.REPLACE_DISK_PRI
  elif opts.on_secondary:
    mode = constants.REPLACE_DISK_SEC
  elif opts.auto:
    mode = constants.REPLACE_DISK_AUTO
    if disks:
      raise errors.OpPrereqError("Cannot specify disks when using automatic"
                                 " mode", errors.ECODE_INVAL)
  elif new_2ndary is not None or iallocator is not None:
    # replace secondary
    mode = constants.REPLACE_DISK_CHG

  op = opcodes.OpInstanceReplaceDisks(instance_name=args[0], disks=disks,
                                      remote_node=new_2ndary, mode=mode,
                                      iallocator=iallocator,
                                      early_release=opts.early_release,
                                      ignore_ipolicy=opts.ignore_ipolicy)
  SubmitOrSend(op, opts)
  return 0


def FailoverInstance(opts, args):
  """Failover an instance.

  The failover is done by shutting it down on its present node and
  starting it on the secondary.

  @param opts: the command line options selected by the user
  @type args: list
  @param args: should contain only one element, the instance name
  @rtype: int
  @return: the desired exit code

  """
  cl = GetClient()
  instance_name = args[0]
  force = opts.force
  iallocator = opts.iallocator
  target_node = opts.dst_node

  if iallocator and target_node:
    raise errors.OpPrereqError("Specify either an iallocator (-I), or a target"
                               " node (-n) but not both", errors.ECODE_INVAL)

  if not force:
    _EnsureInstancesExist(cl, [instance_name])

    usertext = ("Failover will happen to image %s."
                " This requires a shutdown of the instance. Continue?" %
                (instance_name,))
    if not AskUser(usertext):
      return 1

  op = opcodes.OpInstanceFailover(instance_name=instance_name,
                                  ignore_consistency=opts.ignore_consistency,
                                  shutdown_timeout=opts.shutdown_timeout,
                                  iallocator=iallocator,
                                  target_node=target_node,
                                  ignore_ipolicy=opts.ignore_ipolicy)
  SubmitOrSend(op, opts, cl=cl)
  return 0


def MigrateInstance(opts, args):
  """Migrate an instance.

  The migrate is done without shutdown.

  @param opts: the command line options selected by the user
  @type args: list
  @param args: should contain only one element, the instance name
  @rtype: int
  @return: the desired exit code

  """
  cl = GetClient()
  instance_name = args[0]
  force = opts.force
  iallocator = opts.iallocator
  target_node = opts.dst_node

  if iallocator and target_node:
    raise errors.OpPrereqError("Specify either an iallocator (-I), or a target"
                               " node (-n) but not both", errors.ECODE_INVAL)

  if not force:
    _EnsureInstancesExist(cl, [instance_name])

    if opts.cleanup:
      usertext = ("Instance %s will be recovered from a failed migration."
                  " Note that the migration procedure (including cleanup)" %
                  (instance_name,))
    else:
      usertext = ("Instance %s will be migrated. Note that migration" %
                  (instance_name,))
    usertext += (" might impact the instance if anything goes wrong"
                 " (e.g. due to bugs in the hypervisor). Continue?")
    if not AskUser(usertext):
      return 1

  # this should be removed once --non-live is deprecated
  if not opts.live and opts.migration_mode is not None:
    raise errors.OpPrereqError("Only one of the --non-live and "
                               "--migration-mode options can be passed",
                               errors.ECODE_INVAL)
  if not opts.live: # --non-live passed
    mode = constants.HT_MIGRATION_NONLIVE
  else:
    mode = opts.migration_mode

  op = opcodes.OpInstanceMigrate(instance_name=instance_name, mode=mode,
                                 cleanup=opts.cleanup, iallocator=iallocator,
                                 target_node=target_node,
                                 allow_failover=opts.allow_failover,
                                 allow_runtime_changes=opts.allow_runtime_chgs,
                                 ignore_ipolicy=opts.ignore_ipolicy,
                                 ignore_hvversions=opts.ignore_hvversions)
  SubmitOrSend(op, cl=cl, opts=opts)
  return 0


def MoveInstance(opts, args):
  """Move an instance.

  @param opts: the command line options selected by the user
  @type args: list
  @param args: should contain only one element, the instance name
  @rtype: int
  @return: the desired exit code

  """
  cl = GetClient()
  instance_name = args[0]
  force = opts.force

  if not force:
    usertext = ("Instance %s will be moved."
                " This requires a shutdown of the instance. Continue?" %
                (instance_name,))
    if not AskUser(usertext):
      return 1

  op = opcodes.OpInstanceMove(instance_name=instance_name,
                              target_node=opts.node,
                              compress=opts.compress,
                              shutdown_timeout=opts.shutdown_timeout,
                              ignore_consistency=opts.ignore_consistency,
                              ignore_ipolicy=opts.ignore_ipolicy)
  SubmitOrSend(op, opts, cl=cl)
  return 0


def ConnectToInstanceConsole(opts, args):
  """Connect to the console of an instance.

  @param opts: the command line options selected by the user
  @type args: list
  @param args: should contain only one element, the instance name
  @rtype: int
  @return: the desired exit code

  """
  instance_name = args[0]

  cl = GetClient()
  try:
    cluster_name = cl.QueryConfigValues(["cluster_name"])[0]
    idata = cl.QueryInstances([instance_name], ["console", "oper_state"], False)
    if not idata:
      raise errors.OpPrereqError("Instance '%s' does not exist" % instance_name,
                                 errors.ECODE_NOENT)
  finally:
    # Ensure client connection is closed while external commands are run
    cl.Close()

  del cl

  ((console_data, oper_state), ) = idata
  if not console_data:
    if oper_state:
      # Instance is running
      raise errors.OpExecError("Console information for instance %s is"
                               " unavailable" % instance_name)
    else:
      raise errors.OpExecError("Instance %s is not running, can't get console" %
                               instance_name)

  return _DoConsole(objects.InstanceConsole.FromDict(console_data),
                    opts.show_command, cluster_name)


def _DoConsole(console, show_command, cluster_name, feedback_fn=ToStdout,
               _runcmd_fn=utils.RunCmd):
  """Acts based on the result of L{opcodes.OpInstanceConsole}.

  @type console: L{objects.InstanceConsole}
  @param console: Console object
  @type show_command: bool
  @param show_command: Whether to just display commands
  @type cluster_name: string
  @param cluster_name: Cluster name as retrieved from master daemon

  """
  console.Validate()

  if console.kind == constants.CONS_MESSAGE:
    feedback_fn(console.message)
  elif console.kind == constants.CONS_VNC:
    feedback_fn("Instance %s has VNC listening on %s:%s (display %s),"
                " URL <vnc://%s:%s/>",
                console.instance, console.host, console.port,
                console.display, console.host, console.port)
  elif console.kind == constants.CONS_SPICE:
    feedback_fn("Instance %s has SPICE listening on %s:%s", console.instance,
                console.host, console.port)
  elif console.kind == constants.CONS_SSH:
    # Convert to string if not already one
    if isinstance(console.command, basestring):
      cmd = console.command
    else:
      cmd = utils.ShellQuoteArgs(console.command)

    srun = ssh.SshRunner(cluster_name=cluster_name)
    ssh_cmd = srun.BuildCmd(console.host, console.user, cmd,
                            port=console.port,
                            batch=True, quiet=False, tty=True)

    if show_command:
      feedback_fn(utils.ShellQuoteArgs(ssh_cmd))
    else:
      result = _runcmd_fn(ssh_cmd, interactive=True)
      if result.failed:
        logging.error("Console command \"%s\" failed with reason '%s' and"
                      " output %r", result.cmd, result.fail_reason,
                      result.output)
        raise errors.OpExecError("Connection to console of instance %s failed,"
                                 " please check cluster configuration" %
                                 console.instance)
  else:
    raise errors.GenericError("Unknown console type '%s'" % console.kind)

  return constants.EXIT_SUCCESS


def _FormatDiskDetails(dev_type, dev, roman):
  """Formats the logical_id of a disk.

  """

  if dev_type == constants.DT_DRBD8:
    drbd_info = dev["drbd_info"]
    data = [
      ("nodeA", "%s, minor=%s" %
                (drbd_info["primary_node"],
                 compat.TryToRoman(drbd_info["primary_minor"],
                                   convert=roman))),
      ("nodeB", "%s, minor=%s" %
                (drbd_info["secondary_node"],
                 compat.TryToRoman(drbd_info["secondary_minor"],
                                   convert=roman))),
      ("port", str(compat.TryToRoman(drbd_info["port"], convert=roman))),
      ]
  elif dev_type == constants.DT_PLAIN:
    vg_name, lv_name = dev["logical_id"]
    data = ["%s/%s" % (vg_name, lv_name)]
  else:
    data = [str(dev["logical_id"])]

  return data


def _FormatBlockDevInfo(idx, top_level, dev, roman):
  """Show block device information.

  This is only used by L{ShowInstanceConfig}, but it's too big to be
  left for an inline definition.

  @type idx: int
  @param idx: the index of the current disk
  @type top_level: boolean
  @param top_level: if this a top-level disk?
  @type dev: dict
  @param dev: dictionary with disk information
  @type roman: boolean
  @param roman: whether to try to use roman integers
  @return: a list of either strings, tuples or lists
      (which should be formatted at a higher indent level)

  """
  def helper(dtype, status):
    """Format one line for physical device status.

    @type dtype: str
    @param dtype: a constant from the L{constants.DTS_BLOCK} set
    @type status: tuple
    @param status: a tuple as returned from L{backend.FindBlockDevice}
    @return: the string representing the status

    """
    if not status:
      return "not active"
    txt = ""
    (path, major, minor, syncp, estt, degr, ldisk_status) = status
    if major is None:
      major_string = "N/A"
    else:
      major_string = str(compat.TryToRoman(major, convert=roman))

    if minor is None:
      minor_string = "N/A"
    else:
      minor_string = str(compat.TryToRoman(minor, convert=roman))

    txt += ("%s (%s:%s)" % (path, major_string, minor_string))
    if dtype in (constants.DT_DRBD8, ):
      if syncp is not None:
        sync_text = "*RECOVERING* %5.2f%%," % syncp
        if estt:
          sync_text += " ETA %ss" % compat.TryToRoman(estt, convert=roman)
        else:
          sync_text += " ETA unknown"
      else:
        sync_text = "in sync"
      if degr:
        degr_text = "*DEGRADED*"
      else:
        degr_text = "ok"
      if ldisk_status == constants.LDS_FAULTY:
        ldisk_text = " *MISSING DISK*"
      elif ldisk_status == constants.LDS_UNKNOWN:
        ldisk_text = " *UNCERTAIN STATE*"
      else:
        ldisk_text = ""
      txt += (" %s, status %s%s" % (sync_text, degr_text, ldisk_text))
    elif dtype == constants.DT_PLAIN:
      if ldisk_status == constants.LDS_FAULTY:
        ldisk_text = " *FAILED* (failed drive?)"
      else:
        ldisk_text = ""
      txt += ldisk_text
    return txt

  # the header
  if top_level:
    if dev["iv_name"] is not None:
      txt = dev["iv_name"]
    else:
      txt = "disk %s" % compat.TryToRoman(idx, convert=roman)
  else:
    txt = "child %s" % compat.TryToRoman(idx, convert=roman)
  if isinstance(dev["size"], int):
    nice_size = utils.FormatUnit(dev["size"], "h", roman)
  else:
    nice_size = str(dev["size"])
  data = [(txt, "%s, size %s" % (dev["dev_type"], nice_size))]
  if top_level:
    if dev["spindles"] is not None:
      data.append(("spindles", dev["spindles"]))
    data.append(("access mode", dev["mode"]))
  if dev["logical_id"] is not None:
    try:
      l_id = _FormatDiskDetails(dev["dev_type"], dev, roman)
    except ValueError:
      l_id = [str(dev["logical_id"])]
    if len(l_id) == 1:
      data.append(("logical_id", l_id[0]))
    else:
      data.extend(l_id)

  if dev["pstatus"]:
    data.append(("on primary", helper(dev["dev_type"], dev["pstatus"])))

  if dev["sstatus"]:
    data.append(("on secondary", helper(dev["dev_type"], dev["sstatus"])))

  data.append(("name", dev["name"]))
  data.append(("UUID", dev["uuid"]))

  if dev["children"]:
    data.append(("child devices", [
      _FormatBlockDevInfo(c_idx, False, child, roman)
      for c_idx, child in enumerate(dev["children"])
      ]))
  return data


def _FormatInstanceNicInfo(idx, nic, roman=False):
  """Helper function for L{_FormatInstanceInfo()}"""
  (name, uuid, ip, mac, mode, link, vlan, _, netinfo) = nic
  network_name = None
  if netinfo:
    network_name = netinfo["name"]
  return [
    ("nic/%s" % str(compat.TryToRoman(idx, roman)), ""),
    ("MAC", str(mac)),
    ("IP", str(ip)),
    ("mode", str(mode)),
    ("link", str(link)),
    ("vlan", str(compat.TryToRoman(vlan, roman))),
    ("network", str(network_name)),
    ("UUID", str(uuid)),
    ("name", str(name)),
    ]


def _FormatInstanceNodesInfo(instance):
  """Helper function for L{_FormatInstanceInfo()}"""
  pgroup = ("%s (UUID %s)" %
            (instance["pnode_group_name"], instance["pnode_group_uuid"]))
  secs = utils.CommaJoin(("%s (group %s, group UUID %s)" %
                          (name, group_name, group_uuid))
                         for (name, group_name, group_uuid) in
                           zip(instance["snodes"],
                               instance["snodes_group_names"],
                               instance["snodes_group_uuids"]))
  return [
    [
      ("primary", instance["pnode"]),
      ("group", pgroup),
      ],
    [("secondaries", secs)],
    ]


def _GetVncConsoleInfo(instance):
  """Helper function for L{_FormatInstanceInfo()}"""
  vnc_bind_address = instance["hv_actual"].get(constants.HV_VNC_BIND_ADDRESS,
                                               None)
  if vnc_bind_address:
    port = instance["network_port"]
    display = int(port) - constants.VNC_BASE_PORT
    if display > 0 and vnc_bind_address == constants.IP4_ADDRESS_ANY:
      vnc_console_port = "%s:%s (display %s)" % (instance["pnode"],
                                                 port,
                                                 display)
    elif display > 0 and netutils.IP4Address.IsValid(vnc_bind_address):
      vnc_console_port = ("%s:%s (node %s) (display %s)" %
                           (vnc_bind_address, port,
                            instance["pnode"], display))
    else:
      # vnc bind address is a file
      vnc_console_port = "%s:%s" % (instance["pnode"],
                                    vnc_bind_address)
    ret = "vnc to %s" % vnc_console_port
  else:
    ret = None
  return ret


def _FormatInstanceInfo(instance, roman_integers):
  """Format instance information for L{cli.PrintGenericInfo()}"""
  istate = "configured to be %s" % instance["config_state"]
  if instance["run_state"]:
    istate += ", actual state is %s" % instance["run_state"]
  info = [
    ("Instance name", instance["name"]),
    ("UUID", instance["uuid"]),
    ("Serial number",
     str(compat.TryToRoman(instance["serial_no"], convert=roman_integers))),
    ("Creation time", utils.FormatTime(instance["ctime"])),
    ("Modification time", utils.FormatTime(instance["mtime"])),
    ("State", istate),
    ("Nodes", _FormatInstanceNodesInfo(instance)),
    ("Operating system", instance["os"]),
    ("Operating system parameters",
     FormatParamsDictInfo(instance["os_instance"], instance["os_actual"],
                          roman_integers)),
    ]

  if "network_port" in instance:
    info.append(("Allocated network port",
                 str(compat.TryToRoman(instance["network_port"],
                                       convert=roman_integers))))
  info.append(("Hypervisor", instance["hypervisor"]))
  console = _GetVncConsoleInfo(instance)
  if console:
    info.append(("console connection", console))
  # deprecated "memory" value, kept for one version for compatibility
  # TODO(ganeti 2.7) remove.
  be_actual = copy.deepcopy(instance["be_actual"])
  be_actual["memory"] = be_actual[constants.BE_MAXMEM]
  info.extend([
    ("Hypervisor parameters",
     FormatParamsDictInfo(instance["hv_instance"], instance["hv_actual"],
                          roman_integers)),
    ("Back-end parameters",
     FormatParamsDictInfo(instance["be_instance"], be_actual,
                          roman_integers)),
    ("NICs", [
      _FormatInstanceNicInfo(idx, nic, roman_integers)
      for (idx, nic) in enumerate(instance["nics"])
      ]),
    ("Disk template", instance["disk_template"]),
    ("Disks", [
      _FormatBlockDevInfo(idx, True, device, roman_integers)
      for (idx, device) in enumerate(instance["disks"])
      ]),
    ])
  return info


def ShowInstanceConfig(opts, args):
  """Compute instance run-time status.

  @param opts: the command line options selected by the user
  @type args: list
  @param args: either an empty list, and then we query all
      instances, or should contain a list of instance names
  @rtype: int
  @return: the desired exit code

  """
  if not args and not opts.show_all:
    ToStderr("No instance selected."
             " Please pass in --all if you want to query all instances.\n"
             "Note that this can take a long time on a big cluster.")
    return 1
  elif args and opts.show_all:
    ToStderr("Cannot use --all if you specify instance names.")
    return 1

  retcode = 0
  op = opcodes.OpInstanceQueryData(instances=args, static=opts.static,
                                   use_locking=not opts.static)
  result = SubmitOpCode(op, opts=opts)
  if not result:
    ToStdout("No instances.")
    return 1

  PrintGenericInfo([
    _FormatInstanceInfo(instance, opts.roman_integers)
    for instance in result.values()
    ])
  return retcode


def _ConvertNicDiskModifications(mods):
  """Converts NIC/disk modifications from CLI to opcode.

  When L{opcodes.OpInstanceSetParams} was changed to support adding/removing
  disks at arbitrary indices, its parameter format changed. This function
  converts legacy requests (e.g. "--net add" or "--disk add:size=4G") to the
  newer format and adds support for new-style requests (e.g. "--new 4:add").

  @type mods: list of tuples
  @param mods: Modifications as given by command line parser
  @rtype: list of tuples
  @return: Modifications as understood by L{opcodes.OpInstanceSetParams}

  """
  result = []

  for (identifier, params) in mods:
    if identifier == constants.DDM_ADD:
      # Add item as last item (legacy interface)
      action = constants.DDM_ADD
      identifier = -1
    elif identifier == constants.DDM_ATTACH:
      # Attach item as last item (legacy interface)
      action = constants.DDM_ATTACH
      identifier = -1
    elif identifier == constants.DDM_REMOVE:
      # Remove last item (legacy interface)
      action = constants.DDM_REMOVE
      identifier = -1
    elif identifier == constants.DDM_DETACH:
      # Detach last item (legacy interface)
      action = constants.DDM_DETACH
      identifier = -1
    else:
      # Modifications and adding/attaching/removing/detaching at arbitrary
      # indices
      add = params.pop(constants.DDM_ADD, _MISSING)
      attach = params.pop(constants.DDM_ATTACH, _MISSING)
      remove = params.pop(constants.DDM_REMOVE, _MISSING)
      detach = params.pop(constants.DDM_DETACH, _MISSING)
      modify = params.pop(constants.DDM_MODIFY, _MISSING)

      # Check if the user has requested more than one operation and raise an
      # exception. If no operations have been given, default to modify.
      action = constants.DDM_MODIFY
      ops = {
        constants.DDM_ADD: add,
        constants.DDM_ATTACH: attach,
        constants.DDM_REMOVE: remove,
        constants.DDM_DETACH: detach,
        constants.DDM_MODIFY: modify,
      }
      count = 0
      for op, param in ops.items():
        if param is not _MISSING:
          count += 1
          action = op
      if count > 1:
        raise errors.OpPrereqError(
          "Cannot do more than one of the following operations at the"
          " same time: %s" % ", ".join(ops.keys()),
          errors.ECODE_INVAL)

      assert not (constants.DDMS_VALUES_WITH_MODIFY & set(params.keys()))

    if action in (constants.DDM_REMOVE, constants.DDM_DETACH) and params:
      raise errors.OpPrereqError("Not accepting parameters on removal/detach",
                                 errors.ECODE_INVAL)

    result.append((action, identifier, params))

  return result


def _ParseExtStorageParams(params):
  """Parses the disk params for ExtStorage conversions.

  """
  if params:
    if constants.IDISK_PROVIDER not in params:
      raise errors.OpPrereqError("Missing required parameter '%s' when"
                                 " converting to an ExtStorage disk template" %
                                 constants.IDISK_PROVIDER, errors.ECODE_INVAL)
    else:
      for param in params.keys():
        if (param != constants.IDISK_PROVIDER and
            param in constants.IDISK_PARAMS):
          raise errors.OpPrereqError("Invalid parameter '%s' when converting"
                                     " to an ExtStorage template (it is not"
                                     " allowed modifying existing disk"
                                     " parameters)" % param, errors.ECODE_INVAL)

  return params


def _ParseDiskSizes(mods):
  """Parses disk sizes in parameters.

  """
  for (action, _, params) in mods:
    if params and constants.IDISK_SPINDLES in params:
      params[constants.IDISK_SPINDLES] = \
          int(params[constants.IDISK_SPINDLES])
    if params and constants.IDISK_SIZE in params:
      params[constants.IDISK_SIZE] = \
        utils.ParseUnit(params[constants.IDISK_SIZE])
    elif action == constants.DDM_ADD:
      raise errors.OpPrereqError("Missing required parameter 'size'",
                                 errors.ECODE_INVAL)

  return mods


def SetInstanceParams(opts, args):
  """Modifies an instance.

  All parameters take effect only at the next restart of the instance.

  @param opts: the command line options selected by the user
  @type args: list
  @param args: should contain only one element, the instance name
  @rtype: int
  @return: the desired exit code

  """
  if not (opts.nics or opts.disks or opts.disk_template or opts.hvparams or
          opts.beparams or opts.os or opts.osparams or opts.osparams_private
          or opts.offline_inst or opts.online_inst or opts.runtime_mem or
          opts.new_primary_node or opts.instance_communication is not None):
    ToStderr("Please give at least one of the parameters.")
    return 1

  for param in opts.beparams:
    if isinstance(opts.beparams[param], basestring):
      if opts.beparams[param].lower() == "default":
        opts.beparams[param] = constants.VALUE_DEFAULT

  utils.ForceDictType(opts.beparams, constants.BES_PARAMETER_COMPAT,
                      allowed_values=[constants.VALUE_DEFAULT])

  for param in opts.hvparams:
    if isinstance(opts.hvparams[param], basestring):
      if opts.hvparams[param].lower() == "default":
        opts.hvparams[param] = constants.VALUE_DEFAULT

  utils.ForceDictType(opts.hvparams, constants.HVS_PARAMETER_TYPES,
                      allowed_values=[constants.VALUE_DEFAULT])
  FixHvParams(opts.hvparams)

  nics = _ConvertNicDiskModifications(opts.nics)
  for action, _, __ in nics:
    if action == constants.DDM_MODIFY and opts.hotplug and not opts.force:
      usertext = ("You are about to hot-modify a NIC. This will be done"
                  " by removing the existing NIC and then adding a new one."
                  " Network connection might be lost. Continue?")
      if not AskUser(usertext):
        return 1

  disks = _ParseDiskSizes(_ConvertNicDiskModifications(opts.disks))

  # verify the user provided parameters for disk template conversions
  if opts.disk_template:
    if (opts.ext_params and
          opts.disk_template != constants.DT_EXT):
      ToStderr("Specifying ExtStorage parameters requires converting"
               " to the '%s' disk template" % constants.DT_EXT)
      return 1
    elif (not opts.ext_params and
          opts.disk_template == constants.DT_EXT):
      ToStderr("Provider option is missing, use either the"
               " '--ext-params' or '-e' option")
      return 1

  if ((opts.file_driver or
       opts.file_storage_dir) and
      not opts.disk_template in constants.DTS_FILEBASED):
    ToStderr("Specifying file-based configuration arguments requires"
             " converting to a file-based disk template")
    return 1

  ext_params = _ParseExtStorageParams(opts.ext_params)

  if opts.offline_inst:
    offline = True
  elif opts.online_inst:
    offline = False
  else:
    offline = None

  instance_comm = opts.instance_communication

  op = opcodes.OpInstanceSetParams(instance_name=args[0],
                                   nics=nics,
                                   disks=disks,
                                   hotplug=opts.hotplug,
                                   hotplug_if_possible=opts.hotplug_if_possible,
                                   disk_template=opts.disk_template,
                                   ext_params=ext_params,
                                   file_driver=opts.file_driver,
                                   file_storage_dir=opts.file_storage_dir,
                                   remote_node=opts.node,
                                   iallocator=opts.iallocator,
                                   pnode=opts.new_primary_node,
                                   hvparams=opts.hvparams,
                                   beparams=opts.beparams,
                                   runtime_mem=opts.runtime_mem,
                                   os_name=opts.os,
                                   osparams=opts.osparams,
                                   osparams_private=opts.osparams_private,
                                   force_variant=opts.force_variant,
                                   force=opts.force,
                                   wait_for_sync=opts.wait_for_sync,
                                   offline=offline,
                                   conflicts_check=opts.conflicts_check,
                                   ignore_ipolicy=opts.ignore_ipolicy,
                                   instance_communication=instance_comm)

  # even if here we process the result, we allow submit only
  result = SubmitOrSend(op, opts)

  if result:
    ToStdout("Modified instance %s", args[0])
    for param, data in result:
      ToStdout(" - %-5s -> %s", param, data)
    ToStdout("Please don't forget that most parameters take effect"
             " only at the next (re)start of the instance initiated by"
             " ganeti; restarting from within the instance will"
             " not be enough.")
    if opts.hvparams:
      ToStdout("Note that changing hypervisor parameters without performing a"
               " restart might lead to a crash while performing a live"
               " migration. This will be addressed in future Ganeti versions.")
  return 0


def ChangeGroup(opts, args):
  """Moves an instance to another group.

  """
  (instance_name, ) = args

  cl = GetClient()

  op = opcodes.OpInstanceChangeGroup(instance_name=instance_name,
                                     iallocator=opts.iallocator,
                                     target_groups=opts.to,
                                     early_release=opts.early_release)
  result = SubmitOrSend(op, opts, cl=cl)

  # Keep track of submitted jobs
  jex = JobExecutor(cl=cl, opts=opts)

  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("Instance '%s' changed group successfully.", instance_name)
    rcode = constants.EXIT_SUCCESS
  else:
    ToStdout("There were %s errors while changing group of instance '%s'.",
             bad_cnt, instance_name)
    rcode = constants.EXIT_FAILURE

  return rcode


# multi-instance selection options
m_force_multi = cli_option("--force-multiple", dest="force_multi",
                           help="Do not ask for confirmation when more than"
                           " one instance is affected",
                           action="store_true", default=False)

m_pri_node_opt = cli_option("--primary", dest="multi_mode",
                            help="Filter by nodes (primary only)",
                            const=_EXPAND_NODES_PRI, action="store_const")

m_sec_node_opt = cli_option("--secondary", dest="multi_mode",
                            help="Filter by nodes (secondary only)",
                            const=_EXPAND_NODES_SEC, action="store_const")

m_node_opt = cli_option("--node", dest="multi_mode",
                        help="Filter by nodes (primary and secondary)",
                        const=_EXPAND_NODES_BOTH, action="store_const")

m_clust_opt = cli_option("--all", dest="multi_mode",
                         help="Select all instances in the cluster",
                         const=_EXPAND_CLUSTER, action="store_const")

m_inst_opt = cli_option("--instance", dest="multi_mode",
                        help="Filter by instance name [default]",
                        const=_EXPAND_INSTANCES, action="store_const")

m_node_tags_opt = cli_option("--node-tags", dest="multi_mode",
                             help="Filter by node tag",
                             const=_EXPAND_NODES_BOTH_BY_TAGS,
                             action="store_const")

m_pri_node_tags_opt = cli_option("--pri-node-tags", dest="multi_mode",
                                 help="Filter by primary node tag",
                                 const=_EXPAND_NODES_PRI_BY_TAGS,
                                 action="store_const")

m_sec_node_tags_opt = cli_option("--sec-node-tags", dest="multi_mode",
                                 help="Filter by secondary node tag",
                                 const=_EXPAND_NODES_SEC_BY_TAGS,
                                 action="store_const")

m_inst_tags_opt = cli_option("--tags", dest="multi_mode",
                             help="Filter by instance tag",
                             const=_EXPAND_INSTANCES_BY_TAGS,
                             action="store_const")

# this is defined separately due to readability only
add_opts = [
  FORTHCOMING_OPT,
  COMMIT_OPT,
  NOSTART_OPT,
  OS_OPT,
  FORCE_VARIANT_OPT,
  NO_INSTALL_OPT,
  IGNORE_IPOLICY_OPT,
  INSTANCE_COMMUNICATION_OPT,
  HELPER_STARTUP_TIMEOUT_OPT,
  HELPER_SHUTDOWN_TIMEOUT_OPT,
  ]

commands = {
  "add": (
    AddInstance, [ArgHost(min=1, max=1)],
    COMMON_CREATE_OPTS + add_opts,
    "[...] -t disk-type -n node[:secondary-node] -o os-type <name>",
    "Creates and adds a new instance to the cluster"),
  "batch-create": (
    BatchCreate, [ArgFile(min=1, max=1)],
    [DRY_RUN_OPT, PRIORITY_OPT, IALLOCATOR_OPT] + SUBMIT_OPTS,
    "<instances.json>",
    "Create a bunch of instances based on specs in the file."),
  "console": (
    ConnectToInstanceConsole, ARGS_ONE_INSTANCE,
    [SHOWCMD_OPT, PRIORITY_OPT],
    "[--show-cmd] <instance>", "Opens a console on the specified instance"),
  "failover": (
    FailoverInstance, ARGS_ONE_INSTANCE,
    [FORCE_OPT, IGNORE_CONSIST_OPT] + SUBMIT_OPTS +
    [SHUTDOWN_TIMEOUT_OPT,
     DRY_RUN_OPT, PRIORITY_OPT, DST_NODE_OPT, IALLOCATOR_OPT,
     IGNORE_IPOLICY_OPT, CLEANUP_OPT],
    "[-f] <instance>", "Stops the instance, changes its primary node and"
    " (if it was originally running) starts it on the new node"
    " (the secondary for mirrored instances or any node"
    " for shared storage)."),
  "migrate": (
    MigrateInstance, ARGS_ONE_INSTANCE,
    [FORCE_OPT, NONLIVE_OPT, MIGRATION_MODE_OPT, CLEANUP_OPT, DRY_RUN_OPT,
     PRIORITY_OPT, DST_NODE_OPT, IALLOCATOR_OPT, ALLOW_FAILOVER_OPT,
     IGNORE_IPOLICY_OPT, IGNORE_HVVERSIONS_OPT, NORUNTIME_CHGS_OPT]
    + SUBMIT_OPTS,
    "[-f] <instance>", "Migrate instance to its secondary node"
    " (only for mirrored instances)"),
  "move": (
    MoveInstance, ARGS_ONE_INSTANCE,
    [FORCE_OPT] + SUBMIT_OPTS +
    [SINGLE_NODE_OPT, COMPRESS_OPT,
     SHUTDOWN_TIMEOUT_OPT, DRY_RUN_OPT, PRIORITY_OPT, IGNORE_CONSIST_OPT,
     IGNORE_IPOLICY_OPT],
    "[-f] <instance>", "Move instance to an arbitrary node"
    " (only for instances of type file and lv)"),
  "info": (
    ShowInstanceConfig, ARGS_MANY_INSTANCES,
    [STATIC_OPT, ALL_OPT, ROMAN_OPT, PRIORITY_OPT],
    "[-s] {--all | <instance>...}",
    "Show information on the specified instance(s)"),
  "list": (
    ListInstances, ARGS_MANY_INSTANCES,
    [NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT, VERBOSE_OPT,
     FORCE_FILTER_OPT],
    "[<instance>...]",
    "Lists the instances and their status. The available fields can be shown"
    " using the \"list-fields\" command (see the man page for details)."
    " The default field list is (in order): %s." %
    utils.CommaJoin(_LIST_DEF_FIELDS),
    ),
  "list-fields": (
    ListInstanceFields, [ArgUnknown()],
    [NOHDR_OPT, SEP_OPT],
    "[fields...]",
    "Lists all available fields for instances"),
  "reinstall": (
    ReinstallInstance, [ArgInstance()],
    [FORCE_OPT, OS_OPT, FORCE_VARIANT_OPT, m_force_multi, m_node_opt,
     m_pri_node_opt, m_sec_node_opt, m_clust_opt, m_inst_opt, m_node_tags_opt,
     m_pri_node_tags_opt, m_sec_node_tags_opt, m_inst_tags_opt, SELECT_OS_OPT]
    + SUBMIT_OPTS + [DRY_RUN_OPT, PRIORITY_OPT, OSPARAMS_OPT,
                     OSPARAMS_PRIVATE_OPT, OSPARAMS_SECRET_OPT],
    "[-f] <instance>", "Reinstall a stopped instance"),
  "remove": (
    RemoveInstance, ARGS_ONE_INSTANCE,
    [FORCE_OPT, SHUTDOWN_TIMEOUT_OPT, IGNORE_FAILURES_OPT] + SUBMIT_OPTS
    + [DRY_RUN_OPT, PRIORITY_OPT],
    "[-f] <instance>", "Shuts down the instance and removes it"),
  "rename": (
    RenameInstance,
    [ArgInstance(min=1, max=1), ArgHost(min=1, max=1)],
    [NOIPCHECK_OPT, NONAMECHECK_OPT] + SUBMIT_OPTS
    + [DRY_RUN_OPT, PRIORITY_OPT],
    "<instance> <new_name>", "Rename the instance"),
  "replace-disks": (
    ReplaceDisks, ARGS_ONE_INSTANCE,
    [AUTO_REPLACE_OPT, DISKIDX_OPT, IALLOCATOR_OPT, EARLY_RELEASE_OPT,
     NEW_SECONDARY_OPT, ON_PRIMARY_OPT, ON_SECONDARY_OPT] + SUBMIT_OPTS
    + [DRY_RUN_OPT, PRIORITY_OPT, IGNORE_IPOLICY_OPT],
    "[-s|-p|-a|-n NODE|-I NAME] <instance>",
    "Replaces disks for the instance"),
  "modify": (
    SetInstanceParams, ARGS_ONE_INSTANCE,
    [BACKEND_OPT, DISK_OPT, FORCE_OPT, HVOPTS_OPT, NET_OPT] + SUBMIT_OPTS +
    [DISK_TEMPLATE_OPT, SINGLE_NODE_OPT, IALLOCATOR_OPT,
     OS_OPT, FORCE_VARIANT_OPT,
     OSPARAMS_OPT, OSPARAMS_PRIVATE_OPT, DRY_RUN_OPT, PRIORITY_OPT, NWSYNC_OPT,
     OFFLINE_INST_OPT, ONLINE_INST_OPT, IGNORE_IPOLICY_OPT, RUNTIME_MEM_OPT,
     NOCONFLICTSCHECK_OPT, NEW_PRIMARY_OPT, HOTPLUG_OPT,
     HOTPLUG_IF_POSSIBLE_OPT, INSTANCE_COMMUNICATION_OPT,
     EXT_PARAMS_OPT, FILESTORE_DRIVER_OPT, FILESTORE_DIR_OPT],
    "<instance>", "Alters the parameters of an instance"),
  "shutdown": (
    GenericManyOps("shutdown", _ShutdownInstance), [ArgInstance()],
    [FORCE_OPT, m_node_opt, m_pri_node_opt, m_sec_node_opt, m_clust_opt,
     m_node_tags_opt, m_pri_node_tags_opt, m_sec_node_tags_opt,
     m_inst_tags_opt, m_inst_opt, m_force_multi, TIMEOUT_OPT] + SUBMIT_OPTS
    + [DRY_RUN_OPT, PRIORITY_OPT, IGNORE_OFFLINE_OPT, NO_REMEMBER_OPT],
    "<instance>", "Stops an instance"),
  "startup": (
    GenericManyOps("startup", _StartupInstance), [ArgInstance()],
    [FORCE_OPT, m_force_multi, m_node_opt, m_pri_node_opt, m_sec_node_opt,
     m_node_tags_opt, m_pri_node_tags_opt, m_sec_node_tags_opt,
     m_inst_tags_opt, m_clust_opt, m_inst_opt] + SUBMIT_OPTS +
    [HVOPTS_OPT,
     BACKEND_OPT, DRY_RUN_OPT, PRIORITY_OPT, IGNORE_OFFLINE_OPT,
     NO_REMEMBER_OPT, STARTUP_PAUSED_OPT],
    "<instance>", "Starts an instance"),
  "reboot": (
    GenericManyOps("reboot", _RebootInstance), [ArgInstance()],
    [m_force_multi, REBOOT_TYPE_OPT, IGNORE_SECONDARIES_OPT, m_node_opt,
     m_pri_node_opt, m_sec_node_opt, m_clust_opt, m_inst_opt] + SUBMIT_OPTS +
    [m_node_tags_opt, m_pri_node_tags_opt, m_sec_node_tags_opt,
     m_inst_tags_opt, SHUTDOWN_TIMEOUT_OPT, DRY_RUN_OPT, PRIORITY_OPT],
    "<instance>", "Reboots an instance"),
  "activate-disks": (
    ActivateDisks, ARGS_ONE_INSTANCE,
    SUBMIT_OPTS + [IGNORE_SIZE_OPT, PRIORITY_OPT, WFSYNC_OPT],
    "<instance>", "Activate an instance's disks"),
  "deactivate-disks": (
    DeactivateDisks, ARGS_ONE_INSTANCE,
    [FORCE_OPT] + SUBMIT_OPTS + [DRY_RUN_OPT, PRIORITY_OPT],
    "[-f] <instance>", "Deactivate an instance's disks"),
  "recreate-disks": (
    RecreateDisks, ARGS_ONE_INSTANCE,
    SUBMIT_OPTS +
    [DISK_OPT, NODE_PLACEMENT_OPT, DRY_RUN_OPT, PRIORITY_OPT,
     IALLOCATOR_OPT],
    "<instance>", "Recreate an instance's disks"),
  "grow-disk": (
    GrowDisk,
    [ArgInstance(min=1, max=1), ArgUnknown(min=1, max=1),
     ArgUnknown(min=1, max=1)],
    SUBMIT_OPTS +
    [NWSYNC_OPT, DRY_RUN_OPT, PRIORITY_OPT, ABSOLUTE_OPT, IGNORE_IPOLICY_OPT],
    "<instance> <disk> <size>", "Grow an instance's disk"),
  "change-group": (
    ChangeGroup, ARGS_ONE_INSTANCE,
    [TO_GROUP_OPT, IALLOCATOR_OPT, EARLY_RELEASE_OPT, PRIORITY_OPT]
    + SUBMIT_OPTS,
    "[-I <iallocator>] [--to <group>]", "Change group of instance"),
  "list-tags": (
    ListTags, ARGS_ONE_INSTANCE, [],
    "<instance_name>", "List the tags of the given instance"),
  "add-tags": (
    AddTags, [ArgInstance(min=1, max=1), ArgUnknown()],
    [TAG_SRC_OPT, PRIORITY_OPT] + SUBMIT_OPTS,
    "<instance_name> tag...", "Add tags to the given instance"),
  "remove-tags": (
    RemoveTags, [ArgInstance(min=1, max=1), ArgUnknown()],
    [TAG_SRC_OPT, PRIORITY_OPT] + SUBMIT_OPTS,
    "<instance_name> tag...", "Remove tags from given instance"),
  }

#: dictionary with aliases for commands
aliases = {
  "start": "startup",
  "stop": "shutdown",
  "show": "info",
  }


def Main():
  return GenericMain(commands, aliases=aliases,
                     override={"tag_type": constants.TAG_INSTANCE},
                     env_override=_ENV_OVERRIDE)
