Statistics
| Branch: | Tag: | Revision:

root / image_creator / dialog_wizard.py @ 121f3bc0

History | View | Annotate | Download (11.5 kB)

1 121f3bc0 Nikos Skalkotos
# -*- coding: utf-8 -*-
2 121f3bc0 Nikos Skalkotos
#
3 09ed3d46 Nikos Skalkotos
# Copyright 2012 GRNET S.A. All rights reserved.
4 09ed3d46 Nikos Skalkotos
#
5 09ed3d46 Nikos Skalkotos
# Redistribution and use in source and binary forms, with or
6 09ed3d46 Nikos Skalkotos
# without modification, are permitted provided that the following
7 09ed3d46 Nikos Skalkotos
# conditions are met:
8 09ed3d46 Nikos Skalkotos
#
9 09ed3d46 Nikos Skalkotos
#   1. Redistributions of source code must retain the above
10 09ed3d46 Nikos Skalkotos
#      copyright notice, this list of conditions and the following
11 09ed3d46 Nikos Skalkotos
#      disclaimer.
12 09ed3d46 Nikos Skalkotos
#
13 09ed3d46 Nikos Skalkotos
#   2. Redistributions in binary form must reproduce the above
14 09ed3d46 Nikos Skalkotos
#      copyright notice, this list of conditions and the following
15 09ed3d46 Nikos Skalkotos
#      disclaimer in the documentation and/or other materials
16 09ed3d46 Nikos Skalkotos
#      provided with the distribution.
17 09ed3d46 Nikos Skalkotos
#
18 09ed3d46 Nikos Skalkotos
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
19 09ed3d46 Nikos Skalkotos
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 09ed3d46 Nikos Skalkotos
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 09ed3d46 Nikos Skalkotos
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
22 09ed3d46 Nikos Skalkotos
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 09ed3d46 Nikos Skalkotos
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 09ed3d46 Nikos Skalkotos
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25 09ed3d46 Nikos Skalkotos
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 09ed3d46 Nikos Skalkotos
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 09ed3d46 Nikos Skalkotos
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 09ed3d46 Nikos Skalkotos
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 09ed3d46 Nikos Skalkotos
# POSSIBILITY OF SUCH DAMAGE.
30 09ed3d46 Nikos Skalkotos
#
31 09ed3d46 Nikos Skalkotos
# The views and conclusions contained in the software and
32 09ed3d46 Nikos Skalkotos
# documentation are those of the authors and should not be
33 09ed3d46 Nikos Skalkotos
# interpreted as representing official policies, either expressed
34 09ed3d46 Nikos Skalkotos
# or implied, of GRNET S.A.
35 09ed3d46 Nikos Skalkotos
36 121f3bc0 Nikos Skalkotos
"""This module implements the "wizard" mode of the dialog-based version of
37 121f3bc0 Nikos Skalkotos
snf-image-creator.
38 121f3bc0 Nikos Skalkotos
"""
39 121f3bc0 Nikos Skalkotos
40 fbdf1d8f Nikos Skalkotos
import time
41 fbdf1d8f Nikos Skalkotos
import StringIO
42 09ed3d46 Nikos Skalkotos
43 fbdf1d8f Nikos Skalkotos
from image_creator.kamaki_wrapper import Kamaki, ClientError
44 fbdf1d8f Nikos Skalkotos
from image_creator.util import MD5, FatalError
45 fbdf1d8f Nikos Skalkotos
from image_creator.output.cli import OutputWthProgress
46 023e1217 Nikos Skalkotos
from image_creator.dialog_util import extract_image, update_background_title
47 09ed3d46 Nikos Skalkotos
48 3c33e68a Nikos Skalkotos
PAGE_WIDTH = 70
49 09ed3d46 Nikos Skalkotos
50 09ed3d46 Nikos Skalkotos
51 aeb95900 Nikos Skalkotos
class WizardExit(Exception):
52 88f83027 Nikos Skalkotos
    """Exception used to exit the wizard"""
53 aeb95900 Nikos Skalkotos
    pass
54 aeb95900 Nikos Skalkotos
55 aeb95900 Nikos Skalkotos
56 31160dc8 Nikos Skalkotos
class WizardInvalidData(Exception):
57 88f83027 Nikos Skalkotos
    """Exception triggered when the user provided data are invalid"""
58 31160dc8 Nikos Skalkotos
    pass
59 31160dc8 Nikos Skalkotos
60 31160dc8 Nikos Skalkotos
61 3c33e68a Nikos Skalkotos
class Wizard:
62 88f83027 Nikos Skalkotos
    """Represents a dialog-based wizard
63 88f83027 Nikos Skalkotos

64 88f83027 Nikos Skalkotos
    The wizard is a collection of pages that have a "Next" and a "Back" button
65 88f83027 Nikos Skalkotos
    on them. The pages are used to collect user data.
66 88f83027 Nikos Skalkotos
    """
67 88f83027 Nikos Skalkotos
68 3c33e68a Nikos Skalkotos
    def __init__(self, session):
69 3c33e68a Nikos Skalkotos
        self.session = session
70 3c33e68a Nikos Skalkotos
        self.pages = []
71 3c33e68a Nikos Skalkotos
        self.session['wizard'] = {}
72 baa62724 Nikos Skalkotos
        self.d = session['dialog']
73 3c33e68a Nikos Skalkotos
74 3c33e68a Nikos Skalkotos
    def add_page(self, page):
75 88f83027 Nikos Skalkotos
        """Add a new page to the wizard"""
76 3c33e68a Nikos Skalkotos
        self.pages.append(page)
77 09ed3d46 Nikos Skalkotos
78 09ed3d46 Nikos Skalkotos
    def run(self):
79 88f83027 Nikos Skalkotos
        """Run the wizard"""
80 3c33e68a Nikos Skalkotos
        idx = 0
81 3c33e68a Nikos Skalkotos
        while True:
82 aeb95900 Nikos Skalkotos
            try:
83 aeb95900 Nikos Skalkotos
                idx += self.pages[idx].run(self.session, idx, len(self.pages))
84 aeb95900 Nikos Skalkotos
            except WizardExit:
85 aeb95900 Nikos Skalkotos
                return False
86 31160dc8 Nikos Skalkotos
            except WizardInvalidData:
87 31160dc8 Nikos Skalkotos
                continue
88 09ed3d46 Nikos Skalkotos
89 3c33e68a Nikos Skalkotos
            if idx >= len(self.pages):
90 baa62724 Nikos Skalkotos
                msg = "All necessary information has been gathered:\n\n"
91 baa62724 Nikos Skalkotos
                for page in self.pages:
92 baa62724 Nikos Skalkotos
                    msg += " * %s\n" % page.info
93 66719e36 Nikos Skalkotos
                msg += "\nContinue with the image creation process?"
94 baa62724 Nikos Skalkotos
95 baa62724 Nikos Skalkotos
                ret = self.d.yesno(
96 66719e36 Nikos Skalkotos
                    msg, width=PAGE_WIDTH, height=8 + len(self.pages),
97 66719e36 Nikos Skalkotos
                    ok_label="Yes", cancel="Back", extra_button=1,
98 66719e36 Nikos Skalkotos
                    extra_label="Quit", title="Confirmation")
99 baa62724 Nikos Skalkotos
100 baa62724 Nikos Skalkotos
                if ret == self.d.DIALOG_CANCEL:
101 baa62724 Nikos Skalkotos
                    idx -= 1
102 baa62724 Nikos Skalkotos
                elif ret == self.d.DIALOG_EXTRA:
103 baa62724 Nikos Skalkotos
                    return False
104 baa62724 Nikos Skalkotos
                elif ret == self.d.DIALOG_OK:
105 baa62724 Nikos Skalkotos
                    return True
106 09ed3d46 Nikos Skalkotos
107 3c33e68a Nikos Skalkotos
            if idx < 0:
108 3c33e68a Nikos Skalkotos
                return False
109 09ed3d46 Nikos Skalkotos
110 09ed3d46 Nikos Skalkotos
111 baa62724 Nikos Skalkotos
class WizardPage(object):
112 88f83027 Nikos Skalkotos
    """Represents a page in a wizard"""
113 3c33e68a Nikos Skalkotos
    NEXT = 1
114 3c33e68a Nikos Skalkotos
    PREV = -1
115 fbdf1d8f Nikos Skalkotos
116 baa62724 Nikos Skalkotos
    def __init__(self, **kargs):
117 66719e36 Nikos Skalkotos
        validate = kargs['validate'] if 'validate' in kargs else lambda x: x
118 baa62724 Nikos Skalkotos
        setattr(self, "validate", validate)
119 baa62724 Nikos Skalkotos
120 66719e36 Nikos Skalkotos
        display = kargs['display'] if 'display' in kargs else lambda x: x
121 baa62724 Nikos Skalkotos
        setattr(self, "display", display)
122 baa62724 Nikos Skalkotos
123 fbdf1d8f Nikos Skalkotos
    def run(self, session, index, total):
124 88f83027 Nikos Skalkotos
        """Display this wizard page
125 88f83027 Nikos Skalkotos

126 88f83027 Nikos Skalkotos
        This function is used by the wizard program when accessing a page.
127 88f83027 Nikos Skalkotos
        """
128 fbdf1d8f Nikos Skalkotos
        raise NotImplementedError
129 fbdf1d8f Nikos Skalkotos
130 fbdf1d8f Nikos Skalkotos
131 37ee0098 Nikos Skalkotos
class WizardRadioListPage(WizardPage):
132 88f83027 Nikos Skalkotos
    """Represent a Radio List in a wizard"""
133 baa62724 Nikos Skalkotos
    def __init__(self, name, printable, message, choices, **kargs):
134 baa62724 Nikos Skalkotos
        super(WizardRadioListPage, self).__init__(**kargs)
135 37ee0098 Nikos Skalkotos
        self.name = name
136 baa62724 Nikos Skalkotos
        self.printable = printable
137 37ee0098 Nikos Skalkotos
        self.message = message
138 37ee0098 Nikos Skalkotos
        self.choices = choices
139 37ee0098 Nikos Skalkotos
        self.title = kargs['title'] if 'title' in kargs else ''
140 baa62724 Nikos Skalkotos
        self.default = kargs['default'] if 'default' in kargs else ""
141 37ee0098 Nikos Skalkotos
142 37ee0098 Nikos Skalkotos
    def run(self, session, index, total):
143 37ee0098 Nikos Skalkotos
        d = session['dialog']
144 37ee0098 Nikos Skalkotos
        w = session['wizard']
145 37ee0098 Nikos Skalkotos
146 37ee0098 Nikos Skalkotos
        choices = []
147 37ee0098 Nikos Skalkotos
        for i in range(len(self.choices)):
148 37d581b8 Nikos Skalkotos
            default = 1 if self.choices[i][0] == self.default else 0
149 37ee0098 Nikos Skalkotos
            choices.append((self.choices[i][0], self.choices[i][1], default))
150 37ee0098 Nikos Skalkotos
151 baa62724 Nikos Skalkotos
        (code, answer) = d.radiolist(
152 baa62724 Nikos Skalkotos
            self.message, height=10, width=PAGE_WIDTH, ok_label="Next",
153 baa62724 Nikos Skalkotos
            cancel="Back", choices=choices,
154 baa62724 Nikos Skalkotos
            title="(%d/%d) %s" % (index + 1, total, self.title))
155 37ee0098 Nikos Skalkotos
156 baa62724 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
157 baa62724 Nikos Skalkotos
            return self.PREV
158 37ee0098 Nikos Skalkotos
159 baa62724 Nikos Skalkotos
        w[self.name] = self.validate(answer)
160 baa62724 Nikos Skalkotos
        self.default = answer
161 baa62724 Nikos Skalkotos
        self.info = "%s: %s" % (self.printable, self.display(w[self.name]))
162 37ee0098 Nikos Skalkotos
163 baa62724 Nikos Skalkotos
        return self.NEXT
164 37ee0098 Nikos Skalkotos
165 37ee0098 Nikos Skalkotos
166 fbdf1d8f Nikos Skalkotos
class WizardInputPage(WizardPage):
167 88f83027 Nikos Skalkotos
    """Represents an input field in a wizard"""
168 baa62724 Nikos Skalkotos
    def __init__(self, name, printable, message, **kargs):
169 baa62724 Nikos Skalkotos
        super(WizardInputPage, self).__init__(**kargs)
170 3c33e68a Nikos Skalkotos
        self.name = name
171 baa62724 Nikos Skalkotos
        self.printable = printable
172 3c33e68a Nikos Skalkotos
        self.message = message
173 88f83027 Nikos Skalkotos
        self.info = "%s: <none>" % self.printable
174 3c33e68a Nikos Skalkotos
        self.title = kargs['title'] if 'title' in kargs else ''
175 31160dc8 Nikos Skalkotos
        self.init = kargs['init'] if 'init' in kargs else ''
176 09ed3d46 Nikos Skalkotos
177 3c33e68a Nikos Skalkotos
    def run(self, session, index, total):
178 3c33e68a Nikos Skalkotos
        d = session['dialog']
179 3c33e68a Nikos Skalkotos
        w = session['wizard']
180 09ed3d46 Nikos Skalkotos
181 baa62724 Nikos Skalkotos
        (code, answer) = d.inputbox(
182 baa62724 Nikos Skalkotos
            self.message, init=self.init, width=PAGE_WIDTH, ok_label="Next",
183 baa62724 Nikos Skalkotos
            cancel="Back", title="(%d/%d) %s" % (index + 1, total, self.title))
184 09ed3d46 Nikos Skalkotos
185 baa62724 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
186 baa62724 Nikos Skalkotos
            return self.PREV
187 09ed3d46 Nikos Skalkotos
188 baa62724 Nikos Skalkotos
        value = answer.strip()
189 baa62724 Nikos Skalkotos
        self.init = value
190 baa62724 Nikos Skalkotos
        w[self.name] = self.validate(value)
191 baa62724 Nikos Skalkotos
        self.info = "%s: %s" % (self.printable, self.display(w[self.name]))
192 09ed3d46 Nikos Skalkotos
193 09ed3d46 Nikos Skalkotos
        return self.NEXT
194 09ed3d46 Nikos Skalkotos
195 09ed3d46 Nikos Skalkotos
196 88f83027 Nikos Skalkotos
def start_wizard(session):
197 88f83027 Nikos Skalkotos
    """Run the image creation wizard"""
198 8bd0cbb6 Nikos Skalkotos
    init_token = Kamaki.get_token()
199 8bd0cbb6 Nikos Skalkotos
    if init_token is None:
200 8bd0cbb6 Nikos Skalkotos
        init_token = ""
201 09ed3d46 Nikos Skalkotos
202 39b0429a Nikos Skalkotos
    distro = session['image'].distro
203 39b0429a Nikos Skalkotos
    ostype = session['image'].ostype
204 baa62724 Nikos Skalkotos
    name = WizardInputPage(
205 baa62724 Nikos Skalkotos
        "ImageName", "Image Name", "Please provide a name for the image:",
206 39b0429a Nikos Skalkotos
        title="Image Name", init=ostype if distro == "unknown" else distro)
207 baa62724 Nikos Skalkotos
208 37d581b8 Nikos Skalkotos
    descr = WizardInputPage(
209 baa62724 Nikos Skalkotos
        "ImageDescription", "Image Description",
210 baa62724 Nikos Skalkotos
        "Please provide a description for the image:",
211 37d581b8 Nikos Skalkotos
        title="Image Description", init=session['metadata']['DESCRIPTION'] if
212 37d581b8 Nikos Skalkotos
        'DESCRIPTION' in session['metadata'] else '')
213 baa62724 Nikos Skalkotos
214 37d581b8 Nikos Skalkotos
    registration = WizardRadioListPage(
215 baa62724 Nikos Skalkotos
        "ImageRegistration", "Registration Type",
216 baa62724 Nikos Skalkotos
        "Please provide a registration type:",
217 37d581b8 Nikos Skalkotos
        [("Private", "Image is accessible only by this user"),
218 37d581b8 Nikos Skalkotos
         ("Public", "Everyone can create VMs from this image")],
219 37d581b8 Nikos Skalkotos
        title="Registration Type", default="Private")
220 31160dc8 Nikos Skalkotos
221 31160dc8 Nikos Skalkotos
    def validate_account(token):
222 88f83027 Nikos Skalkotos
        """Check if a token is valid"""
223 76f42c27 Nikos Skalkotos
        d = session['dialog']
224 76f42c27 Nikos Skalkotos
225 31160dc8 Nikos Skalkotos
        if len(token) == 0:
226 31160dc8 Nikos Skalkotos
            d.msgbox("The token cannot be empty", width=PAGE_WIDTH)
227 31160dc8 Nikos Skalkotos
            raise WizardInvalidData
228 31160dc8 Nikos Skalkotos
229 31160dc8 Nikos Skalkotos
        account = Kamaki.get_account(token)
230 31160dc8 Nikos Skalkotos
        if account is None:
231 76f42c27 Nikos Skalkotos
            d.msgbox("The token you provided in not valid!", width=PAGE_WIDTH)
