#!/usr/bin/python
#

# Copyright (C) 2011 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.


"""Tool to translate between ovf and ganeti backup format.

"""

import logging
import optparse
import os

from ganeti import cli
from ganeti import constants
from ganeti import errors
from ganeti import ovf
from ganeti import utils


IMPORT_MODE = "import"
EXPORT_MODE = "export"


def CheckOptions(parser, options_dict, required, forbidden, excluding, mode):
  """Performes check on the command line options.

  Checks whether the required arguments are present and if none of the arguments
  not supported for the current mode are given.

  @type options_dict: list
  @param options_dict: dictionary containing all the options from the command
    line
  @type required: list
  @param required: list of pairs (option, argument) where 'option' is required
    in mode 'mode'
  @type forbidden: list
  @param forbidden: list of pairs (option, argument) which are not allowed in
    mode 'mode'
  @type excluding: list
  @param excluding: list of pairs (argument1, argument2); each pair contains
    mutually exclusive arguments
  @type mode: string
  @param mode: current mode of the converter

  """
  for (option, argument) in required:
    if not options_dict[option]:
      parser.error("Argument %s is required for %s" % (argument, mode))
  for (option, argument) in forbidden:
    if options_dict[option]:
      parser.error("Argument %s is not allowed in %s mode" % (argument, mode))
  for (arg1, arg2) in excluding:
    if options_dict[arg1] and options_dict[arg2]:
      parser.error("Arguments %s and %s exclude each other" % (arg1, arg2))


def ParseOptions():
  """Parses the command line options and arguments.

  In case of mismatching parameters, it will show the correct usage and exit.

  @rtype: tuple
  @return: (mode, sourcefile to read from, additional options)

  """
  usage = ("%%prog {%s|%s} <source-cfg-file> [options...]" %
           (IMPORT_MODE, EXPORT_MODE))
  parser = optparse.OptionParser(usage=usage)

  #global options
  parser.add_option(cli.DEBUG_OPT)
  parser.add_option(cli.VERBOSE_OPT)
  parser.add_option("-n", "--name", dest="name", action="store",
                    help="Name of the instance")
  parser.add_option("--output-dir", dest="output_dir",
                    help="Path to the output directory")

  #import options
  import_group = optparse.OptionGroup(parser, "Import options")
  import_group.add_option(cli.BACKEND_OPT)
  import_group.add_option(cli.DISK_OPT)
  import_group.add_option(cli.DISK_TEMPLATE_OPT)
  import_group.add_option(cli.HYPERVISOR_OPT)
  import_group.add_option(cli.NET_OPT)
  import_group.add_option(cli.NONICS_OPT)
  import_group.add_option(cli.OS_OPT)
  import_group.add_option(cli.OSPARAMS_OPT)
  import_group.add_option(cli.TAG_ADD_OPT)
  parser.add_option_group(import_group)

  #export options
  export_group = optparse.OptionGroup(parser, "Export options")
  export_group.add_option("--compress", dest="compression",
                          action="store_true", default=False,
                          help="The exported disk will be compressed to tar.gz")
  export_group.add_option("--external", dest="ext_usage",
                          action="store_true", default=False,
                          help="The package will be used externally (ommits the"
                               " Ganeti-specific parts of configuration)")
  export_group.add_option("-f", "--format", dest="disk_format",
                          action="store",
                          choices=("raw", "cow", "vmdk"),
                          help="Disk format for export (one of raw/cow/vmdk)")
  export_group.add_option("--ova", dest="ova_package",
                          action="store_true", default=False,
                          help="Export everything into OVA package")
  parser.add_option_group(export_group)

  options, args = parser.parse_args()
  if len(args) != 2:
    parser.error("Wrong number of arguments")
  mode = args.pop(0)
  input_path = os.path.abspath(args.pop(0))

  if mode == IMPORT_MODE:
    required = []
    forbidden = [
      ("compression", "--compress"),
      ("disk_format", "--format"),
      ("ext_usage", "--external"),
      ("ova_package", "--ova"),
    ]
    excluding = [("nics", "no_nics")]
  elif mode == EXPORT_MODE:
    required = [("disk_format", "--format")]
    forbidden = [
      ("beparams", "--backend-parameters"),
      ("disk_template", "--disk-template"),
      ("disks", "--disk"),
      ("hypervisor", "--hypervisor-parameters"),
      ("nics", "--net"),
      ("no_nics", "--no-nics"),
      ("os", "--os-type"),
      ("osparams", "--os-parameters"),
      ("tags", "--tags"),
    ]
    excluding = []
  else:
    parser.error("First argument should be either '%s' or '%s'" %
                 (IMPORT_MODE, EXPORT_MODE))

  options_dict = vars(options)
  CheckOptions(parser, options_dict, required, forbidden, excluding, mode)

  return (mode, input_path, options)


def main():
  """Main routine.

  """
  (mode, input_path, options) = ParseOptions()

  utils.SetupToolLogging(options.debug, options.verbose)

  logging.info("Chosen %s mode, reading the %s file", mode, input_path)
  assert mode in (IMPORT_MODE, EXPORT_MODE)
  converter = None
  try:
    if mode == IMPORT_MODE:
      converter = ovf.OVFImporter(input_path, options)
    elif mode == EXPORT_MODE:
      converter = ovf.OVFExporter(input_path, options)
    converter.Parse()
    converter.Save()
  except errors.OpPrereqError, err:
    if converter:
      converter.Cleanup()
    logging.exception(err)
    return constants.EXIT_FAILURE


if __name__ == "__main__":
  main()
