Example #1
0
def main_menu(session):
    """Show the main menu of the program"""
    d = session['dialog']

    update_background_title(session)

    choices = [("Customize", "Customize image & cloud deployment options"),
               ("Register", "Register image to a cloud"),
               ("Extract", "Dump image to local file system"),
               ("Log", "Show current execution log"),
               ("Reset", "Reset everything and start over again"),
               ("Help", "Get help for using snf-image-creator")]

    default_item = "Customize"

    actions = {
        "Customize": customization_menu,
        "Register": kamaki_menu,
        "Extract": extract_image,
        "Log": show_log
    }
    title = "Image Creator for Synnefo (snf-image-creator v%s)" % version
    while 1:
        (code, choice) = d.menu(
            text="Choose one of the following or press <Exit> to exit.",
            width=WIDTH,
            choices=choices,
            cancel="Exit",
            height=13,
            default_item=default_item,
            menu_height=len(choices),
            title=title)

        if code in (d.CANCEL, d.ESC):
            if confirm_exit(d):
                break
        elif choice == "Reset":
            if confirm_reset(d):
                d.infobox("Resetting snf-image-creator. Please wait ...",
                          width=SMALL_WIDTH)
                raise Reset
        elif choice == "Help":
            d.msgbox(
                "For help, check the online documentation:\n\nhttp://www"
                ".synnefo.org/docs/snf-image-creator/latest/",
                width=WIDTH,
                title="Help")
        elif choice in actions:
            actions[choice](session)

        if len(choice):
            default_item = choice
Example #2
0
def main_menu(session):
    """Show the main menu of the program"""
    d = session['dialog']

    update_background_title(session)

    choices = [("Customize", "Customize image & cloud deployment options"),
               ("Register", "Register image to a cloud"),
               ("Extract", "Dump image to local file system"),
               ("Log", "Show current execution log"),
               ("Reset", "Reset everything and start over again"),
               ("Help", "Get help for using snf-image-creator")]

    default_item = "Customize"

    actions = {"Customize": customization_menu, "Register": kamaki_menu,
               "Extract": extract_image, "Log": show_log}
    title = "Image Creator for Synnefo (snf-image-creator v%s)" % version
    while 1:
        (code, choice) = d.menu(
            text="Choose one of the following or press <Exit> to exit.",
            width=WIDTH, choices=choices, cancel="Exit", height=13,
            default_item=default_item, menu_height=len(choices),
            title=title)

        if code in (d.CANCEL, d.ESC):
            if confirm_exit(d):
                break
        elif choice == "Reset":
            if confirm_reset(d):
                d.infobox("Resetting snf-image-creator. Please wait ...",
                          width=SMALL_WIDTH)
                raise Reset
        elif choice == "Help":
            d.msgbox("For help, check the online documentation:\n\nhttp://www"
                     ".synnefo.org/docs/snf-image-creator/latest/",
                     width=WIDTH, title="Help")
        elif choice in actions:
            actions[choice](session)

        if len(choice):
            default_item = choice
Example #3
0
def sysprep(session):
    """Perform various system preparation tasks on the image"""
    d = session['dialog']
    image = session['image']

    # Is the image already shrinked?
    if image.os.shrinked:
        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=SMALL_WIDTH, defaultno=1) != d.OK:
            return

    wrapper = textwrap.TextWrapper(width=WIDTH-5)

    syspreps = image.os.list_syspreps()

    if len(syspreps) == 0:
        d.msgbox("No system preparation task available to run!",
                 title="System Preparation", width=SMALL_WIDTH)
        return

    while 1:
        choices = []
        index = 0

        help_title = "System Preparation Tasks"
        sysprep_help = "%s\n%s\n\n" % (help_title, '=' * len(help_title))

        for task in syspreps:
            name, descr, display = image.os.sysprep_info(task)
            sysprep_help += "%s\n" % display
            sysprep_help += "%s\n" % ('-' * len(display))
            sysprep_help += "%s\n\n" % wrapper.fill(" ".join(descr.split()))
            enabled = 1 if image.os.sysprep_enabled(task) else 0
            choices.append((str(index + 1), display, enabled))
            index += 1

        (code, tags) = d.checklist(
            "Please choose which system preparation tasks you would like to "
            "run on the image. Press <Params> to view or modify the "
            "customization parameters or <Help> to see details about the "
            "system preparation tasks.", title="Run system preparation tasks",
            choices=choices, width=70, ok_label="Run", help_button=1,
            extra_button=1, extra_label="Params")

        tags = [x.strip('"') for x in tags]  # Needed for OpenSUSE

        if code in (d.CANCEL, d.ESC):
            return False
        elif code == d.EXTRA:
            sysprep_params(session)
        elif code == d.HELP:
            d.scrollbox(sysprep_help, width=WIDTH)
        elif code == d.OK:
            # Enable selected syspreps and disable the rest
            for i in range(len(syspreps)):
                if str(i + 1) in tags:
                    image.os.enable_sysprep(syspreps[i])
                else:
                    image.os.disable_sysprep(syspreps[i])

            if len([s for s in image.os.list_syspreps()
                    if image.os.sysprep_enabled(s)]) == 0:
                d.msgbox("No system preparation task is selected!",
                         title="System Preparation", width=SMALL_WIDTH)
                continue

            infobox = InfoBoxOutput(d, "Image Configuration")
            try:
                image.out.append(infobox)
                try:
                    # The checksum is invalid. We have mounted the image rw
                    if 'checksum' in session:
                        del session['checksum']

                    # Monitor the metadata changes during syspreps
                    with MetadataMonitor(session, image.os.meta):
                        try:
                            image.os.do_sysprep()
                            update_background_title(session)
                            infobox.finalize()
                        except FatalError as error:
                            d.msgbox("System Preparation failed: %s" % error,
                                     title="System Preparation",
                                     width=SMALL_WIDTH)
                finally:
                    image.out.remove(infobox)
            finally:
                infobox.cleanup()
            break
    return True
Example #4
0
def sysprep(session):
    """Perform various system preparation tasks on the image"""
    d = session['dialog']
    image = session['image']

    # Is the image already shrinked?
    if image.os.shrinked:
        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=SMALL_WIDTH,
                   defaultno=1) != d.OK:
            return

    wrapper = textwrap.TextWrapper(width=WIDTH - 5)

    syspreps = image.os.list_syspreps()

    if len(syspreps) == 0:
        d.msgbox("No system preparation task available to run!",
                 title="System Preparation",
                 width=SMALL_WIDTH)
        return

    while 1:
        choices = []
        index = 0

        help_title = "System Preparation Tasks"
        sysprep_help = "%s\n%s\n\n" % (help_title, '=' * len(help_title))

        for task in syspreps:
            _, descr, display = image.os.sysprep_info(task)
            sysprep_help += "%s\n" % display
            sysprep_help += "%s\n" % ('-' * len(display))
            sysprep_help += "%s\n\n" % wrapper.fill(" ".join(descr.split()))
            enabled = 1 if image.os.sysprep_enabled(task) else 0
            choices.append((str(index + 1), display, enabled))
            index += 1

        (code, tags) = d.checklist(
            "Please choose which system preparation tasks you would like to "
            "run on the image. Press <Params> to view or modify the "
            "customization parameters or <Help> to see details about the "
            "system preparation tasks.",
            title="Run system preparation tasks",
            choices=choices,
            width=70,
            ok_label="Run",
            help_button=1,
            extra_button=1,
            extra_label="Params")

        tags = [x.strip('"') for x in tags]  # Needed for OpenSUSE

        if code in (d.CANCEL, d.ESC):
            return False
        elif code == d.EXTRA:
            sysprep_params(session)
        elif code == d.HELP:
            d.scrollbox(sysprep_help, width=WIDTH)
        elif code == d.OK:
            # Enable selected syspreps and disable the rest
            for i, _ in enumerate(syspreps):
                if str(i + 1) in tags:
                    image.os.enable_sysprep(syspreps[i])
                else:
                    image.os.disable_sysprep(syspreps[i])

            if len([
                    s for s in image.os.list_syspreps()
                    if image.os.sysprep_enabled(s)
            ]) == 0:
                d.msgbox("No system preparation task is selected!",
                         title="System Preparation",
                         width=SMALL_WIDTH)
                continue

            infobox = InfoBoxOutput(d, "Image Configuration")
            try:
                image.out.append(infobox)
                try:
                    # The checksum is invalid. We have mounted the image rw
                    if 'checksum' in session:
                        del session['checksum']

                    # Monitor the metadata changes during syspreps
                    with MetadataMonitor(session, image.os.meta):
                        try:
                            image.os.do_sysprep()
                            update_background_title(session)
                            infobox.finalize()
                        except FatalError as error:
                            d.msgbox("System Preparation failed: %s" % error,
                                     title="System Preparation",
                                     width=SMALL_WIDTH)
                finally:
                    image.out.remove(infobox)
            finally:
                infobox.cleanup()
            break
    return True
