blob: fd7aa436475cfa0ef1eadf800547ee54e887408e [file] [log] [blame]
#!/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()