Statistics
| Branch: | Tag: | Revision:

root / image_creator / dialog_menu.py @ 63af9c37

History | View | Annotate | Download (30.2 kB)

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