X-Git-Url: https://code.grnet.gr/git/snf-image-creator/blobdiff_plain/9c354f13446f73458e52ac5bd7063f3e01dabbc7..8e58e69976b0d79f9b7758347c7bfce1ba9f6d8a:/image_creator/dialog_main.py diff --git a/image_creator/dialog_main.py b/image_creator/dialog_main.py index f9dd260..0834cb4 100644 --- a/image_creator/dialog_main.py +++ b/image_creator/dialog_main.py @@ -1,5 +1,6 @@ #!/usr/bin/env python - +# -*- coding: utf-8 -*- +# # Copyright 2012 GRNET S.A. All rights reserved. # # Redistribution and use in source and binary forms, with or @@ -33,12 +34,19 @@ # interpreted as representing official policies, either expressed # or implied, of GRNET S.A. +"""This module is the entrance point for the dialog-based version of the +snf-image-creator program. The main function will create a dialog where the +user is asked if he wants to use the program in expert or wizard mode. +""" + import dialog import sys import os +import stat import textwrap import signal import optparse +import types from image_creator import __version__ as version from image_creator.util import FatalError @@ -47,20 +55,19 @@ from image_creator.output.cli import SimpleOutput from image_creator.output.dialog import GaugeOutput from image_creator.output.composite import CompositeOutput from image_creator.disk import Disk -from image_creator.os_type import os_cls -from image_creator.dialog_wizard import wizard +from image_creator.dialog_wizard import start_wizard from image_creator.dialog_menu import main_menu from image_creator.dialog_util import SMALL_WIDTH, WIDTH, confirm_exit, \ Reset, update_background_title -def image_creator(d, media, out): - +def create_image(d, media, out, tmp): + """Create an image out of `media'""" d.setBackgroundTitle('snf-image-creator') gauge = GaugeOutput(d, "Initialization", "Initializing...") out.add(gauge) - disk = Disk(media, out) + disk = Disk(media, out, tmp) def signal_handler(signum, frame): gauge.cleanup() @@ -70,19 +77,14 @@ def image_creator(d, media, out): signal.signal(signal.SIGTERM, signal_handler) try: snapshot = disk.snapshot() - dev = disk.get_device(snapshot) + image = disk.get_image(snapshot) + out.output("Collecting image metadata ...") metadata = {} - for (key, value) in dev.meta.items(): + for (key, value) in image.meta.items(): metadata[str(key)] = str(value) - dev.mount(readonly=True) - out.output("Collecting image metadata...") - cls = os_cls(dev.distro, dev.ostype) - image_os = cls(dev.root, dev.g, out) - dev.umount() - - for (key, value) in image_os.meta.items(): + for (key, value) in image.os.meta.items(): metadata[str(key)] = str(value) out.success("done") @@ -96,9 +98,7 @@ def image_creator(d, media, out): session = {"dialog": d, "disk": disk, - "snapshot": snapshot, - "device": dev, - "image_os": image_os, + "image": image, "metadata": metadata} msg = "snf-image-creator detected a %s system on the input media. " \ @@ -106,8 +106,9 @@ def image_creator(d, media, out): "image creation process?\n\nChoose to run the wizard," \ " to run the snf-image-creator in expert mode or " \ "press ESC to quit the program." \ - % (dev.ostype if dev.ostype == dev.distro else "%s (%s)" % - (dev.ostype, dev.distro)) + % (image.ostype if image.ostype == image.distro or + image.distro == "unknown" else "%s (%s)" % + (image.ostype, image.distro)) update_background_title(session) @@ -115,7 +116,7 @@ def image_creator(d, media, out): code = d.yesno(msg, width=WIDTH, height=12, yes_label="Wizard", no_label="Expert") if code == d.DIALOG_OK: - if wizard(session): + if start_wizard(session): break elif code == d.DIALOG_CANCEL: main_menu(session) @@ -132,27 +133,70 @@ def image_creator(d, media, out): def select_file(d, media): - root = os.sep + """Select a media file""" + if media == '/': + return '/' + + default = os.getcwd() + os.sep while 1: if media is not None: if not os.path.exists(media): d.msgbox("The file `%s' you choose does not exist." % media, width=SMALL_WIDTH) else: - break + mode = os.stat(media).st_mode + if not stat.S_ISDIR(mode): + break + default = media - (code, media) = d.fselect(root, 10, 50, - title="Please select input media") + (code, media) = d.fselect(default, 10, 60, extra_button=1, + title="Please select an input media.", + extra_label="Bundle Host") if code in (d.DIALOG_CANCEL, d.DIALOG_ESC): if confirm_exit(d, "You canceled the media selection dialog box."): sys.exit(0) else: media = None continue + elif code == d.DIALOG_EXTRA: + return '/' return media +def _dialog_form(self, text, height=20, width=60, form_height=15, fields=[], + **kwargs): + """Display a form box. + + fields is in the form: [(label1, item1, item_length1), ...] + """ + + cmd = ["--form", text, str(height), str(width), str(form_height)] + + label_len = 0 + for field in fields: + if len(field[0]) > label_len: + label_len = len(field[0]) + + input_len = width - label_len - 1 + + line = 1 + for field in fields: + label = field[0] + item = field[1] + item_len = field[2] + cmd.extend((label, str(line), str(1), item, str(line), + str(label_len + 1), str(input_len), str(item_len))) + line += 1 + + code, output = self._perform(*(cmd,), **kwargs) + + if not output: + return (code, []) + + return (code, output.splitlines()) + + def main(): d = dialog.Dialog(dialog="dialog") @@ -171,11 +215,18 @@ def main(): dialog._common_args_syntax["no_label"] = \ lambda string: ("--no-label", string) + # Monkey-patch pythondialog to include support for form dialog boxes + if not hasattr(dialog, 'form'): + d.form = types.MethodType(_dialog_form, d) + usage = "Usage: %prog [options] []" parser = optparse.OptionParser(version=version, usage=usage) parser.add_option("-l", "--logfile", type="string", dest="logfile", default=None, help="log all messages to FILE", metavar="FILE") + parser.add_option("--tmpdir", type="string", dest="tmp", default=None, + help="create large temporary image files under DIR", + metavar="DIR") options, args = parser.parse_args(sys.argv[1:]) @@ -189,7 +240,9 @@ def main(): raise FatalError("You must run %s as root" % parser.get_prog_name()) - media = select_file(d, args[0] if len(args) == 1 else None) + if options.tmp is not None and not os.path.isdir(options.tmp): + raise FatalError("The directory `%s' specified with --tmpdir is " + "not valid" % options.tmp) logfile = None if options.logfile is not None: @@ -199,18 +252,21 @@ def main(): raise FatalError( "Unable to open logfile `%s' for writing. Reason: %s" % (options.logfile, e.strerror)) + + media = select_file(d, args[0] if len(args) == 1 else None) + try: log = SimpleOutput(False, logfile) if logfile is not None \ else Output() while 1: try: out = CompositeOutput([log]) - out.output("Starting %s v%s..." % + out.output("Starting %s v%s ..." % (parser.get_prog_name(), version)) - ret = image_creator(d, media, out) + ret = create_image(d, media, out, options.tmp) sys.exit(ret) except Reset: - log.output("Resetting everything...") + log.output("Resetting everything ...") continue finally: if logfile is not None: