Statistics
| Branch: | Tag: | Revision:

root / image_creator / dialog_main.py @ 5b2ee8c2

History | View | Annotate | Download (8.1 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 02f71654 Nikos Skalkotos
import stat
40 672cabb9 Nikos Skalkotos
import textwrap
41 672cabb9 Nikos Skalkotos
import signal
42 5a0399d8 Nikos Skalkotos
import optparse
43 672cabb9 Nikos Skalkotos
44 672cabb9 Nikos Skalkotos
from image_creator import __version__ as version
45 023e1217 Nikos Skalkotos
from image_creator.util import FatalError
46 c3fe132c Nikos Skalkotos
from image_creator.output import Output
47 789a3763 Nikos Skalkotos
from image_creator.output.cli import SimpleOutput
48 023e1217 Nikos Skalkotos
from image_creator.output.dialog import GaugeOutput
49 c3fe132c Nikos Skalkotos
from image_creator.output.composite import CompositeOutput
50 672cabb9 Nikos Skalkotos
from image_creator.disk import Disk
51 88f83027 Nikos Skalkotos
from image_creator.dialog_wizard import start_wizard
52 023e1217 Nikos Skalkotos
from image_creator.dialog_menu import main_menu
53 023e1217 Nikos Skalkotos
from image_creator.dialog_util import SMALL_WIDTH, WIDTH, confirm_exit, \
54 023e1217 Nikos Skalkotos
    Reset, update_background_title
55 672cabb9 Nikos Skalkotos
56 672cabb9 Nikos Skalkotos
57 f5174d2c Nikos Skalkotos
def create_image(d, media, out, tmp):
58 88f83027 Nikos Skalkotos
    """Create an image out of `media'"""
59 a42a42b3 Nikos Skalkotos
    d.setBackgroundTitle('snf-image-creator')
60 a42a42b3 Nikos Skalkotos
61 789a3763 Nikos Skalkotos
    gauge = GaugeOutput(d, "Initialization", "Initializing...")
62 789a3763 Nikos Skalkotos
    out.add(gauge)
63 c16850ae Nikos Skalkotos
    disk = Disk(media, out, tmp)
64 672cabb9 Nikos Skalkotos
65 9afc4b89 Nikos Skalkotos
    def signal_handler(signum, frame):
66 789a3763 Nikos Skalkotos
        gauge.cleanup()
67 672cabb9 Nikos Skalkotos
        disk.cleanup()
68 672cabb9 Nikos Skalkotos
69 672cabb9 Nikos Skalkotos
    signal.signal(signal.SIGINT, signal_handler)
70 9c354f13 Nikos Skalkotos
    signal.signal(signal.SIGTERM, signal_handler)
71 672cabb9 Nikos Skalkotos
    try:
72 672cabb9 Nikos Skalkotos
        snapshot = disk.snapshot()
73 f5174d2c Nikos Skalkotos
        image = disk.get_image(snapshot)
74 672cabb9 Nikos Skalkotos
75 3afe6b44 Nikos Skalkotos
        out.output("Collecting image metadata ...")
76 a42a42b3 Nikos Skalkotos
        metadata = {}
77 f5174d2c Nikos Skalkotos
        for (key, value) in image.meta.items():
78 a42a42b3 Nikos Skalkotos
            metadata[str(key)] = str(value)
79 a42a42b3 Nikos Skalkotos
80 f5174d2c Nikos Skalkotos
        for (key, value) in image.os.meta.items():
81 a42a42b3 Nikos Skalkotos
            metadata[str(key)] = str(value)
82 a42a42b3 Nikos Skalkotos
83 7f623b20 Nikos Skalkotos
        out.success("done")
84 789a3763 Nikos Skalkotos
        gauge.cleanup()
85 789a3763 Nikos Skalkotos
        out.remove(gauge)
86 672cabb9 Nikos Skalkotos
87 789a3763 Nikos Skalkotos
        # Make sure the signal handler does not call gauge.cleanup again
88 672cabb9 Nikos Skalkotos
        def dummy(self):
89 672cabb9 Nikos Skalkotos
            pass
90 789a3763 Nikos Skalkotos
        gauge.cleanup = type(GaugeOutput.cleanup)(dummy, gauge, GaugeOutput)
91 672cabb9 Nikos Skalkotos
92 672cabb9 Nikos Skalkotos
        session = {"dialog": d,
93 672cabb9 Nikos Skalkotos
                   "disk": disk,
94 f5174d2c Nikos Skalkotos
                   "image": image,
95 672cabb9 Nikos Skalkotos
                   "metadata": metadata}
96 672cabb9 Nikos Skalkotos
97 cf4f52b6 Nikos Skalkotos
        msg = "snf-image-creator detected a %s system on the input media. " \
98 b9cd03ee Nikos Skalkotos
              "Would you like to run a wizard to assist you through the " \
99 b9cd03ee Nikos Skalkotos
              "image creation process?\n\nChoose <Wizard> to run the wizard," \
100 023e1217 Nikos Skalkotos
              " <Expert> to run the snf-image-creator in expert mode or " \
101 023e1217 Nikos Skalkotos
              "press ESC to quit the program." \
102 80411610 Nikos Skalkotos
              % (image.ostype if image.ostype == image.distro or
103 80411610 Nikos Skalkotos
                 image.distro == "unknown" else "%s (%s)" %
104 f5174d2c Nikos Skalkotos
                 (image.ostype, image.distro))
105 cf4f52b6 Nikos Skalkotos
106 3c33e68a Nikos Skalkotos
        update_background_title(session)
107 3c33e68a Nikos Skalkotos
108 cf4f52b6 Nikos Skalkotos
        while True:
109 023e1217 Nikos Skalkotos
            code = d.yesno(msg, width=WIDTH, height=12, yes_label="Wizard",
110 023e1217 Nikos Skalkotos
                           no_label="Expert")
111 cf4f52b6 Nikos Skalkotos
            if code == d.DIALOG_OK:
112 88f83027 Nikos Skalkotos
                if start_wizard(session):
113 cf4f52b6 Nikos Skalkotos
                    break
114 cf4f52b6 Nikos Skalkotos
            elif code == d.DIALOG_CANCEL:
115 cf4f52b6 Nikos Skalkotos
                main_menu(session)
116 cf4f52b6 Nikos Skalkotos
                break
117 5a0399d8 Nikos Skalkotos
118 24684bbb Nikos Skalkotos
            if confirm_exit(d):
119 cf4f52b6 Nikos Skalkotos
                break
120 5a0399d8 Nikos Skalkotos
121 672cabb9 Nikos Skalkotos
        d.infobox("Thank you for using snf-image-creator. Bye", width=53)
122 672cabb9 Nikos Skalkotos
    finally:
123 672cabb9 Nikos Skalkotos
        disk.cleanup()
124 672cabb9 Nikos Skalkotos
125 672cabb9 Nikos Skalkotos
    return 0
126 672cabb9 Nikos Skalkotos
127 672cabb9 Nikos Skalkotos
128 789a3763 Nikos Skalkotos
def select_file(d, media):
129 88f83027 Nikos Skalkotos
    """Select a media file"""
130 f2ddf4db Nikos Skalkotos
    if media == '/':
131 f2ddf4db Nikos Skalkotos
        return '/'
132 f2ddf4db Nikos Skalkotos
133 3664c5f5 Nikos Skalkotos
    default = os.getcwd() + os.sep
134 789a3763 Nikos Skalkotos
    while 1:
135 789a3763 Nikos Skalkotos
        if media is not None:
136 789a3763 Nikos Skalkotos
            if not os.path.exists(media):
137 789a3763 Nikos Skalkotos
                d.msgbox("The file `%s' you choose does not exist." % media,
138 023e1217 Nikos Skalkotos
                         width=SMALL_WIDTH)
139 789a3763 Nikos Skalkotos
            else:
140 02f71654 Nikos Skalkotos
                mode = os.stat(media).st_mode
141 02f71654 Nikos Skalkotos
                if not stat.S_ISDIR(mode):
142 02f71654 Nikos Skalkotos
                    break
143 3664c5f5 Nikos Skalkotos
                default = media
144 789a3763 Nikos Skalkotos
145 3664c5f5 Nikos Skalkotos
        (code, media) = d.fselect(default, 10, 60, extra_button=1,
146 6228d45e Nikos Skalkotos
                                  title="Please select an input media.",
147 02f71654 Nikos Skalkotos
                                  extra_label="Bundle Host")
148 789a3763 Nikos Skalkotos
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
149 789a3763 Nikos Skalkotos
            if confirm_exit(d, "You canceled the media selection dialog box."):
150 789a3763 Nikos Skalkotos
                sys.exit(0)
151 789a3763 Nikos Skalkotos
            else:
152 789a3763 Nikos Skalkotos
                media = None
153 789a3763 Nikos Skalkotos
                continue
154 b686bde9 Nikos Skalkotos
        elif code == d.DIALOG_EXTRA:
155 02f71654 Nikos Skalkotos
            return '/'
156 789a3763 Nikos Skalkotos
157 789a3763 Nikos Skalkotos
    return media
158 789a3763 Nikos Skalkotos
159 789a3763 Nikos Skalkotos
160 672cabb9 Nikos Skalkotos
def main():
161 672cabb9 Nikos Skalkotos
162 672cabb9 Nikos Skalkotos
    d = dialog.Dialog(dialog="dialog")
163 672cabb9 Nikos Skalkotos
164 f9d8c3d9 Nikos Skalkotos
    # Add extra button in dialog library
165 f9d8c3d9 Nikos Skalkotos
    dialog._common_args_syntax["extra_button"] = \
166 f9d8c3d9 Nikos Skalkotos
        lambda enable: dialog._simple_option("--extra-button", enable)
167 f9d8c3d9 Nikos Skalkotos
168 f9d8c3d9 Nikos Skalkotos
    dialog._common_args_syntax["extra_label"] = \
169 f9d8c3d9 Nikos Skalkotos
        lambda string: ("--extra-label", string)
170 f9d8c3d9 Nikos Skalkotos
171 b9cd03ee Nikos Skalkotos
    # Allow yes-no label overwriting
172 b9cd03ee Nikos Skalkotos
    dialog._common_args_syntax["yes_label"] = \
173 b9cd03ee Nikos Skalkotos
        lambda string: ("--yes-label", string)
174 b9cd03ee Nikos Skalkotos
175 b9cd03ee Nikos Skalkotos
    dialog._common_args_syntax["no_label"] = \
176 b9cd03ee Nikos Skalkotos
        lambda string: ("--no-label", string)
177 b9cd03ee Nikos Skalkotos
178 789a3763 Nikos Skalkotos
    usage = "Usage: %prog [options] [<input_media>]"
179 789a3763 Nikos Skalkotos
    parser = optparse.OptionParser(version=version, usage=usage)
180 789a3763 Nikos Skalkotos
    parser.add_option("-l", "--logfile", type="string", dest="logfile",
181 789a3763 Nikos Skalkotos
                      default=None, help="log all messages to FILE",
182 789a3763 Nikos Skalkotos
                      metavar="FILE")
183 c16850ae Nikos Skalkotos
    parser.add_option("--tmpdir", type="string", dest="tmp", default=None,
184 c16850ae Nikos Skalkotos
                      help="create large temporary image files under DIR",
185 c16850ae Nikos Skalkotos
                      metavar="DIR")
186 789a3763 Nikos Skalkotos
187 789a3763 Nikos Skalkotos
    options, args = parser.parse_args(sys.argv[1:])
188 789a3763 Nikos Skalkotos
189 789a3763 Nikos Skalkotos
    if len(args) > 1:
190 789a3763 Nikos Skalkotos
        parser.error("Wrong number of arguments")
191 789a3763 Nikos Skalkotos
192 789a3763 Nikos Skalkotos
    d.setBackgroundTitle('snf-image-creator')
193 789a3763 Nikos Skalkotos
194 789a3763 Nikos Skalkotos
    try:
195 789a3763 Nikos Skalkotos
        if os.geteuid() != 0:
196 023e1217 Nikos Skalkotos
            raise FatalError("You must run %s as root" %
197 789a3763 Nikos Skalkotos
                             parser.get_prog_name())
198 789a3763 Nikos Skalkotos
199 c16850ae Nikos Skalkotos
        if options.tmp is not None and not os.path.isdir(options.tmp):
200 c16850ae Nikos Skalkotos
            raise FatalError("The directory `%s' specified with --tmpdir is "
201 c16850ae Nikos Skalkotos
                             "not valid" % options.tmp)
202 789a3763 Nikos Skalkotos
203 789a3763 Nikos Skalkotos
        logfile = None
204 789a3763 Nikos Skalkotos
        if options.logfile is not None:
205 672cabb9 Nikos Skalkotos
            try:
206 789a3763 Nikos Skalkotos
                logfile = open(options.logfile, 'w')
207 789a3763 Nikos Skalkotos
            except IOError as e:
208 789a3763 Nikos Skalkotos
                raise FatalError(
209 023e1217 Nikos Skalkotos
                    "Unable to open logfile `%s' for writing. Reason: %s" %
210 789a3763 Nikos Skalkotos
                    (options.logfile, e.strerror))
211 c16850ae Nikos Skalkotos
212 c16850ae Nikos Skalkotos
        media = select_file(d, args[0] if len(args) == 1 else None)
213 c16850ae Nikos Skalkotos
214 789a3763 Nikos Skalkotos
        try:
215 789a3763 Nikos Skalkotos
            log = SimpleOutput(False, logfile) if logfile is not None \
216 023e1217 Nikos Skalkotos
                else Output()
217 789a3763 Nikos Skalkotos
            while 1:
218 789a3763 Nikos Skalkotos
                try:
219 c3fe132c Nikos Skalkotos
                    out = CompositeOutput([log])
220 3afe6b44 Nikos Skalkotos
                    out.output("Starting %s v%s ..." %
221 789a3763 Nikos Skalkotos
                               (parser.get_prog_name(), version))
222 f5174d2c Nikos Skalkotos
                    ret = create_image(d, media, out, options.tmp)
223 789a3763 Nikos Skalkotos
                    sys.exit(ret)
224 789a3763 Nikos Skalkotos
                except Reset:
225 3afe6b44 Nikos Skalkotos
                    log.output("Resetting everything ...")
226 789a3763 Nikos Skalkotos
                    continue
227 789a3763 Nikos Skalkotos
        finally:
228 789a3763 Nikos Skalkotos
            if logfile is not None:
229 789a3763 Nikos Skalkotos
                logfile.close()
230 789a3763 Nikos Skalkotos
    except FatalError as e:
231 023e1217 Nikos Skalkotos
        msg = textwrap.fill(str(e), width=WIDTH)
232 023e1217 Nikos Skalkotos
        d.infobox(msg, width=WIDTH, title="Fatal Error")
233 789a3763 Nikos Skalkotos
        sys.exit(1)
234 672cabb9 Nikos Skalkotos
235 672cabb9 Nikos Skalkotos
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :