Statistics
| Branch: | Tag: | Revision:

root / image_creator / dialog_wizard.py @ 71b0ab28

History | View | Annotate | Download (11.4 kB)

1 09ed3d46 Nikos Skalkotos
#!/usr/bin/env python
2 09ed3d46 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 fbdf1d8f Nikos Skalkotos
import time
37 fbdf1d8f Nikos Skalkotos
import StringIO
38 09ed3d46 Nikos Skalkotos
39 fbdf1d8f Nikos Skalkotos
from image_creator.kamaki_wrapper import Kamaki, ClientError
40 fbdf1d8f Nikos Skalkotos
from image_creator.util import MD5, FatalError
41 fbdf1d8f Nikos Skalkotos
from image_creator.output.cli import OutputWthProgress
42 023e1217 Nikos Skalkotos
from image_creator.dialog_util import extract_image, update_background_title
43 09ed3d46 Nikos Skalkotos
44 3c33e68a Nikos Skalkotos
PAGE_WIDTH = 70
45 09ed3d46 Nikos Skalkotos
46 09ed3d46 Nikos Skalkotos
47 aeb95900 Nikos Skalkotos
class WizardExit(Exception):
48 88f83027 Nikos Skalkotos
    """Exception used to exit the wizard"""
49 aeb95900 Nikos Skalkotos
    pass
50 aeb95900 Nikos Skalkotos
51 aeb95900 Nikos Skalkotos
52 31160dc8 Nikos Skalkotos
class WizardInvalidData(Exception):
53 88f83027 Nikos Skalkotos
    """Exception triggered when the user provided data are invalid"""
54 31160dc8 Nikos Skalkotos
    pass
55 31160dc8 Nikos Skalkotos
56 31160dc8 Nikos Skalkotos
57 3c33e68a Nikos Skalkotos
class Wizard:
58 88f83027 Nikos Skalkotos
    """Represents a dialog-based wizard
59 88f83027 Nikos Skalkotos

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

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