Statistics
| Branch: | Tag: | Revision:

root / image_creator / dialog_main.py @ fbdf1d8f

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