diff --git a/src/pylorax/creator.py b/src/pylorax/creator.py index e7963fcb..b20b777f 100644 --- a/src/pylorax/creator.py +++ b/src/pylorax/creator.py @@ -36,8 +36,8 @@ from pykickstart.version import makeVersion # Use the Lorax treebuilder branch for iso creation from pylorax import ArchData from pylorax.base import DataHolder -from pylorax.executils import execWithRedirect, runcmd -from pylorax.imgutils import PartitionMount +from pylorax.executils import execWithRedirect +from pylorax.imgutils import DracutChroot, PartitionMount from pylorax.imgutils import mount, umount, Mount from pylorax.imgutils import mksquashfs, mkrootfsimg from pylorax.imgutils import copytree @@ -243,7 +243,7 @@ def rebuild_initrds_for_live(opts, sys_root_dir, results_dir): # 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) + args = ["--nomdadmconf", "--nolvmconf"] + dracut_args(opts) kdir = "boot" if opts.ostree: @@ -272,25 +272,18 @@ def rebuild_initrds_for_live(opts, sys_root_dir, results_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") + with DracutChroot(sys_root_dir, bind=[(results_dir, "/results")]) as dracut: + 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) - 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) + kver = kernel.version + dracut.Run(args + ["/results/"+outfile, kver]) + shutil.copy2(joinpaths(sys_root_dir, kernel.path), results_dir) def create_pxe_config(template, images_dir, live_image_name, add_args = None): """ diff --git a/src/pylorax/imgutils.py b/src/pylorax/imgutils.py index 13d9b280..d713e4c1 100644 --- a/src/pylorax/imgutils.py +++ b/src/pylorax/imgutils.py @@ -473,6 +473,42 @@ class PartitionMount(object): execWithRedirect("kpartx", ["-d", "-s", self.disk_img]) +class DracutChroot(object): + """Setup the chroot for running dracut inside it, cleanup when done + + This mount /proc, /dev, and /var/tmp plus optional bind mounted directories + as a list of (source, destination) tuples where destination is relative to the chroot. + """ + def __init__(self, root, bind=None): + self.root = root + self.bind = [("/var/tmp", "/var/tmp")] + (bind if bind else []) + + def __enter__(self): + for d in [d for _, d in self.bind] + ["/proc", "/dev"]: + if not os.path.exists(self.root + d): + logger.warning("Making missing dracut chroot directory: %s", d) + os.makedirs(self.root + d) + + runcmd(["mount", "-t", "proc", "-o", "nosuid,noexec,nodev", "proc", self.root + "/proc" ]) + runcmd(["mount", "-t", "devtmpfs", "-o", "mode=0755,noexec,nosuid,strictatime", "devtmpfs", self.root + "/dev" ]) + + for s, d in self.bind: + runcmd(["mount", "-o", "bind", s, self.root + d]) + + return self + + def __exit__(self, exc_type, exc_value, tracebk): + runcmd(["umount", self.root + "/proc" ]) + runcmd(["umount", self.root + "/dev" ]) + + # cleanup bind mounts + for _, d in self.bind: + runcmd(["umount", self.root + d ]) + + def Run(self, args): + runcmd(["dracut"] + args, root=self.root) + + ######## Functions for making filesystem images ########################## def mkfsimage(fstype, rootdir, outfile, size=None, mkfsargs=None, mountargs="", graft=None): diff --git a/src/pylorax/treebuilder.py b/src/pylorax/treebuilder.py index d57370d3..bc93d4f7 100644 --- a/src/pylorax/treebuilder.py +++ b/src/pylorax/treebuilder.py @@ -31,6 +31,7 @@ from pylorax.sysutils import joinpaths, remove from pylorax.base import DataHolder from pylorax.ltmpl import LoraxTemplateRunner import pylorax.imgutils as imgutils +from pylorax.imgutils import DracutChroot from pylorax.executils import runcmd, runcmd_output, execWithCapture templatemap = { @@ -310,32 +311,31 @@ class TreeBuilder(object): name of the kernel. ''' add_args = add_args or [] - dracut = ["dracut", "--nomdadmconf", "--nolvmconf"] + add_args + args = ["--nomdadmconf", "--nolvmconf"] + add_args if not backup: - dracut.append("--force") + args.append("--force") if not self.kernels: raise Exception("No kernels found, cannot rebuild_initrds") - for kernel in self.kernels: - if prefix: - idir = os.path.dirname(kernel.path) - outfile = joinpaths(idir, prefix+'-'+kernel.version+'.img') - elif hasattr(kernel, "initrd"): - # If there is an existing initrd, use that - outfile = kernel.initrd.path - else: - # Construct an initrd from the kernel name - outfile = kernel.path.replace("vmlinuz-", "initrd-") + ".img" - logger.info("rebuilding %s", outfile) - logger.info("dracut warnings about /proc are safe to ignore") + with DracutChroot(self.vars.inroot) as dracut: + for kernel in self.kernels: + if prefix: + idir = os.path.dirname(kernel.path) + outfile = joinpaths(idir, prefix+'-'+kernel.version+'.img') + elif hasattr(kernel, "initrd"): + # If there is an existing initrd, use that + outfile = kernel.initrd.path + else: + # Construct an initrd from the kernel name + outfile = kernel.path.replace("vmlinuz-", "initrd-") + ".img" + logger.info("rebuilding %s", outfile) - if backup: - initrd = joinpaths(self.vars.inroot, outfile) - if os.path.exists(initrd): - os.rename(initrd, initrd + backup) - cmd = dracut + [outfile, kernel.version] - runcmd(cmd, root=self.vars.inroot) + if backup: + initrd = joinpaths(self.vars.inroot, outfile) + if os.path.exists(initrd): + os.rename(initrd, initrd + backup) + dracut.Run(args + [outfile, kernel.version]) def build(self): templatefile = templatemap[self.vars.arch.basearch]