Beispiel #1
0
def make_livecd(opts, mount_dir, work_dir):
    """
    Take the content from the disk image and make a livecd out of it

    :param opts: options passed to livemedia-creator
    :type opts: argparse options
    :param str mount_dir: Directory tree to compress
    :param str work_dir: Output compressed image to work_dir+images/install.img

    This uses wwood's squashfs live initramfs method:
     * put the real / into LiveOS/rootfs.img
     * make a squashfs of the LiveOS/rootfs.img tree
     * This is loaded by dracut when the cmdline is passed to the kernel:
       root=live:CDLABEL=<volid> rd.live.image
    """
    kernel_arch = get_arch(mount_dir)

    arch = ArchData(kernel_arch)
    # TODO: Need to get release info from someplace...
    product = DataHolder(name=opts.project, version=opts.releasever, release="",
                            variant="", bugurl="", isfinal=False)

    # Link /images to work_dir/images to make the templates happy
    if os.path.islink(joinpaths(mount_dir, "images")):
        os.unlink(joinpaths(mount_dir, "images"))
    execWithRedirect("/bin/ln", ["-s", joinpaths(work_dir, "images"),
                                 joinpaths(mount_dir, "images")])

    # The templates expect the config files to be in /tmp/config_files
    # I think these should be release specific, not from lorax, but for now
    configdir = joinpaths(opts.lorax_templates,"live/config_files/")
    configdir_path = "tmp/config_files"
    fullpath = joinpaths(mount_dir, configdir_path)
    if os.path.exists(fullpath):
        remove(fullpath)
    copytree(configdir, fullpath)

    isolabel = opts.volid or "{0.name}-{0.version}-{1.basearch}".format(product, arch)
    if len(isolabel) > 32:
        isolabel = isolabel[:32]
        log.warning("Truncating isolabel to 32 chars: %s", isolabel)

    tb = TreeBuilder(product=product, arch=arch, domacboot=opts.domacboot,
                     inroot=mount_dir, outroot=work_dir,
                     runtime=RUNTIME, isolabel=isolabel,
                     templatedir=joinpaths(opts.lorax_templates,"live/"),
                     extra_boot_args=opts.extra_boot_args)
    log.info("Rebuilding initrds")
    if not opts.dracut_args:
        dracut_args = DRACUT_DEFAULT
    else:
        dracut_args = []
        for arg in opts.dracut_args:
            dracut_args += arg.split(" ", 1)
    log.info("dracut args = %s", dracut_args)
    tb.rebuild_initrds(add_args=dracut_args)
    log.info("Building boot.iso")
    tb.build()

    return work_dir
Beispiel #2
0
def run_creator(opts, cancel_func=None):
    """Run the image creator process

    :param opts: Commandline options to control the process
    :type opts: Either a DataHolder or ArgumentParser
    :param cancel_func: Function that returns True to cancel build
    :type cancel_func: function
    :returns: The result directory and the disk image path.
    :rtype: Tuple of str

    This function takes the opts arguments and creates the selected output image.
    See the cmdline --help for livemedia-creator for the possible options

    (Yes, this is not ideal, but we can fix that later)
    """
    result_dir = None

    # Parse the kickstart
    if opts.ks:
        ks_version = makeVersion()
        ks = KickstartParser(ks_version,
                             errorsAreFatal=False,
                             missingIncludeIsFatal=False)
        ks.readKickstart(opts.ks[0])

    # live iso usually needs dracut-live so warn the user if it is missing
    if opts.ks and opts.make_iso:
        if "dracut-live" not in ks.handler.packages.packageList:
            log.error("dracut-live package is missing from the kickstart.")
            raise RuntimeError(
                "dracut-live package is missing from the kickstart.")

    # Make the disk or filesystem image
    if not opts.disk_image and not opts.fs_image:
        if not opts.ks:
            raise RuntimeError("Image creation requires a kickstart file")

        # Check the kickstart for problems
        errors = check_kickstart(ks, opts)
        if errors:
            list(log.error(e) for e in errors)
            raise RuntimeError("\n".join(errors))

        # Make the image. Output of this is either a partitioned disk image or a fsimage
        try:
            disk_img = make_image(opts, ks, cancel_func=cancel_func)
        except InstallError as e:
            log.error("ERROR: Image creation failed: %s", e)
            raise RuntimeError("Image creation failed: %s" % e)

    if opts.image_only:
        return (result_dir, disk_img)

    if opts.make_iso:
        work_dir = tempfile.mkdtemp(prefix="lmc-work-")
        log.info("working dir is %s", work_dir)

        if (opts.fs_image or opts.no_virt) and not opts.disk_image:
            # Create iso from a filesystem image
            disk_img = opts.fs_image or disk_img

            if not make_squashfs(opts, disk_img, work_dir):
                log.error("squashfs.img creation failed")
                raise RuntimeError("squashfs.img creation failed")

            if cancel_func and cancel_func():
                raise RuntimeError("ISO creation canceled")

            with Mount(disk_img, opts="loop") as mount_dir:
                result_dir = make_livecd(opts, mount_dir, work_dir)
        else:
            # Create iso from a partitioned disk image
            disk_img = opts.disk_image or disk_img
            with PartitionMount(disk_img) as img_mount:
                if img_mount and img_mount.mount_dir:
                    make_runtime(opts, img_mount.mount_dir, work_dir,
                                 calculate_disk_size(opts, ks) / 1024.0)
                    result_dir = make_livecd(opts, img_mount.mount_dir,
                                             work_dir)

        # --iso-only removes the extra build artifacts, keeping only the boot.iso
        if opts.iso_only and result_dir:
            boot_iso = joinpaths(result_dir, "images/boot.iso")
            if not os.path.exists(boot_iso):
                log.error("%s is missing, skipping --iso-only.", boot_iso)
            else:
                iso_dir = tempfile.mkdtemp(prefix="lmc-result-")
                dest_file = joinpaths(iso_dir, opts.iso_name or "boot.iso")
                shutil.move(boot_iso, dest_file)
                shutil.rmtree(result_dir)
                result_dir = iso_dir

        # cleanup the mess
        # cleanup work_dir?
        if disk_img and not (opts.keep_image or opts.disk_image
                             or opts.fs_image):
            os.unlink(disk_img)
            log.info("Disk image erased")
            disk_img = None
    elif opts.make_appliance:
        if not opts.ks:
            networks = []
        else:
            networks = ks.handler.network.network
        make_appliance(opts.disk_image or disk_img, opts.app_name,
                       opts.app_template, opts.app_file, networks, opts.ram,
                       opts.vcpus or 1, opts.arch, opts.title, opts.project,
                       opts.releasever)
    elif opts.make_pxe_live:
        work_dir = tempfile.mkdtemp(prefix="lmc-work-")
        log.info("working dir is %s", work_dir)
        disk_img = opts.fs_image or opts.disk_image or disk_img
        log.debug("disk image is %s", disk_img)

        result_dir = make_live_images(opts, work_dir, disk_img)
        if result_dir is None:
            log.error("Creating PXE live image failed.")
            raise RuntimeError("Creating PXE live image failed.")

    if opts.result_dir != opts.tmp and result_dir:
        copytree(result_dir, opts.result_dir, preserve=False)
        shutil.rmtree(result_dir)
        result_dir = None

    return (result_dir, disk_img)
Beispiel #3
0
def run_creator(opts, callback_func=None):
    """Run the image creator process

    :param opts: Commandline options to control the process
    :type opts: Either a DataHolder or ArgumentParser
    :returns: The result directory and the disk image path.
    :rtype: Tuple of str

    This function takes the opts arguments and creates the selected output image.
    See the cmdline --help for livemedia-creator for the possible options

    (Yes, this is not ideal, but we can fix that later)
    """
    result_dir = None

    # Parse the kickstart
    if opts.ks:
        ks_version = makeVersion()
        ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False)
        ks.readKickstart(opts.ks[0])

    # live iso usually needs dracut-live so warn the user if it is missing
    if opts.ks and opts.make_iso:
        if "dracut-live" not in ks.handler.packages.packageList:
            log.error("dracut-live package is missing from the kickstart.")
            raise RuntimeError("dracut-live package is missing from the kickstart.")

    # Make the disk or filesystem image
    if not opts.disk_image and not opts.fs_image:
        if not opts.ks:
            raise RuntimeError("Image creation requires a kickstart file")

        errors = []
        if opts.no_virt and ks.handler.method.method not in ("url", "nfs") \
           and not ks.handler.ostreesetup.seen:
            errors.append("Only url, nfs and ostreesetup install methods are currently supported."
                          "Please fix your kickstart file." )

        if ks.handler.method.method in ("url", "nfs") and not ks.handler.network.seen:
            errors.append("The kickstart must activate networking if "
                          "the url or nfs install method is used.")

        if ks.handler.displaymode.displayMode is not None:
            errors.append("The kickstart must not set a display mode (text, cmdline, "
                          "graphical), this will interfere with livemedia-creator.")

        if opts.make_fsimage or (opts.make_pxe_live and opts.no_virt):
            # Make sure the kickstart isn't using autopart and only has a / mountpoint
            part_ok = not any(p for p in ks.handler.partition.partitions
                                 if p.mountpoint not in ["/", "swap"])
            if not part_ok or ks.handler.autopart.seen:
                errors.append("Filesystem images must use a single / part, not autopart or "
                              "multiple partitions. swap is allowed but not used.")

        if not opts.no_virt and ks.handler.reboot.action != KS_SHUTDOWN:
            errors.append("The kickstart must include shutdown when using virt installation.")

        if errors:
            list(log.error(e) for e in errors)
            raise RuntimeError("\n".join(errors))

        # Make the image. Output of this is either a partitioned disk image or a fsimage
        try:
            disk_img = make_image(opts, ks)
        except InstallError as e:
            log.error("ERROR: Image creation failed: %s", e)
            raise RuntimeError("Image creation failed: %s" % e)

    if opts.image_only:
        return (result_dir, disk_img)

    if opts.make_iso:
        work_dir = tempfile.mkdtemp(prefix="lmc-work-")
        log.info("working dir is %s", work_dir)

        if (opts.fs_image or opts.no_virt) and not opts.disk_image:
            # Create iso from a filesystem image
            disk_img = opts.fs_image or disk_img

            if not make_squashfs(opts, disk_img, work_dir):
                log.error("squashfs.img creation failed")
                raise RuntimeError("squashfs.img creation failed")

            with Mount(disk_img, opts="loop") as mount_dir:
                result_dir = make_livecd(opts, mount_dir, work_dir)
        else:
            # Create iso from a partitioned disk image
            disk_img = opts.disk_image or disk_img
            with PartitionMount(disk_img) as img_mount:
                if img_mount and img_mount.mount_dir:
                    make_runtime(opts, img_mount.mount_dir, work_dir, calculate_disk_size(opts, ks)/1024.0)
                    result_dir = make_livecd(opts, img_mount.mount_dir, work_dir)

        # --iso-only removes the extra build artifacts, keeping only the boot.iso
        if opts.iso_only and result_dir:
            boot_iso = joinpaths(result_dir, "images/boot.iso")
            if not os.path.exists(boot_iso):
                log.error("%s is missing, skipping --iso-only.", boot_iso)
            else:
                iso_dir = tempfile.mkdtemp(prefix="lmc-result-")
                dest_file = joinpaths(iso_dir, opts.iso_name or "boot.iso")
                shutil.move(boot_iso, dest_file)
                shutil.rmtree(result_dir)
                result_dir = iso_dir

        # cleanup the mess
        # cleanup work_dir?
        if disk_img and not (opts.keep_image or opts.disk_image or opts.fs_image):
            os.unlink(disk_img)
            log.info("Disk image erased")
            disk_img = None
    elif opts.make_appliance:
        if not opts.ks:
            networks = []
        else:
            networks = ks.handler.network.network
        make_appliance(opts.disk_image or disk_img, opts.app_name,
                       opts.app_template, opts.app_file, networks, opts.ram,
                       opts.vcpus or 1, opts.arch, opts.title, opts.project, opts.releasever)
    elif opts.make_pxe_live:
        work_dir = tempfile.mkdtemp(prefix="lmc-work-")
        log.info("working dir is %s", work_dir)
        disk_img = opts.fs_image or opts.disk_image or disk_img
        log.debug("disk image is %s", disk_img)

        result_dir = make_live_images(opts, work_dir, disk_img)
        if result_dir is None:
            log.error("Creating PXE live image failed.")
            raise RuntimeError("Creating PXE live image failed.")

    if opts.result_dir != opts.tmp and result_dir:
        copytree(result_dir, opts.result_dir, preserve=False)
        shutil.rmtree(result_dir)
        result_dir = None

    return (result_dir, disk_img)