Example #5
0
def create_image(session, answers):
    """Create an image using the information collected by the wizard"""
    image = session['image']

    with_progress = OutputWthProgress()
    image.out.append(with_progress)
    try:
        image.out.clear()

        if 'virtio' in answers and image.os.sysprep_params['virtio'].value:
            image.os.install_virtio_drivers()

        # Sysprep
        image.os.do_sysprep()
        metadata = image.os.meta

        update_background_title(session)

        metadata['DESCRIPTION'] = answers['ImageDescription']

        # MD5
        session['checksum'] = image.md5()

        image.out.info()
        try:
            image.out.info("Uploading image to the cloud:")
            account = Kamaki.get_account(answers['Cloud'])
            assert account, "Cloud: %s is not valid" % answers['Cloud']
            kamaki = Kamaki(account, image.out)

            name = "%s-%s.diskdump" % (answers['ImageName'],
                                       time.strftime("%Y%m%d%H%M"))
            with image.raw_device() as raw:
                with open(raw, 'rb') as device:
                    remote = kamaki.upload(device, image.size, name, CONTAINER,
                                           None,
                                           "(1/3)  Calculating block hashes",
                                           "(2/3)  Uploading image blocks")

            image.out.info("(3/3)  Uploading md5sum file ...", False)
            md5sumstr = '%s %s\n' % (session['checksum'], name)
            kamaki.upload(StringIO.StringIO(md5sumstr), size=len(md5sumstr),
                          remote_path="%s.%s" % (name, 'md5sum'),
                          container=CONTAINER, content_type="text/plain")
            image.out.success('done')
            image.out.info()

            image.out.info('Registering %s image with the cloud ...' %
                           answers['RegistrationType'].lower(), False)
            result = kamaki.register(answers['ImageName'], remote, metadata,
                                     answers['RegistrationType'] == "Public")
            image.out.success('done')
            image.out.info("Uploading metadata file ...", False)
            metastring = unicode(
                json.dumps(result, ensure_ascii=False)).encode('utf8')
            kamaki.upload(StringIO.StringIO(metastring), size=len(metastring),
                          remote_path="%s.%s" % (name, 'meta'),
                          container=CONTAINER, content_type="application/json")
            image.out.success('done')

            if answers['RegistrationType'] == "Public":
                image.out.info("Sharing md5sum file ...", False)
                kamaki.share("%s.md5sum" % name)
                image.out.success('done')
                image.out.info("Sharing metadata file ...", False)
                kamaki.share("%s.meta" % name)
                image.out.success('done')

            image.out.info()

        except ClientError as error:
            raise FatalError("Storage service client: %d %s" %
                             (error.status, error.message))
    finally:
        image.out.remove(with_progress)

    text = "The %s image was successfully uploaded to the storage service " \
           "and registered with the compute service of %s. Would you like " \
           "to keep a local copy?" % \
           (answers['RegistrationType'].lower(), answers['Cloud'])

    if session['dialog'].yesno(text, width=PAGE_WIDTH) == session['dialog'].OK:
        extract_image(session)
Example #6
0
def create_image(d, media, out, tmp, snapshot):
    """Create an image out of `media'"""
    d.setBackgroundTitle('snf-image-creator')

    gauge = GaugeOutput(d, "Initialization", "Initializing...")
    out.append(gauge)
    disk = Disk(media, out, tmp)

    # pylint: disable=unused-argument
    def signal_handler(signum, frame):
        gauge.cleanup()
        disk.cleanup()

    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)
    try:

        device = disk.file if not snapshot else disk.snapshot()

        image = disk.get_image(device)

        gauge.cleanup()
        out.remove(gauge)

        # Make sure the signal handler does not call gauge.cleanup again
        def dummy(self):  # pylint: disable=unused-argument
            pass
        gauge.cleanup = type(GaugeOutput.cleanup)(dummy, gauge, GaugeOutput)

        session = {"dialog": d,
                   "disk": disk,
                   "image": image}

        if image.is_unsupported():

            session['excluded_tasks'] = [-1]
            session['task_metadata'] = ["EXCLUDE_ALL_TASKS"]

            msg = "The system on the input media is not supported." \
                "\n\nReason: %s\n\n" \
                "We highly recommend not to create an image out of this, " \
                "since the image won't be cleaned up and you will not be " \
                "able to configure it during the deployment. Press <YES> if " \
                "you still want to continue with the image creation process." \
                % image._unsupported

            if d.yesno(msg, width=WIDTH, defaultno=1, height=12) == d.OK:
                main_menu(session)

            d.infobox("Thank you for using snf-image-creator. Bye", width=53)
            return 0

        msg = "snf-image-creator detected a %s system on the input media. " \
              "Would you like to run a wizard to assist you through the " \
              "image creation process?\n\nChoose <Wizard> to run the wizard," \
              " <Expert> to run snf-image-creator in expert mode or press " \
              "ESC to quit the program." \
              % (image.ostype.capitalize() if image.ostype == image.distro or
                 image.distro == "unknown" else "%s (%s)" %
                 (image.ostype.capitalize(), image.distro.capitalize()))

        update_background_title(session)

        while True:
            code = d.yesno(msg, width=WIDTH, height=12, yes_label="Wizard",
                           no_label="Expert")
            if code == d.OK:
                if start_wizard(session):
                    break
            elif code == d.CANCEL:
                main_menu(session)
                break

            if confirm_exit(d):
                break

        d.infobox("Thank you for using snf-image-creator. Bye", width=53)
    finally:
        disk.cleanup()

    return 0
def create_image(d, media, out, tmp, snapshot):
    """Create an image out of `media'"""
    d.setBackgroundTitle('snf-image-creator')

    gauge = GaugeOutput(d, "Initialization", "Initializing...")
    out.append(gauge)
    disk = Disk(media, out, tmp)

    # pylint: disable=unused-argument
    def signal_handler(signum, frame):
        gauge.cleanup()
        disk.cleanup()

    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)
    try:

        device = disk.file if not snapshot else disk.snapshot()

        image = disk.get_image(device)

        gauge.cleanup()
        out.remove(gauge)

        # Make sure the signal handler does not call gauge.cleanup again
        def dummy(self):  # pylint: disable=unused-argument
            pass

        gauge.cleanup = type(GaugeOutput.cleanup)(dummy, gauge, GaugeOutput)

        session = {"dialog": d, "disk": disk, "image": image}

        if image.is_unsupported():

            session['excluded_tasks'] = [-1]
            session['task_metadata'] = ["EXCLUDE_ALL_TASKS"]

            msg = "The system on the input media is not supported." \
                "\n\nReason: %s\n\n" \
                "We highly recommend not to create an image out of this, " \
                "since the image won't be cleaned up and you will not be " \
                "able to configure it during the deployment. Press <YES> if " \
                "you still want to continue with the image creation process." \
                % image._unsupported

            if d.yesno(msg, width=WIDTH, defaultno=1, height=12) == d.OK:
                main_menu(session)

            d.infobox("Thank you for using snf-image-creator. Bye", width=53)
            return 0

        msg = "snf-image-creator detected a %s system on the input media. " \
              "Would you like to run a wizard to assist you through the " \
              "image creation process?\n\nChoose <Wizard> to run the wizard," \
              " <Expert> to run snf-image-creator in expert mode or press " \
              "ESC to quit the program." \
              % (image.ostype.capitalize() if image.ostype == image.distro or
                 image.distro == "unknown" else "%s (%s)" %
                 (image.ostype.capitalize(), image.distro.capitalize()))

        update_background_title(session)

        while True:
            code = d.yesno(msg,
                           width=WIDTH,
                           height=12,
                           yes_label="Wizard",
                           no_label="Expert")
            if code == d.OK:
                if start_wizard(session):
                    break
            elif code == d.CANCEL:
                main_menu(session)
                break

            if confirm_exit(d):
                break

        d.infobox("Thank you for using snf-image-creator. Bye", width=53)
    finally:
        disk.cleanup()

    return 0
def create_image(session, answers):
    """Create an image using the information collected by the wizard"""
    image = session['image']

    with_progress = OutputWthProgress()
    image.out.append(with_progress)
    try:
        image.out.clear()

        if 'virtio' in answers and image.os.sysprep_params['virtio'].value:
            image.os.install_virtio_drivers()

        # Sysprep
        image.os.do_sysprep()
        metadata = image.os.meta

        update_background_title(session)

        metadata['DESCRIPTION'] = answers['ImageDescription']

        # MD5
        session['checksum'] = image.md5()

        image.out.info()
        try:
            image.out.info("Uploading image to the cloud:")
            account = Kamaki.get_account(answers['Cloud'])
            assert account, "Cloud: %s is not valid" % answers['Cloud']
            kamaki = Kamaki(account, image.out)

            name = "%s-%s.diskdump" % (answers['ImageName'],
                                       time.strftime("%Y%m%d%H%M"))
            with image.raw_device() as raw:
                with open(raw, 'rb') as device:
                    remote = kamaki.upload(device, image.size, name, CONTAINER,
                                           None,
                                           "(1/3)  Calculating block hashes",
                                           "(2/3)  Uploading image blocks")

            image.out.info("(3/3)  Uploading md5sum file ...", False)
            md5sumstr = '%s %s\n' % (session['checksum'], name)
            kamaki.upload(StringIO.StringIO(md5sumstr),
                          size=len(md5sumstr),
                          remote_path="%s.%s" % (name, 'md5sum'),
                          container=CONTAINER,
                          content_type="text/plain")
            image.out.success('done')
            image.out.info()

            image.out.info(
                'Registering %s image with the cloud ...' %
                answers['RegistrationType'].lower(), False)
            result = kamaki.register(answers['ImageName'], remote, metadata,
                                     answers['RegistrationType'] == "Public")
            image.out.success('done')
            image.out.info("Uploading metadata file ...", False)
            metastring = unicode(json.dumps(result,
                                            ensure_ascii=False)).encode('utf8')
            kamaki.upload(StringIO.StringIO(metastring),
                          size=len(metastring),
                          remote_path="%s.%s" % (name, 'meta'),
                          container=CONTAINER,
                          content_type="application/json")
            image.out.success('done')

            if answers['RegistrationType'] == "Public":
                image.out.info("Sharing md5sum file ...", False)
                kamaki.share("%s.md5sum" % name)
                image.out.success('done')
                image.out.info("Sharing metadata file ...", False)
                kamaki.share("%s.meta" % name)
                image.out.success('done')

            image.out.info()

        except ClientError as error:
            raise FatalError("Storage service client: %d %s" %
                             (error.status, error.message))
    finally:
        image.out.remove(with_progress)

    text = "The %s image was successfully uploaded to the storage service " \
           "and registered with the compute service of %s. Would you like " \
           "to keep a local copy?" % \
           (answers['RegistrationType'].lower(), answers['Cloud'])

    if session['dialog'].yesno(text, width=PAGE_WIDTH) == session['dialog'].OK:
        extract_image(session)