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
36 IMPORT_MODE = "import"
37 EXPORT_MODE = "export"
40 def CheckOptions(parser, options_dict, required, forbidden, excluding, mode):
41 """Performes check on the command line options.
43 Checks whether the required arguments are present and if none of the arguments
44 not supported for the current mode are given.
46 @type options_dict: list
47 @param options_dict: dictionary containing all the options from the command
50 @param required: list of pairs (option, argument) where 'option' is required
53 @param forbidden: list of pairs (option, argument) which are not allowed in
56 @param excluding: list of pairs (argument1, argument2); each pair contains
57 mutually exclusive arguments
59 @param mode: current mode of the converter
62 for (option, argument) in required:
63 if not options_dict[option]:
64 parser.error("Argument %s is required for %s" % (argument, mode))
65 for (option, argument) in forbidden:
66 if options_dict[option]:
67 parser.error("Argument %s is not allowed in %s mode" % (argument, mode))
68 for (arg1, arg2) in excluding:
69 if options_dict[arg1] and options_dict[arg2]:
70 parser.error("Arguments %s and %s exclude each other" % (arg1, arg2))
74 """Parses the command line options and arguments.
76 In case of mismatching parameters, it will show the correct usage and exit.
79 @return: (mode, sourcefile to read from, additional options)
82 usage = ("%%prog {%s|%s} <source-cfg-file> [options...]" %
83 (IMPORT_MODE, EXPORT_MODE))
84 parser = optparse.OptionParser(usage=usage)
87 parser.add_option(cli.DEBUG_OPT)
88 parser.add_option(cli.VERBOSE_OPT)
89 parser.add_option("-n", "--name", dest="name", action="store",
90 help="Name of the instance")
91 parser.add_option("--output-dir", dest="output_dir",
92 help="Path to the output directory")
95 import_group = optparse.OptionGroup(parser, "Import options")
96 import_group.add_option(cli.BACKEND_OPT)
97 import_group.add_option(cli.DISK_OPT)
98 import_group.add_option(cli.DISK_TEMPLATE_OPT)
99 import_group.add_option(cli.HYPERVISOR_OPT)
100 import_group.add_option(cli.NET_OPT)
101 import_group.add_option(cli.NONICS_OPT)
102 import_group.add_option(cli.OS_OPT)
103 import_group.add_option(cli.OSPARAMS_OPT)
104 import_group.add_option(cli.TAG_ADD_OPT)
105 parser.add_option_group(import_group)
108 export_group = optparse.OptionGroup(parser, "Export options")
109 export_group.add_option("--compress", dest="compression",
110 action="store_true", default=False,
111 help="The exported disk will be compressed to tar.gz")
112 export_group.add_option("--external", dest="ext_usage",
113 action="store_true", default=False,
114 help="The package will be used externally (ommits the"
115 " Ganeti-specific parts of configuration)")
116 export_group.add_option("-f", "--format", dest="disk_format",
118 choices=("raw", "cow", "vmdk"),
119 help="Disk format for export (one of raw/cow/vmdk)")
120 export_group.add_option("--ova", dest="ova_package",
121 action="store_true", default=False,
122 help="Export everything into OVA package")
123 parser.add_option_group(export_group)
125 options, args = parser.parse_args()
127 parser.error("Wrong number of arguments")
129 input_path = os.path.abspath(args.pop(0))
131 if mode == IMPORT_MODE:
134 ("compression", "--compress"),
135 ("disk_format", "--format"),
136 ("ext_usage", "--external"),
137 ("ova_package", "--ova"),
139 excluding = [("nics", "no_nics")]
140 elif mode == EXPORT_MODE:
141 required = [("disk_format", "--format")]
143 ("beparams", "--backend-parameters"),
144 ("disk_template", "--disk-template"),
146 ("hypervisor", "--hypervisor-parameters"),
148 ("no_nics", "--no-nics"),
150 ("osparams", "--os-parameters"),
155 parser.error("First argument should be either '%s' or '%s'" %
156 (IMPORT_MODE, EXPORT_MODE))
158 options_dict = vars(options)
159 CheckOptions(parser, options_dict, required, forbidden, excluding, mode)
161 return (mode, input_path, options)
164 def SetupLogging(options):
165 """Setting up logging infrastructure.
167 @type options: optparse.Values
168 @param options: parsed command line options
171 formatter = logging.Formatter("%(asctime)s: %(levelname)s %(message)s")
173 stderr_handler = logging.StreamHandler()
174 stderr_handler.setFormatter(formatter)
176 stderr_handler.setLevel(logging.NOTSET)
177 elif options.verbose:
178 stderr_handler.setLevel(logging.INFO)
180 stderr_handler.setLevel(logging.WARNING)
182 root_logger = logging.getLogger("")
183 root_logger.setLevel(logging.NOTSET)
184 root_logger.addHandler(stderr_handler)
191 (mode, input_path, options) = ParseOptions()
192 SetupLogging(options)
193 logging.info("Chosen %s mode, reading the %s file", mode, input_path)
194 assert mode in (IMPORT_MODE, EXPORT_MODE)
197 if mode == IMPORT_MODE:
198 converter = ovf.OVFImporter(input_path, options)
199 elif mode == EXPORT_MODE:
200 converter = ovf.OVFExporter(input_path, options)
203 except errors.OpPrereqError, err:
206 logging.exception(err)
207 return constants.EXIT_FAILURE
210 if __name__ == "__main__":