232 31160dc8 Nikos Skalkotos
            raise WizardInvalidData
233 31160dc8 Nikos Skalkotos
234 31160dc8 Nikos Skalkotos
        return account
235 31160dc8 Nikos Skalkotos
236 37d581b8 Nikos Skalkotos
    account = WizardInputPage(
237 baa62724 Nikos Skalkotos
        "Account", "Account",
238 baa62724 Nikos Skalkotos
        "Please provide your ~okeanos authentication token:",
239 baa62724 Nikos Skalkotos
        title="~okeanos account", init=init_token, validate=validate_account,
240 baa62724 Nikos Skalkotos
        display=lambda account: account['username'])
241 fbdf1d8f Nikos Skalkotos
242 3c33e68a Nikos Skalkotos
    w = Wizard(session)
243 fbdf1d8f Nikos Skalkotos
244 3c33e68a Nikos Skalkotos
    w.add_page(name)
245 3c33e68a Nikos Skalkotos
    w.add_page(descr)
246 37d581b8 Nikos Skalkotos
    w.add_page(registration)
247 3c33e68a Nikos Skalkotos
    w.add_page(account)
248 fbdf1d8f Nikos Skalkotos
249 fbdf1d8f Nikos Skalkotos
    if w.run():
250 023e1217 Nikos Skalkotos
        create_image(session)
251 fbdf1d8f Nikos Skalkotos
    else:
252 fbdf1d8f Nikos Skalkotos
        return False
253 fbdf1d8f Nikos Skalkotos
254 fbdf1d8f Nikos Skalkotos
    return True
255 fbdf1d8f Nikos Skalkotos
256 fbdf1d8f Nikos Skalkotos
257 023e1217 Nikos Skalkotos
def create_image(session):
258 88f83027 Nikos Skalkotos
    """Create an image using the information collected by the wizard"""
259 37ee0098 Nikos Skalkotos
    d = session['dialog']
260 f5174d2c Nikos Skalkotos
    image = session['image']
261 fbdf1d8f Nikos Skalkotos
    wizard = session['wizard']
262 fbdf1d8f Nikos Skalkotos
263 8bd0cbb6 Nikos Skalkotos
    # Save Kamaki credentials
264 baa62724 Nikos Skalkotos
    Kamaki.save_token(wizard['Account']['auth_token'])
265 8bd0cbb6 Nikos Skalkotos
266 789a3763 Nikos Skalkotos
    with_progress = OutputWthProgress(True)
267 f5174d2c Nikos Skalkotos
    out = image.out
268 789a3763 Nikos Skalkotos
    out.add(with_progress)
269 789a3763 Nikos Skalkotos
    try:
270 789a3763 Nikos Skalkotos
        out.clear()
271 fbdf1d8f Nikos Skalkotos
272 789a3763 Nikos Skalkotos
        #Sysprep
273 f5174d2c Nikos Skalkotos
        image.os.do_sysprep()
274 f5174d2c Nikos Skalkotos
        metadata = image.os.meta
275 1d413d1e Nikos Skalkotos
276 789a3763 Nikos Skalkotos
        #Shrink
277 f5174d2c Nikos Skalkotos
        size = image.shrink()
278 3793498a Nikos Skalkotos
        session['shrinked'] = True
279 023e1217 Nikos Skalkotos
        update_background_title(session)
280 fbdf1d8f Nikos Skalkotos
281 f5174d2c Nikos Skalkotos
        metadata.update(image.meta)
282 789a3763 Nikos Skalkotos
        metadata['DESCRIPTION'] = wizard['ImageDescription']
283 fbdf1d8f Nikos Skalkotos
284 789a3763 Nikos Skalkotos
        #MD5
285 789a3763 Nikos Skalkotos
        md5 = MD5(out)
286 f5174d2c Nikos Skalkotos
        session['checksum'] = md5.compute(image.device, size)
287 fbdf1d8f Nikos Skalkotos
288 789a3763 Nikos Skalkotos
        #Metadata
289 789a3763 Nikos Skalkotos
        metastring = '\n'.join(
290 789a3763 Nikos Skalkotos
            ['%s=%s' % (key, value) for (key, value) in metadata.items()])
291 789a3763 Nikos Skalkotos
        metastring += '\n'
292 fbdf1d8f Nikos Skalkotos
293 fbdf1d8f Nikos Skalkotos
        out.output()
294 789a3763 Nikos Skalkotos
        try:
295 789a3763 Nikos Skalkotos
            out.output("Uploading image to pithos:")
296 baa62724 Nikos Skalkotos
            kamaki = Kamaki(wizard['Account'], out)
297 789a3763 Nikos Skalkotos
298 789a3763 Nikos Skalkotos
            name = "%s-%s.diskdump" % (wizard['ImageName'],
299 789a3763 Nikos Skalkotos
                                       time.strftime("%Y%m%d%H%M"))
300 789a3763 Nikos Skalkotos
            pithos_file = ""
301 f5174d2c Nikos Skalkotos
            with open(image.device, 'rb') as f:
302 789a3763 Nikos Skalkotos
                pithos_file = kamaki.upload(f, size, name,
303 023e1217 Nikos Skalkotos
                                            "(1/4)  Calculating block hashes",
304 023e1217 Nikos Skalkotos
                                            "(2/4)  Uploading missing blocks")
305 789a3763 Nikos Skalkotos
306 663f5f80 Nikos Skalkotos
            out.output("(3/4)  Uploading metadata file ...", False)
307 789a3763 Nikos Skalkotos
            kamaki.upload(StringIO.StringIO(metastring), size=len(metastring),
308 789a3763 Nikos Skalkotos
                          remote_path="%s.%s" % (name, 'meta'))
309 789a3763 Nikos Skalkotos
            out.success('done')
310 663f5f80 Nikos Skalkotos
            out.output("(4/4)  Uploading md5sum file ...", False)
311 789a3763 Nikos Skalkotos
            md5sumstr = '%s %s\n' % (session['checksum'], name)
312 789a3763 Nikos Skalkotos
            kamaki.upload(StringIO.StringIO(md5sumstr), size=len(md5sumstr),
313 789a3763 Nikos Skalkotos
                          remote_path="%s.%s" % (name, 'md5sum'))
314 789a3763 Nikos Skalkotos
            out.success('done')
315 789a3763 Nikos Skalkotos
            out.output()
316 789a3763 Nikos Skalkotos
317 769526cb Nikos Skalkotos
            is_public = True if wizard['ImageRegistration'] == "Public" else \
318 769526cb Nikos Skalkotos
                False
319 37d581b8 Nikos Skalkotos
            out.output('Registering %s image with ~okeanos ...' %
320 769526cb Nikos Skalkotos
                       wizard['ImageRegistration'].lower(), False)
321 37d581b8 Nikos Skalkotos
            kamaki.register(wizard['ImageName'], pithos_file, metadata,
322 37d581b8 Nikos Skalkotos
                            is_public)
323 789a3763 Nikos Skalkotos
            out.success('done')
324 3afe6b44 Nikos Skalkotos
            if is_public:
325 3afe6b44 Nikos Skalkotos
                out.output("Sharing md5sum file ...", False)
326 3afe6b44 Nikos Skalkotos
                kamaki.share("%s.md5sum" % name)
327 3afe6b44 Nikos Skalkotos
                out.success('done')
328 3afe6b44 Nikos Skalkotos
                out.output("Sharing metadata file ...", False)
329 3afe6b44 Nikos Skalkotos
                kamaki.share("%s.meta" % name)
330 3afe6b44 Nikos Skalkotos
                out.success('done')
331 3afe6b44 Nikos Skalkotos
332 789a3763 Nikos Skalkotos
            out.output()
333 789a3763 Nikos Skalkotos
334 789a3763 Nikos Skalkotos
        except ClientError as e:
335 789a3763 Nikos Skalkotos
            raise FatalError("Pithos client: %d %s" % (e.status, e.message))
336 789a3763 Nikos Skalkotos
    finally:
337 789a3763 Nikos Skalkotos
        out.remove(with_progress)
338 09ed3d46 Nikos Skalkotos
339 37d581b8 Nikos Skalkotos
    msg = "The %s image was successfully uploaded and registered with " \
340 37d581b8 Nikos Skalkotos
          "~okeanos. Would you like to keep a local copy of the image?" \
341 769526cb Nikos Skalkotos
          % wizard['ImageRegistration'].lower()
342 37ee0098 Nikos Skalkotos
    if not d.yesno(msg, width=PAGE_WIDTH):
343 023e1217 Nikos Skalkotos
        extract_image(session)
344 37ee0098 Nikos Skalkotos
345 09ed3d46 Nikos Skalkotos
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :