Statistics
| Branch: | Tag: | Revision:

root / image_creator / main.py @ 71b0ab28

History | View | Annotate | Download (12.8 kB)

1 ae48a082 Nikos Skalkotos
#!/usr/bin/env python
2 ae48a082 Nikos Skalkotos
3 574f2712 Nikos Skalkotos
# Copyright 2012 GRNET S.A. All rights reserved.
4 d57775d4 Nikos Skalkotos
#
5 d57775d4 Nikos Skalkotos
# Redistribution and use in source and binary forms, with or
6 d57775d4 Nikos Skalkotos
# without modification, are permitted provided that the following
7 d57775d4 Nikos Skalkotos
# conditions are met:
8 d57775d4 Nikos Skalkotos
#
9 d57775d4 Nikos Skalkotos
#   1. Redistributions of source code must retain the above
10 d57775d4 Nikos Skalkotos
#      copyright notice, this list of conditions and the following
11 d57775d4 Nikos Skalkotos
#      disclaimer.
12 d57775d4 Nikos Skalkotos
#
13 d57775d4 Nikos Skalkotos
#   2. Redistributions in binary form must reproduce the above
14 d57775d4 Nikos Skalkotos
#      copyright notice, this list of conditions and the following
15 d57775d4 Nikos Skalkotos
#      disclaimer in the documentation and/or other materials
16 d57775d4 Nikos Skalkotos
#      provided with the distribution.
17 d57775d4 Nikos Skalkotos
#
18 d57775d4 Nikos Skalkotos
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
19 d57775d4 Nikos Skalkotos
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 d57775d4 Nikos Skalkotos
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 d57775d4 Nikos Skalkotos
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
22 d57775d4 Nikos Skalkotos
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 d57775d4 Nikos Skalkotos
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 d57775d4 Nikos Skalkotos
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25 d57775d4 Nikos Skalkotos
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 d57775d4 Nikos Skalkotos
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 d57775d4 Nikos Skalkotos
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 d57775d4 Nikos Skalkotos
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 d57775d4 Nikos Skalkotos
# POSSIBILITY OF SUCH DAMAGE.
30 d57775d4 Nikos Skalkotos
#
31 d57775d4 Nikos Skalkotos
# The views and conclusions contained in the software and
32 d57775d4 Nikos Skalkotos
# documentation are those of the authors and should not be
33 d57775d4 Nikos Skalkotos
# interpreted as representing official policies, either expressed
34 d57775d4 Nikos Skalkotos
# or implied, of GRNET S.A.
35 d57775d4 Nikos Skalkotos
36 c408053f Nikos Skalkotos
from image_creator import __version__ as version
37 d57775d4 Nikos Skalkotos
from image_creator.disk import Disk
38 3582e34d Nikos Skalkotos
from image_creator.util import FatalError, MD5
39 4e58b51b Nikos Skalkotos
from image_creator.output.cli import SilentOutput, SimpleOutput, \
40 f99fe99d Nikos Skalkotos
    OutputWthProgress
41 3b7d3fc7 Nikos Skalkotos
from image_creator.kamaki_wrapper import Kamaki, ClientError
42 d57775d4 Nikos Skalkotos
import sys
43 d57775d4 Nikos Skalkotos
import os
44 c408053f Nikos Skalkotos
import optparse
45 b1395967 Nikos Skalkotos
import StringIO
46 9c354f13 Nikos Skalkotos
import signal
47 3ccb2618 Nikos Skalkotos
48 c408053f Nikos Skalkotos
49 0ae01e26 Nikos Skalkotos
def check_writable_dir(option, opt_str, value, parser):
50 0ae01e26 Nikos Skalkotos
    dirname = os.path.dirname(value)
51 0ae01e26 Nikos Skalkotos
    name = os.path.basename(value)
52 0ae01e26 Nikos Skalkotos
    if dirname and not os.path.isdir(dirname):
53 b5430a9f Nikos Skalkotos
        raise FatalError("`%s' is not an existing directory" % dirname)
54 c408053f Nikos Skalkotos
55 0ae01e26 Nikos Skalkotos
    if not name:
56 b5430a9f Nikos Skalkotos
        raise FatalError("`%s' is not a valid file name" % dirname)
57 c408053f Nikos Skalkotos
58 c408053f Nikos Skalkotos
    setattr(parser.values, option.dest, value)
59 c408053f Nikos Skalkotos
60 c408053f Nikos Skalkotos
61 c408053f Nikos Skalkotos
def parse_options(input_args):
62 0ae01e26 Nikos Skalkotos
    usage = "Usage: %prog [options] <input_media>"
63 c408053f Nikos Skalkotos
    parser = optparse.OptionParser(version=version, usage=usage)
64 c408053f Nikos Skalkotos
65 0ae01e26 Nikos Skalkotos
    parser.add_option("-o", "--outfile", type="string", dest="outfile",
66 f99fe99d Nikos Skalkotos
                      default=None, action="callback",
67 f99fe99d Nikos Skalkotos
                      callback=check_writable_dir, help="dump image to FILE",
68 f99fe99d Nikos Skalkotos
                      metavar="FILE")
69 979096dd Nikos Skalkotos
70 997ac76a Nikos Skalkotos
    parser.add_option("-f", "--force", dest="force", default=False,
71 f99fe99d Nikos Skalkotos
                      action="store_true",
72 f99fe99d Nikos Skalkotos
                      help="overwrite output files if they exist")
73 76d4a1c9 Nikos Skalkotos
74 979096dd Nikos Skalkotos
    parser.add_option("-s", "--silent", dest="silent", default=False,
75 c16850ae Nikos Skalkotos
                      help="output only errors",
76 f99fe99d Nikos Skalkotos
                      action="store_true")
77 0ae01e26 Nikos Skalkotos
78 b5430a9f Nikos Skalkotos
    parser.add_option("-u", "--upload", dest="upload", type="string",
79 f99fe99d Nikos Skalkotos
                      default=False,
80 f99fe99d Nikos Skalkotos
                      help="upload the image to pithos with name FILENAME",
81 f99fe99d Nikos Skalkotos
                      metavar="FILENAME")
82 1a3f1298 Nikos Skalkotos
83 b5430a9f Nikos Skalkotos
    parser.add_option("-r", "--register", dest="register", type="string",
84 f99fe99d Nikos Skalkotos
                      default=False,
85 dcf9274b Vangelis Koukis
                      help="register the image with ~okeanos as IMAGENAME",
86 f99fe99d Nikos Skalkotos
                      metavar="IMAGENAME")
87 1a3f1298 Nikos Skalkotos
88 7d3dc857 Nikos Skalkotos
    parser.add_option("-m", "--metadata", dest="metadata", default=[],
89 c16850ae Nikos Skalkotos
                      help="add custom KEY=VALUE metadata to the image",
90 f99fe99d Nikos Skalkotos
                      action="append", metavar="KEY=VALUE")
91 7d3dc857 Nikos Skalkotos
92 997ac76a Nikos Skalkotos
    parser.add_option("-t", "--token", dest="token", type="string",
93 c2cf27e8 Nikos Skalkotos
                      default=None, help="use this authentication token when "
94 c2cf27e8 Nikos Skalkotos
                      "uploading/registering images")
95 997ac76a Nikos Skalkotos
96 997ac76a Nikos Skalkotos
    parser.add_option("--print-sysprep", dest="print_sysprep", default=False,
97 f99fe99d Nikos Skalkotos
                      help="print the enabled and disabled system preparation "
98 f99fe99d Nikos Skalkotos
                      "operations for this input media", action="store_true")
99 997ac76a Nikos Skalkotos
100 997ac76a Nikos Skalkotos
    parser.add_option("--enable-sysprep", dest="enabled_syspreps", default=[],
101 f99fe99d Nikos Skalkotos
                      help="run SYSPREP operation on the input media",
102 f99fe99d Nikos Skalkotos
                      action="append", metavar="SYSPREP")
103 997ac76a Nikos Skalkotos
104 997ac76a Nikos Skalkotos
    parser.add_option("--disable-sysprep", dest="disabled_syspreps",
105 f99fe99d Nikos Skalkotos
                      help="prevent SYSPREP operation from running on the "
106 f99fe99d Nikos Skalkotos
                      "input media", default=[], action="append",
107 f99fe99d Nikos Skalkotos
                      metavar="SYSPREP")
108 997ac76a Nikos Skalkotos
109 997ac76a Nikos Skalkotos
    parser.add_option("--no-sysprep", dest="sysprep", default=True,
110 c16850ae Nikos Skalkotos
                      help="don't perform any system preparation operation",
111 f99fe99d Nikos Skalkotos
                      action="store_false")
112 997ac76a Nikos Skalkotos
113 997ac76a Nikos Skalkotos
    parser.add_option("--no-shrink", dest="shrink", default=True,
114 f99fe99d Nikos Skalkotos
                      help="don't shrink any partition", action="store_false")
115 997ac76a Nikos Skalkotos
116 37d581b8 Nikos Skalkotos
    parser.add_option("--public", dest="public", default=False,
117 aa486e93 Nikos Skalkotos
                      help="register image with cyclades as public",
118 37d581b8 Nikos Skalkotos
                      action="store_true")
119 37d581b8 Nikos Skalkotos
120 c16850ae Nikos Skalkotos
    parser.add_option("--tmpdir", dest="tmp", type="string", default=None,
121 c16850ae Nikos Skalkotos
                      help="create large temporary image files under DIR",
122 c16850ae Nikos Skalkotos
                      metavar="DIR")
123 c16850ae Nikos Skalkotos
124 c408053f Nikos Skalkotos
    options, args = parser.parse_args(input_args)
125 c408053f Nikos Skalkotos
126 0ae01e26 Nikos Skalkotos
    if len(args) != 1:
127 0ae01e26 Nikos Skalkotos
        parser.error('Wrong number of arguments')
128 7d3dc857 Nikos Skalkotos
129 c408053f Nikos Skalkotos
    options.source = args[0]
130 c408053f Nikos Skalkotos
    if not os.path.exists(options.source):
131 b5430a9f Nikos Skalkotos
        raise FatalError("Input media `%s' is not accessible" % options.source)
132 c408053f Nikos Skalkotos
133 f99fe99d Nikos Skalkotos
    if options.register and not options.upload:
134 b5430a9f Nikos Skalkotos
        raise FatalError("You also need to set -u when -r option is set")
135 1a3f1298 Nikos Skalkotos
136 997ac76a Nikos Skalkotos
    if options.upload and options.token is None:
137 37d581b8 Nikos Skalkotos
        raise FatalError(
138 37d581b8 Nikos Skalkotos
            "Image uploading cannot be performed. "
139 31160dc8 Nikos Skalkotos
            "No authentication token is specified. Use -t to set a token")
140 997ac76a Nikos Skalkotos
141 c16850ae Nikos Skalkotos
    if options.tmp is not None and not os.path.isdir(options.tmp):
142 c16850ae Nikos Skalkotos
        raise FatalError("The directory `%s' specified with --tmpdir is not "
143 31160dc8 Nikos Skalkotos
                         "valid" % options.tmp)
144 c16850ae Nikos Skalkotos
145 7d3dc857 Nikos Skalkotos
    meta = {}
146 7d3dc857 Nikos Skalkotos
    for m in options.metadata:
147 7d3dc857 Nikos Skalkotos
        try:
148 7d3dc857 Nikos Skalkotos
            key, value = m.split('=', 1)
149 7d3dc857 Nikos Skalkotos
        except ValueError:
150 31160dc8 Nikos Skalkotos
            raise FatalError("Metadata option: `%s' is not in KEY=VALUE "
151 31160dc8 Nikos Skalkotos
                             "format." % m)
152 7d3dc857 Nikos Skalkotos
        meta[key] = value
153 7d3dc857 Nikos Skalkotos
    options.metadata = meta
154 7d3dc857 Nikos Skalkotos
155 c408053f Nikos Skalkotos
    return options
156 d57775d4 Nikos Skalkotos
157 8c574358 Nikos Skalkotos
158 22a6d232 Nikos Skalkotos
def image_creator():
159 c408053f Nikos Skalkotos
    options = parse_options(sys.argv[1:])
160 c408053f Nikos Skalkotos
161 f99fe99d Nikos Skalkotos
    if options.outfile is None and not options.upload and not \
162 f99fe99d Nikos Skalkotos
            options.print_sysprep:
163 f99fe99d Nikos Skalkotos
        raise FatalError("At least one of `-o', `-u' or `--print-sysprep' "
164 f99fe99d Nikos Skalkotos
                         "must be set")
165 76d4a1c9 Nikos Skalkotos
166 e77e66a9 Nikos Skalkotos
    if options.silent:
167 4e58b51b Nikos Skalkotos
        out = SilentOutput()
168 e77e66a9 Nikos Skalkotos
    else:
169 4e58b51b Nikos Skalkotos
        out = OutputWthProgress(True) if sys.stderr.isatty() else \
170 f99fe99d Nikos Skalkotos
            SimpleOutput(False)
171 e77e66a9 Nikos Skalkotos
172 e108efd2 Nikos Skalkotos
    title = 'snf-image-creator %s' % version
173 e77e66a9 Nikos Skalkotos
    out.output(title)
174 e77e66a9 Nikos Skalkotos
    out.output('=' * len(title))
175 979096dd Nikos Skalkotos
176 c408053f Nikos Skalkotos
    if os.geteuid() != 0:
177 f99fe99d Nikos Skalkotos
        raise FatalError("You must run %s as root"
178 f99fe99d Nikos Skalkotos
                         % os.path.basename(sys.argv[0]))
179 c408053f Nikos Skalkotos
180 69aa33fa Nikos Skalkotos
    if not options.force and options.outfile is not None:
181 8e3065a0 Nikos Skalkotos
        for extension in ('', '.meta', '.md5sum'):
182 0ae01e26 Nikos Skalkotos
            filename = "%s%s" % (options.outfile, extension)
183 c408053f Nikos Skalkotos
            if os.path.exists(filename):
184 03eb7dc8 Nikos Skalkotos
                raise FatalError("Output file `%s' exists "
185 03eb7dc8 Nikos Skalkotos
                                 "(use --force to overwrite it)." % filename)
186 31160dc8 Nikos Skalkotos
187 31160dc8 Nikos Skalkotos
    # Check if the authentication token is valid. The earlier the better
188 c2cf27e8 Nikos Skalkotos
    if options.token is not None:
189 c2cf27e8 Nikos Skalkotos
        try:
190 c2cf27e8 Nikos Skalkotos
            account = Kamaki.get_account(options.token)
191 c2cf27e8 Nikos Skalkotos
            if account is None:
192 c2cf27e8 Nikos Skalkotos
                raise FatalError("The authentication token you provided is not"
193 c2cf27e8 Nikos Skalkotos
                                 " valid!")
194 03eb7dc8 Nikos Skalkotos
            else:
195 03eb7dc8 Nikos Skalkotos
                kamaki = Kamaki(account, out)
196 c2cf27e8 Nikos Skalkotos
        except ClientError as e:
197 c2cf27e8 Nikos Skalkotos
            raise FatalError("Astakos client: %d %s" % (e.status, e.message))
198 c2cf27e8 Nikos Skalkotos
199 03eb7dc8 Nikos Skalkotos
    if options.upload and not options.force:
200 03eb7dc8 Nikos Skalkotos
        if kamaki.object_exists(options.upload):
201 03eb7dc8 Nikos Skalkotos
            raise FatalError("Remote pithos object `%s' exists "
202 03eb7dc8 Nikos Skalkotos
                             "(use --force to overwrite it)." % options.upload)
203 03eb7dc8 Nikos Skalkotos
        if kamaki.object_exists("%s.md5sum" % options.upload):
204 03eb7dc8 Nikos Skalkotos
            raise FatalError("Remote pithos object `%s.md5sum' exists "
205 03eb7dc8 Nikos Skalkotos
                             "(use --force to overwrite it)." % options.upload)
206 03eb7dc8 Nikos Skalkotos
207 03eb7dc8 Nikos Skalkotos
    if options.register and not options.force:
208 03eb7dc8 Nikos Skalkotos
        if kamaki.object_exists("%s.meta" % options.upload):
209 03eb7dc8 Nikos Skalkotos
            raise FatalError("Remote pithos object `%s.meta' exists "
210 03eb7dc8 Nikos Skalkotos
                             "(use --force to overwrite it)." % options.upload)
211 03eb7dc8 Nikos Skalkotos
212 c16850ae Nikos Skalkotos
    disk = Disk(options.source, out, options.tmp)
213 9c354f13 Nikos Skalkotos
214 9c354f13 Nikos Skalkotos
    def signal_handler(signum, frame):
215 9c354f13 Nikos Skalkotos
        disk.cleanup()
216 9c354f13 Nikos Skalkotos
217 9c354f13 Nikos Skalkotos
    signal.signal(signal.SIGINT, signal_handler)
218 9c354f13 Nikos Skalkotos
    signal.signal(signal.SIGTERM, signal_handler)
219 d57775d4 Nikos Skalkotos
    try:
220 e22aa3a9 Nikos Skalkotos
        snapshot = disk.snapshot()
221 e22aa3a9 Nikos Skalkotos
222 f5174d2c Nikos Skalkotos
        image = disk.get_image(snapshot)
223 df499fea Nikos Skalkotos
224 71b0ab28 Nikos Skalkotos
        for sysprep in options.disabled_syspreps:
225 71b0ab28 Nikos Skalkotos
            image.os.disable_sysprep(image.os.get_sysprep_by_name(sysprep))
226 71b0ab28 Nikos Skalkotos
227 71b0ab28 Nikos Skalkotos
        for sysprep in options.enabled_syspreps:
228 71b0ab28 Nikos Skalkotos
            image.os.enable_sysprep(image.os.get_sysprep_by_name(sysprep))
229 71b0ab28 Nikos Skalkotos
230 71b0ab28 Nikos Skalkotos
        if options.print_sysprep:
231 71b0ab28 Nikos Skalkotos
            image.os.print_syspreps()
232 71b0ab28 Nikos Skalkotos
            out.output()
233 71b0ab28 Nikos Skalkotos
234 71b0ab28 Nikos Skalkotos
        if options.outfile is None and not options.upload:
235 71b0ab28 Nikos Skalkotos
            return 0
236 71b0ab28 Nikos Skalkotos
237 71b0ab28 Nikos Skalkotos
        if options.sysprep:
238 71b0ab28 Nikos Skalkotos
            image.os.do_sysprep()
239 71b0ab28 Nikos Skalkotos
240 71b0ab28 Nikos Skalkotos
        metadata = image.os.meta
241 1a3f1298 Nikos Skalkotos
242 f5174d2c Nikos Skalkotos
        size = options.shrink and image.shrink() or image.size
243 f5174d2c Nikos Skalkotos
        metadata.update(image.meta)
244 ae48a082 Nikos Skalkotos
245 7d3dc857 Nikos Skalkotos
        # Add command line metadata to the collected ones...
246 7d3dc857 Nikos Skalkotos
        metadata.update(options.metadata)
247 7d3dc857 Nikos Skalkotos
248 e77e66a9 Nikos Skalkotos
        md5 = MD5(out)
249 f5174d2c Nikos Skalkotos
        checksum = md5.compute(image.device, size)
250 8e3065a0 Nikos Skalkotos
251 143e9484 Nikos Skalkotos
        metastring = '\n'.join(
252 f99fe99d Nikos Skalkotos
            ['%s=%s' % (key, value) for (key, value) in metadata.items()])
253 143e9484 Nikos Skalkotos
        metastring += '\n'
254 0ae01e26 Nikos Skalkotos
255 b1395967 Nikos Skalkotos
        if options.outfile is not None:
256 f5174d2c Nikos Skalkotos
            image.dump(options.outfile)
257 997ac76a Nikos Skalkotos
258 663f5f80 Nikos Skalkotos
            out.output('Dumping metadata file ...', False)
259 b1395967 Nikos Skalkotos
            with open('%s.%s' % (options.outfile, 'meta'), 'w') as f:
260 5b801534 Nikos Skalkotos
                f.write(metastring)
261 e77e66a9 Nikos Skalkotos
            out.success('done')
262 b1395967 Nikos Skalkotos
263 663f5f80 Nikos Skalkotos
            out.output('Dumping md5sum file ...', False)
264 b1395967 Nikos Skalkotos
            with open('%s.%s' % (options.outfile, 'md5sum'), 'w') as f:
265 f99fe99d Nikos Skalkotos
                f.write('%s %s\n' % (checksum,
266 f99fe99d Nikos Skalkotos
                                     os.path.basename(options.outfile)))
267 e77e66a9 Nikos Skalkotos
            out.success('done')
268 b1395967 Nikos Skalkotos
269 f5174d2c Nikos Skalkotos
        # Destroy the image instance. We only need the snapshot from now on
270 f5174d2c Nikos Skalkotos
        disk.destroy_image(image)
271 e22aa3a9 Nikos Skalkotos
272 e77e66a9 Nikos Skalkotos
        out.output()
273 3b7d3fc7 Nikos Skalkotos
        try:
274 3b7d3fc7 Nikos Skalkotos
            uploaded_obj = ""
275 3b7d3fc7 Nikos Skalkotos
            if options.upload:
276 3b7d3fc7 Nikos Skalkotos
                out.output("Uploading image to pithos:")
277 825fe2a6 Nikos Skalkotos
                with open(snapshot, 'rb') as f:
278 37d581b8 Nikos Skalkotos
                    uploaded_obj = kamaki.upload(
279 37d581b8 Nikos Skalkotos
                        f, size, options.upload,
280 03eb7dc8 Nikos Skalkotos
                        "(1/3)  Calculating block hashes",
281 03eb7dc8 Nikos Skalkotos
                        "(2/3)  Uploading missing blocks")
282 03eb7dc8 Nikos Skalkotos
                out.output("(3/3)  Uploading md5sum file ...", False)
283 f99fe99d Nikos Skalkotos
                md5sumstr = '%s %s\n' % (checksum,
284 f99fe99d Nikos Skalkotos
                                         os.path.basename(options.upload))
285 3b7d3fc7 Nikos Skalkotos
                kamaki.upload(StringIO.StringIO(md5sumstr),
286 3b7d3fc7 Nikos Skalkotos
                              size=len(md5sumstr),
287 3b7d3fc7 Nikos Skalkotos
                              remote_path="%s.%s" % (options.upload, 'md5sum'))
288 3b7d3fc7 Nikos Skalkotos
                out.success('done')
289 3b7d3fc7 Nikos Skalkotos
                out.output()
290 3b7d3fc7 Nikos Skalkotos
291 3b7d3fc7 Nikos Skalkotos
            if options.register:
292 37d581b8 Nikos Skalkotos
                img_type = 'public' if options.public else 'private'
293 37d581b8 Nikos Skalkotos
                out.output('Registering %s image with ~okeanos ...' % img_type,
294 37d581b8 Nikos Skalkotos
                           False)
295 37d581b8 Nikos Skalkotos
                kamaki.register(options.register, uploaded_obj, metadata,
296 37d581b8 Nikos Skalkotos
                                options.public)
297 3b7d3fc7 Nikos Skalkotos
                out.success('done')
298 03eb7dc8 Nikos Skalkotos
                out.output("Uploading metadata file ...", False)
299 03eb7dc8 Nikos Skalkotos
                kamaki.upload(StringIO.StringIO(metastring),
300 03eb7dc8 Nikos Skalkotos
                              size=len(metastring),
301 03eb7dc8 Nikos Skalkotos
                              remote_path="%s.%s" % (options.upload, 'meta'))
302 03eb7dc8 Nikos Skalkotos
                out.success('done')
303 3afe6b44 Nikos Skalkotos
                if options.public:
304 3afe6b44 Nikos Skalkotos
                    out.output("Sharing md5sum file ...", False)
305 3afe6b44 Nikos Skalkotos
                    kamaki.share("%s.md5sum" % options.upload)
306 3afe6b44 Nikos Skalkotos
                    out.success('done')
307 3afe6b44 Nikos Skalkotos
                    out.output("Sharing metadata file ...", False)
308 3afe6b44 Nikos Skalkotos
                    kamaki.share("%s.meta" % options.upload)
309 3afe6b44 Nikos Skalkotos
                    out.success('done')
310 3afe6b44 Nikos Skalkotos
311 3b7d3fc7 Nikos Skalkotos
                out.output()
312 3b7d3fc7 Nikos Skalkotos
        except ClientError as e:
313 3b7d3fc7 Nikos Skalkotos
            raise FatalError("Pithos client: %d %s" % (e.status, e.message))
314 997ac76a Nikos Skalkotos
315 d57775d4 Nikos Skalkotos
    finally:
316 fd9af948 Nikos Skalkotos
        out.output('cleaning up ...')
317 d57775d4 Nikos Skalkotos
        disk.cleanup()
318 d57775d4 Nikos Skalkotos
319 e77e66a9 Nikos Skalkotos
    out.success("snf-image-creator exited without errors")
320 b1395967 Nikos Skalkotos
321 c408053f Nikos Skalkotos
    return 0
322 c408053f Nikos Skalkotos
323 ae48a082 Nikos Skalkotos
324 0ae01e26 Nikos Skalkotos
def main():
325 c408053f Nikos Skalkotos
    try:
326 0ae01e26 Nikos Skalkotos
        ret = image_creator()
327 c408053f Nikos Skalkotos
        sys.exit(ret)
328 c408053f Nikos Skalkotos
    except FatalError as e:
329 bb4db5a8 Nikos Skalkotos
        colored = sys.stderr.isatty()
330 bb4db5a8 Nikos Skalkotos
        SimpleOutput(colored).error(e)
331 c408053f Nikos Skalkotos
        sys.exit(1)
332 d57775d4 Nikos Skalkotos
333 0ae01e26 Nikos Skalkotos
if __name__ == '__main__':
334 0ae01e26 Nikos Skalkotos
    main()
335 ae48a082 Nikos Skalkotos
336 d57775d4 Nikos Skalkotos
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :