Statistics
| Branch: | Tag: | Revision:

root / image_creator / dialog_menu.py @ 121f3bc0

History | View | Annotate | Download (25.3 kB)

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