Skip to content
Snippets Groups Projects
  • Iustin Pop's avatar
    Add a identify-defaults options for import · e588764d
    Iustin Pop authored
    
    When importing an instance, all the saved valued will be used as
    explicitly specified values, overriding the cluster defaults. This means
    export+import will change the status (from default to explicitly
    specified) of parameters.
    
    This patch adds a new option that changes the behaviour to identify
    parameter values which are equal to the current cluster defaults and
    mark them as such. It does this for hv, be and nic parameters.
    
    Signed-off-by: default avatarIustin Pop <iustin@google.com>
    Reviewed-by: default avatarMichael Hanselmann <hansmi@google.com>
    e588764d
gnt-backup 4.62 KiB
#!/usr/bin/python
#

# Copyright (C) 2006, 2007 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.

"""Backup related commands"""

# pylint: disable-msg=W0401,W0613,W0614,C0103
# W0401: Wildcard import ganeti.cli
# W0613: Unused argument, since all functions follow the same API
# W0614: Unused import %s from wildcard import (since we need cli)
# C0103: Invalid name gnt-backup

import sys

from ganeti.cli import *
from ganeti import opcodes
from ganeti import constants


_VALUE_TRUE = "true"


def PrintExportList(opts, args):
  """Prints a list of all the exported system images.

  @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

  """
  exports = GetClient().QueryExports(opts.nodes, False)
  retcode = 0
  for node in exports:
    ToStdout("Node: %s", node)
    ToStdout("Exports:")
    if isinstance(exports[node], list):
      for instance_name in exports[node]:
        ToStdout("\t%s", instance_name)
    else:
      ToStdout("  Could not get exports list")
      retcode = 1
  return retcode


def ExportInstance(opts, args):
  """Export an instance to an image in the cluster.

  @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 exported
  @rtype: int
  @return: the desired exit code

  """
  op = opcodes.OpExportInstance(instance_name=args[0],
                                target_node=opts.node,
                                shutdown=opts.shutdown,
                                shutdown_timeout=opts.shutdown_timeout)

  fin_resu, dlist = SubmitOpCode(op, opts=opts)
  if not isinstance(dlist, list):
    ToStderr("Cannot parse execution results")
    return 1
  # TODO: handle diskless instances
  if dlist.count(False) == 0:
    # all OK
    rcode = 0
  elif dlist.count(True) == 0:
    ToStderr("Error: No disks were backed up successfully."
             " The export doesn't have any valid data,"
             " it is recommended to retry the operation.")
    rcode = 1
  else:
    ToStderr("Partial export failure: %d disks backed up, %d disks failed.",
             dlist.count(True), dlist.count(False))
    rcode = 2
  if not fin_resu:
    rcode = 1
  return rcode

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

  This is just a wrapper over GenericInstanceCreate.

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


def RemoveExport(opts, args):
  """Remove an export from the cluster.

  @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 whose backup should be removed
  @rtype: int
  @return: the desired exit code

  """
  op = opcodes.OpRemoveExport(instance_name=args[0])

  SubmitOpCode(op, opts=opts)
  return 0


# this is defined separately due to readability only
import_opts = [
  BACKEND_OPT,
  DISK_OPT,
  DISK_TEMPLATE_OPT,
  FILESTORE_DIR_OPT,
  FILESTORE_DRIVER_OPT,
  HYPERVISOR_OPT,
  IALLOCATOR_OPT,
  IDENTIFY_DEFAULTS_OPT,
  NET_OPT,
  NODE_PLACEMENT_OPT,
  NOIPCHECK_OPT,
  NONAMECHECK_OPT,
  NONICS_OPT,
  NWSYNC_OPT,
  OS_SIZE_OPT,
  SRC_DIR_OPT,
  SRC_NODE_OPT,
  SUBMIT_OPT,
  ]

commands = {
  'list': (
    PrintExportList, ARGS_NONE,
    [NODE_LIST_OPT],
    "", "Lists instance exports available in the ganeti cluster"),
  'export': (
    ExportInstance, ARGS_ONE_INSTANCE,
    [FORCE_OPT, SINGLE_NODE_OPT, NOSHUTDOWN_OPT, SHUTDOWN_TIMEOUT_OPT],
    "-n <target_node> [opts...] <name>",
    "Exports an instance to an image"),
  'import': (
    ImportInstance, ARGS_ONE_INSTANCE, import_opts,
    "[...] -t disk-type -n node[:secondary-node] <name>",
    "Imports an instance from an exported image"),
  'remove': (
    RemoveExport, [ArgUnknown(min=1, max=1)], [],
    "<name>", "Remove exports of named instance from the filesystem."),
  }


if __name__ == '__main__':
  sys.exit(GenericMain(commands))