bee_layer_classify only ever tracked regular files and symlinks (`find ... -type f -o -type l`), so any directory that is empty at build time — like /var/log/nvidia-dcgm, correctly created and chowned by the datacenter-gpu-manager postinst — was silently dropped from every layer's rsync --files-from list and never reached the built ISO. This is why bbc6fb1's78d1b9bfollow-up (seeding a marker file just for that one path) kept the directory alive: it was a targeted workaround for a general gap in the classifier, not a fix of it. Replace that workaround with the general mechanism: classify also walks every directory, computes the subset that is empty all the way down (no file or symlink anywhere in its subtree — a directory that does hold files needs no entry, rsync already recreates it as an implied parent), and assigns each one to a layer via the same dpkg-ownership / injected-rule precedence used for files. Add an injected rule routing /var/log/nvidia-dcgm to 20-nvidia-platform, alongside the DCGM binaries that actually use it, instead of letting it fall through to base by default. bee_layer_build folds each layer's empty-dir list into the same rsync --files-from call; recursion into a directory that is by-construction empty copies nothing extra. Revert the 9000/9999 hook changes from78d1b9bnow that they're redundant, and cover the new path with test-squashfs-layers.sh (ruled, unruled, and nested-empty directories, asserted present in the merged rootfs after a real mksquashfs/unsquashfs round-trip). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
204 lines
8.7 KiB
Bash
204 lines
8.7 KiB
Bash
#!/bin/sh
|
|
# test-squashfs-layers.sh - regression tests for lib/squashfs-layers.sh.
|
|
#
|
|
# Builds a synthetic mini-rootfs, splits it, and asserts the semantic layer
|
|
# contract holds. Requires mksquashfs / unsquashfs / rsync; skips cleanly when
|
|
# they are not installed (e.g. on a developer macOS box).
|
|
set -eu
|
|
|
|
BUILDER_DIR="$(CDPATH= cd -- "$(dirname "$0")" && pwd)"
|
|
. "$BUILDER_DIR/lib/squashfs-layers.sh"
|
|
|
|
for tool in mksquashfs unsquashfs rsync; do
|
|
command -v "$tool" >/dev/null 2>&1 || {
|
|
echo "test-squashfs-layers: $tool not available, skipping"
|
|
exit 0
|
|
}
|
|
done
|
|
|
|
T="$(mktemp -d)"
|
|
trap 'rm -rf "$T"' EXIT INT TERM HUP
|
|
ROOT="$T/root"
|
|
|
|
mk() { mkdir -p "$(dirname "$ROOT/$1")"; printf '%s' "${2:-x}" > "$ROOT/$1"; }
|
|
mkbig() { mkdir -p "$(dirname "$ROOT/$1")"; head -c "${2:-1048576}" /dev/urandom > "$ROOT/$1"; }
|
|
listf() { mkdir -p "$ROOT/var/lib/dpkg/info"; printf '%s\n' "$@" > "$ROOT/var/lib/dpkg/info/$1.list"; }
|
|
|
|
# --- base rootfs ---
|
|
mk usr/lib/systemd/systemd "#!systemd"
|
|
( cd "$ROOT/usr" && mkdir -p sbin && ln -s ../lib/systemd/systemd sbin/init )
|
|
mk usr/local/bin/bee "#!bee"
|
|
mk etc/hostname "easy-bee"
|
|
mk usr/bin/true "#!true"
|
|
mk usr/bin/dmidecode "#!dmi"
|
|
( cd "$ROOT" && ln -s usr/bin bin && ln -s usr/bin sbin && ln -s usr/lib lib && ln -s usr/lib lib64 )
|
|
listf base-files /etc/hostname /usr/bin/true
|
|
listf dmidecode /usr/bin/dmidecode
|
|
|
|
# --- 05 firmware: non-NVIDIA device firmware. The bare "/lib" entry mimics the
|
|
# real firmware-* .list files and must NOT drag the /lib symlink out of base.
|
|
listf firmware-iwlwifi /lib /lib/firmware /lib/firmware/iwlwifi-cc-a0-77.ucode
|
|
mk usr/lib/firmware/iwlwifi-cc-a0-77.ucode
|
|
listf firmware-realtek /lib/firmware/rtl_nic/rtl8168h-2.fw
|
|
mk usr/lib/firmware/rtl_nic/rtl8168h-2.fw
|
|
|
|
# --- 08 desktop ---
|
|
listf chromium /usr/bin/chromium
|
|
mk usr/bin/chromium "#!chromium"
|
|
listf xserver-xorg-core /usr/bin/Xorg
|
|
mk usr/bin/Xorg "#!Xorg"
|
|
listf lightdm /usr/sbin/lightdm
|
|
mk usr/sbin/lightdm "#!lightdm"
|
|
listf libgl1-mesa-dri /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so
|
|
mk usr/lib/x86_64-linux-gnu/dri/swrast_dri.so
|
|
listf fonts-dejavu-core /usr/share/fonts/truetype/dejavu/DejaVuSans.ttf
|
|
mk usr/share/fonts/truetype/dejavu/DejaVuSans.ttf
|
|
|
|
# --- 10 driver: dpkg + injected ---
|
|
listf firmware-nvidia-gsp /lib /lib/firmware /lib/firmware/nvidia/580.159.03/gsp_ga10x.bin
|
|
mk usr/lib/firmware/nvidia/580.159.03/gsp_ga10x.bin
|
|
mk usr/lib/firmware/nvidia/580.159.03/gsp_tu10x.bin
|
|
listf nvidia-modprobe /usr/bin/nvidia-modprobe
|
|
mk usr/bin/nvidia-modprobe
|
|
mk usr/local/lib/nvidia/nvidia.ko
|
|
mk usr/local/lib/nvidia/nvidia-uvm.ko
|
|
mk usr/local/bin/nvidia-smi "#!nvidia-smi"
|
|
mk usr/lib/libnvidia-ml.so.1
|
|
mk usr/lib/libnvidia-ml.so.580.159.03
|
|
mk usr/lib/libcuda.so.1
|
|
mk etc/OpenCL/vendors/nvidia.icd "libnvidia-opencl.so.1"
|
|
mk etc/systemd/system/bee-nvidia.service "[Unit]"
|
|
mk usr/local/bin/bee-nvidia-load "#!load"
|
|
|
|
# --- 20 platform ---
|
|
listf nvidia-fabricmanager /usr/bin/nv-fabricmanager /usr/lib/systemd/system/nvidia-fabricmanager.service
|
|
mk usr/bin/nv-fabricmanager
|
|
mk usr/lib/systemd/system/nvidia-fabricmanager.service "[Unit]"
|
|
listf libnvidia-nscq /usr/lib/x86_64-linux-gnu/libnvidia-nscq.so.580.159.03
|
|
mk usr/lib/x86_64-linux-gnu/libnvidia-nscq.so.580.159.03
|
|
listf datacenter-gpu-manager-4-core /usr/bin/dcgmi /usr/bin/nv-hostengine
|
|
mk usr/bin/dcgmi "#!dcgmi"
|
|
mk usr/bin/nv-hostengine "#!nvh"
|
|
mk etc/systemd/system/nvidia-fabricmanager.service.d/bee-nvswitch-check.conf "[Service]"
|
|
|
|
# --- 30 cuda libs (injected) ---
|
|
mk usr/lib/libcudart.so.13
|
|
mk usr/lib/libcublas.so.13
|
|
mk usr/lib/libcublasLt.so.13
|
|
mk usr/lib/libnccl.so.2
|
|
mk usr/local/bin/all_reduce_perf "#!arp"
|
|
mk usr/local/lib/bee/bee-gpu-burn-worker "#!worker"
|
|
|
|
# --- 40 dcgm cuda ---
|
|
listf datacenter-gpu-manager-4-cuda13 /usr/bin/dcgmproftester12
|
|
mkbig usr/bin/dcgmproftester12 3145728
|
|
mk usr/local/bin/bee-dcgmproftester-staggered "#!stag"
|
|
|
|
# a plain "nvidia" in the path must NOT be enough on its own: an unowned,
|
|
# unruled file under an nvidia dir stays in base.
|
|
mk usr/share/doc/nvidia-random/README "notes"
|
|
|
|
# --- empty directories: no file/symlink anywhere in their subtree, so they
|
|
# never appear in all.files and must be classified/carried separately.
|
|
mkdir -p "$ROOT/var/log/nvidia-dcgm" # ruled -> 20-nvidia-platform
|
|
mkdir -p "$ROOT/var/lib/bee-empty-unruled" # unruled -> base
|
|
mkdir -p "$ROOT/var/lib/bee-empty-nested/still-empty" # nested empty branch -> base
|
|
|
|
fail() { echo "FAIL: $*" >&2; exit 1; }
|
|
in_layer() { LC_ALL=C grep -qx "$2" "$WD/$1.files" || fail "expected $2 in layer $1"; }
|
|
in_dir_layer() { LC_ALL=C grep -qx "$2" "$WD/$1.dirs" || fail "expected empty dir $2 in layer $1"; }
|
|
|
|
MONO="$T/filesystem-v14.99.squashfs"
|
|
mksquashfs "$ROOT" "$MONO" -comp zstd -noappend -no-progress -no-xattrs >/dev/null
|
|
|
|
R2="$T/r2"; unsquashfs -d "$R2" "$MONO" >/dev/null
|
|
WD="$T/cls"
|
|
bee_layer_classify "$R2" nvidia "$WD"
|
|
|
|
in_layer 00-base usr/sbin/init
|
|
in_layer 00-base usr/lib/systemd/systemd
|
|
in_layer 00-base usr/local/bin/bee
|
|
in_layer 00-base etc/hostname
|
|
in_layer 00-base usr/bin/dmidecode
|
|
in_layer 00-base bin
|
|
in_layer 00-base sbin
|
|
in_layer 00-base lib
|
|
in_layer 00-base lib64
|
|
in_layer 05-firmware usr/lib/firmware/iwlwifi-cc-a0-77.ucode
|
|
in_layer 05-firmware usr/lib/firmware/rtl_nic/rtl8168h-2.fw
|
|
in_layer 08-desktop usr/bin/chromium
|
|
in_layer 08-desktop usr/bin/Xorg
|
|
in_layer 08-desktop usr/sbin/lightdm
|
|
in_layer 08-desktop usr/lib/x86_64-linux-gnu/dri/swrast_dri.so
|
|
in_layer 08-desktop usr/share/fonts/truetype/dejavu/DejaVuSans.ttf
|
|
in_layer 10-nvidia-driver usr/local/lib/nvidia/nvidia.ko
|
|
in_layer 10-nvidia-driver usr/local/bin/nvidia-smi
|
|
in_layer 10-nvidia-driver usr/lib/libnvidia-ml.so.1
|
|
in_layer 10-nvidia-driver usr/lib/libcuda.so.1
|
|
in_layer 10-nvidia-driver usr/lib/firmware/nvidia/580.159.03/gsp_ga10x.bin
|
|
in_layer 10-nvidia-driver etc/OpenCL/vendors/nvidia.icd
|
|
in_layer 10-nvidia-driver etc/systemd/system/bee-nvidia.service
|
|
in_layer 10-nvidia-driver usr/bin/nvidia-modprobe
|
|
in_layer 20-nvidia-platform usr/bin/nv-fabricmanager
|
|
in_layer 20-nvidia-platform usr/lib/x86_64-linux-gnu/libnvidia-nscq.so.580.159.03
|
|
in_layer 20-nvidia-platform usr/bin/dcgmi
|
|
in_layer 20-nvidia-platform usr/bin/nv-hostengine
|
|
in_layer 20-nvidia-platform etc/systemd/system/nvidia-fabricmanager.service.d/bee-nvswitch-check.conf
|
|
in_layer 30-nvidia-cuda-libs usr/lib/libcudart.so.13
|
|
in_layer 30-nvidia-cuda-libs usr/lib/libcublasLt.so.13
|
|
in_layer 30-nvidia-cuda-libs usr/lib/libnccl.so.2
|
|
in_layer 30-nvidia-cuda-libs usr/local/bin/all_reduce_perf
|
|
in_layer 30-nvidia-cuda-libs usr/local/lib/bee/bee-gpu-burn-worker
|
|
in_layer 40-nvidia-dcgm-cuda usr/bin/dcgmproftester12
|
|
in_layer 40-nvidia-dcgm-cuda usr/local/bin/bee-dcgmproftester-staggered
|
|
in_layer 00-base usr/share/doc/nvidia-random/README
|
|
|
|
in_dir_layer 20-nvidia-platform var/log/nvidia-dcgm
|
|
in_dir_layer 00-base var/lib/bee-empty-unruled
|
|
in_dir_layer 00-base var/lib/bee-empty-nested
|
|
in_dir_layer 00-base var/lib/bee-empty-nested/still-empty
|
|
|
|
OUT="$T/out"
|
|
bee_layer_build "$R2" "$WD" "$OUT" 14.99 nvidia
|
|
bee_layer_verify_each "$OUT" 14.99 nvidia
|
|
bee_layer_merge "$OUT" 14.99 nvidia "$T/merged"
|
|
|
|
[ -d "$T/merged/var/log/nvidia-dcgm" ] || fail "empty dir var/log/nvidia-dcgm missing from merged rootfs"
|
|
[ -d "$T/merged/var/lib/bee-empty-unruled" ] || fail "empty dir var/lib/bee-empty-unruled missing from merged rootfs"
|
|
[ -d "$T/merged/var/lib/bee-empty-nested/still-empty" ] || fail "nested empty dir missing from merged rootfs"
|
|
|
|
MODLIVE="$T/live"; mkdir -p "$MODLIVE"
|
|
cp "$OUT"/filesystem-v14.99-*.squashfs "$MODLIVE/"
|
|
bee_layer_write_module_file "$MODLIVE" 14.99 nvidia
|
|
expect_mod="filesystem-v14.99-00-base.squashfs
|
|
filesystem-v14.99-05-firmware.squashfs
|
|
filesystem-v14.99-08-desktop.squashfs
|
|
filesystem-v14.99-10-nvidia-driver.squashfs
|
|
filesystem-v14.99-20-nvidia-platform.squashfs
|
|
filesystem-v14.99-30-nvidia-cuda-libs.squashfs
|
|
filesystem-v14.99-40-nvidia-dcgm-cuda.squashfs"
|
|
[ "$(cat "$MODLIVE/filesystem.module")" = "$expect_mod" ] || fail "module file order wrong"
|
|
|
|
# --- failure modes ---
|
|
# missing layer -> merge fails
|
|
rm -f "$OUT/filesystem-v14.99-20-nvidia-platform.squashfs"
|
|
if bee_layer_merge "$OUT" 14.99 nvidia "$T/m2" >/dev/null 2>&1; then
|
|
fail "merge succeeded with a missing layer"
|
|
fi
|
|
bee_layer_build "$R2" "$WD" "$OUT" 14.99 nvidia >/dev/null # restore
|
|
|
|
# size ceiling -> build fails
|
|
if BEE_LAYER_MAX_MIB=0 bee_layer_build "$R2" "$WD" "$T/out0" 14.99 nvidia >/dev/null 2>&1; then
|
|
fail "build ignored the size ceiling"
|
|
fi
|
|
|
|
# incomplete partition -> classify fails
|
|
rm -rf "$WD"; bee_layer_classify "$R2" nvidia "$WD"
|
|
echo "usr/bin/does-not-exist" >> "$WD/10-nvidia-driver.files"
|
|
_total=$(wc -l < "$WD/all.files")
|
|
_sum=0
|
|
for s in $(bee_layer_slugs_for_variant nvidia); do _sum=$((_sum + $(wc -l < "$WD/$s.files"))); done
|
|
[ "$_sum" -ne "$_total" ] || fail "tampered partition should not still sum to the tree size"
|
|
|
|
echo "squashfs layer tests: OK"
|