4 # Copyright (C) 2011 Google Inc.
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 """Tool to translate between ovf and ganeti backup format.
30 from ganeti import cli
31 from ganeti import constants
32 from ganeti import errors
33 from ganeti import ovf
34 from ganeti import utils
37 IMPORT_MODE = "import"
38 EXPORT_MODE = "export"
41 def CheckOptions(parser, options_dict, required, forbidden, excluding, mode):
42 """Performes check on the command line options.
44 Checks whether the required arguments are present and if none of the arguments
45 not supported for the current mode are given.
47 @type options_dict: list
48 @param options_dict: dictionary containing all the options from the command
51 @param required: list of pairs (option, argument) where 'option' is required
54 @param forbidden: list of pairs (option, argument) which are not allowed in
57 @param excluding: list of pairs (argument1, argument2); each pair contains
58 mutually exclusive arguments
60 @param mode: current mode of the converter
63 for (option, argument) in required:
64 if not options_dict[option]:
65 parser.error("Argument %s is required for %s" % (argument, mode))
66 for (option, argument) in forbidden:
67 if options_dict[option]:
68 parser.error("Argument %s is not allowed in %s mode" % (argument, mode))
69 for (arg1, arg2) in excluding:
70 if options_dict[arg1] and options_dict[arg2]:
71 parser.error("Arguments %s and %s exclude each other" % (arg1, arg2))
75 """Parses the command line options and arguments.
77 In case of mismatching parameters, it will show the correct usage and exit.
80 @return: (mode, sourcefile to read from, additional options)
83 usage = ("%%prog {%s|%s} <source-cfg-file> [options...]" %
84 (IMPORT_MODE, EXPORT_MODE))
85 parser = optparse.OptionParser(usage=usage)
88 parser.add_option(cli.DEBUG_OPT)
89 parser.add_option(cli.VERBOSE_OPT)
90 parser.add_option("-n", "--name", dest="name", action="store",
91 help="Name of the instance")
92 parser.add_option("--output-dir", dest="output_dir",
93 help="Path to the output directory")
96 import_group = optparse.OptionGroup(parser, "Import options")
97 import_group.add_option(cli.BACKEND_OPT)
98 import_group.add_option(cli.DISK_OPT)
99 import_group.add_option(cli.DISK_TEMPLATE_OPT)
100 import_group.add_option(cli.HYPERVISOR_OPT)
101 import_group.add_option(cli.NET_OPT)
102 import_group.add_option(cli.NONICS_OPT)
103 import_group.add_option(cli.OS_OPT)
104 import_group.add_option(cli.OSPARAMS_OPT)
105 import_group.add_option(cli.TAG_ADD_OPT)
106 parser.add_option_group(import_group)
109 export_group = optparse.OptionGroup(parser, "Export options")
110 export_group.add_option("--compress", dest="compression",
111 action="store_true", default=False,
112 help="The exported disk will be compressed to tar.gz")
113 export_group.add_option("--external", dest="ext_usage",
114 action="store_true", default=False,
115 help="The package will be used externally (ommits the"
116 " Ganeti-specific parts of configuration)")
117 export_group.add_option("-f", "--format", dest="disk_format",
119 choices=("raw", "cow", "vmdk"),
120 help="Disk format for export (one of raw/cow/vmdk)")
121 export_group.add_option("--ova", dest="ova_package",
122 action="store_true", default=False,
123 help="Export everything into OVA package")
124 parser.add_option_group(export_group)
126 options, args = parser.parse_args()
128 parser.error("Wrong number of arguments")
130 input_path = os.path.abspath(args.pop(0))
132 if mode == IMPORT_MODE:
135 ("compression", "--compress"),
136 ("disk_format", "--format"),
137 ("ext_usage", "--external"),
138 ("ova_package", "--ova"),
140 excluding = [("nics", "no_nics")]
141 elif mode == EXPORT_MODE:
142 required = [("disk_format", "--format")]
144 ("beparams", "--backend-parameters"),
145 ("disk_template", "--disk-template"),
147 ("hypervisor", "--hypervisor-parameters"),
149 ("no_nics", "--no-nics"),
151 ("osparams", "--os-parameters"),
156 parser.error("First argument should be either '%s' or '%s'" %
157 (IMPORT_MODE, EXPORT_MODE))
159 options_dict = vars(options)
160 CheckOptions(parser, options_dict, required, forbidden, excluding, mode)
162 return (mode, input_path, options)
169 (mode, input_path, options) = ParseOptions()
171 utils.SetupToolLogging(options.debug, options.verbose)
173 logging.info("Chosen %s mode, reading the %s file", mode, input_path)
174 assert mode in (IMPORT_MODE, EXPORT_MODE)
177 if mode == IMPORT_MODE:
178 converter = ovf.OVFImporter(input_path, options)
179 elif mode == EXPORT_MODE:
180 converter = ovf.OVFExporter(input_path, options)
183 except errors.OpPrereqError, err:
186 logging.exception(err)
187 return constants.EXIT_FAILURE
190 if __name__ == "__main__":