Statistics
| Branch: | Tag: | Revision:

root / image_creator / dialog_main.py @ 121f3bc0

History | View | Annotate | Download (8.3 kB)

1 672cabb9 Nikos Skalkotos
#!/usr/bin/env python
2 121f3bc0 Nikos Skalkotos
# -*- coding: utf-8 -*-
3 121f3bc0 Nikos Skalkotos
#
4 672cabb9 Nikos Skalkotos
# Copyright 2012 GRNET S.A. All rights reserved.
5 672cabb9 Nikos Skalkotos
#
6 672cabb9 Nikos Skalkotos
# Redistribution and use in source and binary forms, with or
7 672cabb9 Nikos Skalkotos
# without modification, are permitted provided that the following
8 672cabb9 Nikos Skalkotos
# conditions are met:
9 672cabb9 Nikos Skalkotos
#
10 672cabb9 Nikos Skalkotos
#   1. Redistributions of source code must retain the above
11 672cabb9 Nikos Skalkotos
#      copyright notice, this list of conditions and the following
12 672cabb9 Nikos Skalkotos
#      disclaimer.
13 672cabb9 Nikos Skalkotos
#
14 672cabb9 Nikos Skalkotos
#   2. Redistributions in binary form must reproduce the above
15 672cabb9 Nikos Skalkotos
#      copyright notice, this list of conditions and the following
16 672cabb9 Nikos Skalkotos
#      disclaimer in the documentation and/or other materials
17 672cabb9 Nikos Skalkotos
#      provided with the distribution.
18 672cabb9 Nikos Skalkotos
#
19 672cabb9 Nikos Skalkotos
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
20 672cabb9 Nikos Skalkotos
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 672cabb9 Nikos Skalkotos
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 672cabb9 Nikos Skalkotos
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
23 672cabb9 Nikos Skalkotos
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 672cabb9 Nikos Skalkotos
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 672cabb9 Nikos Skalkotos
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 672cabb9 Nikos Skalkotos
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 672cabb9 Nikos Skalkotos
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 672cabb9 Nikos Skalkotos
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 672cabb9 Nikos Skalkotos
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 672cabb9 Nikos Skalkotos
# POSSIBILITY OF SUCH DAMAGE.
31 672cabb9 Nikos Skalkotos
#
32 672cabb9 Nikos Skalkotos
# The views and conclusions contained in the software and
33 672cabb9 Nikos Skalkotos
# documentation are those of the authors and should not be
34 672cabb9 Nikos Skalkotos
# interpreted as representing official policies, either expressed
35 672cabb9 Nikos Skalkotos
# or implied, of GRNET S.A.
36 672cabb9 Nikos Skalkotos
37 121f3bc0 Nikos Skalkotos
"""This module is the entrance point for the dialog-based version of the
38 121f3bc0 Nikos Skalkotos
snf-image-creator program. The main function will create a dialog where the
39 121f3bc0 Nikos Skalkotos
user is asked if he wants to use the program in expert or wizard mode.
40 121f3bc0 Nikos Skalkotos
"""
41 121f3bc0 Nikos Skalkotos
42 672cabb9 Nikos Skalkotos
import dialog
43 672cabb9 Nikos Skalkotos
import sys
44 672cabb9 Nikos Skalkotos
import os
45 02f71654 Nikos Skalkotos
import stat
46 672cabb9 Nikos Skalkotos
import textwrap
47 672cabb9 Nikos Skalkotos
import signal
48 5a0399d8 Nikos Skalkotos
import optparse
49 672cabb9 Nikos Skalkotos
50 672cabb9 Nikos Skalkotos
from image_creator import __version__ as version
51 023e1217 Nikos Skalkotos
from image_creator.util import FatalError
52 c3fe132c Nikos Skalkotos
from image_creator.output import Output
53 789a3763 Nikos Skalkotos
from image_creator.output.cli import SimpleOutput
54 023e1217 Nikos Skalkotos
from image_creator.output.dialog import GaugeOutput
55 c3fe132c Nikos Skalkotos
from image_creator.output.composite import CompositeOutput
56 672cabb9 Nikos Skalkotos
from image_creator.disk import Disk
57 88f83027 Nikos Skalkotos
from image_creator.dialog_wizard import start_wizard
58 023e1217 Nikos Skalkotos
from image_creator.dialog_menu import main_menu
59 023e1217 Nikos Skalkotos
from image_creator.dialog_util import SMALL_WIDTH, WIDTH, confirm_exit, \
60 023e1217 Nikos Skalkotos
    Reset, update_background_title
61 672cabb9 Nikos Skalkotos
62 672cabb9 Nikos Skalkotos
63 f5174d2c Nikos Skalkotos
def create_image(d, media, out, tmp):
64 88f83027 Nikos Skalkotos
    """Create an image out of `media'"""
65 a42a42b3 Nikos Skalkotos
    d.setBackgroundTitle('snf-image-creator')
66 a42a42b3 Nikos Skalkotos
67 789a3763 Nikos Skalkotos
    gauge = GaugeOutput(d, "Initialization", "Initializing...")
68 789a3763 Nikos Skalkotos
    out.add(gauge)
69 c16850ae Nikos Skalkotos
    disk = Disk(media, out, tmp)
70 672cabb9 Nikos Skalkotos
71 9afc4b89 Nikos Skalkotos
    def signal_handler(signum, frame):
72 789a3763 Nikos Skalkotos
        gauge.cleanup()
73 672cabb9 Nikos Skalkotos
        disk.cleanup()
74 672cabb9 Nikos Skalkotos
75 672cabb9 Nikos Skalkotos
    signal.signal(signal.SIGINT, signal_handler)
76 9c354f13 Nikos Skalkotos
    signal.signal(signal.SIGTERM, signal_handler)
77 672cabb9 Nikos Skalkotos
    try:
78 672cabb9 Nikos Skalkotos
        snapshot = disk.snapshot()
79 f5174d2c Nikos Skalkotos
        image = disk.get_image(snapshot)
80 672cabb9 Nikos Skalkotos
81 3afe6b44 Nikos Skalkotos
        out.output("Collecting image metadata ...")
82 a42a42b3 Nikos Skalkotos
        metadata = {}
83 f5174d2c Nikos Skalkotos
        for (key, value) in image.meta.items():
84 a42a42b3 Nikos Skalkotos
            metadata[str(key)] = str(value)
85 a42a42b3 Nikos Skalkotos
86 f5174d2c Nikos Skalkotos
        for (key, value) in image.os.meta.items():
87 a42a42b3 Nikos Skalkotos
            metadata[str(key)] = str(value)
88 a42a42b3 Nikos Skalkotos
89 7f623b20 Nikos Skalkotos
        out.success("done")
90 789a3763 Nikos Skalkotos
        gauge.cleanup()
91 789a3763 Nikos Skalkotos
        out.remove(gauge)
92 672cabb9 Nikos Skalkotos
93 789a3763 Nikos Skalkotos
        # Make sure the signal handler does not call gauge.cleanup again
94 672cabb9 Nikos Skalkotos
        def dummy(self):
95 672cabb9 Nikos Skalkotos
            pass
96 789a3763 Nikos Skalkotos
        gauge.cleanup = type(GaugeOutput.cleanup)(dummy, gauge, GaugeOutput)
97 672cabb9 Nikos Skalkotos
98 672cabb9 Nikos Skalkotos
        session = {"dialog": d,
99 672cabb9 Nikos Skalkotos
                   "disk": disk,
100 f5174d2c Nikos Skalkotos
                   "image": image,
101 672cabb9 Nikos Skalkotos
                   "metadata": metadata}
102 672cabb9 Nikos Skalkotos
103 cf4f52b6 Nikos Skalkotos
        msg = "snf-image-creator detected a %s system on the input media. " \
104 b9cd03ee Nikos Skalkotos
              "Would you like to run a wizard to assist you through the " \
105 b9cd03ee Nikos Skalkotos
              "image creation process?\n\nChoose <Wizard> to run the wizard," \
106 023e1217 Nikos Skalkotos
              " <Expert> to run the snf-image-creator in expert mode or " \
107 023e1217 Nikos Skalkotos
              "press ESC to quit the program." \
108 80411610 Nikos Skalkotos
              % (image.ostype if image.ostype == image.distro or
109 80411610 Nikos Skalkotos
                 image.distro == "unknown" else "%s (%s)" %
110 f5174d2c Nikos Skalkotos
                 (image.ostype, image.distro))
111 cf4f52b6 Nikos Skalkotos
112 3c33e68a Nikos Skalkotos
        update_background_title(session)
113 3c33e68a Nikos Skalkotos
114 cf4f52b6 Nikos Skalkotos
        while True:
115 023e1217 Nikos Skalkotos
            code = d.yesno(msg, width=WIDTH, height=12, yes_label="Wizard",
116 023e1217 Nikos Skalkotos
                           no_label="Expert")
117 cf4f52b6 Nikos Skalkotos
            if code == d.DIALOG_OK:
118 88f83027 Nikos Skalkotos
                if start_wizard(session):
119 cf4f52b6 Nikos Skalkotos
                    break
120 cf4f52b6 Nikos Skalkotos
            elif code == d.DIALOG_CANCEL:
121 cf4f52b6 Nikos Skalkotos
                main_menu(session)
122 cf4f52b6 Nikos Skalkotos
                break
123 5a0399d8 Nikos Skalkotos
124 24684bbb Nikos Skalkotos
            if confirm_exit(d):
125 cf4f52b6 Nikos Skalkotos
                break
126 5a0399d8 Nikos Skalkotos
127 672cabb9 Nikos Skalkotos
        d.infobox("Thank you for using snf-image-creator. Bye", width=53)
128 672cabb9 Nikos Skalkotos
    finally:
129 672cabb9 Nikos Skalkotos
        disk.cleanup()
130 672cabb9 Nikos Skalkotos
131 672cabb9 Nikos Skalkotos
    return 0
132 672cabb9 Nikos Skalkotos
133 672cabb9 Nikos Skalkotos
134 789a3763 Nikos Skalkotos
def select_file(d, media):
135 88f83027 Nikos Skalkotos
    """Select a media file"""
136 f2ddf4db Nikos Skalkotos
    if media == '/':
137 f2ddf4db Nikos Skalkotos
        return '/'
138 f2ddf4db Nikos Skalkotos
139 3664c5f5 Nikos Skalkotos
    default = os.getcwd() + os.sep
140 789a3763 Nikos Skalkotos
    while 1:
141 789a3763 Nikos Skalkotos
        if media is not None:
142 789a3763 Nikos Skalkotos
            if not os.path.exists(media):
143 789a3763 Nikos Skalkotos
                d.msgbox("The file `%s' you choose does not exist." % media,
144 023e1217 Nikos Skalkotos
                         width=SMALL_WIDTH)
145 789a3763 Nikos Skalkotos
            else:
146 02f71654 Nikos Skalkotos
                mode = os.stat(media).st_mode
147 02f71654 Nikos Skalkotos
                if not stat.S_ISDIR(mode):
148 02f71654 Nikos Skalkotos
                    break
149 3664c5f5 Nikos Skalkotos
                default = media
150 789a3763 Nikos Skalkotos
151 3664c5f5 Nikos Skalkotos
        (code, media) = d.fselect(default, 10, 60, extra_button=1,
152 6228d45e Nikos Skalkotos
                                  title="Please select an input media.",
153 02f71654 Nikos Skalkotos
                                  extra_label="Bundle Host")
154 789a3763 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
155 789a3763 Nikos Skalkotos
            if confirm_exit(d, "You canceled the media selection dialog box."):
156 789a3763 Nikos Skalkotos
                sys.exit(0)
157 789a3763 Nikos Skalkotos
            else:
158 789a3763 Nikos Skalkotos
                media = None
159 789a3763 Nikos Skalkotos
                continue
160 b686bde9 Nikos Skalkotos
        elif code == d.DIALOG_EXTRA:
161 02f71654 Nikos Skalkotos
            return '/'
162 789a3763 Nikos Skalkotos
163 789a3763 Nikos Skalkotos
    return media
164 789a3763 Nikos Skalkotos
165 789a3763 Nikos Skalkotos
166 672cabb9 Nikos Skalkotos
def main():
167 672cabb9 Nikos Skalkotos
168 672cabb9 Nikos Skalkotos
    d = dialog.Dialog(dialog="dialog")
169 672cabb9 Nikos Skalkotos
170 f9d8c3d9 Nikos Skalkotos
    # Add extra button in dialog library
171 f9d8c3d9 Nikos Skalkotos
    dialog._common_args_syntax["extra_button"] = \
172 f9d8c3d9 Nikos Skalkotos
        lambda enable: dialog._simple_option("--extra-button", enable)
173 f9d8c3d9 Nikos Skalkotos
174 f9d8c3d9 Nikos Skalkotos
    dialog._common_args_syntax["extra_label"] = \
175 f9d8c3d9 Nikos Skalkotos
        lambda string: ("--extra-label", string)
176 f9d8c3d9 Nikos Skalkotos
177 b9cd03ee Nikos Skalkotos
    # Allow yes-no label overwriting
178 b9cd03ee Nikos Skalkotos
    dialog._common_args_syntax["yes_label"] = \
179 b9cd03ee Nikos Skalkotos
        lambda string: ("--yes-label", string)
180 b9cd03ee Nikos Skalkotos
181 b9cd03ee Nikos Skalkotos
    dialog._common_args_syntax["no_label"] = \
182 b9cd03ee Nikos Skalkotos
        lambda string: ("--no-label", string)
183 b9cd03ee Nikos Skalkotos
184 789a3763 Nikos Skalkotos
    usage = "Usage: %prog [options] [<input_media>]"
185 789a3763 Nikos Skalkotos
    parser = optparse.OptionParser(version=version, usage=usage)
186 789a3763 Nikos Skalkotos
    parser.add_option("-l", "--logfile", type="string", dest="logfile",
187 789a3763 Nikos Skalkotos
                      default=None, help="log all messages to FILE",
188 789a3763 Nikos Skalkotos
                      metavar="FILE")
189 c16850ae Nikos Skalkotos
    parser.add_option("--tmpdir", type="string", dest="tmp", default=None,
190 c16850ae Nikos Skalkotos
                      help="create large temporary image files under DIR",
191 c16850ae Nikos Skalkotos
                      metavar="DIR")
192 789a3763 Nikos Skalkotos
193 789a3763 Nikos Skalkotos
    options, args = parser.parse_args(sys.argv[1:])
194 789a3763 Nikos Skalkotos
195 789a3763 Nikos Skalkotos
    if len(args) > 1:
196 789a3763 Nikos Skalkotos
        parser.error("Wrong number of arguments")
197 789a3763 Nikos Skalkotos
198 789a3763 Nikos Skalkotos
    d.setBackgroundTitle('snf-image-creator')
199 789a3763 Nikos Skalkotos
200 789a3763 Nikos Skalkotos
    try:
201 789a3763 Nikos Skalkotos
        if os.geteuid() != 0:
202 023e1217 Nikos Skalkotos
            raise FatalError("You must run %s as root" %
203 789a3763 Nikos Skalkotos
                             parser.get_prog_name())
204 789a3763 Nikos Skalkotos
205 c16850ae Nikos Skalkotos
        if options.tmp is not None and not os.path.isdir(options.tmp):
206 c16850ae Nikos Skalkotos
            raise FatalError("The directory `%s' specified with --tmpdir is "
207 c16850ae Nikos Skalkotos
                             "not valid" % options.tmp)
208 789a3763 Nikos Skalkotos
209 789a3763 Nikos Skalkotos
        logfile = None
210 789a3763 Nikos Skalkotos
        if options.logfile is not None:
211 672cabb9 Nikos Skalkotos
            try:
212 789a3763 Nikos Skalkotos
                logfile = open(options.logfile, 'w')
213 789a3763 Nikos Skalkotos
            except IOError as e:
214 789a3763 Nikos Skalkotos
                raise FatalError(
215 023e1217 Nikos Skalkotos
                    "Unable to open logfile `%s' for writing. Reason: %s" %
216 789a3763 Nikos Skalkotos
                    (options.logfile, e.strerror))
217 c16850ae Nikos Skalkotos
218 c16850ae Nikos Skalkotos
        media = select_file(d, args[0] if len(args) == 1 else None)
219 c16850ae Nikos Skalkotos
220 789a3763 Nikos Skalkotos
        try:
221 789a3763 Nikos Skalkotos
            log = SimpleOutput(False, logfile) if logfile is not None \
222 023e1217 Nikos Skalkotos
                else Output()
223 789a3763 Nikos Skalkotos
            while 1:
224 789a3763 Nikos Skalkotos
                try:
225 c3fe132c Nikos Skalkotos
                    out = CompositeOutput([log])
226 3afe6b44 Nikos Skalkotos
                    out.output("Starting %s v%s ..." %
227 789a3763 Nikos Skalkotos
                               (parser.get_prog_name(), version))
228 f5174d2c Nikos Skalkotos
                    ret = create_image(d, media, out, options.tmp)
229 789a3763 Nikos Skalkotos
                    sys.exit(ret)
230 789a3763 Nikos Skalkotos
                except Reset:
231 3afe6b44 Nikos Skalkotos
                    log.output("Resetting everything ...")
232 789a3763 Nikos Skalkotos
                    continue
233 789a3763 Nikos Skalkotos
        finally:
234 789a3763 Nikos Skalkotos
            if logfile is not None:
235 789a3763 Nikos Skalkotos
                logfile.close()
236 789a3763 Nikos Skalkotos
    except FatalError as e:
237 023e1217 Nikos Skalkotos
        msg = textwrap.fill(str(e), width=WIDTH)
238 023e1217 Nikos Skalkotos
        d.infobox(msg, width=WIDTH, title="Fatal Error")
239 789a3763 Nikos Skalkotos
        sys.exit(1)
240 672cabb9 Nikos Skalkotos
241 672cabb9 Nikos Skalkotos
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :