Statistics
| Branch: | Tag: | Revision:

root / image_creator / dialog_menu.py @ 56884b64

History | View | Annotate | Download (24.2 kB)

1 023e1217 Nikos Skalkotos
#!/usr/bin/env python
2 023e1217 Nikos Skalkotos
3 023e1217 Nikos Skalkotos
# Copyright 2012 GRNET S.A. All rights reserved.
4 023e1217 Nikos Skalkotos
#
5 023e1217 Nikos Skalkotos
# Redistribution and use in source and binary forms, with or
6 023e1217 Nikos Skalkotos
# without modification, are permitted provided that the following
7 023e1217 Nikos Skalkotos
# conditions are met:
8 023e1217 Nikos Skalkotos
#
9 023e1217 Nikos Skalkotos
#   1. Redistributions of source code must retain the above
10 023e1217 Nikos Skalkotos
#      copyright notice, this list of conditions and the following
11 023e1217 Nikos Skalkotos
#      disclaimer.
12 023e1217 Nikos Skalkotos
#
13 023e1217 Nikos Skalkotos
#   2. Redistributions in binary form must reproduce the above
14 023e1217 Nikos Skalkotos
#      copyright notice, this list of conditions and the following
15 023e1217 Nikos Skalkotos
#      disclaimer in the documentation and/or other materials
16 023e1217 Nikos Skalkotos
#      provided with the distribution.
17 023e1217 Nikos Skalkotos
#
18 023e1217 Nikos Skalkotos
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
19 023e1217 Nikos Skalkotos
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 023e1217 Nikos Skalkotos
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 023e1217 Nikos Skalkotos
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
22 023e1217 Nikos Skalkotos
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 023e1217 Nikos Skalkotos
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 023e1217 Nikos Skalkotos
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25 023e1217 Nikos Skalkotos
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 023e1217 Nikos Skalkotos
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 023e1217 Nikos Skalkotos
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 023e1217 Nikos Skalkotos
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 023e1217 Nikos Skalkotos
# POSSIBILITY OF SUCH DAMAGE.
30 023e1217 Nikos Skalkotos
#
31 023e1217 Nikos Skalkotos
# The views and conclusions contained in the software and
32 023e1217 Nikos Skalkotos
# documentation are those of the authors and should not be
33 023e1217 Nikos Skalkotos
# interpreted as representing official policies, either expressed
34 023e1217 Nikos Skalkotos
# or implied, of GRNET S.A.
35 023e1217 Nikos Skalkotos
36 023e1217 Nikos Skalkotos
import sys
37 023e1217 Nikos Skalkotos
import os
38 023e1217 Nikos Skalkotos
import textwrap
39 023e1217 Nikos Skalkotos
import StringIO
40 023e1217 Nikos Skalkotos
41 023e1217 Nikos Skalkotos
from image_creator import __version__ as version
42 023e1217 Nikos Skalkotos
from image_creator.util import MD5
43 023e1217 Nikos Skalkotos
from image_creator.output.dialog import GaugeOutput, InfoBoxOutput
44 023e1217 Nikos Skalkotos
from image_creator.kamaki_wrapper import Kamaki, ClientError
45 023e1217 Nikos Skalkotos
from image_creator.help import get_help_file
46 023e1217 Nikos Skalkotos
from image_creator.dialog_util import SMALL_WIDTH, WIDTH, \
47 0a116b9d Nikos Skalkotos
    update_background_title, confirm_reset, confirm_exit, Reset, \
48 0a116b9d Nikos Skalkotos
    extract_image, extract_metadata_string
49 023e1217 Nikos Skalkotos
50 023e1217 Nikos Skalkotos
CONFIGURATION_TASKS = [
51 023e1217 Nikos Skalkotos
    ("Partition table manipulation", ["FixPartitionTable"],
52 023e1217 Nikos Skalkotos
        ["linux", "windows"]),
53 023e1217 Nikos Skalkotos
    ("File system resize",
54 023e1217 Nikos Skalkotos
        ["FilesystemResizeUnmounted", "FilesystemResizeMounted"],
55 023e1217 Nikos Skalkotos
        ["linux", "windows"]),
56 023e1217 Nikos Skalkotos
    ("Swap partition configuration", ["AddSwap"], ["linux"]),
57 023e1217 Nikos Skalkotos
    ("SSH keys removal", ["DeleteSSHKeys"], ["linux"]),
58 023e1217 Nikos Skalkotos
    ("Temporal RDP disabling", ["DisableRemoteDesktopConnections"],
59 023e1217 Nikos Skalkotos
        ["windows"]),
60 023e1217 Nikos Skalkotos
    ("SELinux relabeling at next boot", ["SELinuxAutorelabel"], ["linux"]),
61 023e1217 Nikos Skalkotos
    ("Hostname/Computer Name assignment", ["AssignHostname"],
62 023e1217 Nikos Skalkotos
        ["windows", "linux"]),
63 023e1217 Nikos Skalkotos
    ("Password change", ["ChangePassword"], ["windows", "linux"]),
64 023e1217 Nikos Skalkotos
    ("File injection", ["EnforcePersonality"], ["windows", "linux"])
65 023e1217 Nikos Skalkotos
]
66 023e1217 Nikos Skalkotos
67 023e1217 Nikos Skalkotos
68 023e1217 Nikos Skalkotos
class metadata_monitor(object):
69 023e1217 Nikos Skalkotos
    def __init__(self, session, meta):
70 023e1217 Nikos Skalkotos
        self.session = session
71 023e1217 Nikos Skalkotos
        self.meta = meta
72 023e1217 Nikos Skalkotos
73 023e1217 Nikos Skalkotos
    def __enter__(self):
74 023e1217 Nikos Skalkotos
        self.old = {}
75 023e1217 Nikos Skalkotos
        for (k, v) in self.meta.items():
76 023e1217 Nikos Skalkotos
            self.old[k] = v
77 023e1217 Nikos Skalkotos
78 023e1217 Nikos Skalkotos
    def __exit__(self, type, value, traceback):
79 023e1217 Nikos Skalkotos
        d = self.session['dialog']
80 023e1217 Nikos Skalkotos
81 023e1217 Nikos Skalkotos
        altered = {}
82 023e1217 Nikos Skalkotos
        added = {}
83 023e1217 Nikos Skalkotos
84 023e1217 Nikos Skalkotos
        for (k, v) in self.meta.items():
85 023e1217 Nikos Skalkotos
            if k not in self.old:
86 023e1217 Nikos Skalkotos
                added[k] = v
87 023e1217 Nikos Skalkotos
            elif self.old[k] != v:
88 023e1217 Nikos Skalkotos
                altered[k] = v
89 023e1217 Nikos Skalkotos
90 023e1217 Nikos Skalkotos
        if not (len(added) or len(altered)):
91 023e1217 Nikos Skalkotos
            return
92 023e1217 Nikos Skalkotos
93 023e1217 Nikos Skalkotos
        msg = "The last action has changed some image properties:\n\n"
94 023e1217 Nikos Skalkotos
        if len(added):
95 023e1217 Nikos Skalkotos
            msg += "New image properties:\n"
96 023e1217 Nikos Skalkotos
            for (k, v) in added.items():
97 023e1217 Nikos Skalkotos
                msg += '    %s: "%s"\n' % (k, v)
98 023e1217 Nikos Skalkotos
            msg += "\n"
99 023e1217 Nikos Skalkotos
        if len(altered):
100 023e1217 Nikos Skalkotos
            msg += "Updated image properties:\n"
101 023e1217 Nikos Skalkotos
            for (k, v) in altered.items():
102 023e1217 Nikos Skalkotos
                msg += '    %s: "%s" -> "%s"\n' % (k, self.old[k], v)
103 023e1217 Nikos Skalkotos
            msg += "\n"
104 023e1217 Nikos Skalkotos
105 023e1217 Nikos Skalkotos
        self.session['metadata'].update(added)
106 023e1217 Nikos Skalkotos
        self.session['metadata'].update(altered)
107 023e1217 Nikos Skalkotos
        d.msgbox(msg, title="Image Property Changes", width=SMALL_WIDTH)
108 023e1217 Nikos Skalkotos
109 023e1217 Nikos Skalkotos
110 023e1217 Nikos Skalkotos
def upload_image(session):
111 023e1217 Nikos Skalkotos
    d = session["dialog"]
112 023e1217 Nikos Skalkotos
    dev = session['device']
113 023e1217 Nikos Skalkotos
    size = dev.size
114 023e1217 Nikos Skalkotos
115 023e1217 Nikos Skalkotos
    if "account" not in session:
116 023e1217 Nikos Skalkotos
        d.msgbox("You need to provide your ~okeanos login username before you "
117 023e1217 Nikos Skalkotos
                 "can upload images to pithos+", width=SMALL_WIDTH)
118 023e1217 Nikos Skalkotos
        return False
119 023e1217 Nikos Skalkotos
120 023e1217 Nikos Skalkotos
    if "token" not in session:
121 023e1217 Nikos Skalkotos
        d.msgbox("You need to provide your ~okeanos account authentication "
122 023e1217 Nikos Skalkotos
                 "token before you can upload images to pithos+",
123 023e1217 Nikos Skalkotos
                 width=SMALL_WIDTH)
124 023e1217 Nikos Skalkotos
        return False
125 023e1217 Nikos Skalkotos
126 023e1217 Nikos Skalkotos
    while 1:
127 023e1217 Nikos Skalkotos
        init = session["upload"] if "upload" in session else ''
128 023e1217 Nikos Skalkotos
        (code, answer) = d.inputbox("Please provide a filename:", init=init,
129 023e1217 Nikos Skalkotos
                                    width=WIDTH)
130 023e1217 Nikos Skalkotos
131 023e1217 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
132 023e1217 Nikos Skalkotos
            return False
133 023e1217 Nikos Skalkotos
134 023e1217 Nikos Skalkotos
        filename = answer.strip()
135 023e1217 Nikos Skalkotos
        if len(filename) == 0:
136 023e1217 Nikos Skalkotos
            d.msgbox("Filename cannot be empty", width=SMALL_WIDTH)
137 023e1217 Nikos Skalkotos
            continue
138 023e1217 Nikos Skalkotos
        session['upload'] = filename
139 023e1217 Nikos Skalkotos
        break
140 023e1217 Nikos Skalkotos
141 023e1217 Nikos Skalkotos
    gauge = GaugeOutput(d, "Image Upload", "Uploading...")
142 023e1217 Nikos Skalkotos
    try:
143 023e1217 Nikos Skalkotos
        out = dev.out
144 023e1217 Nikos Skalkotos
        out.add(gauge)
145 023e1217 Nikos Skalkotos
        try:
146 023e1217 Nikos Skalkotos
            if 'checksum' not in session:
147 023e1217 Nikos Skalkotos
                md5 = MD5(out)
148 023e1217 Nikos Skalkotos
                session['checksum'] = md5.compute(session['snapshot'], size)
149 023e1217 Nikos Skalkotos
150 023e1217 Nikos Skalkotos
            kamaki = Kamaki(session['account'], session['token'], out)
151 023e1217 Nikos Skalkotos
            try:
152 023e1217 Nikos Skalkotos
                # Upload image file
153 023e1217 Nikos Skalkotos
                with open(session['snapshot'], 'rb') as f:
154 023e1217 Nikos Skalkotos
                    session["pithos_uri"] = \
155 023e1217 Nikos Skalkotos
                        kamaki.upload(f, size, filename,
156 023e1217 Nikos Skalkotos
                                      "Calculating block hashes",
157 023e1217 Nikos Skalkotos
                                      "Uploading missing blocks")
158 023e1217 Nikos Skalkotos
                # Upload metadata file
159 023e1217 Nikos Skalkotos
                out.output("Uploading metadata file...")
160 023e1217 Nikos Skalkotos
                metastring = extract_metadata_string(session)
161 023e1217 Nikos Skalkotos
                kamaki.upload(StringIO.StringIO(metastring),
162 023e1217 Nikos Skalkotos
                              size=len(metastring),
163 023e1217 Nikos Skalkotos
                              remote_path="%s.meta" % filename)
164 023e1217 Nikos Skalkotos
                out.success("done")
165 023e1217 Nikos Skalkotos
166 023e1217 Nikos Skalkotos
                # Upload md5sum file
167 023e1217 Nikos Skalkotos
                out.output("Uploading md5sum file...")
168 023e1217 Nikos Skalkotos
                md5str = "%s %s\n" % (session['checksum'], filename)
169 023e1217 Nikos Skalkotos
                kamaki.upload(StringIO.StringIO(md5str), size=len(md5str),
170 023e1217 Nikos Skalkotos
                              remote_path="%s.md5sum" % filename)
171 023e1217 Nikos Skalkotos
                out.success("done")
172 023e1217 Nikos Skalkotos
173 023e1217 Nikos Skalkotos
            except ClientError as e:
174 023e1217 Nikos Skalkotos
                d.msgbox("Error in pithos+ client: %s" % e.message,
175 023e1217 Nikos Skalkotos
                         title="Pithos+ Client Error", width=SMALL_WIDTH)
176 023e1217 Nikos Skalkotos
                if 'pithos_uri' in session:
177 023e1217 Nikos Skalkotos
                    del session['pithos_uri']
178 023e1217 Nikos Skalkotos
                return False
179 023e1217 Nikos Skalkotos
        finally:
180 023e1217 Nikos Skalkotos
            out.remove(gauge)
181 023e1217 Nikos Skalkotos
    finally:
182 023e1217 Nikos Skalkotos
        gauge.cleanup()
183 023e1217 Nikos Skalkotos
184 023e1217 Nikos Skalkotos
    d.msgbox("Image file `%s' was successfully uploaded to pithos+" % filename,
185 023e1217 Nikos Skalkotos
             width=SMALL_WIDTH)
186 023e1217 Nikos Skalkotos
187 023e1217 Nikos Skalkotos
    return True
188 023e1217 Nikos Skalkotos
189 023e1217 Nikos Skalkotos
190 023e1217 Nikos Skalkotos
def register_image(session):
191 023e1217 Nikos Skalkotos
    d = session["dialog"]
192 023e1217 Nikos Skalkotos
    dev = session['device']
193 023e1217 Nikos Skalkotos
194 023e1217 Nikos Skalkotos
    if "account" not in session:
195 023e1217 Nikos Skalkotos
        d.msgbox("You need to provide your ~okeanos login username before you "
196 023e1217 Nikos Skalkotos
                 "can register an images to cyclades",
197 023e1217 Nikos Skalkotos
                 width=SMALL_WIDTH)
198 023e1217 Nikos Skalkotos
        return False
199 023e1217 Nikos Skalkotos
200 023e1217 Nikos Skalkotos
    if "token" not in session:
201 023e1217 Nikos Skalkotos
        d.msgbox("You need to provide your ~okeanos account authentication "
202 023e1217 Nikos Skalkotos
                 "token before you can register an images to cyclades",
203 023e1217 Nikos Skalkotos
                 width=SMALL_WIDTH)
204 023e1217 Nikos Skalkotos
        return False
205 023e1217 Nikos Skalkotos
206 023e1217 Nikos Skalkotos
    if "pithos_uri" not in session:
207 023e1217 Nikos Skalkotos
        d.msgbox("You need to upload the image to pithos+ before you can "
208 023e1217 Nikos Skalkotos
                 "register it to cyclades", width=SMALL_WIDTH)
209 023e1217 Nikos Skalkotos
        return False
210 023e1217 Nikos Skalkotos
211 023e1217 Nikos Skalkotos
    while 1:
212 023e1217 Nikos Skalkotos
        (code, answer) = d.inputbox("Please provide a registration name:",
213 023e1217 Nikos Skalkotos
                                    width=WIDTH)
214 023e1217 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
215 023e1217 Nikos Skalkotos
            return False
216 023e1217 Nikos Skalkotos
217 023e1217 Nikos Skalkotos
        name = answer.strip()
218 023e1217 Nikos Skalkotos
        if len(name) == 0:
219 023e1217 Nikos Skalkotos
            d.msgbox("Registration name cannot be empty", width=SMALL_WIDTH)
220 023e1217 Nikos Skalkotos
            continue
221 023e1217 Nikos Skalkotos
        break
222 023e1217 Nikos Skalkotos
223 023e1217 Nikos Skalkotos
    metadata = {}
224 023e1217 Nikos Skalkotos
    metadata.update(session['metadata'])
225 023e1217 Nikos Skalkotos
    if 'task_metadata' in session:
226 023e1217 Nikos Skalkotos
        for key in session['task_metadata']:
227 023e1217 Nikos Skalkotos
            metadata[key] = 'yes'
228 023e1217 Nikos Skalkotos
229 023e1217 Nikos Skalkotos
    gauge = GaugeOutput(d, "Image Registration", "Registering image...")
230 023e1217 Nikos Skalkotos
    try:
231 023e1217 Nikos Skalkotos
        out = dev.out
232 023e1217 Nikos Skalkotos
        out.add(gauge)
233 023e1217 Nikos Skalkotos
        try:
234 023e1217 Nikos Skalkotos
            out.output("Registering image with Cyclades...")
235 023e1217 Nikos Skalkotos
            try:
236 023e1217 Nikos Skalkotos
                kamaki = Kamaki(session['account'], session['token'], out)
237 023e1217 Nikos Skalkotos
                kamaki.register(name, session['pithos_uri'], metadata)
238 023e1217 Nikos Skalkotos
                out.success('done')
239 023e1217 Nikos Skalkotos
            except ClientError as e:
240 023e1217 Nikos Skalkotos
                d.msgbox("Error in pithos+ client: %s" % e.message)
241 023e1217 Nikos Skalkotos
                return False
242 023e1217 Nikos Skalkotos
        finally:
243 023e1217 Nikos Skalkotos
            out.remove(gauge)
244 023e1217 Nikos Skalkotos
    finally:
245 023e1217 Nikos Skalkotos
        gauge.cleanup()
246 023e1217 Nikos Skalkotos
247 023e1217 Nikos Skalkotos
    d.msgbox("Image `%s' was successfully registered with Cyclades as `%s'" %
248 023e1217 Nikos Skalkotos
             (session['upload'], name), width=SMALL_WIDTH)
249 023e1217 Nikos Skalkotos
    return True
250 023e1217 Nikos Skalkotos
251 023e1217 Nikos Skalkotos
252 023e1217 Nikos Skalkotos
def kamaki_menu(session):
253 023e1217 Nikos Skalkotos
    d = session['dialog']
254 023e1217 Nikos Skalkotos
    default_item = "Account"
255 023e1217 Nikos Skalkotos
256 023e1217 Nikos Skalkotos
    account = Kamaki.get_account()
257 023e1217 Nikos Skalkotos
    if account:
258 023e1217 Nikos Skalkotos
        session['account'] = account
259 023e1217 Nikos Skalkotos
260 023e1217 Nikos Skalkotos
    token = Kamaki.get_token()
261 023e1217 Nikos Skalkotos
    if token:
262 023e1217 Nikos Skalkotos
        session['token'] = token
263 023e1217 Nikos Skalkotos
264 023e1217 Nikos Skalkotos
    while 1:
265 023e1217 Nikos Skalkotos
        account = session["account"] if "account" in session else "<none>"
266 023e1217 Nikos Skalkotos
        token = session["token"] if "token" in session else "<none>"
267 023e1217 Nikos Skalkotos
        upload = session["upload"] if "upload" in session else "<none>"
268 023e1217 Nikos Skalkotos
269 6f9e1534 Nikos Skalkotos
        choices = [("Account", "Change your ~okeanos user id: %s" % account),
270 023e1217 Nikos Skalkotos
                   ("Token", "Change your ~okeanos token: %s" % token),
271 023e1217 Nikos Skalkotos
                   ("Upload", "Upload image to pithos+"),
272 023e1217 Nikos Skalkotos
                   ("Register", "Register the image to cyclades: %s" % upload)]
273 023e1217 Nikos Skalkotos
274 023e1217 Nikos Skalkotos
        (code, choice) = d.menu(
275 023e1217 Nikos Skalkotos
            text="Choose one of the following or press <Back> to go back.",
276 023e1217 Nikos Skalkotos
            width=WIDTH, choices=choices, cancel="Back", height=13,
277 023e1217 Nikos Skalkotos
            menu_height=5, default_item=default_item,
278 023e1217 Nikos Skalkotos
            title="Image Registration Menu")
279 023e1217 Nikos Skalkotos
280 023e1217 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
281 023e1217 Nikos Skalkotos
            return False
282 023e1217 Nikos Skalkotos
283 023e1217 Nikos Skalkotos
        if choice == "Account":
284 023e1217 Nikos Skalkotos
            default_item = "Account"
285 023e1217 Nikos Skalkotos
            (code, answer) = d.inputbox(
286 6f9e1534 Nikos Skalkotos
                "Please provide your ~okeanos account user id:",
287 023e1217 Nikos Skalkotos
                init=session["account"] if "account" in session else '',
288 023e1217 Nikos Skalkotos
                width=WIDTH)
289 023e1217 Nikos Skalkotos
            if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
290 023e1217 Nikos Skalkotos
                continue
291 023e1217 Nikos Skalkotos
            if len(answer) == 0 and "account" in session:
292 023e1217 Nikos Skalkotos
                    del session["account"]
293 023e1217 Nikos Skalkotos
            else:
294 023e1217 Nikos Skalkotos
                session["account"] = answer.strip()
295 023e1217 Nikos Skalkotos
                Kamaki.save_account(session['account'])
296 023e1217 Nikos Skalkotos
                default_item = "Token"
297 023e1217 Nikos Skalkotos
        elif choice == "Token":
298 023e1217 Nikos Skalkotos
            default_item = "Token"
299 023e1217 Nikos Skalkotos
            (code, answer) = d.inputbox(
300 023e1217 Nikos Skalkotos
                "Please provide your ~okeanos account authetication token:",
301 023e1217 Nikos Skalkotos
                init=session["token"] if "token" in session else '',
302 023e1217 Nikos Skalkotos
                width=WIDTH)
303 023e1217 Nikos Skalkotos
            if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
304 023e1217 Nikos Skalkotos
                continue
305 023e1217 Nikos Skalkotos
            if len(answer) == 0 and "token" in session:
306 023e1217 Nikos Skalkotos
                del session["token"]
307 023e1217 Nikos Skalkotos
            else:
308 023e1217 Nikos Skalkotos
                session["token"] = answer.strip()
309 023e1217 Nikos Skalkotos
                Kamaki.save_token(session['token'])
310 023e1217 Nikos Skalkotos
                default_item = "Upload"
311 023e1217 Nikos Skalkotos
        elif choice == "Upload":
312 023e1217 Nikos Skalkotos
            if upload_image(session):
313 023e1217 Nikos Skalkotos
                default_item = "Register"
314 023e1217 Nikos Skalkotos
            else:
315 023e1217 Nikos Skalkotos
                default_item = "Upload"
316 023e1217 Nikos Skalkotos
        elif choice == "Register":
317 023e1217 Nikos Skalkotos
            if register_image(session):
318 023e1217 Nikos Skalkotos
                return True
319 023e1217 Nikos Skalkotos
            else:
320 023e1217 Nikos Skalkotos
                default_item = "Register"
321 023e1217 Nikos Skalkotos
322 023e1217 Nikos Skalkotos
323 023e1217 Nikos Skalkotos
def add_property(session):
324 023e1217 Nikos Skalkotos
    d = session['dialog']
325 023e1217 Nikos Skalkotos
326 023e1217 Nikos Skalkotos
    while 1:
327 023e1217 Nikos Skalkotos
        (code, answer) = d.inputbox("Please provide a name for a new image"
328 023e1217 Nikos Skalkotos
                                    " property:", width=WIDTH)
329 023e1217 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
330 023e1217 Nikos Skalkotos
            return False
331 023e1217 Nikos Skalkotos
332 023e1217 Nikos Skalkotos
        name = answer.strip()
333 023e1217 Nikos Skalkotos
        if len(name) == 0:
334 023e1217 Nikos Skalkotos
            d.msgbox("A property name cannot be empty", width=SMALL_WIDTH)
335 023e1217 Nikos Skalkotos
            continue
336 023e1217 Nikos Skalkotos
337 023e1217 Nikos Skalkotos
        break
338 023e1217 Nikos Skalkotos
339 023e1217 Nikos Skalkotos
    while 1:
340 023e1217 Nikos Skalkotos
        (code, answer) = d.inputbox("Please provide a value for image "
341 023e1217 Nikos Skalkotos
                                    "property %s" % name, width=WIDTH)
342 023e1217 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
343 023e1217 Nikos Skalkotos
            return False
344 023e1217 Nikos Skalkotos
345 023e1217 Nikos Skalkotos
        value = answer.strip()
346 023e1217 Nikos Skalkotos
        if len(value) == 0:
347 023e1217 Nikos Skalkotos
            d.msgbox("Value cannot be empty", width=SMALL_WIDTH)
348 023e1217 Nikos Skalkotos
            continue
349 023e1217 Nikos Skalkotos
350 023e1217 Nikos Skalkotos
        break
351 023e1217 Nikos Skalkotos
352 023e1217 Nikos Skalkotos
    session['metadata'][name] = value
353 023e1217 Nikos Skalkotos
354 023e1217 Nikos Skalkotos
    return True
355 023e1217 Nikos Skalkotos
356 023e1217 Nikos Skalkotos
357 023e1217 Nikos Skalkotos
def modify_properties(session):
358 023e1217 Nikos Skalkotos
    d = session['dialog']
359 023e1217 Nikos Skalkotos
360 023e1217 Nikos Skalkotos
    while 1:
361 023e1217 Nikos Skalkotos
        choices = []
362 023e1217 Nikos Skalkotos
        for (key, val) in session['metadata'].items():
363 023e1217 Nikos Skalkotos
            choices.append((str(key), str(val)))
364 023e1217 Nikos Skalkotos
365 023e1217 Nikos Skalkotos
        (code, choice) = d.menu(
366 023e1217 Nikos Skalkotos
            "In this menu you can edit existing image properties or add new "
367 023e1217 Nikos Skalkotos
            "ones. Be careful! Most properties have special meaning and "
368 023e1217 Nikos Skalkotos
            "alter the image deployment behaviour. Press <HELP> to see more "
369 023e1217 Nikos Skalkotos
            "information about image properties. Press <BACK> when done.",
370 023e1217 Nikos Skalkotos
            height=18, width=WIDTH, choices=choices, menu_height=10,
371 023e1217 Nikos Skalkotos
            ok_label="Edit", extra_button=1, extra_label="Add", cancel="Back",
372 023e1217 Nikos Skalkotos
            help_button=1, title="Image Properties")
373 023e1217 Nikos Skalkotos
374 023e1217 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
375 023e1217 Nikos Skalkotos
            return True
376 023e1217 Nikos Skalkotos
        # Edit button
377 023e1217 Nikos Skalkotos
        elif code == d.DIALOG_OK:
378 023e1217 Nikos Skalkotos
            (code, answer) = d.inputbox("Please provide a new value for the "
379 023e1217 Nikos Skalkotos
                                        "image property with name `%s':" %
380 023e1217 Nikos Skalkotos
                                        choice,
381 023e1217 Nikos Skalkotos
                                        init=session['metadata'][choice],
382 023e1217 Nikos Skalkotos
                                        width=WIDTH)
383 023e1217 Nikos Skalkotos
            if code not in (d.DIALOG_CANCEL, d.DIALOG_ESC):
384 023e1217 Nikos Skalkotos
                value = answer.strip()
385 023e1217 Nikos Skalkotos
                if len(value) == 0:
386 023e1217 Nikos Skalkotos
                    d.msgbox("Value cannot be empty!")
387 023e1217 Nikos Skalkotos
                    continue
388 023e1217 Nikos Skalkotos
                else:
389 023e1217 Nikos Skalkotos
                    session['metadata'][choice] = value
390 023e1217 Nikos Skalkotos
        # ADD button
391 023e1217 Nikos Skalkotos
        elif code == d.DIALOG_EXTRA:
392 023e1217 Nikos Skalkotos
            add_property(session)
393 023e1217 Nikos Skalkotos
        elif code == 'help':
394 023e1217 Nikos Skalkotos
            help_file = get_help_file("image_properties")
395 023e1217 Nikos Skalkotos
            assert os.path.exists(help_file)
396 023e1217 Nikos Skalkotos
            d.textbox(help_file, title="Image Properties", width=70, height=40)
397 023e1217 Nikos Skalkotos
398 023e1217 Nikos Skalkotos
399 023e1217 Nikos Skalkotos
def delete_properties(session):
400 023e1217 Nikos Skalkotos
    d = session['dialog']
401 023e1217 Nikos Skalkotos
402 023e1217 Nikos Skalkotos
    choices = []
403 023e1217 Nikos Skalkotos
    for (key, val) in session['metadata'].items():
404 023e1217 Nikos Skalkotos
        choices.append((key, "%s" % val, 0))
405 023e1217 Nikos Skalkotos
406 023e1217 Nikos Skalkotos
    (code, to_delete) = d.checklist("Choose which properties to delete:",
407 023e1217 Nikos Skalkotos
                                    choices=choices, width=WIDTH)
408 023e1217 Nikos Skalkotos
409 023e1217 Nikos Skalkotos
    # If the user exits with ESC or CANCEL, the returned tag list is empty.
410 023e1217 Nikos Skalkotos
    for i in to_delete:
411 023e1217 Nikos Skalkotos
        del session['metadata'][i]
412 023e1217 Nikos Skalkotos
413 023e1217 Nikos Skalkotos
    cnt = len(to_delete)
414 023e1217 Nikos Skalkotos
    if cnt > 0:
415 023e1217 Nikos Skalkotos
        d.msgbox("%d image properties were deleted." % cnt, width=SMALL_WIDTH)
416 023e1217 Nikos Skalkotos
        return True
417 023e1217 Nikos Skalkotos
    else:
418 023e1217 Nikos Skalkotos
        return False
419 023e1217 Nikos Skalkotos
420 023e1217 Nikos Skalkotos
421 023e1217 Nikos Skalkotos
def exclude_tasks(session):
422 023e1217 Nikos Skalkotos
    d = session['dialog']
423 023e1217 Nikos Skalkotos
424 023e1217 Nikos Skalkotos
    index = 0
425 023e1217 Nikos Skalkotos
    displayed_index = 1
426 023e1217 Nikos Skalkotos
    choices = []
427 023e1217 Nikos Skalkotos
    mapping = {}
428 023e1217 Nikos Skalkotos
    if 'excluded_tasks' not in session:
429 023e1217 Nikos Skalkotos
        session['excluded_tasks'] = []
430 023e1217 Nikos Skalkotos
431 023e1217 Nikos Skalkotos
    if -1 in session['excluded_tasks']:
432 023e1217 Nikos Skalkotos
        if not d.yesno("Image deployment configuration is disabled. "
433 023e1217 Nikos Skalkotos
                       "Do you wish to enable it?", width=SMALL_WIDTH):
434 023e1217 Nikos Skalkotos
            session['excluded_tasks'].remove(-1)
435 023e1217 Nikos Skalkotos
        else:
436 023e1217 Nikos Skalkotos
            return False
437 023e1217 Nikos Skalkotos
438 023e1217 Nikos Skalkotos
    for (msg, task, osfamily) in CONFIGURATION_TASKS:
439 023e1217 Nikos Skalkotos
        if session['metadata']['OSFAMILY'] in osfamily:
440 023e1217 Nikos Skalkotos
            checked = 1 if index in session['excluded_tasks'] else 0
441 023e1217 Nikos Skalkotos
            choices.append((str(displayed_index), msg, checked))
442 023e1217 Nikos Skalkotos
            mapping[displayed_index] = index
443 023e1217 Nikos Skalkotos
            displayed_index += 1
444 023e1217 Nikos Skalkotos
        index += 1
445 023e1217 Nikos Skalkotos
446 023e1217 Nikos Skalkotos
    while 1:
447 023e1217 Nikos Skalkotos
        (code, tags) = d.checklist(
448 023e1217 Nikos Skalkotos
            text="Please choose which configuration tasks you would like to "
449 023e1217 Nikos Skalkotos
                 "prevent from running during image deployment. "
450 023e1217 Nikos Skalkotos
                 "Press <No Config> to supress any configuration. "
451 023e1217 Nikos Skalkotos
                 "Press <Help> for more help on the image deployment "
452 023e1217 Nikos Skalkotos
                 "configuration tasks.",
453 023e1217 Nikos Skalkotos
            choices=choices, height=19, list_height=8, width=WIDTH,
454 023e1217 Nikos Skalkotos
            help_button=1, extra_button=1, extra_label="No Config",
455 023e1217 Nikos Skalkotos
            title="Exclude Configuration Tasks")
456 023e1217 Nikos Skalkotos
457 023e1217 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
458 023e1217 Nikos Skalkotos
            return False
459 023e1217 Nikos Skalkotos
        elif code == d.DIALOG_HELP:
460 023e1217 Nikos Skalkotos
            help_file = get_help_file("configuration_tasks")
461 023e1217 Nikos Skalkotos
            assert os.path.exists(help_file)
462 023e1217 Nikos Skalkotos
            d.textbox(help_file, title="Configuration Tasks",
463 023e1217 Nikos Skalkotos
                      width=70, height=40)
464 023e1217 Nikos Skalkotos
        # No Config button
465 023e1217 Nikos Skalkotos
        elif code == d.DIALOG_EXTRA:
466 023e1217 Nikos Skalkotos
            session['excluded_tasks'] = [-1]
467 023e1217 Nikos Skalkotos
            session['task_metadata'] = ["EXCLUDE_ALL_TASKS"]
468 023e1217 Nikos Skalkotos
            break
469 023e1217 Nikos Skalkotos
        elif code == d.DIALOG_OK:
470 023e1217 Nikos Skalkotos
            session['excluded_tasks'] = []
471 023e1217 Nikos Skalkotos
            for tag in tags:
472 023e1217 Nikos Skalkotos
                session['excluded_tasks'].append(mapping[int(tag)])
473 023e1217 Nikos Skalkotos
474 023e1217 Nikos Skalkotos
            exclude_metadata = []
475 023e1217 Nikos Skalkotos
            for task in session['excluded_tasks']:
476 023e1217 Nikos Skalkotos
                exclude_metadata.extend(CONFIGURATION_TASKS[task][1])
477 023e1217 Nikos Skalkotos
478 023e1217 Nikos Skalkotos
            session['task_metadata'] = map(lambda x: "EXCLUDE_TASK_%s" % x,
479 023e1217 Nikos Skalkotos
                                           exclude_metadata)
480 023e1217 Nikos Skalkotos
            break
481 023e1217 Nikos Skalkotos
482 023e1217 Nikos Skalkotos
    return True
483 023e1217 Nikos Skalkotos
484 023e1217 Nikos Skalkotos
485 023e1217 Nikos Skalkotos
def sysprep(session):
486 023e1217 Nikos Skalkotos
    d = session['dialog']
487 023e1217 Nikos Skalkotos
    image_os = session['image_os']
488 023e1217 Nikos Skalkotos
489 023e1217 Nikos Skalkotos
    # Is the image already shrinked?
490 023e1217 Nikos Skalkotos
    if 'shrinked' in session and session['shrinked']:
491 023e1217 Nikos Skalkotos
        msg = "It seems you have shrinked the image. Running system " \
492 023e1217 Nikos Skalkotos
              "preparation tasks on a shrinked image is dangerous."
493 023e1217 Nikos Skalkotos
494 023e1217 Nikos Skalkotos
        if d.yesno("%s\n\nDo you really want to continue?" % msg,
495 023e1217 Nikos Skalkotos
                   width=SMALL_WIDTH, defaultno=1):
496 023e1217 Nikos Skalkotos
            return
497 023e1217 Nikos Skalkotos
498 023e1217 Nikos Skalkotos
    wrapper = textwrap.TextWrapper(width=WIDTH - 5)
499 023e1217 Nikos Skalkotos
500 023e1217 Nikos Skalkotos
    help_title = "System Preperation Tasks"
501 023e1217 Nikos Skalkotos
    sysprep_help = "%s\n%s\n\n" % (help_title, '=' * len(help_title))
502 023e1217 Nikos Skalkotos
503 023e1217 Nikos Skalkotos
    if 'exec_syspreps' not in session:
504 023e1217 Nikos Skalkotos
        session['exec_syspreps'] = []
505 023e1217 Nikos Skalkotos
506 023e1217 Nikos Skalkotos
    all_syspreps = image_os.list_syspreps()
507 023e1217 Nikos Skalkotos
    # Only give the user the choice between syspreps that have not ran yet
508 023e1217 Nikos Skalkotos
    syspreps = [s for s in all_syspreps if s not in session['exec_syspreps']]
509 023e1217 Nikos Skalkotos
510 023e1217 Nikos Skalkotos
    if len(syspreps) == 0:
511 023e1217 Nikos Skalkotos
        d.msgbox("No system preparation task available to run!",
512 023e1217 Nikos Skalkotos
                 title="System Preperation", width=SMALL_WIDTH)
513 023e1217 Nikos Skalkotos
        return
514 023e1217 Nikos Skalkotos
515 023e1217 Nikos Skalkotos
    while 1:
516 023e1217 Nikos Skalkotos
        choices = []
517 023e1217 Nikos Skalkotos
        index = 0
518 023e1217 Nikos Skalkotos
        for sysprep in syspreps:
519 023e1217 Nikos Skalkotos
            name, descr = image_os.sysprep_info(sysprep)
520 023e1217 Nikos Skalkotos
            display_name = name.replace('-', ' ').capitalize()
521 023e1217 Nikos Skalkotos
            sysprep_help += "%s\n" % display_name
522 023e1217 Nikos Skalkotos
            sysprep_help += "%s\n" % ('-' * len(display_name))
523 023e1217 Nikos Skalkotos
            sysprep_help += "%s\n\n" % wrapper.fill(" ".join(descr.split()))
524 023e1217 Nikos Skalkotos
            enabled = 1 if sysprep.enabled else 0
525 023e1217 Nikos Skalkotos
            choices.append((str(index + 1), display_name, enabled))
526 023e1217 Nikos Skalkotos
            index += 1
527 023e1217 Nikos Skalkotos
528 023e1217 Nikos Skalkotos
        (code, tags) = d.checklist(
529 023e1217 Nikos Skalkotos
            "Please choose which system preparation tasks you would like to "
530 023e1217 Nikos Skalkotos
            "run on the image. Press <Help> to see details about the system "
531 023e1217 Nikos Skalkotos
            "preparation tasks.", title="Run system preparation tasks",
532 023e1217 Nikos Skalkotos
            choices=choices, width=70, ok_label="Run", help_button=1)
533 023e1217 Nikos Skalkotos
534 023e1217 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
535 023e1217 Nikos Skalkotos
            return False
536 023e1217 Nikos Skalkotos
        elif code == d.DIALOG_HELP:
537 023e1217 Nikos Skalkotos
            d.scrollbox(sysprep_help, width=WIDTH)
538 023e1217 Nikos Skalkotos
        elif code == d.DIALOG_OK:
539 023e1217 Nikos Skalkotos
            # Enable selected syspreps and disable the rest
540 023e1217 Nikos Skalkotos
            for i in range(len(syspreps)):
541 023e1217 Nikos Skalkotos
                if str(i + 1) in tags:
542 023e1217 Nikos Skalkotos
                    image_os.enable_sysprep(syspreps[i])
543 023e1217 Nikos Skalkotos
                    session['exec_syspreps'].append(syspreps[i])
544 023e1217 Nikos Skalkotos
                else:
545 023e1217 Nikos Skalkotos
                    image_os.disable_sysprep(syspreps[i])
546 023e1217 Nikos Skalkotos
547 023e1217 Nikos Skalkotos
            infobox = InfoBoxOutput(d, "Image Configuration")
548 023e1217 Nikos Skalkotos
            try:
549 023e1217 Nikos Skalkotos
                dev = session['device']
550 023e1217 Nikos Skalkotos
                dev.out.add(infobox)
551 023e1217 Nikos Skalkotos
                try:
552 023e1217 Nikos Skalkotos
                    dev.mount(readonly=False)
553 023e1217 Nikos Skalkotos
                    try:
554 023e1217 Nikos Skalkotos
                        # The checksum is invalid. We have mounted the image rw
555 023e1217 Nikos Skalkotos
                        if 'checksum' in session:
556 023e1217 Nikos Skalkotos
                            del session['checksum']
557 023e1217 Nikos Skalkotos
558 023e1217 Nikos Skalkotos
                        # Monitor the metadata changes during syspreps
559 023e1217 Nikos Skalkotos
                        with metadata_monitor(session, image_os.meta):
560 023e1217 Nikos Skalkotos
                            image_os.do_sysprep()
561 023e1217 Nikos Skalkotos
                            infobox.finalize()
562 023e1217 Nikos Skalkotos
563 023e1217 Nikos Skalkotos
                        # Disable syspreps that have ran
564 023e1217 Nikos Skalkotos
                        for sysprep in session['exec_syspreps']:
565 023e1217 Nikos Skalkotos
                            image_os.disable_sysprep(sysprep)
566 023e1217 Nikos Skalkotos
                    finally:
567 023e1217 Nikos Skalkotos
                        dev.umount()
568 023e1217 Nikos Skalkotos
                finally:
569 023e1217 Nikos Skalkotos
                    dev.out.remove(infobox)
570 023e1217 Nikos Skalkotos
            finally:
571 023e1217 Nikos Skalkotos
                infobox.cleanup()
572 023e1217 Nikos Skalkotos
            break
573 023e1217 Nikos Skalkotos
    return True
574 023e1217 Nikos Skalkotos
575 023e1217 Nikos Skalkotos
576 023e1217 Nikos Skalkotos
def shrink(session):
577 023e1217 Nikos Skalkotos
    d = session['dialog']
578 023e1217 Nikos Skalkotos
    dev = session['device']
579 023e1217 Nikos Skalkotos
580 023e1217 Nikos Skalkotos
    shrinked = 'shrinked' in session and session['shrinked']
581 023e1217 Nikos Skalkotos
582 023e1217 Nikos Skalkotos
    if shrinked:
583 023e1217 Nikos Skalkotos
        d.msgbox("The image is already shrinked!", title="Image Shrinking",
584 023e1217 Nikos Skalkotos
                 width=SMALL_WIDTH)
585 023e1217 Nikos Skalkotos
        return True
586 023e1217 Nikos Skalkotos
587 023e1217 Nikos Skalkotos
    msg = "This operation will shrink the last partition of the image to " \
588 023e1217 Nikos Skalkotos
          "reduce the total image size. If the last partition is a swap " \
589 023e1217 Nikos Skalkotos
          "partition, then this partition is removed and the partition " \
590 023e1217 Nikos Skalkotos
          "before that is shrinked. The removed swap partition will be " \
591 023e1217 Nikos Skalkotos
          "recreated during image deployment."
592 023e1217 Nikos Skalkotos
593 023e1217 Nikos Skalkotos
    if not d.yesno("%s\n\nDo you want to continue?" % msg, width=WIDTH,
594 023e1217 Nikos Skalkotos
                   height=12, title="Image Shrinking"):
595 023e1217 Nikos Skalkotos
        with metadata_monitor(session, dev.meta):
596 023e1217 Nikos Skalkotos
            infobox = InfoBoxOutput(d, "Image Shrinking", height=4)
597 023e1217 Nikos Skalkotos
            dev.out.add(infobox)
598 023e1217 Nikos Skalkotos
            try:
599 023e1217 Nikos Skalkotos
                dev.shrink()
600 023e1217 Nikos Skalkotos
                infobox.finalize()
601 023e1217 Nikos Skalkotos
            finally:
602 023e1217 Nikos Skalkotos
                dev.out.remove(infobox)
603 023e1217 Nikos Skalkotos
604 023e1217 Nikos Skalkotos
        session['shrinked'] = True
605 023e1217 Nikos Skalkotos
        update_background_title(session)
606 023e1217 Nikos Skalkotos
    else:
607 023e1217 Nikos Skalkotos
        return False
608 023e1217 Nikos Skalkotos
609 023e1217 Nikos Skalkotos
    return True
610 023e1217 Nikos Skalkotos
611 023e1217 Nikos Skalkotos
612 023e1217 Nikos Skalkotos
def customization_menu(session):
613 023e1217 Nikos Skalkotos
    d = session['dialog']
614 023e1217 Nikos Skalkotos
615 023e1217 Nikos Skalkotos
    choices = [("Sysprep", "Run various image preparation tasks"),
616 023e1217 Nikos Skalkotos
               ("Shrink", "Shrink image"),
617 023e1217 Nikos Skalkotos
               ("View/Modify", "View/Modify image properties"),
618 023e1217 Nikos Skalkotos
               ("Delete", "Delete image properties"),
619 023e1217 Nikos Skalkotos
               ("Exclude", "Exclude various deployment tasks from running")]
620 023e1217 Nikos Skalkotos
621 023e1217 Nikos Skalkotos
    default_item = 0
622 023e1217 Nikos Skalkotos
623 023e1217 Nikos Skalkotos
    actions = {"Sysprep": sysprep,
624 023e1217 Nikos Skalkotos
               "Shrink": shrink,
625 023e1217 Nikos Skalkotos
               "View/Modify": modify_properties,
626 023e1217 Nikos Skalkotos
               "Delete": delete_properties,
627 023e1217 Nikos Skalkotos
               "Exclude": exclude_tasks}
628 023e1217 Nikos Skalkotos
    while 1:
629 023e1217 Nikos Skalkotos
        (code, choice) = d.menu(
630 023e1217 Nikos Skalkotos
            text="Choose one of the following or press <Back> to exit.",
631 023e1217 Nikos Skalkotos
            width=WIDTH, choices=choices, cancel="Back", height=13,
632 023e1217 Nikos Skalkotos
            menu_height=len(choices), default_item=choices[default_item][0],
633 023e1217 Nikos Skalkotos
            title="Image Customization Menu")
634 023e1217 Nikos Skalkotos
635 023e1217 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
636 023e1217 Nikos Skalkotos
            break
637 023e1217 Nikos Skalkotos
        elif choice in actions:
638 023e1217 Nikos Skalkotos
            default_item = [entry[0] for entry in choices].index(choice)
639 023e1217 Nikos Skalkotos
            if actions[choice](session):
640 023e1217 Nikos Skalkotos
                default_item = (default_item + 1) % len(choices)
641 023e1217 Nikos Skalkotos
642 023e1217 Nikos Skalkotos
643 023e1217 Nikos Skalkotos
def main_menu(session):
644 023e1217 Nikos Skalkotos
    d = session['dialog']
645 023e1217 Nikos Skalkotos
    dev = session['device']
646 023e1217 Nikos Skalkotos
647 023e1217 Nikos Skalkotos
    update_background_title(session)
648 023e1217 Nikos Skalkotos
649 023e1217 Nikos Skalkotos
    choices = [("Customize", "Customize image & ~okeanos deployment options"),
650 023e1217 Nikos Skalkotos
               ("Register", "Register image to ~okeanos"),
651 023e1217 Nikos Skalkotos
               ("Extract", "Dump image to local file system"),
652 023e1217 Nikos Skalkotos
               ("Reset", "Reset everything and start over again"),
653 023e1217 Nikos Skalkotos
               ("Help", "Get help for using snf-image-creator")]
654 023e1217 Nikos Skalkotos
655 023e1217 Nikos Skalkotos
    default_item = "Customize"
656 023e1217 Nikos Skalkotos
657 023e1217 Nikos Skalkotos
    actions = {"Customize": customization_menu, "Register": kamaki_menu,
658 023e1217 Nikos Skalkotos
               "Extract": extract_image}
659 023e1217 Nikos Skalkotos
    while 1:
660 023e1217 Nikos Skalkotos
        (code, choice) = d.menu(
661 023e1217 Nikos Skalkotos
            text="Choose one of the following or press <Exit> to exit.",
662 023e1217 Nikos Skalkotos
            width=WIDTH, choices=choices, cancel="Exit", height=13,
663 023e1217 Nikos Skalkotos
            default_item=default_item, menu_height=len(choices),
664 023e1217 Nikos Skalkotos
            title="Image Creator for ~okeanos (snf-image-creator version %s)" %
665 023e1217 Nikos Skalkotos
                  version)
666 023e1217 Nikos Skalkotos
667 023e1217 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
668 023e1217 Nikos Skalkotos
            if confirm_exit(d):
669 023e1217 Nikos Skalkotos
                break
670 023e1217 Nikos Skalkotos
        elif choice == "Reset":
671 023e1217 Nikos Skalkotos
            if confirm_reset(d):
672 023e1217 Nikos Skalkotos
                d.infobox("Resetting snf-image-creator. Please wait...",
673 023e1217 Nikos Skalkotos
                          width=SMALL_WIDTH)
674 023e1217 Nikos Skalkotos
                raise Reset
675 023e1217 Nikos Skalkotos
        elif choice in actions:
676 023e1217 Nikos Skalkotos
            actions[choice](session)
677 023e1217 Nikos Skalkotos
678 023e1217 Nikos Skalkotos
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :