Statistics
| Branch: | Tag: | Revision:

root / image_creator / dialog_main.py @ ea947a64

History | View | Annotate | Download (29.7 kB)

1 672cabb9 Nikos Skalkotos
#!/usr/bin/env python
2 672cabb9 Nikos Skalkotos
3 672cabb9 Nikos Skalkotos
# Copyright 2012 GRNET S.A. All rights reserved.
4 672cabb9 Nikos Skalkotos
#
5 672cabb9 Nikos Skalkotos
# Redistribution and use in source and binary forms, with or
6 672cabb9 Nikos Skalkotos
# without modification, are permitted provided that the following
7 672cabb9 Nikos Skalkotos
# conditions are met:
8 672cabb9 Nikos Skalkotos
#
9 672cabb9 Nikos Skalkotos
#   1. Redistributions of source code must retain the above
10 672cabb9 Nikos Skalkotos
#      copyright notice, this list of conditions and the following
11 672cabb9 Nikos Skalkotos
#      disclaimer.
12 672cabb9 Nikos Skalkotos
#
13 672cabb9 Nikos Skalkotos
#   2. Redistributions in binary form must reproduce the above
14 672cabb9 Nikos Skalkotos
#      copyright notice, this list of conditions and the following
15 672cabb9 Nikos Skalkotos
#      disclaimer in the documentation and/or other materials
16 672cabb9 Nikos Skalkotos
#      provided with the distribution.
17 672cabb9 Nikos Skalkotos
#
18 672cabb9 Nikos Skalkotos
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
19 672cabb9 Nikos Skalkotos
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 672cabb9 Nikos Skalkotos
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 672cabb9 Nikos Skalkotos
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
22 672cabb9 Nikos Skalkotos
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 672cabb9 Nikos Skalkotos
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 672cabb9 Nikos Skalkotos
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25 672cabb9 Nikos Skalkotos
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 672cabb9 Nikos Skalkotos
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 672cabb9 Nikos Skalkotos
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 672cabb9 Nikos Skalkotos
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 672cabb9 Nikos Skalkotos
# POSSIBILITY OF SUCH DAMAGE.
30 672cabb9 Nikos Skalkotos
#
31 672cabb9 Nikos Skalkotos
# The views and conclusions contained in the software and
32 672cabb9 Nikos Skalkotos
# documentation are those of the authors and should not be
33 672cabb9 Nikos Skalkotos
# interpreted as representing official policies, either expressed
34 672cabb9 Nikos Skalkotos
# or implied, of GRNET S.A.
35 672cabb9 Nikos Skalkotos
36 672cabb9 Nikos Skalkotos
import dialog
37 672cabb9 Nikos Skalkotos
import sys
38 672cabb9 Nikos Skalkotos
import os
39 672cabb9 Nikos Skalkotos
import textwrap
40 672cabb9 Nikos Skalkotos
import signal
41 2a21ff92 Nikos Skalkotos
import StringIO
42 672cabb9 Nikos Skalkotos
43 672cabb9 Nikos Skalkotos
from image_creator import __version__ as version
44 672cabb9 Nikos Skalkotos
from image_creator.util import FatalError, MD5
45 9afc4b89 Nikos Skalkotos
from image_creator.output.dialog import GaugeOutput, InfoBoxOutput
46 672cabb9 Nikos Skalkotos
from image_creator.disk import Disk
47 672cabb9 Nikos Skalkotos
from image_creator.os_type import os_cls
48 2a21ff92 Nikos Skalkotos
from image_creator.kamaki_wrapper import Kamaki, ClientError
49 7f623b20 Nikos Skalkotos
from image_creator.help import get_help_file
50 672cabb9 Nikos Skalkotos
51 672cabb9 Nikos Skalkotos
MSGBOX_WIDTH = 60
52 672cabb9 Nikos Skalkotos
YESNO_WIDTH = 50
53 672cabb9 Nikos Skalkotos
MENU_WIDTH = 70
54 f9d8c3d9 Nikos Skalkotos
INPUTBOX_WIDTH = 70
55 7f623b20 Nikos Skalkotos
CHECKBOX_WIDTH = 70
56 9afc4b89 Nikos Skalkotos
HELP_WIDTH = 70
57 a42a42b3 Nikos Skalkotos
INFOBOX_WIDTH = 70
58 7f623b20 Nikos Skalkotos
59 7f623b20 Nikos Skalkotos
CONFIGURATION_TASKS = [
60 1f42adc8 Nikos Skalkotos
    ("Partition table manipulation", ["FixPartitionTable"],
61 1f42adc8 Nikos Skalkotos
        ["linux", "windows"]),
62 1f42adc8 Nikos Skalkotos
    ("File system resize",
63 1f42adc8 Nikos Skalkotos
        ["FilesystemResizeUnmounted", "FilesystemResizeMounted"],
64 1f42adc8 Nikos Skalkotos
        ["linux", "windows"]),
65 1f42adc8 Nikos Skalkotos
    ("Swap partition configuration", ["AddSwap"], ["linux"]),
66 1f42adc8 Nikos Skalkotos
    ("SSH keys removal", ["DeleteSSHKeys"], ["linux"]),
67 1f42adc8 Nikos Skalkotos
    ("Temporal RDP disabling", ["DisableRemoteDesktopConnections"],
68 1f42adc8 Nikos Skalkotos
        ["windows"]),
69 1f42adc8 Nikos Skalkotos
    ("SELinux relabeling at next boot", ["SELinuxAutorelabel"], ["linux"]),
70 1f42adc8 Nikos Skalkotos
    ("Hostname/Computer Name assignment", ["AssignHostname"],
71 1f42adc8 Nikos Skalkotos
        ["windows", "linux"]),
72 1f42adc8 Nikos Skalkotos
    ("Password change", ["ChangePassword"], ["windows", "linux"]),
73 1f42adc8 Nikos Skalkotos
    ("File injection", ["EnforcePersonality"], ["windows", "linux"])
74 7f623b20 Nikos Skalkotos
]
75 672cabb9 Nikos Skalkotos
76 672cabb9 Nikos Skalkotos
77 672cabb9 Nikos Skalkotos
class Reset(Exception):
78 672cabb9 Nikos Skalkotos
    pass
79 672cabb9 Nikos Skalkotos
80 672cabb9 Nikos Skalkotos
81 330fd618 Nikos Skalkotos
class metadata_monitor(object):
82 330fd618 Nikos Skalkotos
    def __init__(self, session, meta):
83 330fd618 Nikos Skalkotos
        self.session = session
84 330fd618 Nikos Skalkotos
        self.meta = meta
85 330fd618 Nikos Skalkotos
86 330fd618 Nikos Skalkotos
    def __enter__(self):
87 330fd618 Nikos Skalkotos
        self.old = {}
88 330fd618 Nikos Skalkotos
        for (k, v) in self.meta.items():
89 330fd618 Nikos Skalkotos
            self.old[k] = v
90 330fd618 Nikos Skalkotos
91 330fd618 Nikos Skalkotos
    def __exit__(self, type, value, traceback):
92 330fd618 Nikos Skalkotos
        d = self.session['dialog']
93 330fd618 Nikos Skalkotos
94 330fd618 Nikos Skalkotos
        altered = {}
95 330fd618 Nikos Skalkotos
        added = {}
96 330fd618 Nikos Skalkotos
97 330fd618 Nikos Skalkotos
        for (k, v) in self.meta.items():
98 330fd618 Nikos Skalkotos
            if k not in self.old:
99 330fd618 Nikos Skalkotos
                added[k] = v
100 330fd618 Nikos Skalkotos
            elif self.old[k] != v:
101 330fd618 Nikos Skalkotos
                altered[k] = v
102 330fd618 Nikos Skalkotos
103 330fd618 Nikos Skalkotos
        if not (len(added) or len(altered)):
104 330fd618 Nikos Skalkotos
            return
105 330fd618 Nikos Skalkotos
106 330fd618 Nikos Skalkotos
        msg = "The last action has changed some image properties:\n\n"
107 330fd618 Nikos Skalkotos
        if len(added):
108 330fd618 Nikos Skalkotos
            msg += "New image properties:\n"
109 330fd618 Nikos Skalkotos
            for (k, v) in added.items():
110 330fd618 Nikos Skalkotos
                msg += '    %s: "%s"\n' % (k, v)
111 330fd618 Nikos Skalkotos
            msg += "\n"
112 330fd618 Nikos Skalkotos
        if len(altered):
113 330fd618 Nikos Skalkotos
            msg += "Updated image properties:\n"
114 330fd618 Nikos Skalkotos
            for (k, v) in altered.items():
115 330fd618 Nikos Skalkotos
                msg += '    %s: "%s" -> "%s"\n' % (k, self.old[k], v)
116 330fd618 Nikos Skalkotos
            msg += "\n"
117 330fd618 Nikos Skalkotos
118 330fd618 Nikos Skalkotos
        self.session['metadata'].update(added)
119 330fd618 Nikos Skalkotos
        self.session['metadata'].update(altered)
120 330fd618 Nikos Skalkotos
        d.msgbox(msg, title="Image Property Changes", width=MSGBOX_WIDTH)
121 330fd618 Nikos Skalkotos
122 330fd618 Nikos Skalkotos
123 ea947a64 Nikos Skalkotos
def extract_metadata_string(session):
124 ea947a64 Nikos Skalkotos
    metadata = ['%s=%s' % (k, v) for (k, v) in session['metadata'].items()]
125 ea947a64 Nikos Skalkotos
126 ea947a64 Nikos Skalkotos
    if 'task_metadata' in session:
127 ea947a64 Nikos Skalkotos
        metadata.extend("%s=yes" % m for m in session['task_metadata'])
128 ea947a64 Nikos Skalkotos
129 ea947a64 Nikos Skalkotos
    return '\n'.join(metadata) + '\n'
130 ea947a64 Nikos Skalkotos
131 ea947a64 Nikos Skalkotos
132 672cabb9 Nikos Skalkotos
def confirm_exit(d, msg=''):
133 672cabb9 Nikos Skalkotos
    return not d.yesno("%s Do you want to exit?" % msg, width=YESNO_WIDTH)
134 672cabb9 Nikos Skalkotos
135 672cabb9 Nikos Skalkotos
136 672cabb9 Nikos Skalkotos
def confirm_reset(d):
137 a42a42b3 Nikos Skalkotos
    return not d.yesno("Are you sure you want to reset everything?",
138 74585c56 Nikos Skalkotos
                       width=YESNO_WIDTH, defaultno=1)
139 672cabb9 Nikos Skalkotos
140 f9d8c3d9 Nikos Skalkotos
141 9afc4b89 Nikos Skalkotos
def update_background_title(session):
142 9afc4b89 Nikos Skalkotos
    d = session['dialog']
143 9afc4b89 Nikos Skalkotos
    dev = session['device']
144 9afc4b89 Nikos Skalkotos
145 9afc4b89 Nikos Skalkotos
    MB = 2 ** 20
146 9afc4b89 Nikos Skalkotos
147 9afc4b89 Nikos Skalkotos
    size = (dev.meta['SIZE'] + MB - 1) // MB
148 a42a42b3 Nikos Skalkotos
    shrinked = 'shrinked' in session and session['shrinked'] == True
149 a42a42b3 Nikos Skalkotos
    postfix = " (shrinked)" if shrinked else ''
150 a42a42b3 Nikos Skalkotos
151 a42a42b3 Nikos Skalkotos
    title = "OS: %s, Distro: %s, Size: %dMB%s" % \
152 a42a42b3 Nikos Skalkotos
            (dev.ostype, dev.distro, size, postfix)
153 9afc4b89 Nikos Skalkotos
154 9afc4b89 Nikos Skalkotos
    d.setBackgroundTitle(title)
155 9afc4b89 Nikos Skalkotos
156 9afc4b89 Nikos Skalkotos
157 2a21ff92 Nikos Skalkotos
def extract_image(session):
158 2a21ff92 Nikos Skalkotos
    d = session['dialog']
159 2a21ff92 Nikos Skalkotos
    dir = os.getcwd()
160 2a21ff92 Nikos Skalkotos
    while 1:
161 2a21ff92 Nikos Skalkotos
        if dir and dir[-1] != os.sep:
162 2a21ff92 Nikos Skalkotos
            dir = dir + os.sep
163 2a21ff92 Nikos Skalkotos
164 2a21ff92 Nikos Skalkotos
        (code, path) = d.fselect(dir, 10, 50, title="Save image as...")
165 2a21ff92 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
166 2a21ff92 Nikos Skalkotos
            return False
167 2a21ff92 Nikos Skalkotos
168 2a21ff92 Nikos Skalkotos
        if os.path.isdir(path):
169 f9d8c3d9 Nikos Skalkotos
            dir = path
170 2a21ff92 Nikos Skalkotos
            continue
171 2a21ff92 Nikos Skalkotos
172 2a21ff92 Nikos Skalkotos
        if os.path.isdir("%s.meta" % path):
173 2a21ff92 Nikos Skalkotos
            d.msgbox("Can't overwrite directory `%s.meta'" % path,
174 2a21ff92 Nikos Skalkotos
                     width=MSGBOX_WIDTH)
175 2a21ff92 Nikos Skalkotos
            continue
176 2a21ff92 Nikos Skalkotos
177 2a21ff92 Nikos Skalkotos
        if os.path.isdir("%s.md5sum" % path):
178 2a21ff92 Nikos Skalkotos
            d.msgbox("Can't overwrite directory `%s.md5sum'" % path,
179 2a21ff92 Nikos Skalkotos
                     width=MSGBOX_WIDTH)
180 2a21ff92 Nikos Skalkotos
            continue
181 2a21ff92 Nikos Skalkotos
182 2a21ff92 Nikos Skalkotos
        basedir = os.path.dirname(path)
183 2a21ff92 Nikos Skalkotos
        name = os.path.basename(path)
184 2a21ff92 Nikos Skalkotos
        if not os.path.exists(basedir):
185 2a21ff92 Nikos Skalkotos
            d.msgbox("Directory `%s' does not exist" % basedir,
186 2a21ff92 Nikos Skalkotos
                     width=MSGBOX_WIDTH)
187 2a21ff92 Nikos Skalkotos
            continue
188 2a21ff92 Nikos Skalkotos
189 2a21ff92 Nikos Skalkotos
        dir = basedir
190 2a21ff92 Nikos Skalkotos
        if len(name) == 0:
191 2a21ff92 Nikos Skalkotos
            continue
192 2a21ff92 Nikos Skalkotos
193 2a21ff92 Nikos Skalkotos
        files = ["%s%s" % (path, ext) for ext in ('', '.meta', '.md5sum')]
194 2a21ff92 Nikos Skalkotos
        overwrite = filter(os.path.exists, files)
195 2a21ff92 Nikos Skalkotos
196 2a21ff92 Nikos Skalkotos
        if len(overwrite) > 0:
197 2a21ff92 Nikos Skalkotos
            if d.yesno("The following file(s) exist:\n"
198 1f42adc8 Nikos Skalkotos
                       "%s\nDo you want to overwrite them?" %
199 1f42adc8 Nikos Skalkotos
                       "\n".join(overwrite), width=YESNO_WIDTH):
200 2a21ff92 Nikos Skalkotos
                continue
201 2a21ff92 Nikos Skalkotos
202 2a21ff92 Nikos Skalkotos
        out = GaugeOutput(d, "Image Extraction", "Extracting image...")
203 2a21ff92 Nikos Skalkotos
        try:
204 2a21ff92 Nikos Skalkotos
            dev = session['device']
205 2a21ff92 Nikos Skalkotos
            if "checksum" not in session:
206 2a21ff92 Nikos Skalkotos
                size = dev.meta['SIZE']
207 2a21ff92 Nikos Skalkotos
                md5 = MD5(out)
208 2a21ff92 Nikos Skalkotos
                session['checksum'] = md5.compute(session['snapshot'], size)
209 2a21ff92 Nikos Skalkotos
210 2a21ff92 Nikos Skalkotos
            # Extract image file
211 2a21ff92 Nikos Skalkotos
            dev.out = out
212 2a21ff92 Nikos Skalkotos
            dev.dump(path)
213 2a21ff92 Nikos Skalkotos
214 2a21ff92 Nikos Skalkotos
            # Extract metadata file
215 2a21ff92 Nikos Skalkotos
            out.output("Extracting metadata file...")
216 2a21ff92 Nikos Skalkotos
            with open('%s.meta' % path, 'w') as f:
217 ea947a64 Nikos Skalkotos
                f.write(extract_metadata_string(session))
218 2a21ff92 Nikos Skalkotos
            out.success('done')
219 2a21ff92 Nikos Skalkotos
220 2a21ff92 Nikos Skalkotos
            # Extract md5sum file
221 2a21ff92 Nikos Skalkotos
            out.output("Extracting md5sum file...")
222 2a21ff92 Nikos Skalkotos
            md5str = "%s %s\n" % (session['checksum'], name)
223 2a21ff92 Nikos Skalkotos
            with open('%s.md5sum' % path, 'w') as f:
224 2a21ff92 Nikos Skalkotos
                f.write(md5str)
225 2a21ff92 Nikos Skalkotos
            out.success("done")
226 2a21ff92 Nikos Skalkotos
227 2a21ff92 Nikos Skalkotos
        finally:
228 2a21ff92 Nikos Skalkotos
            out.cleanup()
229 2a21ff92 Nikos Skalkotos
        d.msgbox("Image file `%s' was successfully extracted!" % path,
230 2a21ff92 Nikos Skalkotos
                 width=MSGBOX_WIDTH)
231 2a21ff92 Nikos Skalkotos
        break
232 2a21ff92 Nikos Skalkotos
233 2a21ff92 Nikos Skalkotos
    return True
234 2a21ff92 Nikos Skalkotos
235 672cabb9 Nikos Skalkotos
236 672cabb9 Nikos Skalkotos
def upload_image(session):
237 672cabb9 Nikos Skalkotos
    d = session["dialog"]
238 2a21ff92 Nikos Skalkotos
    size = session['device'].meta['SIZE']
239 672cabb9 Nikos Skalkotos
240 672cabb9 Nikos Skalkotos
    if "account" not in session:
241 672cabb9 Nikos Skalkotos
        d.msgbox("You need to provide your ~okeanos login username before you "
242 672cabb9 Nikos Skalkotos
                 "can upload images to pithos+", width=MSGBOX_WIDTH)
243 672cabb9 Nikos Skalkotos
        return False
244 672cabb9 Nikos Skalkotos
245 672cabb9 Nikos Skalkotos
    if "token" not in session:
246 672cabb9 Nikos Skalkotos
        d.msgbox("You need to provide your ~okeanos account authentication "
247 672cabb9 Nikos Skalkotos
                 "token before you can upload images to pithos+",
248 672cabb9 Nikos Skalkotos
                 width=MSGBOX_WIDTH)
249 672cabb9 Nikos Skalkotos
        return False
250 672cabb9 Nikos Skalkotos
251 672cabb9 Nikos Skalkotos
    while 1:
252 f9d8c3d9 Nikos Skalkotos
        init = session["upload"] if "upload" in session else ''
253 2a21ff92 Nikos Skalkotos
        (code, answer) = d.inputbox("Please provide a filename:", init=init,
254 2a21ff92 Nikos Skalkotos
                                    width=INPUTBOX_WIDTH)
255 f9d8c3d9 Nikos Skalkotos
256 672cabb9 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
257 672cabb9 Nikos Skalkotos
            return False
258 672cabb9 Nikos Skalkotos
259 2a21ff92 Nikos Skalkotos
        filename = answer.strip()
260 2a21ff92 Nikos Skalkotos
        if len(filename) == 0:
261 672cabb9 Nikos Skalkotos
            d.msgbox("Filename cannot be empty", width=MSGBOX_WIDTH)
262 672cabb9 Nikos Skalkotos
            continue
263 f9d8c3d9 Nikos Skalkotos
264 2a21ff92 Nikos Skalkotos
        break
265 672cabb9 Nikos Skalkotos
266 2a21ff92 Nikos Skalkotos
    out = GaugeOutput(d, "Image Upload", "Uploading...")
267 2a21ff92 Nikos Skalkotos
    if 'checksum' not in session:
268 2a21ff92 Nikos Skalkotos
        md5 = MD5(out)
269 2a21ff92 Nikos Skalkotos
        session['checksum'] = md5.compute(session['snapshot'], size)
270 2a21ff92 Nikos Skalkotos
    try:
271 2a21ff92 Nikos Skalkotos
        kamaki = Kamaki(session['account'], session['token'], out)
272 2a21ff92 Nikos Skalkotos
        try:
273 2a21ff92 Nikos Skalkotos
            # Upload image file
274 2a21ff92 Nikos Skalkotos
            with open(session['snapshot'], 'rb') as f:
275 2a21ff92 Nikos Skalkotos
                session["upload"] = kamaki.upload(f, size, filename,
276 2a21ff92 Nikos Skalkotos
                                                  "Calculating block hashes",
277 2a21ff92 Nikos Skalkotos
                                                  "Uploading missing blocks")
278 2a21ff92 Nikos Skalkotos
            # Upload metadata file
279 2a21ff92 Nikos Skalkotos
            out.output("Uploading metadata file...")
280 ea947a64 Nikos Skalkotos
            metastring = extract_metadata_string(session)
281 2a21ff92 Nikos Skalkotos
            kamaki.upload(StringIO.StringIO(metastring), size=len(metastring),
282 2a21ff92 Nikos Skalkotos
                          remote_path="%s.meta" % filename)
283 2a21ff92 Nikos Skalkotos
            out.success("done")
284 2a21ff92 Nikos Skalkotos
285 2a21ff92 Nikos Skalkotos
            # Upload md5sum file
286 2a21ff92 Nikos Skalkotos
            out.output("Uploading md5sum file...")
287 2a21ff92 Nikos Skalkotos
            md5str = "%s %s\n" % (session['checksum'], filename)
288 2a21ff92 Nikos Skalkotos
            kamaki.upload(StringIO.StringIO(md5str), size=len(md5str),
289 2a21ff92 Nikos Skalkotos
                          remote_path="%s.md5sum" % filename)
290 2a21ff92 Nikos Skalkotos
            out.success("done")
291 2a21ff92 Nikos Skalkotos
292 2a21ff92 Nikos Skalkotos
        except ClientError as e:
293 2a21ff92 Nikos Skalkotos
            d.msgbox("Error in pithos+ client: %s" % e.message,
294 2a21ff92 Nikos Skalkotos
                     title="Pithos+ Client Error", width=MSGBOX_WIDTH)
295 2a21ff92 Nikos Skalkotos
            if 'upload' in session:
296 2a21ff92 Nikos Skalkotos
                del session['upload']
297 2a21ff92 Nikos Skalkotos
            return False
298 2a21ff92 Nikos Skalkotos
    finally:
299 2a21ff92 Nikos Skalkotos
        out.cleanup()
300 2a21ff92 Nikos Skalkotos
301 f9d8c3d9 Nikos Skalkotos
    d.msgbox("Image file `%s' was successfully uploaded to pithos+" % filename,
302 2a21ff92 Nikos Skalkotos
             width=MSGBOX_WIDTH)
303 7f623b20 Nikos Skalkotos
304 2a21ff92 Nikos Skalkotos
    return True
305 672cabb9 Nikos Skalkotos
306 672cabb9 Nikos Skalkotos
307 672cabb9 Nikos Skalkotos
def register_image(session):
308 672cabb9 Nikos Skalkotos
    d = session["dialog"]
309 672cabb9 Nikos Skalkotos
310 672cabb9 Nikos Skalkotos
    if "account" not in session:
311 672cabb9 Nikos Skalkotos
        d.msgbox("You need to provide your ~okeanos login username before you "
312 672cabb9 Nikos Skalkotos
                 "can register an images to cyclades",
313 672cabb9 Nikos Skalkotos
                 width=MSGBOX_WIDTH)
314 672cabb9 Nikos Skalkotos
        return False
315 672cabb9 Nikos Skalkotos
316 672cabb9 Nikos Skalkotos
    if "token" not in session:
317 672cabb9 Nikos Skalkotos
        d.msgbox("You need to provide your ~okeanos account authentication "
318 672cabb9 Nikos Skalkotos
                 "token before you can register an images to cyclades",
319 672cabb9 Nikos Skalkotos
                 width=MSGBOX_WIDTH)
320 672cabb9 Nikos Skalkotos
        return False
321 672cabb9 Nikos Skalkotos
322 672cabb9 Nikos Skalkotos
    if "upload" not in session:
323 09743d3a Nikos Skalkotos
        d.msgbox("You need to upload the image to pithos+ before you can "
324 09743d3a Nikos Skalkotos
                 "register it to cyclades", width=MSGBOX_WIDTH)
325 672cabb9 Nikos Skalkotos
        return False
326 672cabb9 Nikos Skalkotos
327 2a21ff92 Nikos Skalkotos
    while 1:
328 1f42adc8 Nikos Skalkotos
        (code, answer) = d.inputbox("Please provide a registration name:",
329 1f42adc8 Nikos Skalkotos
                                    width=INPUTBOX_WIDTH)
330 2a21ff92 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
331 2a21ff92 Nikos Skalkotos
            return False
332 2a21ff92 Nikos Skalkotos
333 2a21ff92 Nikos Skalkotos
        name = answer.strip()
334 2a21ff92 Nikos Skalkotos
        if len(name) == 0:
335 2a21ff92 Nikos Skalkotos
            d.msgbox("Registration name cannot be empty", width=MSGBOX_WIDTH)
336 2a21ff92 Nikos Skalkotos
            continue
337 2a21ff92 Nikos Skalkotos
        break
338 2a21ff92 Nikos Skalkotos
339 ea947a64 Nikos Skalkotos
    metadata = {}
340 ea947a64 Nikos Skalkotos
    metadata.update(session['metadata'])
341 ea947a64 Nikos Skalkotos
    if 'task_metadata' in session:
342 ea947a64 Nikos Skalkotos
        for key in session['task_metadata']:
343 ea947a64 Nikos Skalkotos
            metadata[key] = 'yes'
344 ea947a64 Nikos Skalkotos
345 2a21ff92 Nikos Skalkotos
    out = GaugeOutput(d, "Image Registration", "Registrating image...")
346 2a21ff92 Nikos Skalkotos
    try:
347 2a21ff92 Nikos Skalkotos
        out.output("Registring image to cyclades...")
348 2a21ff92 Nikos Skalkotos
        try:
349 2a21ff92 Nikos Skalkotos
            kamaki = Kamaki(session['account'], session['token'], out)
350 ea947a64 Nikos Skalkotos
            kamaki.register(name, session['upload'], metadata)
351 2a21ff92 Nikos Skalkotos
            out.success('done')
352 2a21ff92 Nikos Skalkotos
        except ClientError as e:
353 2a21ff92 Nikos Skalkotos
            d.msgbox("Error in pithos+ client: %s" % e.message)
354 2a21ff92 Nikos Skalkotos
            return False
355 2a21ff92 Nikos Skalkotos
    finally:
356 2a21ff92 Nikos Skalkotos
        out.cleanup()
357 2a21ff92 Nikos Skalkotos
358 2a21ff92 Nikos Skalkotos
    d.msgbox("Image `%s' was successfully registered to cyclades as `%s'" %
359 2a21ff92 Nikos Skalkotos
             (session['upload'], name), width=MSGBOX_WIDTH)
360 672cabb9 Nikos Skalkotos
    return True
361 672cabb9 Nikos Skalkotos
362 672cabb9 Nikos Skalkotos
363 672cabb9 Nikos Skalkotos
def kamaki_menu(session):
364 672cabb9 Nikos Skalkotos
    d = session['dialog']
365 672cabb9 Nikos Skalkotos
    default_item = "Account"
366 672cabb9 Nikos Skalkotos
    while 1:
367 672cabb9 Nikos Skalkotos
        account = session["account"] if "account" in session else "<none>"
368 672cabb9 Nikos Skalkotos
        token = session["token"] if "token" in session else "<none>"
369 672cabb9 Nikos Skalkotos
        upload = session["upload"] if "upload" in session else "<none>"
370 9afc4b89 Nikos Skalkotos
371 9afc4b89 Nikos Skalkotos
        choices = [("Account", "Change your ~okeanos username: %s" % account),
372 9afc4b89 Nikos Skalkotos
                   ("Token", "Change your ~okeanos token: %s" % token),
373 9afc4b89 Nikos Skalkotos
                   ("Upload", "Upload image to pithos+"),
374 09743d3a Nikos Skalkotos
                   ("Register", "Register the image to cyclades: %s" % upload)]
375 9afc4b89 Nikos Skalkotos
376 672cabb9 Nikos Skalkotos
        (code, choice) = d.menu(
377 9afc4b89 Nikos Skalkotos
            text="Choose one of the following or press <Back> to go back.",
378 74585c56 Nikos Skalkotos
            width=MENU_WIDTH, choices=choices, cancel="Back",
379 9afc4b89 Nikos Skalkotos
            default_item=default_item, title="Image Registration Menu")
380 672cabb9 Nikos Skalkotos
381 672cabb9 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
382 672cabb9 Nikos Skalkotos
            return False
383 672cabb9 Nikos Skalkotos
384 672cabb9 Nikos Skalkotos
        if choice == "Account":
385 672cabb9 Nikos Skalkotos
            default_item = "Account"
386 672cabb9 Nikos Skalkotos
            (code, answer) = d.inputbox(
387 672cabb9 Nikos Skalkotos
                "Please provide your ~okeanos account e-mail address:",
388 672cabb9 Nikos Skalkotos
                init=session["account"] if "account" in session else '',
389 672cabb9 Nikos Skalkotos
                width=70)
390 672cabb9 Nikos Skalkotos
            if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
391 672cabb9 Nikos Skalkotos
                continue
392 672cabb9 Nikos Skalkotos
            if len(answer) == 0 and "account" in session:
393 672cabb9 Nikos Skalkotos
                    del session["account"]
394 672cabb9 Nikos Skalkotos
            else:
395 672cabb9 Nikos Skalkotos
                session["account"] = answer.strip()
396 672cabb9 Nikos Skalkotos
                default_item = "Token"
397 672cabb9 Nikos Skalkotos
        elif choice == "Token":
398 672cabb9 Nikos Skalkotos
            default_item = "Token"
399 672cabb9 Nikos Skalkotos
            (code, answer) = d.inputbox(
400 672cabb9 Nikos Skalkotos
                "Please provide your ~okeanos account authetication token:",
401 672cabb9 Nikos Skalkotos
                init=session["token"] if "token" in session else '',
402 672cabb9 Nikos Skalkotos
                width=70)
403 672cabb9 Nikos Skalkotos
            if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
404 672cabb9 Nikos Skalkotos
                continue
405 672cabb9 Nikos Skalkotos
            if len(answer) == 0 and "token" in session:
406 672cabb9 Nikos Skalkotos
                del session["token"]
407 672cabb9 Nikos Skalkotos
            else:
408 672cabb9 Nikos Skalkotos
                session["token"] = answer.strip()
409 672cabb9 Nikos Skalkotos
                default_item = "Upload"
410 672cabb9 Nikos Skalkotos
        elif choice == "Upload":
411 672cabb9 Nikos Skalkotos
            if upload_image(session):
412 672cabb9 Nikos Skalkotos
                default_item = "Register"
413 672cabb9 Nikos Skalkotos
            else:
414 672cabb9 Nikos Skalkotos
                default_item = "Upload"
415 672cabb9 Nikos Skalkotos
        elif choice == "Register":
416 672cabb9 Nikos Skalkotos
            if register_image(session):
417 672cabb9 Nikos Skalkotos
                return True
418 672cabb9 Nikos Skalkotos
            else:
419 672cabb9 Nikos Skalkotos
                default_item = "Register"
420 672cabb9 Nikos Skalkotos
421 672cabb9 Nikos Skalkotos
422 f9d8c3d9 Nikos Skalkotos
def add_property(session):
423 f9d8c3d9 Nikos Skalkotos
    d = session['dialog']
424 f9d8c3d9 Nikos Skalkotos
425 f9d8c3d9 Nikos Skalkotos
    while 1:
426 f9d8c3d9 Nikos Skalkotos
        (code, answer) = d.inputbox("Please provide a name for a new image"
427 f9d8c3d9 Nikos Skalkotos
                                    " property:", width=INPUTBOX_WIDTH)
428 f9d8c3d9 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
429 f9d8c3d9 Nikos Skalkotos
            return False
430 f9d8c3d9 Nikos Skalkotos
431 f9d8c3d9 Nikos Skalkotos
        name = answer.strip()
432 f9d8c3d9 Nikos Skalkotos
        if len(name) == 0:
433 f9d8c3d9 Nikos Skalkotos
            d.msgbox("A property name cannot be empty", width=MSGBOX_WIDTH)
434 f9d8c3d9 Nikos Skalkotos
            continue
435 f9d8c3d9 Nikos Skalkotos
436 f9d8c3d9 Nikos Skalkotos
        break
437 f9d8c3d9 Nikos Skalkotos
438 f9d8c3d9 Nikos Skalkotos
    while 1:
439 f9d8c3d9 Nikos Skalkotos
        (code, answer) = d.inputbox("Please provide a value for image "
440 1f42adc8 Nikos Skalkotos
                                    "property %s" % name, width=INPUTBOX_WIDTH)
441 f9d8c3d9 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
442 f9d8c3d9 Nikos Skalkotos
            return False
443 f9d8c3d9 Nikos Skalkotos
444 f9d8c3d9 Nikos Skalkotos
        value = answer.strip()
445 f9d8c3d9 Nikos Skalkotos
        if len(value) == 0:
446 f9d8c3d9 Nikos Skalkotos
            d.msgbox("Value cannot be empty", width=MSGBOX_WIDTH)
447 f9d8c3d9 Nikos Skalkotos
            continue
448 f9d8c3d9 Nikos Skalkotos
449 f9d8c3d9 Nikos Skalkotos
        break
450 f9d8c3d9 Nikos Skalkotos
451 f9d8c3d9 Nikos Skalkotos
    session['metadata'][name] = value
452 f9d8c3d9 Nikos Skalkotos
453 f9d8c3d9 Nikos Skalkotos
    return True
454 f9d8c3d9 Nikos Skalkotos
455 f9d8c3d9 Nikos Skalkotos
456 f9d8c3d9 Nikos Skalkotos
def modify_properties(session):
457 f9d8c3d9 Nikos Skalkotos
    d = session['dialog']
458 f9d8c3d9 Nikos Skalkotos
459 f9d8c3d9 Nikos Skalkotos
    while 1:
460 f9d8c3d9 Nikos Skalkotos
        choices = []
461 f9d8c3d9 Nikos Skalkotos
        for (key, val) in session['metadata'].items():
462 f9d8c3d9 Nikos Skalkotos
            choices.append((str(key), str(val)))
463 f9d8c3d9 Nikos Skalkotos
464 f9d8c3d9 Nikos Skalkotos
        (code, choice) = d.menu(
465 f9d8c3d9 Nikos Skalkotos
            "In this menu you can edit existing image properties or add new "
466 a42a42b3 Nikos Skalkotos
            "ones. Be careful! Most properties have special meaning and "
467 f9d8c3d9 Nikos Skalkotos
            "alter the image deployment behaviour. Press <HELP> to see more "
468 f9d8c3d9 Nikos Skalkotos
            "information about image properties. Press <BACK> when done.",
469 9afc4b89 Nikos Skalkotos
            height=18, width=MENU_WIDTH, choices=choices, menu_height=10,
470 9afc4b89 Nikos Skalkotos
            ok_label="Edit", extra_button=1, extra_label="Add", cancel="Back",
471 74585c56 Nikos Skalkotos
            help_button=1, title="Image Properties")
472 f9d8c3d9 Nikos Skalkotos
473 f9d8c3d9 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
474 1f42adc8 Nikos Skalkotos
            return True
475 f9d8c3d9 Nikos Skalkotos
        # Edit button
476 f9d8c3d9 Nikos Skalkotos
        elif code == d.DIALOG_OK:
477 1f42adc8 Nikos Skalkotos
            (code, answer) = d.inputbox("Please provide a new value for the "
478 1f42adc8 Nikos Skalkotos
                                        "image property with name `%s':" %
479 1f42adc8 Nikos Skalkotos
                                        choice,
480 1f42adc8 Nikos Skalkotos
                                        init=session['metadata'][choice],
481 1f42adc8 Nikos Skalkotos
                                        width=INPUTBOX_WIDTH)
482 f9d8c3d9 Nikos Skalkotos
            if code not in (d.DIALOG_CANCEL, d.DIALOG_ESC):
483 f9d8c3d9 Nikos Skalkotos
                value = answer.strip()
484 f9d8c3d9 Nikos Skalkotos
                if len(value) == 0:
485 f9d8c3d9 Nikos Skalkotos
                    d.msgbox("Value cannot be empty!")
486 f9d8c3d9 Nikos Skalkotos
                    continue
487 f9d8c3d9 Nikos Skalkotos
                else:
488 f9d8c3d9 Nikos Skalkotos
                    session['metadata'][choice] = value
489 f9d8c3d9 Nikos Skalkotos
        # ADD button
490 f9d8c3d9 Nikos Skalkotos
        elif code == d.DIALOG_EXTRA:
491 f9d8c3d9 Nikos Skalkotos
            add_property(session)
492 09743d3a Nikos Skalkotos
        elif code == 'help':
493 09743d3a Nikos Skalkotos
            help_file = get_help_file("image_properties")
494 09743d3a Nikos Skalkotos
            assert os.path.exists(help_file)
495 09743d3a Nikos Skalkotos
            d.textbox(help_file, title="Image Properties", width=70, height=40)
496 f9d8c3d9 Nikos Skalkotos
497 f9d8c3d9 Nikos Skalkotos
498 f9d8c3d9 Nikos Skalkotos
def delete_properties(session):
499 f9d8c3d9 Nikos Skalkotos
    d = session['dialog']
500 f9d8c3d9 Nikos Skalkotos
501 f9d8c3d9 Nikos Skalkotos
    choices = []
502 f9d8c3d9 Nikos Skalkotos
    for (key, val) in session['metadata'].items():
503 f9d8c3d9 Nikos Skalkotos
        choices.append((key, "%s" % val, 0))
504 f9d8c3d9 Nikos Skalkotos
505 f9d8c3d9 Nikos Skalkotos
    (code, to_delete) = d.checklist("Choose which properties to delete:",
506 7f623b20 Nikos Skalkotos
                                    choices=choices, width=CHECKBOX_WIDTH)
507 9afc4b89 Nikos Skalkotos
508 f9d8c3d9 Nikos Skalkotos
    # If the user exits with ESC or CANCEL, the returned tag list is empty.
509 f9d8c3d9 Nikos Skalkotos
    for i in to_delete:
510 f9d8c3d9 Nikos Skalkotos
        del session['metadata'][i]
511 f9d8c3d9 Nikos Skalkotos
512 9afc4b89 Nikos Skalkotos
    cnt = len(to_delete)
513 9afc4b89 Nikos Skalkotos
    if cnt > 0:
514 9afc4b89 Nikos Skalkotos
        d.msgbox("%d image properties were deleted." % cnt, width=MSGBOX_WIDTH)
515 1f42adc8 Nikos Skalkotos
        return True
516 1f42adc8 Nikos Skalkotos
    else:
517 1f42adc8 Nikos Skalkotos
        return False
518 f9d8c3d9 Nikos Skalkotos
519 f9d8c3d9 Nikos Skalkotos
520 7f623b20 Nikos Skalkotos
def exclude_tasks(session):
521 f9d8c3d9 Nikos Skalkotos
    d = session['dialog']
522 f9d8c3d9 Nikos Skalkotos
523 7f623b20 Nikos Skalkotos
    index = 0
524 7f623b20 Nikos Skalkotos
    displayed_index = 1
525 f9d8c3d9 Nikos Skalkotos
    choices = []
526 7f623b20 Nikos Skalkotos
    mapping = {}
527 7f623b20 Nikos Skalkotos
    if 'excluded_tasks' not in session:
528 7f623b20 Nikos Skalkotos
        session['excluded_tasks'] = []
529 7f623b20 Nikos Skalkotos
530 7f623b20 Nikos Skalkotos
    if -1 in session['excluded_tasks']:
531 7f623b20 Nikos Skalkotos
        if not d.yesno("Image deployment configuration is disabled. "
532 7f623b20 Nikos Skalkotos
                       "Do you wish to enable it?", width=YESNO_WIDTH):
533 7f623b20 Nikos Skalkotos
            session['excluded_tasks'].remove(-1)
534 7f623b20 Nikos Skalkotos
        else:
535 1f42adc8 Nikos Skalkotos
            return False
536 7f623b20 Nikos Skalkotos
537 7f623b20 Nikos Skalkotos
    for (msg, task, osfamily) in CONFIGURATION_TASKS:
538 7f623b20 Nikos Skalkotos
        if session['metadata']['OSFAMILY'] in osfamily:
539 7f623b20 Nikos Skalkotos
            checked = 1 if index in session['excluded_tasks'] else 0
540 7f623b20 Nikos Skalkotos
            choices.append((str(displayed_index), msg, checked))
541 7f623b20 Nikos Skalkotos
            mapping[displayed_index] = index
542 7f623b20 Nikos Skalkotos
            displayed_index += 1
543 7f623b20 Nikos Skalkotos
        index += 1
544 f9d8c3d9 Nikos Skalkotos
545 7f623b20 Nikos Skalkotos
    while 1:
546 7f623b20 Nikos Skalkotos
        (code, tags) = d.checklist(
547 9afc4b89 Nikos Skalkotos
            text="Please choose which configuration tasks you would like to "
548 9afc4b89 Nikos Skalkotos
                 "prevent from running during image deployment. "
549 9afc4b89 Nikos Skalkotos
                 "Press <No Config> to supress any configuration. "
550 9afc4b89 Nikos Skalkotos
                 "Press <Help> for more help on the image deployment "
551 9afc4b89 Nikos Skalkotos
                 "configuration tasks.",
552 9afc4b89 Nikos Skalkotos
            choices=choices, height=19, list_height=8, width=CHECKBOX_WIDTH,
553 9afc4b89 Nikos Skalkotos
            help_button=1, extra_button=1, extra_label="No Config",
554 9afc4b89 Nikos Skalkotos
            title="Exclude Configuration Tasks")
555 f9d8c3d9 Nikos Skalkotos
556 7f623b20 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
557 1f42adc8 Nikos Skalkotos
            return False
558 7f623b20 Nikos Skalkotos
        elif code == d.DIALOG_HELP:
559 7f623b20 Nikos Skalkotos
            help_file = get_help_file("configuration_tasks")
560 7f623b20 Nikos Skalkotos
            assert os.path.exists(help_file)
561 7f623b20 Nikos Skalkotos
            d.textbox(help_file, title="Configuration Tasks",
562 9afc4b89 Nikos Skalkotos
                      width=70, height=40)
563 9afc4b89 Nikos Skalkotos
        # No Config button
564 7f623b20 Nikos Skalkotos
        elif code == d.DIALOG_EXTRA:
565 7f623b20 Nikos Skalkotos
            session['excluded_tasks'] = [-1]
566 7f623b20 Nikos Skalkotos
            session['task_metadata'] = ["EXCLUDE_ALL_TASKS"]
567 7f623b20 Nikos Skalkotos
            break
568 7f623b20 Nikos Skalkotos
        elif code == d.DIALOG_OK:
569 7f623b20 Nikos Skalkotos
            session['excluded_tasks'] = []
570 7f623b20 Nikos Skalkotos
            for tag in tags:
571 7f623b20 Nikos Skalkotos
                session['excluded_tasks'].append(mapping[int(tag)])
572 f9d8c3d9 Nikos Skalkotos
573 7f623b20 Nikos Skalkotos
            exclude_metadata = []
574 7f623b20 Nikos Skalkotos
            for task in session['excluded_tasks']:
575 7f623b20 Nikos Skalkotos
                exclude_metadata.extend(CONFIGURATION_TASKS[task][1])
576 f9d8c3d9 Nikos Skalkotos
577 1f42adc8 Nikos Skalkotos
            session['task_metadata'] = map(lambda x: "EXCLUDE_TASK_%s" % x,
578 1f42adc8 Nikos Skalkotos
                                           exclude_metadata)
579 7f623b20 Nikos Skalkotos
            break
580 7f623b20 Nikos Skalkotos
581 1f42adc8 Nikos Skalkotos
    return True
582 1f42adc8 Nikos Skalkotos
583 7f623b20 Nikos Skalkotos
584 7f623b20 Nikos Skalkotos
def sysprep(session):
585 f9d8c3d9 Nikos Skalkotos
    d = session['dialog']
586 7f623b20 Nikos Skalkotos
    image_os = session['image_os']
587 7f623b20 Nikos Skalkotos
588 a42a42b3 Nikos Skalkotos
    # Is the image already shrinked?
589 a42a42b3 Nikos Skalkotos
    if 'shrinked' in session and session['shrinked'] == True:
590 a42a42b3 Nikos Skalkotos
        msg = "It seems you have shrinked the image. Running system " \
591 a42a42b3 Nikos Skalkotos
              "preparation tasks on a shrinked image is dangerous."
592 a42a42b3 Nikos Skalkotos
593 a42a42b3 Nikos Skalkotos
        if d.yesno("%s\n\nDo you really want to continue?" % msg,
594 a42a42b3 Nikos Skalkotos
                   width=YESNO_WIDTH, defaultno=1):
595 a42a42b3 Nikos Skalkotos
            return
596 a42a42b3 Nikos Skalkotos
597 9afc4b89 Nikos Skalkotos
    wrapper = textwrap.TextWrapper(width=65)
598 9afc4b89 Nikos Skalkotos
599 9afc4b89 Nikos Skalkotos
    help_title = "System Preperation Tasks"
600 9afc4b89 Nikos Skalkotos
    sysprep_help = "%s\n%s\n\n" % (help_title, '=' * len(help_title))
601 9afc4b89 Nikos Skalkotos
602 9afc4b89 Nikos Skalkotos
    if 'exec_syspreps' not in session:
603 9afc4b89 Nikos Skalkotos
        session['exec_syspreps'] = []
604 7f623b20 Nikos Skalkotos
605 9afc4b89 Nikos Skalkotos
    all_syspreps = image_os.list_syspreps()
606 9afc4b89 Nikos Skalkotos
    # Only give the user the choice between syspreps that have not ran yet
607 9afc4b89 Nikos Skalkotos
    syspreps = [s for s in all_syspreps if s not in session['exec_syspreps']]
608 f9d8c3d9 Nikos Skalkotos
609 a42a42b3 Nikos Skalkotos
    if len(syspreps) == 0:
610 a42a42b3 Nikos Skalkotos
        d.msgbox("No system preparation task left to run!", width=MSGBOX_WIDTH)
611 a42a42b3 Nikos Skalkotos
        return
612 a42a42b3 Nikos Skalkotos
613 7f623b20 Nikos Skalkotos
    while 1:
614 7f623b20 Nikos Skalkotos
        choices = []
615 7f623b20 Nikos Skalkotos
        index = 0
616 7f623b20 Nikos Skalkotos
        for sysprep in syspreps:
617 7f623b20 Nikos Skalkotos
            name, descr = image_os.sysprep_info(sysprep)
618 7f623b20 Nikos Skalkotos
            display_name = name.replace('-', ' ').capitalize()
619 9afc4b89 Nikos Skalkotos
            sysprep_help += "%s\n" % display_name
620 9afc4b89 Nikos Skalkotos
            sysprep_help += "%s\n" % ('-' * len(display_name))
621 9afc4b89 Nikos Skalkotos
            sysprep_help += "%s\n\n" % wrapper.fill(" ".join(descr.split()))
622 7f623b20 Nikos Skalkotos
            enabled = 1 if sysprep.enabled else 0
623 7f623b20 Nikos Skalkotos
            choices.append((str(index + 1), display_name, enabled))
624 7f623b20 Nikos Skalkotos
            index += 1
625 7f623b20 Nikos Skalkotos
626 7f623b20 Nikos Skalkotos
        (code, tags) = d.checklist(
627 7f623b20 Nikos Skalkotos
            "Please choose which system preperation tasks you would like to "
628 7f623b20 Nikos Skalkotos
            "run on the image. Press <Help> to see details about the system "
629 9afc4b89 Nikos Skalkotos
            "preperation tasks.", title="Run system preperation tasks",
630 9afc4b89 Nikos Skalkotos
            choices=choices, width=70, ok_label="Run", help_button=1)
631 7f623b20 Nikos Skalkotos
632 7f623b20 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
633 1f42adc8 Nikos Skalkotos
            return False
634 9afc4b89 Nikos Skalkotos
        elif code == d.DIALOG_HELP:
635 9afc4b89 Nikos Skalkotos
            d.scrollbox(sysprep_help, width=HELP_WIDTH)
636 9afc4b89 Nikos Skalkotos
        elif code == d.DIALOG_OK:
637 9afc4b89 Nikos Skalkotos
            # Enable selected syspreps and disable the rest
638 9afc4b89 Nikos Skalkotos
            for i in range(len(syspreps)):
639 9afc4b89 Nikos Skalkotos
                if str(i + 1) in tags:
640 9afc4b89 Nikos Skalkotos
                    image_os.enable_sysprep(syspreps[i])
641 9afc4b89 Nikos Skalkotos
                    session['exec_syspreps'].append(syspreps[i])
642 9afc4b89 Nikos Skalkotos
                else:
643 9afc4b89 Nikos Skalkotos
                    image_os.disable_sysprep(syspreps[i])
644 9afc4b89 Nikos Skalkotos
645 9afc4b89 Nikos Skalkotos
            out = InfoBoxOutput(d, "Image Configuration")
646 9afc4b89 Nikos Skalkotos
            try:
647 9afc4b89 Nikos Skalkotos
                dev = session['device']
648 9afc4b89 Nikos Skalkotos
                dev.out = out
649 9afc4b89 Nikos Skalkotos
                dev.mount(readonly=False)
650 9afc4b89 Nikos Skalkotos
                try:
651 9afc4b89 Nikos Skalkotos
                    # The checksum is invalid. We have mounted the image rw
652 9afc4b89 Nikos Skalkotos
                    if 'checksum' in session:
653 9afc4b89 Nikos Skalkotos
                        del session['checksum']
654 9afc4b89 Nikos Skalkotos
655 330fd618 Nikos Skalkotos
                    # Monitor the metadata changes during syspreps
656 330fd618 Nikos Skalkotos
                    with metadata_monitor(session, image_os.meta):
657 330fd618 Nikos Skalkotos
                        image_os.out = out
658 330fd618 Nikos Skalkotos
                        image_os.do_sysprep()
659 330fd618 Nikos Skalkotos
                        image_os.out.finalize()
660 a42a42b3 Nikos Skalkotos
661 9afc4b89 Nikos Skalkotos
                    # Disable syspreps that have ran
662 9afc4b89 Nikos Skalkotos
                    for sysprep in session['exec_syspreps']:
663 9afc4b89 Nikos Skalkotos
                        image_os.disable_sysprep(sysprep)
664 9afc4b89 Nikos Skalkotos
665 9afc4b89 Nikos Skalkotos
                finally:
666 9afc4b89 Nikos Skalkotos
                    dev.umount()
667 9afc4b89 Nikos Skalkotos
            finally:
668 9afc4b89 Nikos Skalkotos
                out.cleanup()
669 9afc4b89 Nikos Skalkotos
            break
670 1f42adc8 Nikos Skalkotos
    return True
671 7f623b20 Nikos Skalkotos
672 7f623b20 Nikos Skalkotos
673 a42a42b3 Nikos Skalkotos
def shrink(session):
674 a42a42b3 Nikos Skalkotos
    d = session['dialog']
675 a42a42b3 Nikos Skalkotos
    dev = session['device']
676 a42a42b3 Nikos Skalkotos
677 a42a42b3 Nikos Skalkotos
    shrinked = 'shrinked' in session and session['shrinked'] == True
678 a42a42b3 Nikos Skalkotos
679 a42a42b3 Nikos Skalkotos
    if shrinked:
680 a42a42b3 Nikos Skalkotos
        d.msgbox("You have already shrinked your image!")
681 1f42adc8 Nikos Skalkotos
        return True
682 a42a42b3 Nikos Skalkotos
683 a42a42b3 Nikos Skalkotos
    msg = "This operation will shrink the last partition of the image to " \
684 a42a42b3 Nikos Skalkotos
          "reduce the total image size. If the last partition is a swap " \
685 a42a42b3 Nikos Skalkotos
          "partition, then this partition is removed and the partition " \
686 a42a42b3 Nikos Skalkotos
          "before that is shrinked. The removed swap partition will be " \
687 a42a42b3 Nikos Skalkotos
          "recreated during image deployment."
688 a42a42b3 Nikos Skalkotos
689 a42a42b3 Nikos Skalkotos
    if not d.yesno("%s\n\nDo you want to continue?" % msg, width=70,
690 a42a42b3 Nikos Skalkotos
                   height=12, title="Image Shrinking"):
691 330fd618 Nikos Skalkotos
        with metadata_monitor(session, dev.meta):
692 ea947a64 Nikos Skalkotos
            dev.out = InfoBoxOutput(d, "Image Shrinking", height=4)
693 330fd618 Nikos Skalkotos
            dev.shrink()
694 330fd618 Nikos Skalkotos
            dev.out.finalize()
695 330fd618 Nikos Skalkotos
696 a42a42b3 Nikos Skalkotos
        session['shrinked'] = True
697 a42a42b3 Nikos Skalkotos
        update_background_title(session)
698 1f42adc8 Nikos Skalkotos
    else:
699 1f42adc8 Nikos Skalkotos
        return False
700 1f42adc8 Nikos Skalkotos
701 1f42adc8 Nikos Skalkotos
    return True
702 a42a42b3 Nikos Skalkotos
703 a42a42b3 Nikos Skalkotos
704 a42a42b3 Nikos Skalkotos
def customization_menu(session):
705 7f623b20 Nikos Skalkotos
    d = session['dialog']
706 7f623b20 Nikos Skalkotos
707 9afc4b89 Nikos Skalkotos
    choices = [("Sysprep", "Run various image preperation tasks"),
708 9afc4b89 Nikos Skalkotos
               ("Shrink", "Shrink image"),
709 9afc4b89 Nikos Skalkotos
               ("View/Modify", "View/Modify image properties"),
710 9afc4b89 Nikos Skalkotos
               ("Delete", "Delete image properties"),
711 9afc4b89 Nikos Skalkotos
               ("Exclude", "Exclude various deployment tasks from running")]
712 9afc4b89 Nikos Skalkotos
713 1f42adc8 Nikos Skalkotos
    default_item = 0
714 9afc4b89 Nikos Skalkotos
715 7f623b20 Nikos Skalkotos
    actions = {"Sysprep": sysprep,
716 a42a42b3 Nikos Skalkotos
               "Shrink": shrink,
717 7f623b20 Nikos Skalkotos
               "View/Modify": modify_properties,
718 7f623b20 Nikos Skalkotos
               "Delete": delete_properties,
719 7f623b20 Nikos Skalkotos
               "Exclude": exclude_tasks}
720 f9d8c3d9 Nikos Skalkotos
    while 1:
721 f9d8c3d9 Nikos Skalkotos
        (code, choice) = d.menu(
722 9afc4b89 Nikos Skalkotos
            text="Choose one of the following or press <Back> to exit.",
723 9afc4b89 Nikos Skalkotos
            width=MENU_WIDTH, choices=choices, cancel="Back", height=13,
724 1f42adc8 Nikos Skalkotos
            menu_height=len(choices), default_item=choices[default_item][0],
725 7f623b20 Nikos Skalkotos
            title="Image Customization Menu")
726 f9d8c3d9 Nikos Skalkotos
727 f9d8c3d9 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
728 f9d8c3d9 Nikos Skalkotos
            break
729 f9d8c3d9 Nikos Skalkotos
        elif choice in actions:
730 1f42adc8 Nikos Skalkotos
            default_item = [entry[0] for entry in choices].index(choice)
731 1f42adc8 Nikos Skalkotos
            if actions[choice](session):
732 1f42adc8 Nikos Skalkotos
                default_item = (default_item + 1) % len(choices)
733 f9d8c3d9 Nikos Skalkotos
734 f9d8c3d9 Nikos Skalkotos
735 672cabb9 Nikos Skalkotos
def main_menu(session):
736 672cabb9 Nikos Skalkotos
    d = session['dialog']
737 672cabb9 Nikos Skalkotos
    dev = session['device']
738 9afc4b89 Nikos Skalkotos
739 9afc4b89 Nikos Skalkotos
    update_background_title(session)
740 9afc4b89 Nikos Skalkotos
741 9afc4b89 Nikos Skalkotos
    choices = [("Customize", "Customize image & ~okeanos deployment options"),
742 9afc4b89 Nikos Skalkotos
               ("Register", "Register image to ~okeanos"),
743 9afc4b89 Nikos Skalkotos
               ("Extract", "Dump image to local file system"),
744 9afc4b89 Nikos Skalkotos
               ("Reset", "Reset everything and start over again"),
745 9afc4b89 Nikos Skalkotos
               ("Help", "Get help for using snf-image-creator")]
746 9afc4b89 Nikos Skalkotos
747 672cabb9 Nikos Skalkotos
    default_item = "Customize"
748 672cabb9 Nikos Skalkotos
749 a42a42b3 Nikos Skalkotos
    actions = {"Customize": customization_menu, "Register": kamaki_menu,
750 9afc4b89 Nikos Skalkotos
               "Extract": extract_image}
751 672cabb9 Nikos Skalkotos
    while 1:
752 672cabb9 Nikos Skalkotos
        (code, choice) = d.menu(
753 9afc4b89 Nikos Skalkotos
            text="Choose one of the following or press <Exit> to exit.",
754 9afc4b89 Nikos Skalkotos
            width=MENU_WIDTH, choices=choices, cancel="Exit", height=13,
755 9afc4b89 Nikos Skalkotos
            default_item=default_item, menu_height=len(choices),
756 672cabb9 Nikos Skalkotos
            title="Image Creator for ~okeanos (snf-image-creator version %s)" %
757 672cabb9 Nikos Skalkotos
                  version)
758 672cabb9 Nikos Skalkotos
759 672cabb9 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
760 672cabb9 Nikos Skalkotos
            if confirm_exit(d):
761 672cabb9 Nikos Skalkotos
                break
762 7f623b20 Nikos Skalkotos
        elif choice == "Reset":
763 672cabb9 Nikos Skalkotos
            if confirm_reset(d):
764 a42a42b3 Nikos Skalkotos
                d.infobox("Resetting snf-image-creator. Please wait...",
765 a42a42b3 Nikos Skalkotos
                          width=INFOBOX_WIDTH)
766 672cabb9 Nikos Skalkotos
                raise Reset
767 672cabb9 Nikos Skalkotos
        elif choice in actions:
768 672cabb9 Nikos Skalkotos
            actions[choice](session)
769 672cabb9 Nikos Skalkotos
770 672cabb9 Nikos Skalkotos
771 f9d8c3d9 Nikos Skalkotos
def select_file(d, media):
772 672cabb9 Nikos Skalkotos
    root = os.sep
773 672cabb9 Nikos Skalkotos
    while 1:
774 f9d8c3d9 Nikos Skalkotos
        if media is not None:
775 f9d8c3d9 Nikos Skalkotos
            if not os.path.exists(media):
776 f9d8c3d9 Nikos Skalkotos
                d.msgbox("The file you choose does not exist",
777 f9d8c3d9 Nikos Skalkotos
                         width=MSGBOX_WIDTH)
778 f9d8c3d9 Nikos Skalkotos
            else:
779 f9d8c3d9 Nikos Skalkotos
                break
780 f9d8c3d9 Nikos Skalkotos
781 f9d8c3d9 Nikos Skalkotos
        (code, media) = d.fselect(root, 10, 50,
782 1f42adc8 Nikos Skalkotos
                                  title="Please select input media")
783 672cabb9 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
784 672cabb9 Nikos Skalkotos
            if confirm_exit(d, "You canceled the media selection dialog box."):
785 672cabb9 Nikos Skalkotos
                sys.exit(0)
786 672cabb9 Nikos Skalkotos
            else:
787 f9d8c3d9 Nikos Skalkotos
                media = None
788 672cabb9 Nikos Skalkotos
                continue
789 672cabb9 Nikos Skalkotos
790 f9d8c3d9 Nikos Skalkotos
    return media
791 672cabb9 Nikos Skalkotos
792 672cabb9 Nikos Skalkotos
793 672cabb9 Nikos Skalkotos
def image_creator(d):
794 672cabb9 Nikos Skalkotos
    basename = os.path.basename(sys.argv[0])
795 672cabb9 Nikos Skalkotos
    usage = "Usage: %s [input_media]" % basename
796 672cabb9 Nikos Skalkotos
    if len(sys.argv) > 2:
797 672cabb9 Nikos Skalkotos
        sys.stderr.write("%s\n" % usage)
798 672cabb9 Nikos Skalkotos
        return 1
799 672cabb9 Nikos Skalkotos
800 a42a42b3 Nikos Skalkotos
    d.setBackgroundTitle('snf-image-creator')
801 a42a42b3 Nikos Skalkotos
802 672cabb9 Nikos Skalkotos
    if os.geteuid() != 0:
803 672cabb9 Nikos Skalkotos
        raise FatalError("You must run %s as root" % basename)
804 672cabb9 Nikos Skalkotos
805 f9d8c3d9 Nikos Skalkotos
    media = select_file(d, sys.argv[1] if len(sys.argv) == 2 else None)
806 672cabb9 Nikos Skalkotos
807 9afc4b89 Nikos Skalkotos
    out = GaugeOutput(d, "Initialization", "Initializing...")
808 672cabb9 Nikos Skalkotos
    disk = Disk(media, out)
809 672cabb9 Nikos Skalkotos
810 9afc4b89 Nikos Skalkotos
    def signal_handler(signum, frame):
811 672cabb9 Nikos Skalkotos
        out.cleanup()
812 672cabb9 Nikos Skalkotos
        disk.cleanup()
813 672cabb9 Nikos Skalkotos
814 672cabb9 Nikos Skalkotos
    signal.signal(signal.SIGINT, signal_handler)
815 672cabb9 Nikos Skalkotos
    try:
816 672cabb9 Nikos Skalkotos
        snapshot = disk.snapshot()
817 672cabb9 Nikos Skalkotos
        dev = disk.get_device(snapshot)
818 672cabb9 Nikos Skalkotos
819 a42a42b3 Nikos Skalkotos
820 a42a42b3 Nikos Skalkotos
        metadata = {}
821 a42a42b3 Nikos Skalkotos
        for (key, value) in dev.meta.items():
822 a42a42b3 Nikos Skalkotos
            metadata[str(key)] = str(value)
823 a42a42b3 Nikos Skalkotos
824 7f623b20 Nikos Skalkotos
        dev.mount(readonly=True)
825 ea947a64 Nikos Skalkotos
        out.output("Collecting image metadata...")
826 7f623b20 Nikos Skalkotos
        cls = os_cls(dev.distro, dev.ostype)
827 7f623b20 Nikos Skalkotos
        image_os = cls(dev.root, dev.g, out)
828 7f623b20 Nikos Skalkotos
        dev.umount()
829 a42a42b3 Nikos Skalkotos
830 a42a42b3 Nikos Skalkotos
        for (key, value) in image_os.meta.items():
831 a42a42b3 Nikos Skalkotos
            metadata[str(key)] = str(value)
832 a42a42b3 Nikos Skalkotos
833 7f623b20 Nikos Skalkotos
        out.success("done")
834 672cabb9 Nikos Skalkotos
        out.cleanup()
835 672cabb9 Nikos Skalkotos
836 672cabb9 Nikos Skalkotos
        # Make sure the signal handler does not call out.cleanup again
837 672cabb9 Nikos Skalkotos
        def dummy(self):
838 672cabb9 Nikos Skalkotos
            pass
839 9afc4b89 Nikos Skalkotos
        out.cleanup = type(GaugeOutput.cleanup)(dummy, out, GaugeOutput)
840 672cabb9 Nikos Skalkotos
841 672cabb9 Nikos Skalkotos
        session = {"dialog": d,
842 672cabb9 Nikos Skalkotos
                   "disk": disk,
843 2a21ff92 Nikos Skalkotos
                   "snapshot": snapshot,
844 672cabb9 Nikos Skalkotos
                   "device": dev,
845 7f623b20 Nikos Skalkotos
                   "image_os": image_os,
846 672cabb9 Nikos Skalkotos
                   "metadata": metadata}
847 672cabb9 Nikos Skalkotos
848 672cabb9 Nikos Skalkotos
        main_menu(session)
849 672cabb9 Nikos Skalkotos
        d.infobox("Thank you for using snf-image-creator. Bye", width=53)
850 672cabb9 Nikos Skalkotos
    finally:
851 672cabb9 Nikos Skalkotos
        disk.cleanup()
852 672cabb9 Nikos Skalkotos
853 672cabb9 Nikos Skalkotos
    return 0
854 672cabb9 Nikos Skalkotos
855 672cabb9 Nikos Skalkotos
856 672cabb9 Nikos Skalkotos
def main():
857 672cabb9 Nikos Skalkotos
858 672cabb9 Nikos Skalkotos
    d = dialog.Dialog(dialog="dialog")
859 672cabb9 Nikos Skalkotos
860 f9d8c3d9 Nikos Skalkotos
    # Add extra button in dialog library
861 f9d8c3d9 Nikos Skalkotos
    dialog._common_args_syntax["extra_button"] = \
862 f9d8c3d9 Nikos Skalkotos
        lambda enable: dialog._simple_option("--extra-button", enable)
863 f9d8c3d9 Nikos Skalkotos
864 f9d8c3d9 Nikos Skalkotos
    dialog._common_args_syntax["extra_label"] = \
865 f9d8c3d9 Nikos Skalkotos
        lambda string: ("--extra-label", string)
866 f9d8c3d9 Nikos Skalkotos
867 672cabb9 Nikos Skalkotos
    while 1:
868 672cabb9 Nikos Skalkotos
        try:
869 672cabb9 Nikos Skalkotos
            try:
870 672cabb9 Nikos Skalkotos
                ret = image_creator(d)
871 672cabb9 Nikos Skalkotos
                sys.exit(ret)
872 672cabb9 Nikos Skalkotos
            except FatalError as e:
873 672cabb9 Nikos Skalkotos
                msg = textwrap.fill(str(e), width=70)
874 a42a42b3 Nikos Skalkotos
                d.infobox(msg, width=INFOBOX_WIDTH, title="Fatal Error")
875 672cabb9 Nikos Skalkotos
                sys.exit(1)
876 672cabb9 Nikos Skalkotos
        except Reset:
877 672cabb9 Nikos Skalkotos
            continue
878 672cabb9 Nikos Skalkotos
879 672cabb9 Nikos Skalkotos
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :