Statistics
| Branch: | Tag: | Revision:

root / image_creator / dialog_main.py @ 5a0399d8

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