Statistics
| Branch: | Tag: | Revision:

root / image_creator / dialog_main.py @ 09ed3d46

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 cf4f52b6 Nikos Skalkotos
    (session['account'], session['token']) = Kamaki.saved_credentials()
370 672cabb9 Nikos Skalkotos
    while 1:
371 672cabb9 Nikos Skalkotos
        account = session["account"] if "account" in session else "<none>"
372 672cabb9 Nikos Skalkotos
        token = session["token"] if "token" in session else "<none>"
373 672cabb9 Nikos Skalkotos
        upload = session["upload"] if "upload" in session else "<none>"
374 9afc4b89 Nikos Skalkotos
375 9afc4b89 Nikos Skalkotos
        choices = [("Account", "Change your ~okeanos username: %s" % account),
376 9afc4b89 Nikos Skalkotos
                   ("Token", "Change your ~okeanos token: %s" % token),
377 9afc4b89 Nikos Skalkotos
                   ("Upload", "Upload image to pithos+"),
378 09743d3a Nikos Skalkotos
                   ("Register", "Register the image to cyclades: %s" % upload)]
379 9afc4b89 Nikos Skalkotos
380 672cabb9 Nikos Skalkotos
        (code, choice) = d.menu(
381 9afc4b89 Nikos Skalkotos
            text="Choose one of the following or press <Back> to go back.",
382 835171dc Nikos Skalkotos
            width=MENU_WIDTH, choices=choices, cancel="Back", height=13,
383 835171dc Nikos Skalkotos
            menu_height=5, default_item=default_item,
384 835171dc Nikos Skalkotos
            title="Image Registration Menu")
385 672cabb9 Nikos Skalkotos
386 672cabb9 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
387 672cabb9 Nikos Skalkotos
            return False
388 672cabb9 Nikos Skalkotos
389 672cabb9 Nikos Skalkotos
        if choice == "Account":
390 672cabb9 Nikos Skalkotos
            default_item = "Account"
391 672cabb9 Nikos Skalkotos
            (code, answer) = d.inputbox(
392 672cabb9 Nikos Skalkotos
                "Please provide your ~okeanos account e-mail address:",
393 672cabb9 Nikos Skalkotos
                init=session["account"] if "account" in session else '',
394 672cabb9 Nikos Skalkotos
                width=70)
395 672cabb9 Nikos Skalkotos
            if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
396 672cabb9 Nikos Skalkotos
                continue
397 672cabb9 Nikos Skalkotos
            if len(answer) == 0 and "account" in session:
398 672cabb9 Nikos Skalkotos
                    del session["account"]
399 672cabb9 Nikos Skalkotos
            else:
400 672cabb9 Nikos Skalkotos
                session["account"] = answer.strip()
401 cf4f52b6 Nikos Skalkotos
                Kamaki.save_account(session['account'])
402 672cabb9 Nikos Skalkotos
                default_item = "Token"
403 672cabb9 Nikos Skalkotos
        elif choice == "Token":
404 672cabb9 Nikos Skalkotos
            default_item = "Token"
405 672cabb9 Nikos Skalkotos
            (code, answer) = d.inputbox(
406 672cabb9 Nikos Skalkotos
                "Please provide your ~okeanos account authetication token:",
407 672cabb9 Nikos Skalkotos
                init=session["token"] if "token" in session else '',
408 672cabb9 Nikos Skalkotos
                width=70)
409 672cabb9 Nikos Skalkotos
            if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
410 672cabb9 Nikos Skalkotos
                continue
411 672cabb9 Nikos Skalkotos
            if len(answer) == 0 and "token" in session:
412 672cabb9 Nikos Skalkotos
                del session["token"]
413 672cabb9 Nikos Skalkotos
            else:
414 672cabb9 Nikos Skalkotos
                session["token"] = answer.strip()
415 cf4f52b6 Nikos Skalkotos
                Kamaki.save_token(session['account'])
416 672cabb9 Nikos Skalkotos
                default_item = "Upload"
417 672cabb9 Nikos Skalkotos
        elif choice == "Upload":
418 672cabb9 Nikos Skalkotos
            if upload_image(session):
419 672cabb9 Nikos Skalkotos
                default_item = "Register"
420 672cabb9 Nikos Skalkotos
            else:
421 672cabb9 Nikos Skalkotos
                default_item = "Upload"
422 672cabb9 Nikos Skalkotos
        elif choice == "Register":
423 672cabb9 Nikos Skalkotos
            if register_image(session):
424 672cabb9 Nikos Skalkotos
                return True
425 672cabb9 Nikos Skalkotos
            else:
426 672cabb9 Nikos Skalkotos
                default_item = "Register"
427 672cabb9 Nikos Skalkotos
428 672cabb9 Nikos Skalkotos
429 f9d8c3d9 Nikos Skalkotos
def add_property(session):
430 f9d8c3d9 Nikos Skalkotos
    d = session['dialog']
431 f9d8c3d9 Nikos Skalkotos
432 f9d8c3d9 Nikos Skalkotos
    while 1:
433 f9d8c3d9 Nikos Skalkotos
        (code, answer) = d.inputbox("Please provide a name for a new image"
434 f9d8c3d9 Nikos Skalkotos
                                    " property:", width=INPUTBOX_WIDTH)
435 f9d8c3d9 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
436 f9d8c3d9 Nikos Skalkotos
            return False
437 f9d8c3d9 Nikos Skalkotos
438 f9d8c3d9 Nikos Skalkotos
        name = answer.strip()
439 f9d8c3d9 Nikos Skalkotos
        if len(name) == 0:
440 f9d8c3d9 Nikos Skalkotos
            d.msgbox("A property name cannot be empty", width=MSGBOX_WIDTH)
441 f9d8c3d9 Nikos Skalkotos
            continue
442 f9d8c3d9 Nikos Skalkotos
443 f9d8c3d9 Nikos Skalkotos
        break
444 f9d8c3d9 Nikos Skalkotos
445 f9d8c3d9 Nikos Skalkotos
    while 1:
446 f9d8c3d9 Nikos Skalkotos
        (code, answer) = d.inputbox("Please provide a value for image "
447 1f42adc8 Nikos Skalkotos
                                    "property %s" % name, width=INPUTBOX_WIDTH)
448 f9d8c3d9 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
449 f9d8c3d9 Nikos Skalkotos
            return False
450 f9d8c3d9 Nikos Skalkotos
451 f9d8c3d9 Nikos Skalkotos
        value = answer.strip()
452 f9d8c3d9 Nikos Skalkotos
        if len(value) == 0:
453 f9d8c3d9 Nikos Skalkotos
            d.msgbox("Value cannot be empty", width=MSGBOX_WIDTH)
454 f9d8c3d9 Nikos Skalkotos
            continue
455 f9d8c3d9 Nikos Skalkotos
456 f9d8c3d9 Nikos Skalkotos
        break
457 f9d8c3d9 Nikos Skalkotos
458 f9d8c3d9 Nikos Skalkotos
    session['metadata'][name] = value
459 f9d8c3d9 Nikos Skalkotos
460 f9d8c3d9 Nikos Skalkotos
    return True
461 f9d8c3d9 Nikos Skalkotos
462 f9d8c3d9 Nikos Skalkotos
463 f9d8c3d9 Nikos Skalkotos
def modify_properties(session):
464 f9d8c3d9 Nikos Skalkotos
    d = session['dialog']
465 f9d8c3d9 Nikos Skalkotos
466 f9d8c3d9 Nikos Skalkotos
    while 1:
467 f9d8c3d9 Nikos Skalkotos
        choices = []
468 f9d8c3d9 Nikos Skalkotos
        for (key, val) in session['metadata'].items():
469 f9d8c3d9 Nikos Skalkotos
            choices.append((str(key), str(val)))
470 f9d8c3d9 Nikos Skalkotos
471 f9d8c3d9 Nikos Skalkotos
        (code, choice) = d.menu(
472 f9d8c3d9 Nikos Skalkotos
            "In this menu you can edit existing image properties or add new "
473 a42a42b3 Nikos Skalkotos
            "ones. Be careful! Most properties have special meaning and "
474 f9d8c3d9 Nikos Skalkotos
            "alter the image deployment behaviour. Press <HELP> to see more "
475 f9d8c3d9 Nikos Skalkotos
            "information about image properties. Press <BACK> when done.",
476 9afc4b89 Nikos Skalkotos
            height=18, width=MENU_WIDTH, choices=choices, menu_height=10,
477 9afc4b89 Nikos Skalkotos
            ok_label="Edit", extra_button=1, extra_label="Add", cancel="Back",
478 74585c56 Nikos Skalkotos
            help_button=1, title="Image Properties")
479 f9d8c3d9 Nikos Skalkotos
480 f9d8c3d9 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
481 1f42adc8 Nikos Skalkotos
            return True
482 f9d8c3d9 Nikos Skalkotos
        # Edit button
483 f9d8c3d9 Nikos Skalkotos
        elif code == d.DIALOG_OK:
484 1f42adc8 Nikos Skalkotos
            (code, answer) = d.inputbox("Please provide a new value for the "
485 1f42adc8 Nikos Skalkotos
                                        "image property with name `%s':" %
486 1f42adc8 Nikos Skalkotos
                                        choice,
487 1f42adc8 Nikos Skalkotos
                                        init=session['metadata'][choice],
488 1f42adc8 Nikos Skalkotos
                                        width=INPUTBOX_WIDTH)
489 f9d8c3d9 Nikos Skalkotos
            if code not in (d.DIALOG_CANCEL, d.DIALOG_ESC):
490 f9d8c3d9 Nikos Skalkotos
                value = answer.strip()
491 f9d8c3d9 Nikos Skalkotos
                if len(value) == 0:
492 f9d8c3d9 Nikos Skalkotos
                    d.msgbox("Value cannot be empty!")
493 f9d8c3d9 Nikos Skalkotos
                    continue
494 f9d8c3d9 Nikos Skalkotos
                else:
495 f9d8c3d9 Nikos Skalkotos
                    session['metadata'][choice] = value
496 f9d8c3d9 Nikos Skalkotos
        # ADD button
497 f9d8c3d9 Nikos Skalkotos
        elif code == d.DIALOG_EXTRA:
498 f9d8c3d9 Nikos Skalkotos
            add_property(session)
499 09743d3a Nikos Skalkotos
        elif code == 'help':
500 09743d3a Nikos Skalkotos
            help_file = get_help_file("image_properties")
501 09743d3a Nikos Skalkotos
            assert os.path.exists(help_file)
502 09743d3a Nikos Skalkotos
            d.textbox(help_file, title="Image Properties", width=70, height=40)
503 f9d8c3d9 Nikos Skalkotos
504 f9d8c3d9 Nikos Skalkotos
505 f9d8c3d9 Nikos Skalkotos
def delete_properties(session):
506 f9d8c3d9 Nikos Skalkotos
    d = session['dialog']
507 f9d8c3d9 Nikos Skalkotos
508 f9d8c3d9 Nikos Skalkotos
    choices = []
509 f9d8c3d9 Nikos Skalkotos
    for (key, val) in session['metadata'].items():
510 f9d8c3d9 Nikos Skalkotos
        choices.append((key, "%s" % val, 0))
511 f9d8c3d9 Nikos Skalkotos
512 f9d8c3d9 Nikos Skalkotos
    (code, to_delete) = d.checklist("Choose which properties to delete:",
513 7f623b20 Nikos Skalkotos
                                    choices=choices, width=CHECKBOX_WIDTH)
514 9afc4b89 Nikos Skalkotos
515 f9d8c3d9 Nikos Skalkotos
    # If the user exits with ESC or CANCEL, the returned tag list is empty.
516 f9d8c3d9 Nikos Skalkotos
    for i in to_delete:
517 f9d8c3d9 Nikos Skalkotos
        del session['metadata'][i]
518 f9d8c3d9 Nikos Skalkotos
519 9afc4b89 Nikos Skalkotos
    cnt = len(to_delete)
520 9afc4b89 Nikos Skalkotos
    if cnt > 0:
521 9afc4b89 Nikos Skalkotos
        d.msgbox("%d image properties were deleted." % cnt, width=MSGBOX_WIDTH)
522 1f42adc8 Nikos Skalkotos
        return True
523 1f42adc8 Nikos Skalkotos
    else:
524 1f42adc8 Nikos Skalkotos
        return False
525 f9d8c3d9 Nikos Skalkotos
526 f9d8c3d9 Nikos Skalkotos
527 7f623b20 Nikos Skalkotos
def exclude_tasks(session):
528 f9d8c3d9 Nikos Skalkotos
    d = session['dialog']
529 f9d8c3d9 Nikos Skalkotos
530 7f623b20 Nikos Skalkotos
    index = 0
531 7f623b20 Nikos Skalkotos
    displayed_index = 1
532 f9d8c3d9 Nikos Skalkotos
    choices = []
533 7f623b20 Nikos Skalkotos
    mapping = {}
534 7f623b20 Nikos Skalkotos
    if 'excluded_tasks' not in session:
535 7f623b20 Nikos Skalkotos
        session['excluded_tasks'] = []
536 7f623b20 Nikos Skalkotos
537 7f623b20 Nikos Skalkotos
    if -1 in session['excluded_tasks']:
538 7f623b20 Nikos Skalkotos
        if not d.yesno("Image deployment configuration is disabled. "
539 7f623b20 Nikos Skalkotos
                       "Do you wish to enable it?", width=YESNO_WIDTH):
540 7f623b20 Nikos Skalkotos
            session['excluded_tasks'].remove(-1)
541 7f623b20 Nikos Skalkotos
        else:
542 1f42adc8 Nikos Skalkotos
            return False
543 7f623b20 Nikos Skalkotos
544 7f623b20 Nikos Skalkotos
    for (msg, task, osfamily) in CONFIGURATION_TASKS:
545 7f623b20 Nikos Skalkotos
        if session['metadata']['OSFAMILY'] in osfamily:
546 7f623b20 Nikos Skalkotos
            checked = 1 if index in session['excluded_tasks'] else 0
547 7f623b20 Nikos Skalkotos
            choices.append((str(displayed_index), msg, checked))
548 7f623b20 Nikos Skalkotos
            mapping[displayed_index] = index
549 7f623b20 Nikos Skalkotos
            displayed_index += 1
550 7f623b20 Nikos Skalkotos
        index += 1
551 f9d8c3d9 Nikos Skalkotos
552 7f623b20 Nikos Skalkotos
    while 1:
553 7f623b20 Nikos Skalkotos
        (code, tags) = d.checklist(
554 9afc4b89 Nikos Skalkotos
            text="Please choose which configuration tasks you would like to "
555 9afc4b89 Nikos Skalkotos
                 "prevent from running during image deployment. "
556 9afc4b89 Nikos Skalkotos
                 "Press <No Config> to supress any configuration. "
557 9afc4b89 Nikos Skalkotos
                 "Press <Help> for more help on the image deployment "
558 9afc4b89 Nikos Skalkotos
                 "configuration tasks.",
559 9afc4b89 Nikos Skalkotos
            choices=choices, height=19, list_height=8, width=CHECKBOX_WIDTH,
560 9afc4b89 Nikos Skalkotos
            help_button=1, extra_button=1, extra_label="No Config",
561 9afc4b89 Nikos Skalkotos
            title="Exclude Configuration Tasks")
562 f9d8c3d9 Nikos Skalkotos
563 7f623b20 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
564 1f42adc8 Nikos Skalkotos
            return False
565 7f623b20 Nikos Skalkotos
        elif code == d.DIALOG_HELP:
566 7f623b20 Nikos Skalkotos
            help_file = get_help_file("configuration_tasks")
567 7f623b20 Nikos Skalkotos
            assert os.path.exists(help_file)
568 7f623b20 Nikos Skalkotos
            d.textbox(help_file, title="Configuration Tasks",
569 9afc4b89 Nikos Skalkotos
                      width=70, height=40)
570 9afc4b89 Nikos Skalkotos
        # No Config button
571 7f623b20 Nikos Skalkotos
        elif code == d.DIALOG_EXTRA:
572 7f623b20 Nikos Skalkotos
            session['excluded_tasks'] = [-1]
573 7f623b20 Nikos Skalkotos
            session['task_metadata'] = ["EXCLUDE_ALL_TASKS"]
574 7f623b20 Nikos Skalkotos
            break
575 7f623b20 Nikos Skalkotos
        elif code == d.DIALOG_OK:
576 7f623b20 Nikos Skalkotos
            session['excluded_tasks'] = []
577 7f623b20 Nikos Skalkotos
            for tag in tags:
578 7f623b20 Nikos Skalkotos
                session['excluded_tasks'].append(mapping[int(tag)])
579 f9d8c3d9 Nikos Skalkotos
580 7f623b20 Nikos Skalkotos
            exclude_metadata = []
581 7f623b20 Nikos Skalkotos
            for task in session['excluded_tasks']:
582 7f623b20 Nikos Skalkotos
                exclude_metadata.extend(CONFIGURATION_TASKS[task][1])
583 f9d8c3d9 Nikos Skalkotos
584 1f42adc8 Nikos Skalkotos
            session['task_metadata'] = map(lambda x: "EXCLUDE_TASK_%s" % x,
585 1f42adc8 Nikos Skalkotos
                                           exclude_metadata)
586 7f623b20 Nikos Skalkotos
            break
587 7f623b20 Nikos Skalkotos
588 1f42adc8 Nikos Skalkotos
    return True
589 1f42adc8 Nikos Skalkotos
590 7f623b20 Nikos Skalkotos
591 7f623b20 Nikos Skalkotos
def sysprep(session):
592 f9d8c3d9 Nikos Skalkotos
    d = session['dialog']
593 7f623b20 Nikos Skalkotos
    image_os = session['image_os']
594 7f623b20 Nikos Skalkotos
595 a42a42b3 Nikos Skalkotos
    # Is the image already shrinked?
596 f99fe99d Nikos Skalkotos
    if 'shrinked' in session and session['shrinked']:
597 a42a42b3 Nikos Skalkotos
        msg = "It seems you have shrinked the image. Running system " \
598 a42a42b3 Nikos Skalkotos
              "preparation tasks on a shrinked image is dangerous."
599 a42a42b3 Nikos Skalkotos
600 a42a42b3 Nikos Skalkotos
        if d.yesno("%s\n\nDo you really want to continue?" % msg,
601 a42a42b3 Nikos Skalkotos
                   width=YESNO_WIDTH, defaultno=1):
602 a42a42b3 Nikos Skalkotos
            return
603 a42a42b3 Nikos Skalkotos
604 9afc4b89 Nikos Skalkotos
    wrapper = textwrap.TextWrapper(width=65)
605 9afc4b89 Nikos Skalkotos
606 9afc4b89 Nikos Skalkotos
    help_title = "System Preperation Tasks"
607 9afc4b89 Nikos Skalkotos
    sysprep_help = "%s\n%s\n\n" % (help_title, '=' * len(help_title))
608 9afc4b89 Nikos Skalkotos
609 9afc4b89 Nikos Skalkotos
    if 'exec_syspreps' not in session:
610 9afc4b89 Nikos Skalkotos
        session['exec_syspreps'] = []
611 7f623b20 Nikos Skalkotos
612 9afc4b89 Nikos Skalkotos
    all_syspreps = image_os.list_syspreps()
613 9afc4b89 Nikos Skalkotos
    # Only give the user the choice between syspreps that have not ran yet
614 9afc4b89 Nikos Skalkotos
    syspreps = [s for s in all_syspreps if s not in session['exec_syspreps']]
615 f9d8c3d9 Nikos Skalkotos
616 a42a42b3 Nikos Skalkotos
    if len(syspreps) == 0:
617 5a0399d8 Nikos Skalkotos
        d.msgbox("No system preparation task available to run!",
618 5a0399d8 Nikos Skalkotos
                 title="System Preperation", width=MSGBOX_WIDTH)
619 a42a42b3 Nikos Skalkotos
        return
620 a42a42b3 Nikos Skalkotos
621 7f623b20 Nikos Skalkotos
    while 1:
622 7f623b20 Nikos Skalkotos
        choices = []
623 7f623b20 Nikos Skalkotos
        index = 0
624 7f623b20 Nikos Skalkotos
        for sysprep in syspreps:
625 7f623b20 Nikos Skalkotos
            name, descr = image_os.sysprep_info(sysprep)
626 7f623b20 Nikos Skalkotos
            display_name = name.replace('-', ' ').capitalize()
627 9afc4b89 Nikos Skalkotos
            sysprep_help += "%s\n" % display_name
628 9afc4b89 Nikos Skalkotos
            sysprep_help += "%s\n" % ('-' * len(display_name))
629 9afc4b89 Nikos Skalkotos
            sysprep_help += "%s\n\n" % wrapper.fill(" ".join(descr.split()))
630 7f623b20 Nikos Skalkotos
            enabled = 1 if sysprep.enabled else 0
631 7f623b20 Nikos Skalkotos
            choices.append((str(index + 1), display_name, enabled))
632 7f623b20 Nikos Skalkotos
            index += 1
633 7f623b20 Nikos Skalkotos
634 7f623b20 Nikos Skalkotos
        (code, tags) = d.checklist(
635 7f623b20 Nikos Skalkotos
            "Please choose which system preperation tasks you would like to "
636 7f623b20 Nikos Skalkotos
            "run on the image. Press <Help> to see details about the system "
637 9afc4b89 Nikos Skalkotos
            "preperation tasks.", title="Run system preperation tasks",
638 9afc4b89 Nikos Skalkotos
            choices=choices, width=70, ok_label="Run", help_button=1)
639 7f623b20 Nikos Skalkotos
640 7f623b20 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
641 1f42adc8 Nikos Skalkotos
            return False
642 9afc4b89 Nikos Skalkotos
        elif code == d.DIALOG_HELP:
643 9afc4b89 Nikos Skalkotos
            d.scrollbox(sysprep_help, width=HELP_WIDTH)
644 9afc4b89 Nikos Skalkotos
        elif code == d.DIALOG_OK:
645 9afc4b89 Nikos Skalkotos
            # Enable selected syspreps and disable the rest
646 9afc4b89 Nikos Skalkotos
            for i in range(len(syspreps)):
647 9afc4b89 Nikos Skalkotos
                if str(i + 1) in tags:
648 9afc4b89 Nikos Skalkotos
                    image_os.enable_sysprep(syspreps[i])
649 9afc4b89 Nikos Skalkotos
                    session['exec_syspreps'].append(syspreps[i])
650 9afc4b89 Nikos Skalkotos
                else:
651 9afc4b89 Nikos Skalkotos
                    image_os.disable_sysprep(syspreps[i])
652 9afc4b89 Nikos Skalkotos
653 9afc4b89 Nikos Skalkotos
            out = InfoBoxOutput(d, "Image Configuration")
654 9afc4b89 Nikos Skalkotos
            try:
655 9afc4b89 Nikos Skalkotos
                dev = session['device']
656 9afc4b89 Nikos Skalkotos
                dev.out = out
657 9afc4b89 Nikos Skalkotos
                dev.mount(readonly=False)
658 9afc4b89 Nikos Skalkotos
                try:
659 9afc4b89 Nikos Skalkotos
                    # The checksum is invalid. We have mounted the image rw
660 9afc4b89 Nikos Skalkotos
                    if 'checksum' in session:
661 9afc4b89 Nikos Skalkotos
                        del session['checksum']
662 9afc4b89 Nikos Skalkotos
663 330fd618 Nikos Skalkotos
                    # Monitor the metadata changes during syspreps
664 330fd618 Nikos Skalkotos
                    with metadata_monitor(session, image_os.meta):
665 330fd618 Nikos Skalkotos
                        image_os.out = out
666 330fd618 Nikos Skalkotos
                        image_os.do_sysprep()
667 330fd618 Nikos Skalkotos
                        image_os.out.finalize()
668 a42a42b3 Nikos Skalkotos
669 9afc4b89 Nikos Skalkotos
                    # Disable syspreps that have ran
670 9afc4b89 Nikos Skalkotos
                    for sysprep in session['exec_syspreps']:
671 9afc4b89 Nikos Skalkotos
                        image_os.disable_sysprep(sysprep)
672 9afc4b89 Nikos Skalkotos
673 9afc4b89 Nikos Skalkotos
                finally:
674 9afc4b89 Nikos Skalkotos
                    dev.umount()
675 9afc4b89 Nikos Skalkotos
            finally:
676 9afc4b89 Nikos Skalkotos
                out.cleanup()
677 9afc4b89 Nikos Skalkotos
            break
678 1f42adc8 Nikos Skalkotos
    return True
679 7f623b20 Nikos Skalkotos
680 7f623b20 Nikos Skalkotos
681 a42a42b3 Nikos Skalkotos
def shrink(session):
682 a42a42b3 Nikos Skalkotos
    d = session['dialog']
683 a42a42b3 Nikos Skalkotos
    dev = session['device']
684 a42a42b3 Nikos Skalkotos
685 f99fe99d Nikos Skalkotos
    shrinked = 'shrinked' in session and session['shrinked']
686 a42a42b3 Nikos Skalkotos
687 a42a42b3 Nikos Skalkotos
    if shrinked:
688 835171dc Nikos Skalkotos
        d.msgbox("The image is already shrinked!", title="Image Shrinking",
689 835171dc Nikos Skalkotos
                 width=MSGBOX_WIDTH)
690 1f42adc8 Nikos Skalkotos
        return True
691 a42a42b3 Nikos Skalkotos
692 a42a42b3 Nikos Skalkotos
    msg = "This operation will shrink the last partition of the image to " \
693 a42a42b3 Nikos Skalkotos
          "reduce the total image size. If the last partition is a swap " \
694 a42a42b3 Nikos Skalkotos
          "partition, then this partition is removed and the partition " \
695 a42a42b3 Nikos Skalkotos
          "before that is shrinked. The removed swap partition will be " \
696 a42a42b3 Nikos Skalkotos
          "recreated during image deployment."
697 a42a42b3 Nikos Skalkotos
698 a42a42b3 Nikos Skalkotos
    if not d.yesno("%s\n\nDo you want to continue?" % msg, width=70,
699 a42a42b3 Nikos Skalkotos
                   height=12, title="Image Shrinking"):
700 330fd618 Nikos Skalkotos
        with metadata_monitor(session, dev.meta):
701 ea947a64 Nikos Skalkotos
            dev.out = InfoBoxOutput(d, "Image Shrinking", height=4)
702 330fd618 Nikos Skalkotos
            dev.shrink()
703 330fd618 Nikos Skalkotos
            dev.out.finalize()
704 330fd618 Nikos Skalkotos
705 a42a42b3 Nikos Skalkotos
        session['shrinked'] = True
706 a42a42b3 Nikos Skalkotos
        update_background_title(session)
707 1f42adc8 Nikos Skalkotos
    else:
708 1f42adc8 Nikos Skalkotos
        return False
709 1f42adc8 Nikos Skalkotos
710 1f42adc8 Nikos Skalkotos
    return True
711 a42a42b3 Nikos Skalkotos
712 a42a42b3 Nikos Skalkotos
713 a42a42b3 Nikos Skalkotos
def customization_menu(session):
714 7f623b20 Nikos Skalkotos
    d = session['dialog']
715 7f623b20 Nikos Skalkotos
716 9afc4b89 Nikos Skalkotos
    choices = [("Sysprep", "Run various image preperation tasks"),
717 9afc4b89 Nikos Skalkotos
               ("Shrink", "Shrink image"),
718 9afc4b89 Nikos Skalkotos
               ("View/Modify", "View/Modify image properties"),
719 9afc4b89 Nikos Skalkotos
               ("Delete", "Delete image properties"),
720 9afc4b89 Nikos Skalkotos
               ("Exclude", "Exclude various deployment tasks from running")]
721 9afc4b89 Nikos Skalkotos
722 1f42adc8 Nikos Skalkotos
    default_item = 0
723 9afc4b89 Nikos Skalkotos
724 7f623b20 Nikos Skalkotos
    actions = {"Sysprep": sysprep,
725 a42a42b3 Nikos Skalkotos
               "Shrink": shrink,
726 7f623b20 Nikos Skalkotos
               "View/Modify": modify_properties,
727 7f623b20 Nikos Skalkotos
               "Delete": delete_properties,
728 7f623b20 Nikos Skalkotos
               "Exclude": exclude_tasks}
729 f9d8c3d9 Nikos Skalkotos
    while 1:
730 f9d8c3d9 Nikos Skalkotos
        (code, choice) = d.menu(
731 9afc4b89 Nikos Skalkotos
            text="Choose one of the following or press <Back> to exit.",
732 9afc4b89 Nikos Skalkotos
            width=MENU_WIDTH, choices=choices, cancel="Back", height=13,
733 1f42adc8 Nikos Skalkotos
            menu_height=len(choices), default_item=choices[default_item][0],
734 7f623b20 Nikos Skalkotos
            title="Image Customization Menu")
735 f9d8c3d9 Nikos Skalkotos
736 f9d8c3d9 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
737 f9d8c3d9 Nikos Skalkotos
            break
738 f9d8c3d9 Nikos Skalkotos
        elif choice in actions:
739 1f42adc8 Nikos Skalkotos
            default_item = [entry[0] for entry in choices].index(choice)
740 1f42adc8 Nikos Skalkotos
            if actions[choice](session):
741 1f42adc8 Nikos Skalkotos
                default_item = (default_item + 1) % len(choices)
742 f9d8c3d9 Nikos Skalkotos
743 f9d8c3d9 Nikos Skalkotos
744 672cabb9 Nikos Skalkotos
def main_menu(session):
745 672cabb9 Nikos Skalkotos
    d = session['dialog']
746 672cabb9 Nikos Skalkotos
    dev = session['device']
747 9afc4b89 Nikos Skalkotos
748 9afc4b89 Nikos Skalkotos
    update_background_title(session)
749 9afc4b89 Nikos Skalkotos
750 9afc4b89 Nikos Skalkotos
    choices = [("Customize", "Customize image & ~okeanos deployment options"),
751 9afc4b89 Nikos Skalkotos
               ("Register", "Register image to ~okeanos"),
752 9afc4b89 Nikos Skalkotos
               ("Extract", "Dump image to local file system"),
753 9afc4b89 Nikos Skalkotos
               ("Reset", "Reset everything and start over again"),
754 9afc4b89 Nikos Skalkotos
               ("Help", "Get help for using snf-image-creator")]
755 9afc4b89 Nikos Skalkotos
756 672cabb9 Nikos Skalkotos
    default_item = "Customize"
757 672cabb9 Nikos Skalkotos
758 a42a42b3 Nikos Skalkotos
    actions = {"Customize": customization_menu, "Register": kamaki_menu,
759 9afc4b89 Nikos Skalkotos
               "Extract": extract_image}
760 672cabb9 Nikos Skalkotos
    while 1:
761 672cabb9 Nikos Skalkotos
        (code, choice) = d.menu(
762 9afc4b89 Nikos Skalkotos
            text="Choose one of the following or press <Exit> to exit.",
763 9afc4b89 Nikos Skalkotos
            width=MENU_WIDTH, choices=choices, cancel="Exit", height=13,
764 9afc4b89 Nikos Skalkotos
            default_item=default_item, menu_height=len(choices),
765 672cabb9 Nikos Skalkotos
            title="Image Creator for ~okeanos (snf-image-creator version %s)" %
766 672cabb9 Nikos Skalkotos
                  version)
767 672cabb9 Nikos Skalkotos
768 672cabb9 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
769 672cabb9 Nikos Skalkotos
            if confirm_exit(d):
770 672cabb9 Nikos Skalkotos
                break
771 7f623b20 Nikos Skalkotos
        elif choice == "Reset":
772 672cabb9 Nikos Skalkotos
            if confirm_reset(d):
773 a42a42b3 Nikos Skalkotos
                d.infobox("Resetting snf-image-creator. Please wait...",
774 a42a42b3 Nikos Skalkotos
                          width=INFOBOX_WIDTH)
775 672cabb9 Nikos Skalkotos
                raise Reset
776 672cabb9 Nikos Skalkotos
        elif choice in actions:
777 672cabb9 Nikos Skalkotos
            actions[choice](session)
778 672cabb9 Nikos Skalkotos
779 672cabb9 Nikos Skalkotos
780 f9d8c3d9 Nikos Skalkotos
def select_file(d, media):
781 672cabb9 Nikos Skalkotos
    root = os.sep
782 672cabb9 Nikos Skalkotos
    while 1:
783 f9d8c3d9 Nikos Skalkotos
        if media is not None:
784 f9d8c3d9 Nikos Skalkotos
            if not os.path.exists(media):
785 f9d8c3d9 Nikos Skalkotos
                d.msgbox("The file you choose does not exist",
786 f9d8c3d9 Nikos Skalkotos
                         width=MSGBOX_WIDTH)
787 f9d8c3d9 Nikos Skalkotos
            else:
788 f9d8c3d9 Nikos Skalkotos
                break
789 f9d8c3d9 Nikos Skalkotos
790 f9d8c3d9 Nikos Skalkotos
        (code, media) = d.fselect(root, 10, 50,
791 1f42adc8 Nikos Skalkotos
                                  title="Please select input media")
792 672cabb9 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
793 672cabb9 Nikos Skalkotos
            if confirm_exit(d, "You canceled the media selection dialog box."):
794 672cabb9 Nikos Skalkotos
                sys.exit(0)
795 672cabb9 Nikos Skalkotos
            else:
796 f9d8c3d9 Nikos Skalkotos
                media = None
797 672cabb9 Nikos Skalkotos
                continue
798 672cabb9 Nikos Skalkotos
799 f9d8c3d9 Nikos Skalkotos
    return media
800 672cabb9 Nikos Skalkotos
801 672cabb9 Nikos Skalkotos
802 672cabb9 Nikos Skalkotos
def image_creator(d):
803 5a0399d8 Nikos Skalkotos
804 5a0399d8 Nikos Skalkotos
    usage = "Usage: %prog [options] [<input_media>]"
805 5a0399d8 Nikos Skalkotos
    parser = optparse.OptionParser(version=version, usage=usage)
806 5a0399d8 Nikos Skalkotos
807 5a0399d8 Nikos Skalkotos
    options, args = parser.parse_args(sys.argv[1:])
808 5a0399d8 Nikos Skalkotos
809 5a0399d8 Nikos Skalkotos
    if len(args) > 1:
810 5a0399d8 Nikos Skalkotos
        parser.error("Wrong numver of arguments")
811 672cabb9 Nikos Skalkotos
812 a42a42b3 Nikos Skalkotos
    d.setBackgroundTitle('snf-image-creator')
813 a42a42b3 Nikos Skalkotos
814 672cabb9 Nikos Skalkotos
    if os.geteuid() != 0:
815 672cabb9 Nikos Skalkotos
        raise FatalError("You must run %s as root" % basename)
816 672cabb9 Nikos Skalkotos
817 5a0399d8 Nikos Skalkotos
    media = select_file(d, args[0] if len(args) == 1 else None)
818 672cabb9 Nikos Skalkotos
819 9afc4b89 Nikos Skalkotos
    out = GaugeOutput(d, "Initialization", "Initializing...")
820 672cabb9 Nikos Skalkotos
    disk = Disk(media, out)
821 672cabb9 Nikos Skalkotos
822 9afc4b89 Nikos Skalkotos
    def signal_handler(signum, frame):
823 672cabb9 Nikos Skalkotos
        out.cleanup()
824 672cabb9 Nikos Skalkotos
        disk.cleanup()
825 672cabb9 Nikos Skalkotos
826 672cabb9 Nikos Skalkotos
    signal.signal(signal.SIGINT, signal_handler)
827 672cabb9 Nikos Skalkotos
    try:
828 672cabb9 Nikos Skalkotos
        snapshot = disk.snapshot()
829 672cabb9 Nikos Skalkotos
        dev = disk.get_device(snapshot)
830 672cabb9 Nikos Skalkotos
831 a42a42b3 Nikos Skalkotos
        metadata = {}
832 a42a42b3 Nikos Skalkotos
        for (key, value) in dev.meta.items():
833 a42a42b3 Nikos Skalkotos
            metadata[str(key)] = str(value)
834 a42a42b3 Nikos Skalkotos
835 7f623b20 Nikos Skalkotos
        dev.mount(readonly=True)
836 ea947a64 Nikos Skalkotos
        out.output("Collecting image metadata...")
837 7f623b20 Nikos Skalkotos
        cls = os_cls(dev.distro, dev.ostype)
838 7f623b20 Nikos Skalkotos
        image_os = cls(dev.root, dev.g, out)
839 7f623b20 Nikos Skalkotos
        dev.umount()
840 a42a42b3 Nikos Skalkotos
841 a42a42b3 Nikos Skalkotos
        for (key, value) in image_os.meta.items():
842 a42a42b3 Nikos Skalkotos
            metadata[str(key)] = str(value)
843 a42a42b3 Nikos Skalkotos
844 7f623b20 Nikos Skalkotos
        out.success("done")
845 672cabb9 Nikos Skalkotos
        out.cleanup()
846 672cabb9 Nikos Skalkotos
847 672cabb9 Nikos Skalkotos
        # Make sure the signal handler does not call out.cleanup again
848 672cabb9 Nikos Skalkotos
        def dummy(self):
849 672cabb9 Nikos Skalkotos
            pass
850 9afc4b89 Nikos Skalkotos
        out.cleanup = type(GaugeOutput.cleanup)(dummy, out, GaugeOutput)
851 672cabb9 Nikos Skalkotos
852 672cabb9 Nikos Skalkotos
        session = {"dialog": d,
853 672cabb9 Nikos Skalkotos
                   "disk": disk,
854 2a21ff92 Nikos Skalkotos
                   "snapshot": snapshot,
855 672cabb9 Nikos Skalkotos
                   "device": dev,
856 7f623b20 Nikos Skalkotos
                   "image_os": image_os,
857 672cabb9 Nikos Skalkotos
                   "metadata": metadata}
858 672cabb9 Nikos Skalkotos
859 cf4f52b6 Nikos Skalkotos
        msg = "snf-image-creator detected a %s system on the input media. " \
860 cf4f52b6 Nikos Skalkotos
              "Would you like to run a wizards to assists you through the " \
861 cf4f52b6 Nikos Skalkotos
              "image creation process?\n\nChoose <Yes> to run the wizard, " \
862 cf4f52b6 Nikos Skalkotos
              "<No> to run the snf-image-creator in expert mode or press " \
863 cf4f52b6 Nikos Skalkotos
              "ESC to quit the program." \
864 cf4f52b6 Nikos Skalkotos
              % (dev.ostype if dev.ostype == dev.distro else "%s/%s" %
865 cf4f52b6 Nikos Skalkotos
                 (dev.distro, dev.ostype))
866 cf4f52b6 Nikos Skalkotos
867 cf4f52b6 Nikos Skalkotos
        while True:
868 cf4f52b6 Nikos Skalkotos
            code = d.yesno(msg, width=YESNO_WIDTH, height=12)
869 cf4f52b6 Nikos Skalkotos
            if code == d.DIALOG_OK:
870 cf4f52b6 Nikos Skalkotos
                if wizard(session):
871 cf4f52b6 Nikos Skalkotos
                    break
872 cf4f52b6 Nikos Skalkotos
            elif code == d.DIALOG_CANCEL:
873 cf4f52b6 Nikos Skalkotos
                main_menu(session)
874 cf4f52b6 Nikos Skalkotos
                break
875 5a0399d8 Nikos Skalkotos
876 cf4f52b6 Nikos Skalkotos
            exit_msg = "You have not selected if you want to run " \
877 cf4f52b6 Nikos Skalkotos
                       "snf-image-creator in wizard or expert mode."
878 cf4f52b6 Nikos Skalkotos
            if confirm_exit(d, exit_msg):
879 cf4f52b6 Nikos Skalkotos
                break
880 5a0399d8 Nikos Skalkotos
881 672cabb9 Nikos Skalkotos
        d.infobox("Thank you for using snf-image-creator. Bye", width=53)
882 672cabb9 Nikos Skalkotos
    finally:
883 672cabb9 Nikos Skalkotos
        disk.cleanup()
884 672cabb9 Nikos Skalkotos
885 672cabb9 Nikos Skalkotos
    return 0
886 672cabb9 Nikos Skalkotos
887 672cabb9 Nikos Skalkotos
888 672cabb9 Nikos Skalkotos
def main():
889 672cabb9 Nikos Skalkotos
890 672cabb9 Nikos Skalkotos
    d = dialog.Dialog(dialog="dialog")
891 672cabb9 Nikos Skalkotos
892 f9d8c3d9 Nikos Skalkotos
    # Add extra button in dialog library
893 f9d8c3d9 Nikos Skalkotos
    dialog._common_args_syntax["extra_button"] = \
894 f9d8c3d9 Nikos Skalkotos
        lambda enable: dialog._simple_option("--extra-button", enable)
895 f9d8c3d9 Nikos Skalkotos
896 f9d8c3d9 Nikos Skalkotos
    dialog._common_args_syntax["extra_label"] = \
897 f9d8c3d9 Nikos Skalkotos
        lambda string: ("--extra-label", string)
898 f9d8c3d9 Nikos Skalkotos
899 672cabb9 Nikos Skalkotos
    while 1:
900 672cabb9 Nikos Skalkotos
        try:
901 672cabb9 Nikos Skalkotos
            try:
902 672cabb9 Nikos Skalkotos
                ret = image_creator(d)
903 672cabb9 Nikos Skalkotos
                sys.exit(ret)
904 672cabb9 Nikos Skalkotos
            except FatalError as e:
905 672cabb9 Nikos Skalkotos
                msg = textwrap.fill(str(e), width=70)
906 a42a42b3 Nikos Skalkotos
                d.infobox(msg, width=INFOBOX_WIDTH, title="Fatal Error")
907 672cabb9 Nikos Skalkotos
                sys.exit(1)
908 672cabb9 Nikos Skalkotos
        except Reset:
909 672cabb9 Nikos Skalkotos
            continue
910 672cabb9 Nikos Skalkotos
911 672cabb9 Nikos Skalkotos
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :