From 48f94bbb6a097f02f984d87a0b165093056a901b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Andr=C3=A1s=20Korn?= Date: Sun, 21 Aug 2022 10:38:22 +0200 Subject: [PATCH] Add support for building grml ISOs with zfs The `ZFS` FAI class will, via the `instsoft.ZFS` hook, install the packages needed to build the zfs modules, build the zfs modules, then remove the development packages again to avoid bloating the ISO. The ZFS `package_config` now only installs `zfsutils-linux` so that the iso contains the userspace zfs tools. In my tests, the ZFS class now only increases the size of the ISO by about 3MB. I wanted to rely on apt autoremove to get rid of automatically installed packages, but for some reason as of 2.5.2 autoremove doesn't actually remove some of the development packages (e.g. gcc-11) even though they're Priority optional, marked as auto-installed, and not depended on by anything that isn't auto-installed. So, to avoid bloating the ISO with hundreds of MB of development packages, the `instsoft.ZFS` script works out which packages it installs and removes those explicitly, using potentially brittle parsing of `apt-get` output. This has been tested to work and should do until a better solution is found. --- etc/grml/fai/config/hooks/instsoft.ZFS | 81 ++++++++++++++++++++++++++++++++++ etc/grml/fai/config/package_config/ZFS | 5 --- 2 files changed, 81 insertions(+), 5 deletions(-) create mode 100755 etc/grml/fai/config/hooks/instsoft.ZFS diff --git a/etc/grml/fai/config/hooks/instsoft.ZFS b/etc/grml/fai/config/hooks/instsoft.ZFS new file mode 100755 index 0000000..2e8a072 --- /dev/null +++ b/etc/grml/fai/config/hooks/instsoft.ZFS @@ -0,0 +1,81 @@ +#!/bin/bash +# Filename: ${GRML_FAI_CONFIG}/hooks/instsoft.ZFS +# Purpose: Build zfs modules in the chroot, then get rid of packages installed for this alone +# Authors: (c) András Korn +# Bug-Reports: see http://grml.org/bugs/ +# License: This file is licensed under the GPL v2, or, at your option, any later version. +################################################################################ + +set -u +set -e + +# We don't want to install build-essential, dkms et al via package_config +# because they will end up bloating the iso; it seems cleaner to install +# them, build the zfs modules, then remove them. +# +# TODO: if https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1009179 is ever +# fixed, switch to building a zfs-modules deb and including that. +# +# TODO: convert this into a framework for other classes to ship dkms +# modules: have a hook/script that installs the build-related packages, +# another that builds whatever must be built, and a third that does the cleanup. +# +# TODO: support other architectures grml and grml-live supports (PRs +# welcome, I'm sure). + +echo "$0: Installing latest kernel and its headers, as well as build-essential." +# For some reason, apt's autoremove function doesn't pick up some of the +# extra packages we install here, e.g. gcc-11, so work around that by +# keeping track of what gets installed. This is an ugly hack and should not +# be needed, but without it the resulting ISO is hundreds of megabytes +# larger. I hope this kludge can go away eventually. +extra_packages=($($ROOTCMD apt-get --assume-no --download-only --mark-auto -u install \ + build-essential linux-image-amd64 linux-headers-amd64 \ + | sed '0,/The following NEW packages will be installed/d;/^[^ ]/,$d')) +$ROOTCMD apt-get --yes --mark-auto -u install build-essential linux-image-amd64 linux-headers-amd64 + +# Remove all but the latest kernel (TODO: support passing in the desired +# kernel version by configuration variable instead of using the latest): +echo "$0: Removing all kernel packages except the latest one, if any." +for kernelversion in $($ROOTCMD sh -c 'cd /boot; ls -rt vmlinuz-*' | sed 's/^vmlinuz-//;$d'); do + echo "$0: Removing obsolete kernel version $kernelversion" + $ROOTCMD apt-get --yes --purge remove "linux-.*$kernelversion.*" +done + +# Earlier Debian releases have a dwarves package; newer ones have pahole. +# This can be needed to build the zfs modules, perhaps depending on kernel +# configuration (TODO: look into this). +echo "$0: Installing pahole or dwarves, whichever is available." +if $ROOTCMD apt-get --yes --mark-auto -u install pahole; then + pahole=pahole +else + $ROOTCMD apt-get --mark-auto --yes -u install dwarves + pahole=dwarves +fi + +echo "$0: Installing zfs-dkms itself." +extra_packages=(${extra_packages[@]} $($ROOTCMD apt-get --assume-no --download-only --mark-auto -u install zfs-dkms | sed '0,/The following NEW packages will be installed/d;/^[^ ]/,$d')) +$ROOTCMD apt-get --yes --mark-auto -u install zfs-dkms + +# Now invoke the dkms kernel postinst script for the only kernel that's left +# -- normally the zfs-dkms postinst script should do this, but maybe it +# didn't, and redoing it is almost free: +kernelversion=$($ROOTCMD sh -c 'ls -1 /boot/vmlinuz-*' | sed 's@.*boot/vmlinuz-@@') +echo "$0: Building zfs-dkms modules for kernel $kernelversion." +$ROOTCMD /etc/kernel/postinst.d/dkms "$kernelversion" + +tempfile=$(mktemp) +echo "$0: Saving built modules into a backup file (removing the dkms package will remove them, but we'll put them back)." +$ROOTCMD tar cf - /lib/modules/$kernelversion/updates/dkms >$tempfile + +echo "$0: Removing packages only needed to build zfs modules." +remove_packages=($(echo "${extra_packages[@]}" zfs-dkms '^linux-headers-.*' build-essential $pahole | tr ' ' '\n' | sort -u)) +$ROOTCMD apt-get --yes --purge --autoremove remove ${remove_packages[@]} +echo "$0: Trying extra hard to get rid of auto-installed packages. This is a hack that is one of the ways we're trying to work around a perceived bug in apt autoremove and should be a no-op." +$ROOTCMD apt-get --yes --purge autoremove + +echo "$0: Restoring backed-up kernel modules." +$ROOTCMD tar xf - <$tempfile +rm $tempfile +$ROOTCMD depmod -a $kernelversion +echo "$0: Completed successfully. Enjoy your zfs." diff --git a/etc/grml/fai/config/package_config/ZFS b/etc/grml/fai/config/package_config/ZFS index c0c2451..02ca370 100644 --- a/etc/grml/fai/config/package_config/ZFS +++ b/etc/grml/fai/config/package_config/ZFS @@ -1,9 +1,4 @@ PACKAGES install -build-essential -# pahole(1), provided by the dwwarves package in older Debian releases and the pahole package in sid as of 2022-08, can be needed to build kernel modules (depending on kernel config?) -# TODO: add a script that removes it once dkms install succeeded so that it doesn't bloat the iso -dwarves -zfs-dkms zfsutils-linux -- 2.1.4