Statistics
| Branch: | Tag: | Revision:

root / tools / ovfconverter @ 1fa6fcba

History | View | Annotate | Download (6.2 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
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()