root / tools / ovfconverter @ a317d77a
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() |