diff --git a/install-external-deps.sh b/install-external-deps.sh index acb9560..b77efac 100755 --- a/install-external-deps.sh +++ b/install-external-deps.sh @@ -45,26 +45,72 @@ ANYSCAN_USE_AF_XDP="${ANYSCAN_USE_AF_XDP:-0}" ANYSCAN_USE_PFRING_ZC="${ANYSCAN_USE_PFRING_ZC:-0}" # Opt-in kernel backport upgrade. Default 0 leaves the running kernel -# untouched (existing AMIs unchanged). Setting 1 installs the Debian -# bookworm-backports kernel image so the host can run kernel 6.16+ -# with the in-flight `ena_xdp_zc` ENA driver patches that AF_XDP -# zerocopy on ENA needs. The PR 65 §10 / anygpt-42 live bench showed -# ENA on kernel 6.12.74 caps the c6in.metal 8-NIC cap=4 throughput -# at ~22M pps in drv+copy mode, vs the 30-50M projection driver-mode -# zerocopy was supposed to deliver. See PR 65 issuecomment-4336192354 -# for the constraint trace. +# untouched (existing AMIs unchanged). Setting 1 installs a Debian +# backports kernel image so the host can run kernel 6.16+ with the +# in-flight `ena_xdp_zc` ENA driver patches that AF_XDP zerocopy on +# ENA needs. The PR 65 §10 / anygpt-42 live bench showed ENA on +# kernel 6.12.74 caps the c6in.metal 8-NIC cap=4 throughput at ~22M +# pps in drv+copy mode, vs the 30-50M projection driver-mode zerocopy +# was supposed to deliver. See PR 65 issuecomment-4336192354 for the +# constraint trace. +# +# The suite and package default to the host's Debian codename: +# trixie-backports / linux-image-amd64 on Debian 13, bookworm-backports +# / linux-image-cloud-amd64 on Debian 12. PR 65 issuecomment-4338158487 +# (anygpt-48) caught the previous static bookworm-backports default +# silently no-op'ing on the Trixie AMI: bookworm-backports +# linux-image-cloud-amd64 resolves to 6.12.74-2~bpo12+1 — exactly the +# kernel the metal already runs — so the opt-in completed "0 upgraded, +# 0 newly installed" and the operator got a green light without ever +# upgrading. Trixie's linux-image-cloud-amd64 is also still 6.12 as of +# 2026-04, so we explicitly switch the package to the non-cloud +# linux-image-amd64 on non-bookworm suites. +# +# Operator-set ANYSCAN_KERNEL_BACKPORT_SUITE / _PACKAGE / _SOURCES_LIST +# still win — the codename detection is just a smarter default. # # Never auto-reboots. The new kernel is staged on disk and the operator # has to schedule the reboot themselves. After install the script # probes `/sys/module/ena/version` + dmesg for `ena_xdp_zc` support # and warns if absent so the operator knows whether the # CURRENTLY-RUNNING kernel will deliver zerocopy. + +# Detect the Debian codename so backport defaults match the running +# release. /etc/os-release VERSION_CODENAME is the canonical source on +# Debian/Ubuntu hosts; missing or unreadable file → fall back to +# "bookworm" so the legacy default doesn't change for hosts where the +# os-release file isn't accessible. Override the file path with +# ANYSCAN_OS_RELEASE_FILE for testing. +detect_debian_codename() { + local release_file="${ANYSCAN_OS_RELEASE_FILE:-/etc/os-release}" + local codename="" + if [ -r "$release_file" ]; then + # shellcheck source=/dev/null + codename="$(. "$release_file" 2>/dev/null && printf '%s\n' "${VERSION_CODENAME:-}")" + fi + if [ -z "$codename" ]; then + codename="bookworm" + fi + printf '%s\n' "$codename" +} + ANYSCAN_INSTALL_KERNEL_BACKPORT="${ANYSCAN_INSTALL_KERNEL_BACKPORT:-0}" ANYSCAN_KERNEL_BACKPORT_MIN_VERSION="${ANYSCAN_KERNEL_BACKPORT_MIN_VERSION:-6.16}" -ANYSCAN_KERNEL_BACKPORT_PACKAGE="${ANYSCAN_KERNEL_BACKPORT_PACKAGE:-linux-image-cloud-amd64}" -ANYSCAN_KERNEL_BACKPORT_SUITE="${ANYSCAN_KERNEL_BACKPORT_SUITE:-bookworm-backports}" -ANYSCAN_KERNEL_BACKPORT_SOURCES_LIST="${ANYSCAN_KERNEL_BACKPORT_SOURCES_LIST:-/etc/apt/sources.list.d/anyscan-bookworm-backports.list}" +_anyscan_codename="$(detect_debian_codename)" +ANYSCAN_KERNEL_BACKPORT_SUITE="${ANYSCAN_KERNEL_BACKPORT_SUITE:-${_anyscan_codename}-backports}" +# Package selection: trixie-backports linux-image-cloud-amd64 is still +# 6.12 as of 2026-04 — only the non-cloud linux-image-amd64 jumps to +# 6.19. Bookworm-backports keeps the legacy linux-image-cloud-amd64 +# default for back-compat on operators still on bookworm hosts. +if [ "$ANYSCAN_KERNEL_BACKPORT_SUITE" = "bookworm-backports" ]; then + _anyscan_default_pkg="linux-image-cloud-amd64" +else + _anyscan_default_pkg="linux-image-amd64" +fi +ANYSCAN_KERNEL_BACKPORT_PACKAGE="${ANYSCAN_KERNEL_BACKPORT_PACKAGE:-$_anyscan_default_pkg}" +ANYSCAN_KERNEL_BACKPORT_SOURCES_LIST="${ANYSCAN_KERNEL_BACKPORT_SOURCES_LIST:-/etc/apt/sources.list.d/anyscan-${ANYSCAN_KERNEL_BACKPORT_SUITE}.list}" ANYSCAN_KERNEL_BACKPORT_MIRROR="${ANYSCAN_KERNEL_BACKPORT_MIRROR:-http://deb.debian.org/debian}" +unset _anyscan_codename _anyscan_default_pkg # True when the existing scanner binary was linked against libxdp at build # time. The AF_XDP build path (USE_AF_XDP=1 in the engine Makefile) adds diff --git a/tools/test-install-external-deps-kernel-backport.sh b/tools/test-install-external-deps-kernel-backport.sh index 5a649a0..dd68980 100755 --- a/tools/test-install-external-deps-kernel-backport.sh +++ b/tools/test-install-external-deps-kernel-backport.sh @@ -211,6 +211,13 @@ run_install_script() { local install_kernel_backport="$2" local uname_release="$3" local apt_present="$4" + # Optional 5th arg: os-release VERSION_CODENAME to write into a + # synthetic /etc/os-release the install script will read via + # ANYSCAN_OS_RELEASE_FILE. When empty, we pre-set + # ANYSCAN_KERNEL_BACKPORT_SUITE/_PACKAGE explicitly to bookworm + # defaults so existing case-1..4 assertions stay stable regardless + # of the test host's actual codename. + local os_release_codename="${5:-}" local repo_dir="$case_dir/engine" local runtime_env="$case_dir/runtime.env" @@ -220,6 +227,7 @@ run_install_script() { local git_log="$case_dir/git.log" local stub_dir="$case_dir/stubs" local sources_list="$case_dir/anyscan-bookworm-backports.list" + local os_release_file="" mkdir -p "$repo_dir" "$artifact_dir" : >"$apt_log" @@ -232,6 +240,12 @@ run_install_script() { prepare_stubs "$stub_dir" "$apt_log" "$make_log" "$git_log" \ "$uname_release" "$apt_present" + if [ -n "$os_release_codename" ]; then + os_release_file="$case_dir/os-release" + printf 'ID=debian\nVERSION_CODENAME=%s\n' "$os_release_codename" \ + >"$os_release_file" + fi + ( # PATH = stub_dir only. prepare_stubs symlinks the essentials # install-external-deps.sh needs (bash, mktemp, install, sed, @@ -242,7 +256,23 @@ run_install_script() { # apt-get` returns false for the install script. export PATH="$stub_dir" export ANYSCAN_INSTALL_KERNEL_BACKPORT="$install_kernel_backport" - export ANYSCAN_KERNEL_BACKPORT_SOURCES_LIST="$sources_list" + if [ -n "$os_release_file" ]; then + # Auto-detect path: let the script derive suite/package from + # the synthetic os-release. Pin the sources-list path to a + # per-case file so the test doesn't try to write under + # /etc/apt — but still derive its name from the codename so + # the assertion side stays meaningful. + export ANYSCAN_OS_RELEASE_FILE="$os_release_file" + export ANYSCAN_KERNEL_BACKPORT_SOURCES_LIST="$case_dir/anyscan-${os_release_codename}-backports.list" + unset ANYSCAN_KERNEL_BACKPORT_SUITE + unset ANYSCAN_KERNEL_BACKPORT_PACKAGE + else + # Legacy path: pin suite/package explicitly so the + # existing case-1..4 assertions hold on any test host. + export ANYSCAN_KERNEL_BACKPORT_SUITE="bookworm-backports" + export ANYSCAN_KERNEL_BACKPORT_PACKAGE="linux-image-cloud-amd64" + export ANYSCAN_KERNEL_BACKPORT_SOURCES_LIST="$sources_list" + fi export ANYSCAN_VULNSCANNER_REPO_DIR="$repo_dir" export ANYSCAN_INSTALL_AFXDP_DEPS=false export ANYSCAN_USE_AF_XDP=0 @@ -351,6 +381,68 @@ else note_fail "knob=1 + no apt-get build" "install-external-deps.sh exited non-zero (see $case_dir/stderr.log)" fi +# --------------------------------------------------------------------------- +# Case 5: knob=1 + Trixie host + kernel 6.12 → suite=trixie-backports, +# package=linux-image-amd64 (NOT linux-image-cloud-amd64). +# Confirms PR 65 issuecomment-4338158487 fix: bookworm-backports default +# silently no-op'd on Trixie because bookworm cloud-amd64 is still 6.12. +# --------------------------------------------------------------------------- +case_dir="$WORK_ROOT/case-trixie-host" +mkdir -p "$case_dir" +if run_install_script "$case_dir" "1" "6.12.74-cloud-amd64" "yes" "trixie"; then + note_pass "knob=1 + trixie host build runs successfully" + assert_contains_substring \ + "knob=1 + trixie: apt-get install -t trixie-backports linux-image-amd64 fires" \ + "install -y --no-install-recommends -t trixie-backports linux-image-amd64" \ + "$case_dir/apt-get.log" + assert_not_contains_substring \ + "knob=1 + trixie: bookworm-backports NOT used (would silently no-op)" \ + "bookworm-backports" \ + "$case_dir/apt-get.log" + assert_not_contains_substring \ + "knob=1 + trixie: linux-image-cloud-amd64 NOT used (still 6.12 in trixie-backports)" \ + "linux-image-cloud-amd64" \ + "$case_dir/apt-get.log" + assert_file_present \ + "knob=1 + trixie: apt source list at trixie-backports path" \ + "$case_dir/anyscan-trixie-backports.list" + assert_contains_substring \ + "knob=1 + trixie: apt source list points at trixie-backports" \ + "trixie-backports" \ + "$case_dir/anyscan-trixie-backports.list" + assert_file_missing \ + "knob=1 + trixie: bookworm-backports source list NOT created" \ + "$case_dir/anyscan-bookworm-backports.list" +else + note_fail "knob=1 + trixie host build" "install-external-deps.sh exited non-zero (see $case_dir/stderr.log)" +fi + +# --------------------------------------------------------------------------- +# Case 6: knob=1 + Bookworm host + kernel 6.12 → legacy default preserved +# (suite=bookworm-backports, package=linux-image-cloud-amd64). +# --------------------------------------------------------------------------- +case_dir="$WORK_ROOT/case-bookworm-host" +mkdir -p "$case_dir" +if run_install_script "$case_dir" "1" "6.12.74-cloud-amd64" "yes" "bookworm"; then + note_pass "knob=1 + bookworm host build runs successfully" + assert_contains_substring \ + "knob=1 + bookworm: apt-get install -t bookworm-backports linux-image-cloud-amd64 fires" \ + "install -y --no-install-recommends -t bookworm-backports linux-image-cloud-amd64" \ + "$case_dir/apt-get.log" + assert_file_present \ + "knob=1 + bookworm: apt source list at bookworm-backports path" \ + "$case_dir/anyscan-bookworm-backports.list" + assert_contains_substring \ + "knob=1 + bookworm: apt source list points at bookworm-backports" \ + "bookworm-backports" \ + "$case_dir/anyscan-bookworm-backports.list" + assert_file_missing \ + "knob=1 + bookworm: trixie-backports source list NOT created" \ + "$case_dir/anyscan-trixie-backports.list" +else + note_fail "knob=1 + bookworm host build" "install-external-deps.sh exited non-zero (see $case_dir/stderr.log)" +fi + printf '\n' printf 'PASS: %d\n' "$PASS" printf 'FAIL: %d\n' "$FAIL"