From 6ed2aaed69f368e7674dcbd2b0c435d35b7f8eb0 Mon Sep 17 00:00:00 2001 From: "Brian C. Lane" Date: Tue, 26 Apr 2016 14:37:19 -0700 Subject: [PATCH] Refactor PXE live creation code This moves the mounting inside make_live_images so that it isn't trying to copy the fsimage while having it mounted. --- src/sbin/livemedia-creator | 107 +++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 51 deletions(-) diff --git a/src/sbin/livemedia-creator b/src/sbin/livemedia-creator index ed908ac5..ed2c4032 100755 --- a/src/sbin/livemedia-creator +++ b/src/sbin/livemedia-creator @@ -685,7 +685,7 @@ def anaconda_cleanup(dirinstall_path): # unmount filesystems for mounted in reversed(open("/proc/mounts").readlines()): (_device, mountpoint, _rest) = mounted.split(" ", 2) - if mountpoint.startswith(dirinstall_path): + if mountpoint.startswith(dirinstall_path) and os.path.ismount(mountpoint): umount(mountpoint) @@ -759,12 +759,18 @@ def novirt_install(opts, disk_img, disk_size): # Make sure the new filesystem is correctly labeled setfiles_args = ["-e", "/proc", "-e", "/sys", "-e", "/dev", "/etc/selinux/targeted/contexts/files/file_contexts", "/"] - if "--dirinstall" in args: - execWithRedirect("setfiles", setfiles_args, root=dirinstall_path) - else: - with PartitionMount(disk_img) as img_mount: - if img_mount and img_mount.mount_dir: - execWithRedirect("setfiles", setfiles_args, root=img_mount.mount_dir) + + # setfiles may not be available, warn instead of fail + try: + if "--dirinstall" in args: + execWithRedirect("setfiles", setfiles_args, root=dirinstall_path) + else: + with PartitionMount(disk_img) as img_mount: + if img_mount and img_mount.mount_dir: + execWithRedirect("setfiles", setfiles_args, root=img_mount.mount_dir) + except (subprocess.CalledProcessError, OSError) as e: + log.warning("Running setfiles on install tree failed: %s", str(e)) + except (subprocess.CalledProcessError, OSError) as e: log.error("Running anaconda failed: %s", e) raise InstallError("novirt_install failed") @@ -1064,15 +1070,14 @@ def make_image(opts, ks): return disk_img -def make_live_images(opts, work_dir, root_dir, rootfs_image=None, size=None): +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 root_dir: Root directory of live filesystem tree - :param str rootfs_image: Path to live rootfs image to be used + :param str disk_img: Path to disk image (fsimage or partitioned) :returns: Path of directory with created images or None :rtype: str @@ -1081,38 +1086,60 @@ def make_live_images(opts, work_dir, root_dir, rootfs_image=None, size=None): it will return None and log the error. """ sys_root = "" - if opts.ostree: - sys_root = find_ostree_root(root_dir) 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 rootfs_image: - # Make sure free blocks are actually zeroed so it will compress - rc = execWithRedirect("/usr/sbin/fsck.ext4", ["-y", "-f", "-E", "discard", rootfs_image]) - if rc != 0: - log.error("Problem zeroing free blocks of %s", rootfs_image) - return None + 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) - rc = execWithRedirect("/bin/ln", [rootfs_image, joinpaths(liveos_dir, "rootfs.img")]) + # Try to hardlink the image, if that fails, copy it + rc = execWithRedirect("/bin/ln", [disk_img, rootfs_img]) if rc != 0: - shutil.copy2(rootfs_image, joinpaths(liveos_dir, "rootfs.img")) + shutil.copy2(disk_img, rootfs_img) else: - log.info("Creating live rootfs image") - mkrootfsimg(root_dir, joinpaths(liveos_dir, "rootfs.img"), "LiveOS", size=size, sysroot=sys_root) + 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) + + # 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) + mksquashfs(squashfs_root_dir, joinpaths(work_dir, live_image_name), compression, compressargs) remove(squashfs_root_dir) log.info("Rebuilding initramfs for live") - rebuild_initrds_for_live(opts, joinpaths(root_dir, sys_root), work_dir) + with Mount(disk_img, opts="loop") as mnt_dir: + rebuild_initrds_for_live(opts, joinpaths(mnt_dir, sys_root), work_dir) if opts.ostree: add_pxe_args.append("ostree=/%s" % sys_root) @@ -1388,34 +1415,12 @@ def main(): 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 disk_img + log.debug("disk image is %s", disk_img) - if opts.fs_image or opts.no_virt: - # Create pxe live images from a filesystem image - disk_img = opts.fs_image or disk_img - with Mount(disk_img, opts="loop") as mnt_dir: - result_dir = make_live_images(opts, work_dir, mnt_dir, rootfs_image=disk_img) - else: - # Create pxe live images from a partitioned disk image - disk_img = opts.disk_image or disk_img - 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: - 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 - result_dir = make_live_images(opts, work_dir, img_mount.mount_dir, size=size) - finally: - if mounted_sysroot_boot_dir: - umount(mounted_sysroot_boot_dir) + result_dir = make_live_images(opts, work_dir, disk_img) if result_dir is None: - log.error("Creating live image failed.") + log.error("Creating PXE live image failed.") sys.exit(1) if opts.result_dir != opts.tmp and result_dir: