Exemplo n.º 1
0
def register_image(session):
    """Register image with the compute service"""
    d = session["dialog"]
    image = session['image']

    assert 'clouds' in session

    try:
        cloud_name = session['current_cloud']
        cloud = session['clouds'][cloud_name]
        account = cloud['account']
    except KeyError:
        cloud = None

    if cloud is None or account is None:
        d.msgbox("You need to select a valid cloud before you can register an "
                 "images with it", width=SMALL_WIDTH)
        return False

    if "uploaded" not in cloud:
        d.msgbox("You need to upload the image to a cloud before you can "
                 "register it", width=SMALL_WIDTH)
        return False

    is_public = False
    _, _, _, container, remote = cloud['uploaded'].split('/')
    name = "" if 'registered' not in cloud else cloud['registered']
    descr = image.meta['DESCRIPTION'] if 'DESCRIPTION' in image.meta else ""

    while 1:
        fields = [("Registration name:", name, 60),
                  ("Description (optional):", descr, 80)]

        (code, output) = d.form(
            "Please provide the following registration info:",
            create_form_elements(fields), height=11, width=WIDTH,
            form_height=2)

        if code in (d.CANCEL, d.ESC):
            return False

        name, descr = output
        name = name.strip()
        descr = descr.strip()

        if len(name) == 0:
            d.msgbox("Registration name cannot be empty", width=SMALL_WIDTH)
            continue

        answer = d.yesno("Make the image public?\\nA public image is "
                         "accessible by every user of the service.",
                         defaultno=1, width=WIDTH)
        if answer == d.ESC:
            continue

        is_public = (answer == d.OK)
        break

    image.meta['DESCRIPTION'] = descr
    metadata = {}
    metadata.update(image.meta)
    if 'task_metadata' in session:
        for key in session['task_metadata']:
            metadata[key] = 'yes'

    img_type = "public" if is_public else "private"
    gauge = GaugeOutput(d, "Image Registration", "Registering image ...")
    try:
        out = session['image'].out
        out.append(gauge)
        try:
            try:
                out.info("Registering %s image with the cloud ..." % img_type,
                         False)
                kamaki = Kamaki(cloud['account'], out)
                cloud['registered'] = kamaki.register(
                    name, cloud['uploaded'], metadata, is_public)
                out.success('done')

                # Upload metadata file
                out.info("Uploading metadata file ...", False)
                metastring = json.dumps(cloud['registered'], indent=4,
                                        ensure_ascii=False)
                kamaki.upload(StringIO.StringIO(metastring),
                              size=len(metastring),
                              remote_path="%s.meta" % remote,
                              container=container,
                              content_type="application/json")
                out.success("done")
                if is_public:
                    out.info("Sharing metadata and md5sum files ...", False)
                    kamaki.share("%s.meta" % remote)
                    kamaki.share("%s.md5sum" % remote)
                    out.success('done')
            except ClientError as error:
                d.msgbox("Error in storage service client: %s" % error.message)
                return False
        finally:
            out.remove(gauge)
    finally:
        gauge.cleanup()

    d.msgbox("%s image `%s' was successfully registered with the cloud as `%s'"
             % (img_type.title(), remote, name), width=SMALL_WIDTH)
    return True
Exemplo n.º 2
0
def upload_image(session):
    """Upload the image to the storage service"""
    d = session["dialog"]
    image = session['image']

    assert 'clouds' in session

    try:
        cloud_name = session['current_cloud']
        cloud = session['clouds'][cloud_name]
        account = cloud['account']
    except KeyError:
        cloud = None

    if cloud is None or not account:
        d.msgbox(
            "You need to select a valid cloud before you can upload "
            "images to it",
            width=SMALL_WIDTH)
        return False

    while 1:
        if 'uploaded' in cloud:
            _, _, _, container, name = cloud['uploaded'].split('/')
        elif 'OS' in session['image'].meta:
            name = "%s.diskdump" % session['image'].meta['OS']
            container = CONTAINER
        else:
            name = ""
            container = CONTAINER

        fields = [("Remote Name:", name, 60), ("Container:", container, 60)]

        (code, output) = d.form("Please provide the following upload info:",
                                create_form_elements(fields),
                                height=11,
                                width=WIDTH,
                                form_height=2)

        if code in (d.CANCEL, d.ESC):
            return False

        name, container = output
        name = name.strip()
        container = container.strip()

        if len(name) == 0:
            d.msgbox("Remote Name cannot be empty", width=SMALL_WIDTH)
            continue

        if len(container) == 0:
            d.msgbox("Container cannot be empty", width=SMALL_WIDTH)
            continue

        kamaki = Kamaki(cloud['account'], None)
        overwrite = []
        for f in (name, "%s.md5sum" % name, "%s.meta" % name):
            if kamaki.object_exists(container, f):
                overwrite.append(f)

        if len(overwrite) > 0:
            if d.yesno("The following storage service object(s) already "
                       "exist(s):\n%s\nDo you want to overwrite them?" %
                       "\n".join(overwrite),
                       width=WIDTH,
                       defaultno=1) != d.OK:
                continue
        break

    gauge = GaugeOutput(d, "Image Upload", "Uploading ...")
    try:
        out = image.out
        out.append(gauge)
        kamaki.out = out
        try:
            if 'checksum' not in session:
                session['checksum'] = image.md5()

            try:
                # Upload image file
                with image.raw_device() as raw:
                    with open(raw, 'rb') as f:
                        cloud["uploaded"] = \
                            kamaki.upload(f, image.size, name, container, None,
                                          "Calculating block hashes",
                                          "Uploading missing blocks")
                # Upload md5sum file
                out.info("Uploading md5sum file ...")
                md5str = "%s %s\n" % (session['checksum'], name)
                kamaki.upload(StringIO.StringIO(md5str),
                              size=len(md5str),
                              remote_path="%s.md5sum" % name,
                              container=container,
                              content_type="text/plain")
                out.success("done")

            except ClientError as e:
                d.msgbox("Error in storage service client: %s" % e.message,
                         title="Storage Service Client Error",
                         width=SMALL_WIDTH)
                if 'uploaded' in cloud:
                    del cloud['uploaded']
                return False
        finally:
            out.remove(gauge)
    finally:
        gauge.cleanup()

    d.msgbox("Image file `%s' was successfully uploaded" % name,
             width=SMALL_WIDTH)

    return True
Exemplo n.º 3
0
def upload_image(session):
    """Upload the image to the storage service"""
    d = session["dialog"]
    image = session['image']

    assert 'clouds' in session

    try:
        cloud_name = session['current_cloud']
        cloud = session['clouds'][cloud_name]
        account = cloud['account']
    except KeyError:
        cloud = None

    if cloud is None or not account:
        d.msgbox("You need to select a valid cloud before you can upload "
                 "images to it", width=SMALL_WIDTH)
        return False

    while 1:
        if 'uploaded' in cloud:
            _, _, _, container, name = cloud['uploaded'].split('/')
        elif 'OS' in session['image'].meta:
            name = "%s.diskdump" % session['image'].meta['OS']
            container = CONTAINER
        else:
            name = ""
            container = CONTAINER

        fields = [("Remote Name:", name, 60), ("Container:", container, 60)]

        (code, output) = d.form("Please provide the following upload info:",
                                create_form_elements(fields), height=11,
                                width=WIDTH, form_height=2)

        if code in (d.CANCEL, d.ESC):
            return False

        name, container = output
        name = name.strip()
        container = container.strip()

        if len(name) == 0:
            d.msgbox("Remote Name cannot be empty", width=SMALL_WIDTH)
            continue

        if len(container) == 0:
            d.msgbox("Container cannot be empty", width=SMALL_WIDTH)
            continue

        kamaki = Kamaki(cloud['account'], None)
        overwrite = []
        for f in (name, "%s.md5sum" % name, "%s.meta" % name):
            if kamaki.object_exists(container, f):
                overwrite.append(f)

        if len(overwrite) > 0:
            if d.yesno("The following storage service object(s) already "
                       "exist(s):\n%s\nDo you want to overwrite them?" %
                       "\n".join(overwrite), width=WIDTH, defaultno=1
                       ) != d.OK:
                continue
        break

    gauge = GaugeOutput(d, "Image Upload", "Uploading ...")
    try:
        out = image.out
        out.append(gauge)
        kamaki.out = out
        try:
            if 'checksum' not in session:
                session['checksum'] = image.md5()

            try:
                # Upload image file
                with image.raw_device() as raw:
                    with open(raw, 'rb') as f:
                        cloud["uploaded"] = \
                            kamaki.upload(f, image.size, name, container, None,
                                          "Calculating block hashes",
                                          "Uploading missing blocks")
                # Upload md5sum file
                out.info("Uploading md5sum file ...")
                md5str = "%s %s\n" % (session['checksum'], name)
                kamaki.upload(StringIO.StringIO(md5str), size=len(md5str),
                              remote_path="%s.md5sum" % name,
                              container=container,
                              content_type="text/plain")
                out.success("done")

            except ClientError as e:
                d.msgbox(
                    "Error in storage service client: %s" % e.message,
                    title="Storage Service Client Error", width=SMALL_WIDTH)
                if 'uploaded' in cloud:
                    del cloud['uploaded']
                return False
        finally:
            out.remove(gauge)
    finally:
        gauge.cleanup()

    d.msgbox("Image file `%s' was successfully uploaded" % name,
             width=SMALL_WIDTH)

    return True
Exemplo n.º 4
0
def register_image(session):
    """Register image with the compute service"""
    d = session["dialog"]
    image = session['image']

    assert 'clouds' in session

    try:
        cloud_name = session['current_cloud']
        cloud = session['clouds'][cloud_name]
        account = cloud['account']
    except KeyError:
        cloud = None

    if cloud is None or account is None:
        d.msgbox(
            "You need to select a valid cloud before you can register an "
            "images with it",
            width=SMALL_WIDTH)
        return False

    if "uploaded" not in cloud:
        d.msgbox(
            "You need to upload the image to a cloud before you can "
            "register it",
            width=SMALL_WIDTH)
        return False

    is_public = False
    _, _, _, container, remote = cloud['uploaded'].split('/')
    name = "" if 'registered' not in cloud else cloud['registered']
    descr = image.meta['DESCRIPTION'] if 'DESCRIPTION' in image.meta else ""

    while 1:
        fields = [("Registration name:", name, 60),
                  ("Description (optional):", descr, 80)]

        (code,
         output) = d.form("Please provide the following registration info:",
                          create_form_elements(fields),
                          height=11,
                          width=WIDTH,
                          form_height=2)

        if code in (d.CANCEL, d.ESC):
            return False

        name, descr = output
        name = name.strip()
        descr = descr.strip()

        if len(name) == 0:
            d.msgbox("Registration name cannot be empty", width=SMALL_WIDTH)
            continue

        answer = d.yesno(
            "Make the image public?\\nA public image is "
            "accessible by every user of the service.",
            defaultno=1,
            width=WIDTH)
        if answer == d.ESC:
            continue

        is_public = (answer == d.OK)
        break

    image.meta['DESCRIPTION'] = descr
    metadata = {}
    metadata.update(image.meta)
    if 'task_metadata' in session:
        for key in session['task_metadata']:
            metadata[key] = 'yes'

    img_type = "public" if is_public else "private"
    gauge = GaugeOutput(d, "Image Registration", "Registering image ...")
    try:
        out = session['image'].out
        out.append(gauge)
        try:
            try:
                out.info("Registering %s image with the cloud ..." % img_type,
                         False)
                kamaki = Kamaki(cloud['account'], out)
                cloud['registered'] = kamaki.register(name, cloud['uploaded'],
                                                      metadata, is_public)
                out.success('done')

                # Upload metadata file
                out.info("Uploading metadata file ...", False)
                metastring = json.dumps(cloud['registered'],
                                        indent=4,
                                        ensure_ascii=False)
                kamaki.upload(StringIO.StringIO(metastring),
                              size=len(metastring),
                              remote_path="%s.meta" % remote,
                              container=container,
                              content_type="application/json")
                out.success("done")
                if is_public:
                    out.info("Sharing metadata and md5sum files ...", False)
                    kamaki.share("%s.meta" % remote)
                    kamaki.share("%s.md5sum" % remote)
                    out.success('done')
            except ClientError as error:
                d.msgbox("Error in storage service client: %s" % error.message)
                return False
        finally:
            out.remove(gauge)
    finally:
        gauge.cleanup()

    d.msgbox(
        "%s image `%s' was successfully registered with the cloud as `%s'" %
        (img_type.title(), remote, name),
        width=SMALL_WIDTH)
    return True
Exemplo n.º 5
0
def extract_image(session):
    """Dump the image to a local file"""
    d = session['dialog']

    dir = os.getcwd()

    while 1:
        if dir and dir[-1] != os.sep:
            dir = dir + os.sep

        path = select_file(d,
                           title="Save image as...",
                           existing=False,
                           basedir=dir)
        if path is None:
            return False

        if os.path.isdir(path):
            dir = path
            continue

        if os.path.isdir("%s.meta" % path):
            d.msgbox("Can't overwrite directory `%s.meta'" % path,
                     width=SMALL_WIDTH)
            continue

        if os.path.isdir("%s.md5sum" % path):
            d.msgbox("Can't overwrite directory `%s.md5sum'" % path,
                     width=SMALL_WIDTH)
            continue

        basedir = os.path.dirname(path)
        name = os.path.basename(path)
        if not os.path.exists(basedir):
            d.msgbox("Directory `%s' does not exist" % basedir,
                     width=SMALL_WIDTH)
            continue

        dir = basedir
        if len(name) == 0:
            continue

        files = ["%s%s" % (path, ext) for ext in ('', '.meta', '.md5sum')]
        overwrite = filter(os.path.exists, files)

        if len(overwrite) > 0:
            if d.yesno("The following file(s) exist:\n"
                       "%s\nDo you want to overwrite them?" %
                       "\n".join(overwrite),
                       width=SMALL_WIDTH) != d.OK:
                continue

        gauge = GaugeOutput(d, "Image Extraction", "Extracting image...")
        try:
            image = session['image']
            out = image.out
            out.append(gauge)
            try:
                if "checksum" not in session:
                    session['checksum'] = image.md5()

                # Extract image file
                image.dump(path)

                # Extract metadata file
                out.info("Extracting metadata file ...", False)
                with open('%s.meta' % path, 'w') as f:
                    f.write(extract_metadata_string(session))
                out.success('done')

                # Extract variant file
                out.info("Extracting variant file ...", False)
                with open('%s.meta' % path, 'w') as f:
                    f.write(extract_variant_string(session, path))
                out.success('done')

                # Extract md5sum file
                out.info("Extracting md5sum file ...", False)
                md5str = "%s %s\n" % (session['checksum'], name)
                with open('%s.md5sum' % path, 'w') as f:
                    f.write(md5str)
                out.success("done")

            finally:
                out.remove(gauge)
        finally:
            gauge.cleanup()
        d.msgbox("Image file `%s' was successfully extracted!" % path,
                 width=SMALL_WIDTH)
        break

    return True
Exemplo n.º 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
Exemplo n.º 7
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
Exemplo n.º 8
0
def extract_image(session):
    """Dump the image to a local file"""
    d = session['dialog']

    dir = os.getcwd()

    while 1:
        if dir and dir[-1] != os.sep:
            dir = dir + os.sep

        path = select_file(d, title="Save image as...", existing=False,
                           basedir=dir)
        if path is None:
            return False

        if os.path.isdir(path):
            dir = path
            continue

        if os.path.isdir("%s.meta" % path):
            d.msgbox("Can't overwrite directory `%s.meta'" % path,
                     width=SMALL_WIDTH)
            continue

        if os.path.isdir("%s.md5sum" % path):
            d.msgbox("Can't overwrite directory `%s.md5sum'" % path,
                     width=SMALL_WIDTH)
            continue

        basedir = os.path.dirname(path)
        name = os.path.basename(path)
        if not os.path.exists(basedir):
            d.msgbox("Directory `%s' does not exist" % basedir,
                     width=SMALL_WIDTH)
            continue

        dir = basedir
        if len(name) == 0:
            continue

        files = ["%s%s" % (path, ext) for ext in ('', '.meta', '.md5sum')]
        overwrite = filter(os.path.exists, files)

        if len(overwrite) > 0:
            if d.yesno("The following file(s) exist:\n"
                       "%s\nDo you want to overwrite them?" %
                       "\n".join(overwrite), width=SMALL_WIDTH) != d.OK:
                continue

        gauge = GaugeOutput(d, "Image Extraction", "Extracting image...")
        try:
            image = session['image']
            out = image.out
            out.append(gauge)
            try:
                if "checksum" not in session:
                    session['checksum'] = image.md5()

                # Extract image file
                image.dump(path)

                # Extract metadata file
                out.info("Extracting metadata file ...", False)
                with open('%s.meta' % path, 'w') as f:
                    f.write(extract_metadata_string(session))
                out.success('done')

                # Extract variant file
                out.info("Extracting variant file ...", False)
                with open('%s.meta' % path, 'w') as f:
                    f.write(extract_variant_string(session, path))
                out.success('done')

                # Extract md5sum file
                out.info("Extracting md5sum file ...", False)
                md5str = "%s %s\n" % (session['checksum'], name)
                with open('%s.md5sum' % path, 'w') as f:
                    f.write(md5str)
                out.success("done")

            finally:
                out.remove(gauge)
        finally:
            gauge.cleanup()
        d.msgbox("Image file `%s' was successfully extracted!" % path,
                 width=SMALL_WIDTH)
        break

    return True