Esempio n. 1
0
def anaconda_cleanup(dirinstall_path):
    """
    Cleanup any leftover mounts from anaconda

    :param str dirinstall_path: Path where anaconda mounts things
    :returns: True if cleanups were successful. False if any of them failed.

    If anaconda crashes it may leave things mounted under this path. It will
    typically be set to /mnt/sysimage/

    Attempts to cleanup may also fail. Catch these and continue trying the
    other mountpoints.
    """
    rc = True
    dirinstall_path = os.path.abspath(dirinstall_path)
    # unmount filesystems
    for mounted in reversed(open("/proc/mounts").readlines()):
        (_device, mountpoint, _rest) = mounted.split(" ", 2)
        if mountpoint.startswith(dirinstall_path) and os.path.ismount(
                mountpoint):
            try:
                umount(mountpoint)
            except subprocess.CalledProcessError:
                log.error("Cleanup of %s failed. See program.log for details",
                          mountpoint)
                rc = False
    return rc
Esempio n. 2
0
def mount_boot_part_over_root(img_mount):
    """
    Mount boot partition to /boot of root fs mounted in img_mount

    Used for OSTree so it finds deployment configurations on live rootfs

    param img_mount: object with mounted disk image root partition
    type img_mount: imgutils.PartitionMount
    """
    root_dir = img_mount.mount_dir
    is_boot_part = lambda dir: os.path.exists(dir + "/loader.0")
    tmp_mount_dir = tempfile.mkdtemp(prefix="lmc-tmpdir-")
    sysroot_boot_dir = None
    for dev, _size in img_mount.loop_devices:
        if dev is img_mount.mount_dev:
            continue
        try:
            mount("/dev/mapper/" + dev, mnt=tmp_mount_dir)
            if is_boot_part(tmp_mount_dir):
                umount(tmp_mount_dir)
                sysroot_boot_dir = joinpaths(root_dir, "boot")
                mount("/dev/mapper/" + dev, mnt=sysroot_boot_dir)
                break
            else:
                umount(tmp_mount_dir)
        except subprocess.CalledProcessError as e:
            log.debug("Looking for boot partition error: %s", e)
    remove(tmp_mount_dir)
    return sysroot_boot_dir
Esempio n. 3
0
def mkfakediskimg(disk_img):
    """Create a fake partitioned disk image

    :param disk_img: Full path to a partitioned disk image
    :type disk_img: str
    :returns: True if it was successful, False if something went wrong

    Include /boot, swap, and / partitions with fake kernel and /etc/passwd
    """
    try:
        mksparse(disk_img, 42 * 1024**2)
        # Make a /boot, / and swap partitions on it
        dev = parted.getDevice(disk_img)
        disk = parted.freshDisk(dev, "gpt")

        # (start, length, flags, name)
        for start, length, flags, name in [
                  (  1024**2,    1024**2, None, "boot"),
                  (2*1024**2,  2*1024**2, parted.PARTITION_SWAP, "swap"),
                  (4*1024**2, 38*1024**2, None, "root")]:
            geo = parted.Geometry(device=dev, start=start//dev.sectorSize, length=length//dev.sectorSize)
            part = parted.Partition(disk=disk, type=parted.PARTITION_NORMAL, geometry=geo)
            part.getPedPartition().set_name(name)
            disk.addPartition(partition=part)
            if flags:
                part.setFlag(flags)
        disk.commit()
        os.sync()
    except parted.PartedException:
        return False

    # Mount the disk's partitions
    loop_devs = kpartx_disk_img(disk_img)

    try:
        # Format the partitions
        runcmd(["mkfs.ext4", "/dev/mapper/" + loop_devs[0][0]])
        runcmd(["mkswap", "/dev/mapper/" + loop_devs[1][0]])
        runcmd(["mkfs.ext4", "/dev/mapper/" + loop_devs[2][0]])

        # Mount the boot partition and make a fake kernel and initrd
        boot_mnt = mount("/dev/mapper/" + loop_devs[0][0])
        try:
            mkfakebootdir(boot_mnt)
        finally:
            umount(boot_mnt)

        # Mount the / partition and make a fake / filesystem with /etc/passwd
        root_mnt = mount("/dev/mapper/" + loop_devs[2][0])
        try:
            mkfakerootdir(root_mnt)
        finally:
            umount(root_mnt)
    except Exception:
        return False
    finally:
        # Remove the disk's mounted partitions
        runcmd(["kpartx", "-d", "-s", disk_img])

    return True
Esempio n. 4
0
def anaconda_cleanup(dirinstall_path):
    """
    Cleanup any leftover mounts from anaconda

    :param str dirinstall_path: Path where anaconda mounts things
    :returns: True if cleanups were successful. False if any of them failed.

    If anaconda crashes it may leave things mounted under this path. It will
    typically be set to /mnt/sysimage/

    Attempts to cleanup may also fail. Catch these and continue trying the
    other mountpoints.

    Anaconda may also leave /run/anaconda.pid behind, clean that up as well.
    """
    # Anaconda may not clean up its /var/run/anaconda.pid file
    # Make sure the process is really finished (it should be, since it was started from a subprocess call)
    # and then remove the pid file.
    if os.path.exists("/var/run/anaconda.pid"):
        # lorax-composer runs anaconda using unshare so the pid is always 1
        if open("/var/run/anaconda.pid").read().strip() == "1":
            os.unlink("/var/run/anaconda.pid")

    rc = True
    dirinstall_path = os.path.abspath(dirinstall_path)
    # unmount filesystems
    for mounted in reversed(open("/proc/mounts").readlines()):
        (_device, mountpoint, _rest) = mounted.split(" ", 2)
        if mountpoint.startswith(dirinstall_path) and os.path.ismount(mountpoint):
            try:
                umount(mountpoint)
            except subprocess.CalledProcessError:
                log.error("Cleanup of %s failed. See program.log for details", mountpoint)
                rc = False
    return rc
Esempio n. 5
0
def rebuild_initrds_for_live(opts, sys_root_dir, results_dir):
    """
    Rebuild intrds for pxe live image (root=live:http://)

    :param opts: options passed to livemedia-creator
    :type opts: argparse options
    :param str sys_root_dir: Path to root of the system
    :param str results_dir: Path of directory for storing results
    """
    # cmdline dracut args override the defaults, but need to be parsed
    log.info("dracut args = %s", dracut_args(opts))

    dracut = ["dracut", "--nomdadmconf", "--nolvmconf"] + dracut_args(opts)

    kdir = "boot"
    if opts.ostree:
        kernels_dir = glob.glob(joinpaths(sys_root_dir, "boot/ostree/*"))
        if kernels_dir:
            kdir = os.path.relpath(kernels_dir[0], sys_root_dir)

    kernels = [kernel for kernel in findkernels(sys_root_dir, kdir)]
    if not kernels:
        raise Exception("No initrds found, cannot rebuild_initrds")

    if opts.ostree:
        # Dracut assumes to have some dirs in disk image
        # /var/tmp for temp files
        vartmp_dir = joinpaths(sys_root_dir, "var/tmp")
        if not os.path.isdir(vartmp_dir):
            os.mkdir(vartmp_dir)
        # /root (maybe not fatal)
        root_dir = joinpaths(sys_root_dir, "var/roothome")
        if not os.path.isdir(root_dir):
            os.mkdir(root_dir)
        # /tmp (maybe not fatal)
        tmp_dir = joinpaths(sys_root_dir, "sysroot/tmp")
        if not os.path.isdir(tmp_dir):
            os.mkdir(tmp_dir)

    # Write the new initramfs directly to the results directory
    os.mkdir(joinpaths(sys_root_dir, "results"))
    mount(results_dir, opts="bind", mnt=joinpaths(sys_root_dir, "results"))
    # Dracut runs out of space inside the minimal rootfs image
    mount("/var/tmp", opts="bind", mnt=joinpaths(sys_root_dir, "var/tmp"))
    for kernel in kernels:
        if hasattr(kernel, "initrd"):
            outfile = os.path.basename(kernel.initrd.path)
        else:
            # Construct an initrd from the kernel name
            outfile = os.path.basename(kernel.path.replace("vmlinuz-", "initrd-") + ".img")
        log.info("rebuilding %s", outfile)
        log.info("dracut warnings about /proc are safe to ignore")

        kver = kernel.version
        cmd = dracut + ["/results/"+outfile, kver]
        runcmd(cmd, root=sys_root_dir)

        shutil.copy2(joinpaths(sys_root_dir, kernel.path), results_dir)
    umount(joinpaths(sys_root_dir, "var/tmp"), delete=False)
    umount(joinpaths(sys_root_dir, "results"), delete=False)
Esempio n. 6
0
def make_live_images(opts, work_dir, disk_img):
    """
    Create live images from direcory or rootfs image

    :param opts: options passed to livemedia-creator
    :type opts: argparse options
    :param str work_dir: Directory for storing results
    :param str disk_img: Path to disk image (fsimage or partitioned)
    :returns: Path of directory with created images or None
    :rtype: str

    fsck.ext4 is run on the rootfs_image to make sure there are no errors and to zero
    out any deleted blocks to make it compress better. If this fails for any reason
    it will return None and log the error.
    """
    sys_root = ""

    squashfs_root_dir = joinpaths(work_dir, "squashfs_root")
    liveos_dir = joinpaths(squashfs_root_dir, "LiveOS")
    os.makedirs(liveos_dir)
    rootfs_img = joinpaths(liveos_dir, "rootfs.img")

    if opts.fs_image or opts.no_virt:
        # Find the ostree root in the fsimage
        if opts.ostree:
            with Mount(disk_img, opts="loop") as mnt_dir:
                sys_root = find_ostree_root(mnt_dir)

        # Try to hardlink the image, if that fails, copy it
        rc = execWithRedirect("/bin/ln", [disk_img, rootfs_img])
        if rc != 0:
            shutil.copy2(disk_img, rootfs_img)
    else:
        is_root_part = None
        if opts.ostree:
            is_root_part = lambda dir: os.path.exists(dir + "/ostree/deploy")
        with PartitionMount(disk_img, mount_ok=is_root_part) as img_mount:
            if img_mount and img_mount.mount_dir:
                try:
                    mounted_sysroot_boot_dir = None
                    if opts.ostree:
                        sys_root = find_ostree_root(img_mount.mount_dir)
                        mounted_sysroot_boot_dir = mount_boot_part_over_root(
                            img_mount)
                    if opts.live_rootfs_keep_size:
                        size = img_mount.mount_size / 1024**3
                    else:
                        size = opts.live_rootfs_size or None
                    log.info("Creating live rootfs image")
                    mkrootfsimg(img_mount.mount_dir,
                                rootfs_img,
                                "LiveOS",
                                size=size,
                                sysroot=sys_root)
                finally:
                    if mounted_sysroot_boot_dir:
                        umount(mounted_sysroot_boot_dir)
    log.debug("sys_root = %s", sys_root)

    # Make sure free blocks are actually zeroed so it will compress
    rc = execWithRedirect("/usr/sbin/fsck.ext4",
                          ["-y", "-f", "-E", "discard", rootfs_img])
    if rc != 0:
        log.error("Problem zeroing free blocks of %s", disk_img)
        return None

    log.info("Packing live rootfs image")
    add_pxe_args = []
    live_image_name = "live-rootfs.squashfs.img"
    compression, compressargs = squashfs_args(opts)
    mksquashfs(squashfs_root_dir, joinpaths(work_dir, live_image_name),
               compression, compressargs)

    log.info("Rebuilding initramfs for live")
    with Mount(rootfs_img, opts="loop") as mnt_dir:
        try:
            mount(joinpaths(mnt_dir, "boot"),
                  opts="bind",
                  mnt=joinpaths(mnt_dir, sys_root, "boot"))
            rebuild_initrds_for_live(opts, joinpaths(mnt_dir, sys_root),
                                     work_dir)
        finally:
            umount(joinpaths(mnt_dir, sys_root, "boot"), delete=False)

    remove(squashfs_root_dir)

    if opts.ostree:
        add_pxe_args.append("ostree=/%s" % sys_root)
    template = joinpaths(opts.lorax_templates, "pxe-live/pxe-config.tmpl")
    create_pxe_config(template, work_dir, live_image_name, add_pxe_args)

    return work_dir
Esempio n. 7
0
File: mount.py Progetto: tagoh/lorax
 def umount(self):
     """Unmount the iso"""
     if not self.initrd_path:
         umount(self.mount_dir)
Esempio n. 8
0
 def umount( self ):
     """Unmount the iso"""
     if not self.initrd_path:
         umount(self.mount_dir)