Statistics
| Branch: | Tag: | Revision:

root / image_creator / dialog_main.py @ 09743d3a

History | View | Annotate | Download (29.5 kB)

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