X-Git-Url: https://code.grnet.gr/git/snf-image-creator/blobdiff_plain/9afc4b89f252e5d239058a3bfeb761ab5627bfd1..330fd6187836ec541efe6fada9514ad0ad3b23da:/image_creator/dialog_main.py diff --git a/image_creator/dialog_main.py b/image_creator/dialog_main.py index 33d399f..fae4c2e 100644 --- a/image_creator/dialog_main.py +++ b/image_creator/dialog_main.py @@ -54,6 +54,7 @@ MENU_WIDTH = 70 INPUTBOX_WIDTH = 70 CHECKBOX_WIDTH = 70 HELP_WIDTH = 70 +INFOBOX_WIDTH = 70 CONFIGURATION_TASKS = [ ("Partition table manipulation", ["FixPartitionTable"], @@ -77,14 +78,55 @@ class Reset(Exception): pass +class metadata_monitor(object): + def __init__(self, session, meta): + self.session = session + self.meta = meta + + def __enter__(self): + self.old = {} + for (k, v) in self.meta.items(): + self.old[k] = v + + def __exit__(self, type, value, traceback): + d = self.session['dialog'] + + altered = {} + added = {} + + for (k, v) in self.meta.items(): + if k not in self.old: + added[k] = v + elif self.old[k] != v: + altered[k] = v + + if not (len(added) or len(altered)): + return + + msg = "The last action has changed some image properties:\n\n" + if len(added): + msg += "New image properties:\n" + for (k, v) in added.items(): + msg += ' %s: "%s"\n' % (k, v) + msg += "\n" + if len(altered): + msg += "Updated image properties:\n" + for (k, v) in altered.items(): + msg += ' %s: "%s" -> "%s"\n' % (k, self.old[k], v) + msg += "\n" + + self.session['metadata'].update(added) + self.session['metadata'].update(altered) + d.msgbox(msg, title="Image Property Changes", width=MSGBOX_WIDTH) + + def confirm_exit(d, msg=''): return not d.yesno("%s Do you want to exit?" % msg, width=YESNO_WIDTH) def confirm_reset(d): - return not d.yesno( - "Are you sure you want to reset everything?", - width=YESNO_WIDTH) + return not d.yesno("Are you sure you want to reset everything?", + width=YESNO_WIDTH) def update_background_title(session): @@ -94,7 +136,11 @@ def update_background_title(session): MB = 2 ** 20 size = (dev.meta['SIZE'] + MB - 1) // MB - title = "OS: %s, Distro: %s, Size: %dMB" % (dev.ostype, dev.distro, size) + shrinked = 'shrinked' in session and session['shrinked'] == True + postfix = " (shrinked)" if shrinked else '' + + title = "OS: %s, Distro: %s, Size: %dMB%s" % \ + (dev.ostype, dev.distro, size, postfix) d.setBackgroundTitle(title) @@ -408,7 +454,7 @@ def modify_properties(session): (code, choice) = d.menu( "In this menu you can edit existing image properties or add new " - "ones. Be carefull! Most properties have special meaning and " + "ones. Be careful! Most properties have special meaning and " "alter the image deployment behaviour. Press to see more " "information about image properties. Press when done.", height=18, width=MENU_WIDTH, choices=choices, menu_height=10, @@ -519,6 +565,15 @@ def sysprep(session): d = session['dialog'] image_os = session['image_os'] + # Is the image already shrinked? + if 'shrinked' in session and session['shrinked'] == True: + msg = "It seems you have shrinked the image. Running system " \ + "preparation tasks on a shrinked image is dangerous." + + if d.yesno("%s\n\nDo you really want to continue?" % msg, + width=YESNO_WIDTH, defaultno=1): + return + wrapper = textwrap.TextWrapper(width=65) help_title = "System Preperation Tasks" @@ -531,6 +586,10 @@ def sysprep(session): # Only give the user the choice between syspreps that have not ran yet syspreps = [s for s in all_syspreps if s not in session['exec_syspreps']] + if len(syspreps) == 0: + d.msgbox("No system preparation task left to run!", width=MSGBOX_WIDTH) + return + while 1: choices = [] index = 0 @@ -573,14 +632,16 @@ def sysprep(session): if 'checksum' in session: del session['checksum'] - image_os.out = out - image_os.do_sysprep() + # Monitor the metadata changes during syspreps + with metadata_monitor(session, image_os.meta): + image_os.out = out + image_os.do_sysprep() + image_os.out.finalize() # Disable syspreps that have ran for sysprep in session['exec_syspreps']: image_os.disable_sysprep(sysprep) - image_os.out.finalize() finally: dev.umount() finally: @@ -588,7 +649,35 @@ def sysprep(session): break -def customize_menu(session): +def shrink(session): + d = session['dialog'] + dev = session['device'] + + shrinked = 'shrinked' in session and session['shrinked'] == True + + if shrinked: + d.msgbox("You have already shrinked your image!") + return + + msg = "This operation will shrink the last partition of the image to " \ + "reduce the total image size. If the last partition is a swap " \ + "partition, then this partition is removed and the partition " \ + "before that is shrinked. The removed swap partition will be " \ + "recreated during image deployment." + + if not d.yesno("%s\n\nDo you want to continue?" % msg, width=70, + height=12, title="Image Shrinking"): + + with metadata_monitor(session, dev.meta): + dev.out = InfoBoxOutput(d, "Image Shrinking", height=3) + dev.shrink() + dev.out.finalize() + + session['shrinked'] = True + update_background_title(session) + + +def customization_menu(session): d = session['dialog'] choices = [("Sysprep", "Run various image preperation tasks"), @@ -600,6 +689,7 @@ def customize_menu(session): default_item = "Sysprep" actions = {"Sysprep": sysprep, + "Shrink": shrink, "View/Modify": modify_properties, "Delete": delete_properties, "Exclude": exclude_tasks} @@ -631,7 +721,7 @@ def main_menu(session): default_item = "Customize" - actions = {"Customize": customize_menu, "Register": kamaki_menu, + actions = {"Customize": customization_menu, "Register": kamaki_menu, "Extract": extract_image} while 1: (code, choice) = d.menu( @@ -646,7 +736,8 @@ def main_menu(session): break elif choice == "Reset": if confirm_reset(d): - d.infobox("Resetting snf-image-creator. Please wait...") + d.infobox("Resetting snf-image-creator. Please wait...", + width=INFOBOX_WIDTH) raise Reset elif choice in actions: actions[choice](session) @@ -681,13 +772,13 @@ def image_creator(d): sys.stderr.write("%s\n" % usage) return 1 + d.setBackgroundTitle('snf-image-creator') + if os.geteuid() != 0: raise FatalError("You must run %s as root" % basename) media = select_file(d, sys.argv[1] if len(sys.argv) == 2 else None) - d.setBackgroundTitle('snf-image-creator') - out = GaugeOutput(d, "Initialization", "Initializing...") disk = Disk(media, out) @@ -701,12 +792,19 @@ def image_creator(d): dev = disk.get_device(snapshot) out.output("Collecting image metadata...") - metadata = dev.meta + + metadata = {} + for (key, value) in dev.meta.items(): + metadata[str(key)] = str(value) + dev.mount(readonly=True) cls = os_cls(dev.distro, dev.ostype) image_os = cls(dev.root, dev.g, out) dev.umount() - metadata.update(image_os.meta) + + for (key, value) in image_os.meta.items(): + metadata[str(key)] = str(value) + out.success("done") out.cleanup() @@ -748,7 +846,7 @@ def main(): sys.exit(ret) except FatalError as e: msg = textwrap.fill(str(e), width=70) - d.infobox(msg, width=70, title="Fatal Error") + d.infobox(msg, width=INFOBOX_WIDTH, title="Fatal Error") sys.exit(1) except Reset: continue