#
#

# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Google Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.

"""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))

  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)


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 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)
    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)

      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)
  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)
  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,
                              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]
    ((console_data, oper_state), ) = \
      cl.QueryInstances([instance_name], ["console", "oper_state"], False)
  finally:
    # Ensure client connection is closed while external commands are run
    cl.Close()

  del cl

  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

  """
  assert 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,
                            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 _FormatListInfo(data):
  return list(str(i) for i in 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")
  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)
  elif dev["physical_id"] is not None:
    data.append(("physical_id:", _FormatListInfo(dev["physical_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):
  """Helper function for L{_FormatInstanceInfo()}"""
  (name, uuid, ip, mac, mode, link, _, netinfo) = nic
  network_name = None
  if netinfo:
    network_name = netinfo["name"]
  return [
    ("nic/%d" % idx, ""),
    ("MAC", str(mac)),
    ("IP", str(ip)),
    ("mode", str(mode)),
    ("link", str(link)),
    ("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"])),
    ]

  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"])),
    ("Back-end parameters",
     FormatParamsDictInfo(instance["be_instance"], be_actual)),
    ("NICs", [
      _FormatInstanceNicInfo(idx, nic)
      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_REMOVE:
      # Remove last item (legacy interface)
      action = constants.DDM_REMOVE
      identifier = -1
    else:
      # Modifications and adding/removing at arbitrary indices
      add = params.pop(constants.DDM_ADD, _MISSING)
      remove = params.pop(constants.DDM_REMOVE, _MISSING)
      modify = params.pop(constants.DDM_MODIFY, _MISSING)

      if modify is _MISSING:
        if not (add is _MISSING or remove is _MISSING):
          raise errors.OpPrereqError("Cannot add and remove at the same time",
                                     errors.ECODE_INVAL)
        elif add is not _MISSING:
          action = constants.DDM_ADD
        elif remove is not _MISSING:
          action = constants.DDM_REMOVE
        else:
          action = constants.DDM_MODIFY

      elif add is _MISSING and remove is _MISSING:
        action = constants.DDM_MODIFY
      else:
        raise errors.OpPrereqError("Cannot modify and add/remove at the"
                                   " same time", errors.ECODE_INVAL)

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

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

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

  return result


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

  """
  for (action, _, params) in mods:
    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.offline_inst or opts.online_inst or opts.runtime_mem or
          opts.new_primary_node):
    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)
  disks = _ParseDiskSizes(_ConvertNicDiskModifications(opts.disks))

  if (opts.disk_template and
      opts.disk_template in constants.DTS_INT_MIRROR and
      not opts.node):
    ToStderr("Changing the disk template to a mirrored one requires"
             " specifying a secondary node")
    return 1

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

  op = opcodes.OpInstanceSetParams(instance_name=args[0],
                                   nics=nics,
                                   disks=disks,
                                   disk_template=opts.disk_template,
                                   remote_node=opts.node,
                                   pnode=opts.new_primary_node,
                                   hvparams=opts.hvparams,
                                   beparams=opts.beparams,
                                   runtime_mem=opts.runtime_mem,
                                   os_name=opts.os,
                                   osparams=opts.osparams,
                                   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)

  # 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.")
  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 = [
  NOSTART_OPT,
  OS_OPT,
  FORCE_VARIANT_OPT,
  NO_INSTALL_OPT,
  IGNORE_IPOLICY_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, 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,
     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],
    "[-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, OS_OPT, FORCE_VARIANT_OPT,
     OSPARAMS_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],
    "<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],
    "<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)
