X-Git-Url: https://code.grnet.gr/git/snf-image-creator/blobdiff_plain/2a21ff92a5af881912920b22dda1cdcc49067300..f9d8c3d9121a6ca664b6ea3cb6c1eb4b573c5df4:/image_creator/dialog_main.py diff --git a/image_creator/dialog_main.py b/image_creator/dialog_main.py index 700825c..2dca2d6 100644 --- a/image_creator/dialog_main.py +++ b/image_creator/dialog_main.py @@ -50,7 +50,23 @@ from image_creator.kamaki_wrapper import Kamaki, ClientError MSGBOX_WIDTH = 60 YESNO_WIDTH = 50 MENU_WIDTH = 70 -INPUTBOX_WIDTH=70 +INPUTBOX_WIDTH = 70 + +CONFIGURATION_TASKS = { + "FixPartitionTable": + "Enlarge last partition to use all the available space", + "FilesystemResizeUnmounted": + "Resize file system to use all the available space", + "AddSwap": "Set up the swap partition and add an entry in fstab", + "DeleteSSHKeys": "Remove ssh keys and in some cases recreate them", + "DisableRemoteDesktopConnections": + "Temporary Disable Remote Desktop Connections", + "40SELinuxAutorelabel": "Force the system to relabel at next boot", + "AssignHostname": "Assign Hostname/Computer Name to the instance", + "ChangePassword": "Changes Password for specified users", + "EnforcePersonality": "Inject files to the instance", + "FilesystemResizeMounted": + "Resize filesystem to use all the available space"} class Reset(Exception): @@ -66,6 +82,7 @@ def confirm_reset(d): "Are you sure you want to reset everything?", width=YESNO_WIDTH) + def extract_image(session): d = session['dialog'] dir = os.getcwd() @@ -78,7 +95,7 @@ def extract_image(session): return False if os.path.isdir(path): - dir=path + dir = path continue if os.path.isdir("%s.meta" % path): @@ -164,10 +181,10 @@ def upload_image(session): return False while 1: - init=session["upload"] if "upload" in session else '' + init = session["upload"] if "upload" in session else '' (code, answer) = d.inputbox("Please provide a filename:", init=init, width=INPUTBOX_WIDTH) - + if code in (d.DIALOG_CANCEL, d.DIALOG_ESC): return False @@ -175,7 +192,7 @@ def upload_image(session): if len(filename) == 0: d.msgbox("Filename cannot be empty", width=MSGBOX_WIDTH) continue - + break out = GaugeOutput(d, "Image Upload", "Uploading...") @@ -215,7 +232,7 @@ def upload_image(session): finally: out.cleanup() - d.msgbox("Image file `%s' was successfully uploaded to pithos+" % filename, + d.msgbox("Image file `%s' was successfully uploaded to pithos+" % filename, width=MSGBOX_WIDTH) return True @@ -288,6 +305,7 @@ def kamaki_menu(session): ("Register", "Register image to cyclades: %s" % upload)], cancel="Back", default_item=default_item, + help_button=1, title="Image Registration Menu") if code in (d.DIALOG_CANCEL, d.DIALOG_ESC): @@ -331,11 +349,144 @@ def kamaki_menu(session): default_item = "Register" +def add_property(session): + d = session['dialog'] + + while 1: + (code, answer) = d.inputbox("Please provide a name for a new image" + " property:", width=INPUTBOX_WIDTH) + if code in (d.DIALOG_CANCEL, d.DIALOG_ESC): + return False + + name = answer.strip() + if len(name) == 0: + d.msgbox("A property name cannot be empty", width=MSGBOX_WIDTH) + continue + + break + + while 1: + (code, answer) = d.inputbox("Please provide a value for image " + "property %s" % name, width=INPUTBOX_WIDTH) + if code in (d.DIALOG_CANCEL, d.DIALOG_ESC): + return False + + value = answer.strip() + if len(value) == 0: + d.msgbox("Value cannot be empty", width=MSGBOX_WIDTH) + continue + + break + + session['metadata'][name] = value + + return True + + +def modify_properties(session): + d = session['dialog'] + + while 1: + choices = [] + for (key, val) in session['metadata'].items(): + choices.append((str(key), str(val))) + + (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 " + "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, + ok_label="EDIT", extra_button=1, extra_label="ADD", cancel="BACK", + help_button=1, help_label="HELP", title="Image Metadata") + + if code in (d.DIALOG_CANCEL, d.DIALOG_ESC): + break + # Edit button + elif code == d.DIALOG_OK: + (code, answer) = d.inputbox("Please provide a new value for " + "the image property with name `%s':" % choice, + init=session['metadata'][choice], width=INPUTBOX_WIDTH) + if code not in (d.DIALOG_CANCEL, d.DIALOG_ESC): + value = answer.strip() + if len(value) == 0: + d.msgbox("Value cannot be empty!") + continue + else: + session['metadata'][choice] = value + # ADD button + elif code == d.DIALOG_EXTRA: + add_property(session) + + +def delete_properties(session): + d = session['dialog'] + + choices = [] + for (key, val) in session['metadata'].items(): + choices.append((key, "%s" % val, 0)) + + (code, to_delete) = d.checklist("Choose which properties to delete:", + choices=choices) + count = len(to_delete) + # If the user exits with ESC or CANCEL, the returned tag list is empty. + for i in to_delete: + del session['metadata'][i] + + if count > 0: + d.msgbox("%d image properties were deleted.", width=MSGBOX_WIDTH) + + +def exclude_task(session): + d = session['dialog'] + + choices = [] + for (key, val) in session['metadata'].items(): + choices.append((key, "%s" % val, 0)) + + (code, to_delete) = d.checklist("Choose which properties to delete:", + choices=choices) + count = len(to_delete) + # If the user exits with ESC or CANCEL, the returned tag list is empty. + for i in to_delete: + del session['metadata'][i] + + if count > 0: + d.msgbox("%d image properties were deleted.", width=MSGBOX_WIDTH) + + +def deploy_menu(session): + d = session['dialog'] + + default_item = "View/Modify" + actions = {"View/Modify": modify_properties, "Delete": delete_properties} + while 1: + (code, choice) = d.menu( + "Choose one of the following or press to exit.", + width=MENU_WIDTH, + choices=[("View/Modify", "View/Modify image properties"), + ("Delete", "Delete image properties"), + ("Exclude", "Exclude configuration tasks from running")], + cancel="Back", + default_item=default_item, + title="Image Deployment Menu") + + if code in (d.DIALOG_CANCEL, d.DIALOG_ESC): + break + elif choice in actions: + default_item = choice + actions[choice](session) + + def main_menu(session): d = session['dialog'] dev = session['device'] d.setBackgroundTitle("OS: %s, Distro: %s" % (dev.ostype, dev.distro)) - actions = {"Register": kamaki_menu, "Extract": extract_image} + actions = {"Deploy": deploy_menu, + "Register": kamaki_menu, + "Extract": extract_image} default_item = "Customize" while 1: @@ -369,24 +520,26 @@ def main_menu(session): actions[choice](session) -def select_file(d): +def select_file(d, media): root = os.sep while 1: - (code, path) = d.fselect(root, 10, 50, + if media is not None: + if not os.path.exists(media): + d.msgbox("The file you choose does not exist", + width=MSGBOX_WIDTH) + else: + break + + (code, media) = d.fselect(root, 10, 50, title="Please select input media") 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 - if not os.path.exists(path): - d.msgbox("The file you choose does not exist", width=MSGBOX_WIDTH) - continue - else: - break - - return path + return media def collect_metadata(dev, out): @@ -413,7 +566,7 @@ def image_creator(d): if os.geteuid() != 0: raise FatalError("You must run %s as root" % basename) - media = sys.argv[1] if len(sys.argv) == 2 else select_file(d) + media = select_file(d, sys.argv[1] if len(sys.argv) == 2 else None) out = InitializationOutput(d) disk = Disk(media, out) @@ -454,6 +607,13 @@ def main(): d = dialog.Dialog(dialog="dialog") + # Add extra button in dialog library + dialog._common_args_syntax["extra_button"] = \ + lambda enable: dialog._simple_option("--extra-button", enable) + + dialog._common_args_syntax["extra_label"] = \ + lambda string: ("--extra-label", string) + while 1: try: try: