This adds the 'squashfs' compression type, which builds runtime images
that stay compressed in RAM. It accomplishes this by building the images
almost exactly like the Live images are built:
1) Create an empty ext4 filesystem on a large sparse file
2) Copy the runtime files into the ext4 filesystem
3) Place the ext4 image at "LiveOS/rootfs.img"
4) Create a squashfs.img which contains LiveOS/rootfs.img
To make this bootable, we need dracut's startup scripts. So before
creating the runtime image, we make a dracut initramfs.img by chrooting
into the runtime and running dracut.
Finally, we add squashfs.img to initramfs.img, along with an extra file
(/etc/cmdline) which directs dracut to use /squashfs.img as its root
device. And there we go! Easy, right?!
---
share/ramdisk.ltmpl | 1 +
src/pylorax/__init__.py | 8 +++-
src/pylorax/constants.py | 2 +
src/pylorax/installtree.py | 98 +++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 106 insertions(+), 3 deletions(-)
# move modules out of the tree again
logger.debug("moving modules outside initrd")
@@ -543,6 +547,98 @@ class LoraxInstallTree(BaseLoraxClass):
logger.debug("compressing")
rc = compressed.wait()
+ def make_dracut_initramfs(self):
+ outfile = "/tmp/initramfs.img" # inside the chroot
+ logger.debug("chrooting into installtree to create initramfs.img")
+ subprocess.check_call(["chroot", self.root,
+ "/sbin/dracut", "--nomdadmconf", "--nolvmconf",
+ "--xz", "--modules", "base dmsquash-live",
+ outfile, self.kernels[0].version])
+ # move output file into installtree workdir
+ self.initramfs = joinpaths(self.workdir, "initramfs.img")
+ shutil.move(joinpaths(self.root, outfile), self.initramfs)
+
+ def make_squashfs_runtime(self, runtime, kernel, type, args):
+ 'This is a little complicated, but dracut wants to find a squashfs
+ image named "squashfs.img" which contains a filesystem image named
+ "LiveOS/rootfs.img".
+ Placing squashfs.img inside a cpio image and concatenating that
+ with the existing initramfs.img will make squashfs.img appear inside
+ initramfs at boot time.'
+ # Check to be sure we have a dracut initramfs to use
+ assert self.initramfs, "make_dracut_initramfs has not been run!"
+
+ # These exact names are required by dracut
+ squashname = "squashfs.img"
+ imgname = "LiveOS/rootfs.img"
+
+ # Create fs image of installtree (2GB sparse file)
+ fsimage = joinpaths(self.workdir, "installtree.img")
+ open(fsimage, "wb").truncate(2*1024**3)
+ mountpoint = joinpaths(self.workdir, "rootfs")
+ os.mkdir(mountpoint, 0755)
+ mkfs = [self.lcmds.MKFS_EXT4, "-q", "-L", "Anaconda", "-F", fsimage]
+ logger.debug("formatting rootfs image: %s" % " ".join(mkfs))
+ subprocess.check_call(mkfs, stdout=subprocess.PIPE)
+ logger.debug("mounting rootfs image at %s", mountpoint)
+ subprocess.check_call([self.lcmds.MOUNT, "-o", "loop",
+ fsimage, mountpoint])
+ try:
+ logger.info("copying installtree into rootfs image")
+ srcfiles = [joinpaths(self.root, f) for f in os.listdir(self.root)]
+ subprocess.check_call(["cp", "-a"] + srcfiles + [mountpoint])
+ finally:
+ logger.debug("unmounting rootfs image")
+ rc = subprocess.call([self.lcmds.UMOUNT, mountpoint])
+ if rc != 0:
+ logger.critical("umount %s failed (returncode %i)", mountpoint, rc)
+ sys.exit(rc)
+ os.rmdir(mountpoint)
+
+ # Make squashfs with rootfs image inside
+ logger.info("creating %s containing %s", squashname, imgname)
+ squashtree = joinpaths(self.workdir, "squashfs")
+ os.makedirs(joinpaths(squashtree, os.path.dirname(imgname)))
+ shutil.move(fsimage, joinpaths(squashtree, imgname))
+ squashimage = joinpaths(self.workdir, squashname)
+ cmd = [self.lcmds.MKSQUASHFS, squashtree, squashimage] + args.split()
+ subprocess.check_call(cmd)
+ shutil.rmtree(squashtree)
+
+ # Put squashimage in a new initramfs image with dracut config
+ logger.debug("creating initramfs image containing %s", squashname)
+ initramfsdir = joinpaths(self.workdir, "initramfs")
+ # write boot cmdline for dracut
+ cmdline = joinpaths(initramfsdir, "etc/cmdline")
+ os.makedirs(os.path.dirname(cmdline))
+ with open(cmdline, "wb") as fobj:
+ fobj.write("root=live:/{0}
".format(squashname))
+ # add squashimage to new cpio image
+ shutil.move(squashimage, initramfsdir)
+ # create cpio container
+ squash_cpio = joinpaths(self.workdir, "squashfs.cpio")
+ chdir = lambda: os.chdir(initramfsdir)
+ find = subprocess.Popen([self.lcmds.FIND, "."], stdout=subprocess.PIPE,
+ preexec_fn=chdir)
+ cpio = subprocess.Popen([self.lcmds.CPIO, "--quiet", "-c", "-o"],
+ stdin=find.stdout,
+ stdout=open(squash_cpio, "wb"),
+ preexec_fn=chdir)
+ cpio.communicate()
+ shutil.rmtree(initramfsdir)
+
+ # create final image
+ logger.debug("concatenating dracut initramfs and squashfs initramfs")
+ logger.debug("initramfs.img size = %i", os.stat(self.initramfs).st_size)
+ with open(runtime.fpath, "wb") as output:
+ for f in self.initramfs, squash_cpio:
+ with open(f, "rb") as fobj:
+ data = fobj.read(4096)
+ while data:
+ output.write(data)
+ data = fobj.read(4096)
+ os.remove(self.initramfs)
+ os.remove(squash_cpio)
@property
def kernels(self):
--
1.7.5.2
_______________________________________________
Anaconda-devel-list mailing list
Anaconda-devel-list@redhat.com
https://www.redhat.com/mailman/listinfo/anaconda-devel-list