Statistics
| Branch: | Tag: | Revision:

root / image_creator / main.py @ 5e18a927

History | View | Annotate | Download (14.4 kB)

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