Revision 7f623b20 image_creator/dialog_main.py

b/image_creator/dialog_main.py
46 46
from image_creator.disk import Disk
47 47
from image_creator.os_type import os_cls
48 48
from image_creator.kamaki_wrapper import Kamaki, ClientError
49
from image_creator.help import get_help_file
49 50

  
50 51
MSGBOX_WIDTH = 60
51 52
YESNO_WIDTH = 50
52 53
MENU_WIDTH = 70
53 54
INPUTBOX_WIDTH = 70
54

  
55
CONFIGURATION_TASKS = {
56
    "FixPartitionTable":
57
        "Enlarge last partition to use all the available space",
58
    "FilesystemResizeUnmounted":
59
        "Resize file system to use all the available space",
60
    "AddSwap": "Set up the swap partition and add an entry in fstab",
61
    "DeleteSSHKeys": "Remove ssh keys and in some cases recreate them",
62
    "DisableRemoteDesktopConnections":
63
        "Temporary Disable Remote Desktop Connections",
64
    "40SELinuxAutorelabel": "Force the system to relabel at next boot",
65
    "AssignHostname": "Assign Hostname/Computer Name to the instance",
66
    "ChangePassword": "Changes Password for specified users",
67
    "EnforcePersonality": "Inject files to the instance",
68
    "FilesystemResizeMounted":
69
        "Resize filesystem to use all the available space"}
55
CHECKBOX_WIDTH = 70
56

  
57
CONFIGURATION_TASKS = [
58
 ("Partition table manipulation", ["FixPartitionTable"],
59
  ["linux", "windows"]),
60
 ("File system resize",
61
  ["FilesystemResizeUnmounted", "FilesystemResizeMounted"],
62
  ["linux", "windows"]),
63
 ("Swap partition configuration", ["AddSwap"], ["linux"]),
64
 ("SSH keys removal", ["DeleteSSHKeys"], ["linux"]),
65
 ("Temporal RDP disabling", ["DisableRemoteDesktopConnections"], ["windows"]),
66
 ("SELinux relabeling at next boot", ["SELinuxAutorelabel"],
67
  ["linux"]),
68
 ("Hostname/Computer Name assignment", ["AssignHostname"],
69
  ["windows", "linux"]),
70
 ("Password change", ["ChangePassword"], ["windows", "linux"]),
71
 ("File injection", ["EnforcePersonality"], ["windows", "linux"])
72
]
70 73

  
71 74

  
72 75
class Reset(Exception):
......
234 237

  
235 238
    d.msgbox("Image file `%s' was successfully uploaded to pithos+" % filename,
236 239
             width=MSGBOX_WIDTH)
240

  
237 241
    return True
238 242

  
239 243

  
......
429 433
        choices.append((key, "%s" % val, 0))
430 434

  
431 435
    (code, to_delete) = d.checklist("Choose which properties to delete:",
432
                                    choices=choices)
436
                                    choices=choices, width=CHECKBOX_WIDTH)
433 437
    count = len(to_delete)
434 438
    # If the user exits with ESC or CANCEL, the returned tag list is empty.
435 439
    for i in to_delete:
......
439 443
        d.msgbox("%d image properties were deleted.", width=MSGBOX_WIDTH)
440 444

  
441 445

  
442
def exclude_task(session):
446
def exclude_tasks(session):
443 447
    d = session['dialog']
444 448

  
449
    index = 0
450
    displayed_index = 1
445 451
    choices = []
446
    for (key, val) in session['metadata'].items():
447
        choices.append((key, "%s" % val, 0))
452
    mapping = {}
453
    if 'excluded_tasks' not in session:
454
        session['excluded_tasks'] = []
455

  
456
    if -1 in session['excluded_tasks']:
457
        if not d.yesno("Image deployment configuration is disabled. "
458
                       "Do you wish to enable it?", width=YESNO_WIDTH):
459
            session['excluded_tasks'].remove(-1)
460
        else:
461
            return
462

  
463
    for (msg, task, osfamily) in CONFIGURATION_TASKS:
464
        if session['metadata']['OSFAMILY'] in osfamily:
