Statistics
| Branch: | Tag: | Revision:

root / tools / ovfconverter @ 36c70d4d

History | View | Annotate | Download (6.7 kB)

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

    
35

    
36
IMPORT_MODE = "import"
37
EXPORT_MODE = "export"
38

    
39

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

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

    
46
  @type options_dict: list
47
  @param options_dict: dictionary containing all the options from the command
48
    line
49
  @type required: list
50
  @param required: list of pairs (option, argument) where 'option' is required
51
    in mode 'mode'
52
  @type forbidden: list
53
  @param forbidden: list of pairs (option, argument) which are not allowed in
54
    mode 'mode'
55
  @type excluding: list
56
  @param excluding: list of pairs (argument1, argument2); each pair contains
57
    mutually exclusive arguments
58
  @type mode: string
59
  @param mode: current mode of the converter
60

    
61
  """
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))
71

    
72

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

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

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

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

    
86
  #global options
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")
93

    
94
  #import options
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)
106

    
107
  #export options
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",
117
                          action="store",
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)
124

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

    
131
  if mode == IMPORT_MODE:
132
    required = []
133
    forbidden = [
134
      ("compression", "--compress"),
135
      ("disk_format", "--format"),
136
      ("ext_usage", "--external"),
137
      ("ova_package", "--ova"),
138
    ]
139
    excluding = [("nics", "no_nics")]
140
  elif mode == EXPORT_MODE:
141
    required = [("disk_format", "--format")]
142
    forbidden = [
143
      ("beparams", "--backend-parameters"),
144
      ("disk_template", "--disk-template"),
145
      ("disks", "--disk"),
146
      ("hypervisor", "--hypervisor-parameters"),
147
      ("nics", "--net"),
148
      ("no_nics", "--no-nics"),
149
      ("os", "--os-type"),
150
      ("osparams", "--os-parameters"),
151
      ("tags", "--tags"),
152
    ]
153
    excluding = []
154
  else:
155
    parser.error("First argument should be either '%s' or '%s'" %
156
                 (IMPORT_MODE, EXPORT_MODE))
157

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

    
161
  return (mode, input_path, options)
162

    
163

    
164
def SetupLogging(options):
165
  """Setting up logging infrastructure.
166

    
167
  @type options: optparse.Values
168
  @param options: parsed command line options
169

    
170
  """
171
  formatter = logging.Formatter("%(asctime)s: %(levelname)s %(message)s")
172

    
173
  stderr_handler = logging.StreamHandler()
174
  stderr_handler.setFormatter(formatter)
175
  if options.debug:
176
    stderr_handler.setLevel(logging.NOTSET)
177
  elif options.verbose:
178
    stderr_handler.setLevel(logging.INFO)
179
  else:
180
    stderr_handler.setLevel(logging.WARNING)
181

    
182
  root_logger = logging.getLogger("")
183
  root_logger.setLevel(logging.NOTSET)
184
  root_logger.addHandler(stderr_handler)
185

    
186

    
187
def main():
188
  """Main routine.
189

    
190
  """
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)
195
  converter = None
196
  try:
197
    if mode == IMPORT_MODE:
198
      converter = ovf.OVFImporter(input_path, options)
199
    elif mode == EXPORT_MODE:
200
      converter = ovf.OVFExporter(input_path, options)
201
    converter.Parse()
202
    converter.Save()
203
  except errors.OpPrereqError, err:
204
    if converter:
205
      converter.Cleanup()
206
    logging.exception(err)
207
    return constants.EXIT_FAILURE
208

    
209

    
210
if __name__ == "__main__":
211
  main()