Statistics
| Branch: | Tag: | Revision:

root / image_creator / dialog_main.py @ 56884b64

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