465
            checked = 1 if index in session['excluded_tasks'] else 0
466
            choices.append((str(displayed_index), msg, checked))
467
            mapping[displayed_index] = index
468
            displayed_index += 1
469
        index += 1
448 470

  
449
    (code, to_delete) = d.checklist("Choose which properties to delete:",
450
                                    choices=choices)
451
    count = len(to_delete)
452
    # If the user exits with ESC or CANCEL, the returned tag list is empty.
453
    for i in to_delete:
454
        del session['metadata'][i]
471
    while 1:
472
        (code, tags) = d.checklist(
473
            "Please choose which configuration tasks you would like to "
474
            "prevent from running during image deployment. "
475
            "Press <No Config> to supress any configuration. "
476
            "Press <Help> for more help on the image deployment configuration "
477
            "tasks.", height=19, list_height=8,
478
            title="Exclude Configuration Tasks", choices=choices,
479
            width=CHECKBOX_WIDTH, help_button=1, extra_button=1,
480
            extra_label="No Config")
455 481

  
456
    if count > 0:
457
        d.msgbox("%d image properties were deleted.", width=MSGBOX_WIDTH)
482
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
483
            break
484
        elif code == d.DIALOG_HELP:
485
            help_file = get_help_file("configuration_tasks")
486
            assert os.path.exists(help_file)
487
            d.textbox(help_file, title="Configuration Tasks",
488
                                                        width=70, height=40)
489
            continue
490
        elif code == d.DIALOG_EXTRA:
491
            session['excluded_tasks'] = [-1]
492
            session['task_metadata'] = ["EXCLUDE_ALL_TASKS"]
493
            break
494
        elif code == d.DIALOG_OK:
495
            session['excluded_tasks'] = []
496
            for tag in tags:
497
                session['excluded_tasks'].append(mapping[int(tag)])
458 498

  
499
            exclude_metadata = []
500
            for task in session['excluded_tasks']:
501
                exclude_metadata.extend(CONFIGURATION_TASKS[task][1])
459 502

  
460
def deploy_menu(session):
503
            session['task_metadata'] = \
504
                        map(lambda x: "EXCLUDE_TASK_%s" % x, exclude_metadata)
505
            break
506

  
507

  
508
def sysprep(session):
461 509
    d = session['dialog']
510
    image_os = session['image_os']
511

  
512
    syspreps = image_os.list_syspreps()
513

  
514
    wrapper = textwrap.TextWrapper()
515
    wrapper.width = 65
516
    sysprep_help = "System Preperation Tasks"
517
    sysprep_help += "\n%s\n\n" % ('=' * len(sysprep_help))
462 518

  
463
    default_item = "View/Modify"
464
    actions = {"View/Modify": modify_properties, "Delete": delete_properties}
519
    while 1:
520
        choices = []
521
        index = 0
522
        for sysprep in syspreps:
523
            name, descr = image_os.sysprep_info(sysprep)
524
            display_name = name.replace('-', ' ').capitalize()
525
            sysprep_help += "%s\n%s\n%s\n\n" % \
526
                            (display_name, '-' * len(display_name),
527
                            wrapper.fill(" ".join(descr.split())))
528
            enabled = 1 if sysprep.enabled else 0
529
            choices.append((str(index + 1), display_name, enabled))
530
            index += 1
531

  
532
        (code, tags) = d.checklist(
533
            "Please choose which system preperation tasks you would like to "
534
            "run on the image. Press <Help> to see details about the system "
535
            "preperation tasks.",
536
            title="Run system preperation tasks", choices=choices,
537
            width=70, ok_label="Run", help_button=1)
538

  
539
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
540
            break
541
        if code == d.DIALOG_HELP:
542
            d.scrollbox(sysprep_help, width=70)
543
            continue
544

  
545

  
546
def customize_menu(session):
547
    d = session['dialog']
548

  
549
    default_item = "Sysprep"
550
    actions = {"Sysprep": sysprep,
551
               "View/Modify": modify_properties,
552
               "Delete": delete_properties,
553
               "Exclude": exclude_tasks}
465 554
    while 1:
466 555
        (code, choice) = d.menu(
467 556
            "Choose one of the following or press <Back> to exit.",
468 557
            width=MENU_WIDTH,
469
            choices=[("View/Modify", "View/Modify image properties"),
558
            choices=[("Sysprep", "Run various image preperation tasks"),
559
                     ("Shrink", "Shrink image"),
560
                     ("View/Modify", "View/Modify image properties"),
470 561
                     ("Delete", "Delete image properties"),
471
                     ("Exclude", "Exclude configuration tasks from running")],
472
        cancel="Back",
473
        default_item=default_item,
474
        title="Image Deployment Menu")
562
                     ("Exclude",
563
                      "Exclude various deployment tasks from running")],
564
            cancel="Back",
565
            default_item=default_item,
566
            title="Image Customization Menu")
475 567

  
476 568
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
477 569
            break
......
484 576
    d = session['dialog']
485 577
    dev = session['device']
486 578
    d.setBackgroundTitle("OS: %s, Distro: %s" % (dev.ostype, dev.distro))
487
    actions = {"Deploy": deploy_menu,
579
    actions = {"Customize": customize_menu,
488 580
               "Register": kamaki_menu,
489 581
               "Extract": extract_image}
490 582
    default_item = "Customize"
......
493 585
        (code, choice) = d.menu(
494 586
            "Choose one of the following or press <Exit> to exit.",
495 587
            width=MENU_WIDTH,
496
            choices=[("Customize", "Run various image customization tasks"),
497
                     ("Deploy", "Configure ~okeanos image deployment options"),
588
            choices=[("Customize",
589
                      "Customize image and ~okeanos deployment options"),
498 590
                     ("Register", "Register image to ~okeanos"),
499 591
                     ("Extract", "Dump image to local file system"),
500 592
                     ("Reset", "Reset everything and start over again"),
501 593
                     ("Help", "Get help for using snf-image-creator")],
502
            cancel="Exit",
503
            default_item=default_item,
594
            cancel="Exit", menu_height=5, height=13, default_item=default_item,
504 595
            title="Image Creator for ~okeanos (snf-image-creator version %s)" %
505 596
                  version)
506 597

  
507 598
        if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
508 599
            if confirm_exit(d):
509 600
                break
510
            else:
511
                continue
512

  
513
        if choice == "Reset":
601
        elif choice == "Reset":
514 602
            if confirm_reset(d):
515 603
                d.infobox("Resetting snf-image-creator. Please wait...")
516 604
                raise Reset
517
            else:
518
                continue
519 605
        elif choice in actions:
520 606
            actions[choice](session)
521 607

  
......
542 628
    return media
543 629

  
544 630

  
545
def collect_metadata(dev, out):
546

  
547
    out.output("Collecting image metadata...")
548
    metadata = dev.meta
549
    dev.mount(readonly=True)
550
    cls = os_cls(dev.distro, dev.ostype)
551
    image_os = cls(dev.root, dev.g, out)
552
    dev.umount()
553
    metadata.update(image_os.meta)
554
    out.success("done")
555

  
556
    return metadata
557

  
558

  
559 631
def image_creator(d):
560 632
    basename = os.path.basename(sys.argv[0])
561 633
    usage = "Usage: %s [input_media]" % basename
......
580 652
        snapshot = disk.snapshot()
581 653
        dev = disk.get_device(snapshot)
582 654

  
583
        metadata = collect_metadata(dev, out)
655
        out.output("Collecting image metadata...")
656
        metadata = dev.meta
657
        dev.mount(readonly=True)
658
        cls = os_cls(dev.distro, dev.ostype)
659
        image_os = cls(dev.root, dev.g, out)
660
        dev.umount()
661
        metadata.update(image_os.meta)
662
        out.success("done")
584 663
        out.cleanup()
585 664

  
586 665
        # Make sure the signal handler does not call out.cleanup again
......
593 672
                   "disk": disk,
594 673
                   "snapshot": snapshot,
595 674
                   "device": dev,
675
                   "image_os": image_os,
596 676
                   "metadata": metadata}
597 677

  
598 678
        main_menu(session)

Also available in: Unified diff