users setup: add masterd to confd group
[ganeti-local] / tools / ovfconverter
1 #!/usr/bin/python
2 #
3
4 # Copyright (C) 2011 Google Inc.
5 #
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.
10 #
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.
15 #
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
19 # 02110-1301, USA.
20
21
22 """Tool to translate between ovf and ganeti backup format.
23
24 """
25
26 import logging
27 import optparse
28 import os
29
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
35
36
37 IMPORT_MODE = "import"
38 EXPORT_MODE = "export"
39
40
41 def CheckOptions(parser, options_dict, required, forbidden, excluding, mode):
42   """Performes check on the command line options.
43
44   Checks whether the required arguments are present and if none of the arguments
45   not supported for the current mode are given.
46
47   @type options_dict: list
48   @param options_dict: dictionary containing all the options from the command
49     line
50   @type required: list
51   @param required: list of pairs (option, argument) where 'option' is required
52     in mode 'mode'
53   @type forbidden: list
54   @param forbidden: list of pairs (option, argument) which are not allowed in
55     mode 'mode'
56   @type excluding: list
57   @param excluding: list of pairs (argument1, argument2); each pair contains
58     mutually exclusive arguments
59   @type mode: string
60   @param mode: current mode of the converter
61
62   """
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))
72
73
74 def ParseOptions():
75   """Parses the command line options and arguments.
76
77   In case of mismatching parameters, it will show the correct usage and exit.
78
79   @rtype: tuple
80   @return: (mode, sourcefile to read from, additional options)
81
82   """
83   usage = ("%%prog {%s|%s} <source-cfg-file> [options...]" %
84            (IMPORT_MODE, EXPORT_MODE))
85   parser = optparse.OptionParser(usage=usage)
86
87   #global options
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")
94
95   #import options
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)
107
108   #export options
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",
118                           action="store",
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)
125
126   options, args = parser.parse_args()
127   if len(args) != 2:
128     parser.error("Wrong number of arguments")
129   mode = args.pop(0)
130   input_path = os.path.abspath(args.pop(0))
131
132   if mode == IMPORT_MODE:
133     required = []
134     forbidden = [
135       ("compression", "--compress"),
136       ("disk_format", "--format"),
137       ("ext_usage", "--external"),
138       ("ova_package", "--ova"),
139     ]
140     excluding = [("nics", "no_nics")]
141   elif mode == EXPORT_MODE:
142     required = [("disk_format", "--format")]
143     forbidden = [
144       ("beparams", "--backend-parameters"),
145       ("disk_template", "--disk-template"),
146       ("disks", "--disk"),
147       ("hypervisor", "--hypervisor-parameters"),
148       ("nics", "--net"),
149       ("no_nics", "--no-nics"),
150       ("os", "--os-type"),
151       ("osparams", "--os-parameters"),
152       ("tags", "--tags"),
153     ]
154     excluding = []
155   else:
156     parser.error("First argument should be either '%s' or '%s'" %
157                  (IMPORT_MODE, EXPORT_MODE))
158
159   options_dict = vars(options)
160   CheckOptions(parser, options_dict, required, forbidden, excluding, mode)
161
162   return (mode, input_path, options)
163
164
165 def main():
166   """Main routine.
167
168   """
169   (mode, input_path, options) = ParseOptions()
170
171   utils.SetupToolLogging(options.debug, options.verbose)
172
173   logging.info("Chosen %s mode, reading the %s file", mode, input_path)
174   assert mode in (IMPORT_MODE, EXPORT_MODE)
175   converter = None
176   try:
177     if mode == IMPORT_MODE:
178       converter = ovf.OVFImporter(input_path, options)
179     elif mode == EXPORT_MODE:
180       converter = ovf.OVFExporter(input_path, options)
181     converter.Parse()
182     converter.Save()
183   except errors.OpPrereqError, err:
184     if converter:
185       converter.Cleanup()
186     logging.exception(err)
187     return constants.EXIT_FAILURE
188
189
190 if __name__ == "__main__":
191   main()