From 74b28495d8c64149adb51dc2e09f2f43304b11ea Mon Sep 17 00:00:00 2001 From: Senthil Ravichandran Date: Sat, 18 Jul 2026 23:12:25 -0700 Subject: [PATCH 1/2] fix(installer): restore Station package preparation Signed-off-by: Senthil Ravichandran --- scripts/prepare-dgx-station-host.sh | 10 ++--- test/install-station-host-preparation.test.ts | 3 +- ...nstall-station-package-transaction.test.ts | 37 ++++++++++++------- 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/scripts/prepare-dgx-station-host.sh b/scripts/prepare-dgx-station-host.sh index 60e7e11b3ab..57f808c1765 100755 --- a/scripts/prepare-dgx-station-host.sh +++ b/scripts/prepare-dgx-station-host.sh @@ -1436,7 +1436,7 @@ create_apt_transaction_guard() { assert_root_directory_safe "$APT_TRANSACTION_GUARD_DIR" "APT transaction guard directory" assert_root_regular_file_safe "$hook_path" 0700 "APT transaction guard" assert_root_regular_file_safe "$targets_path" 0600 "APT transaction target manifest" - APT_TRANSACTION_HOOK=$hook_path + APT_TRANSACTION_HOOK="/bin/bash ${hook_path}" } validate_apt_simulation() { @@ -1496,12 +1496,13 @@ validate_apt_simulation() { simulate_install() { local simulation - [[ "$APT_TRANSACTION_HOOK" =~ ^/run/nemoclaw-apt-transaction\.[A-Za-z0-9]+/verify-plan$ ]] \ + [[ "$APT_TRANSACTION_GUARD_DIR" =~ ^/run/nemoclaw-apt-transaction\.[A-Za-z0-9]+$ && + "$APT_TRANSACTION_HOOK" == "/bin/bash ${APT_TRANSACTION_GUARD_DIR}/verify-plan" ]] \ || fatal "APT transaction guard is not ready" simulation="$(sudo env DEBIAN_FRONTEND=noninteractive LC_ALL=C \ apt-get -s install --no-install-recommends --no-remove \ -o "DPkg::Pre-Install-Pkgs::=${APT_TRANSACTION_HOOK}" \ - -o "DPkg::Tools::options::${APT_TRANSACTION_HOOK}::Version=3" "$@")" \ + -o "DPkg::Tools::options::/bin/bash::Version=3" "$@")" \ || fatal "APT simulation failed" printf '%s\n' "$simulation" validate_apt_simulation "$simulation" "$@" @@ -1516,13 +1517,12 @@ install_packages() { validate_package_availability "${PACKAGE_TRANSACTION_SPECS[@]}" create_apt_transaction_guard simulate_install "${PACKAGE_TRANSACTION_SPECS[@]}" - check_no_workloads require_docker_restart_quiescence "Station prerequisite package installation" info "Installing missing pinned Station prerequisites" sudo env DEBIAN_FRONTEND=noninteractive LC_ALL=C \ apt-get install -y --no-install-recommends --no-remove \ -o "DPkg::Pre-Install-Pkgs::=${APT_TRANSACTION_HOOK}" \ - -o "DPkg::Tools::options::${APT_TRANSACTION_HOOK}::Version=3" \ + -o "DPkg::Tools::options::/bin/bash::Version=3" \ "${PACKAGE_TRANSACTION_SPECS[@]}" cleanup_apt_transaction_guard diff --git a/test/install-station-host-preparation.test.ts b/test/install-station-host-preparation.test.ts index 525650b2f33..592a75a151a 100644 --- a/test/install-station-host-preparation.test.ts +++ b/test/install-station-host-preparation.test.ts @@ -416,13 +416,12 @@ run_apply configure_repositories() { printf 'CONFIGURE_REPOSITORIES\n'; } validate_package_availability() { printf 'VALIDATE_PACKAGES\n'; } simulate_install() { printf 'SIMULATE_INSTALL\n'; } -check_no_workloads() { printf 'RECHECK_ALL_WORKLOADS\n'; } require_docker_restart_quiescence() { printf 'RECHECK_RESTART_QUIESCENCE\n'; } package_state() { printf 'missing\n'; } package_is_exact() { return 0; } create_apt_transaction_guard() { APT_TRANSACTION_GUARD_DIR=/run/nemoclaw-apt-transaction.TEST - APT_TRANSACTION_HOOK="$APT_TRANSACTION_GUARD_DIR/verify-plan" + APT_TRANSACTION_HOOK="/bin/bash $APT_TRANSACTION_GUARD_DIR/verify-plan" } cleanup_apt_transaction_guard() { :; } sudo() { printf 'SUDO %s\n' "$*"; } diff --git a/test/install-station-package-transaction.test.ts b/test/install-station-package-transaction.test.ts index 1cfc13ae06e..c435fd1b6e6 100644 --- a/test/install-station-package-transaction.test.ts +++ b/test/install-station-package-transaction.test.ts @@ -89,13 +89,12 @@ apt-get() { done fi } -check_no_workloads() { printf 'RECHECK_ALL_WORKLOADS\n'; } require_docker_restart_quiescence() { printf 'RECHECK_DOCKER_RESTART\n'; } package_state() { printf 'missing\n'; } package_is_exact() { return 0; } create_apt_transaction_guard() { APT_TRANSACTION_GUARD_DIR=/run/nemoclaw-apt-transaction.TEST - APT_TRANSACTION_HOOK="$APT_TRANSACTION_GUARD_DIR/verify-plan" + APT_TRANSACTION_HOOK="/bin/bash $APT_TRANSACTION_GUARD_DIR/verify-plan" } cleanup_apt_transaction_guard() { printf 'CLEANUP_GUARD\n' @@ -124,14 +123,14 @@ cat "$HOME/apt-cache-calls" expect(aptCommands).toEqual( [ ...EXPECTED_PACKAGE_SPECS.map((spec) => `APT_CACHE show ${spec}`), - `APT_GET -s install --no-install-recommends --no-remove -o DPkg::Pre-Install-Pkgs::=/run/nemoclaw-apt-transaction.TEST/verify-plan -o DPkg::Tools::options::/run/nemoclaw-apt-transaction.TEST/verify-plan::Version=3 ${expectedTuple}`, - `SUDO env DEBIAN_FRONTEND=noninteractive LC_ALL=C apt-get install -y --no-install-recommends --no-remove -o DPkg::Pre-Install-Pkgs::=/run/nemoclaw-apt-transaction.TEST/verify-plan -o DPkg::Tools::options::/run/nemoclaw-apt-transaction.TEST/verify-plan::Version=3 ${expectedTuple}`, + `APT_GET -s install --no-install-recommends --no-remove -o DPkg::Pre-Install-Pkgs::=/bin/bash /run/nemoclaw-apt-transaction.TEST/verify-plan -o DPkg::Tools::options::/bin/bash::Version=3 ${expectedTuple}`, + `SUDO env DEBIAN_FRONTEND=noninteractive LC_ALL=C apt-get install -y --no-install-recommends --no-remove -o DPkg::Pre-Install-Pkgs::=/bin/bash /run/nemoclaw-apt-transaction.TEST/verify-plan -o DPkg::Tools::options::/bin/bash::Version=3 ${expectedTuple}`, ].sort(), ); expect(output).toContain( "SUDO env DEBIAN_FRONTEND=noninteractive LC_ALL=C apt-get -s install --no-install-recommends --no-remove", ); - expect(output).toContain("RECHECK_ALL_WORKLOADS"); + expect(output).toContain("RECHECK_DOCKER_RESTART"); expect(output).toContain("CLEANUP_GUARD"); expect(output).toContain("pinned_packages=installed"); }); @@ -155,7 +154,6 @@ apt-get() { done fi } -check_no_workloads() { :; } require_docker_restart_quiescence() { :; } package_state() { if [[ "$1" == '${retainedSpec}' ]]; then printf 'exact\n'; else printf 'missing\n'; fi @@ -163,7 +161,7 @@ package_state() { package_is_exact() { return 0; } create_apt_transaction_guard() { APT_TRANSACTION_GUARD_DIR=/run/nemoclaw-apt-transaction.TEST - APT_TRANSACTION_HOOK="$APT_TRANSACTION_GUARD_DIR/verify-plan" + APT_TRANSACTION_HOOK="/bin/bash $APT_TRANSACTION_GUARD_DIR/verify-plan" } cleanup_apt_transaction_guard() { APT_TRANSACTION_GUARD_DIR="" @@ -191,8 +189,8 @@ cat "$HOME/apt-cache-calls" expect(aptCommands).toEqual( [ ...missingSpecs.map((spec) => `APT_CACHE show ${spec}`), - `APT_GET -s install --no-install-recommends --no-remove -o DPkg::Pre-Install-Pkgs::=/run/nemoclaw-apt-transaction.TEST/verify-plan -o DPkg::Tools::options::/run/nemoclaw-apt-transaction.TEST/verify-plan::Version=3 ${expectedTuple}`, - `SUDO env DEBIAN_FRONTEND=noninteractive LC_ALL=C apt-get install -y --no-install-recommends --no-remove -o DPkg::Pre-Install-Pkgs::=/run/nemoclaw-apt-transaction.TEST/verify-plan -o DPkg::Tools::options::/run/nemoclaw-apt-transaction.TEST/verify-plan::Version=3 ${expectedTuple}`, + `APT_GET -s install --no-install-recommends --no-remove -o DPkg::Pre-Install-Pkgs::=/bin/bash /run/nemoclaw-apt-transaction.TEST/verify-plan -o DPkg::Tools::options::/bin/bash::Version=3 ${expectedTuple}`, + `SUDO env DEBIAN_FRONTEND=noninteractive LC_ALL=C apt-get install -y --no-install-recommends --no-remove -o DPkg::Pre-Install-Pkgs::=/bin/bash /run/nemoclaw-apt-transaction.TEST/verify-plan -o DPkg::Tools::options::/bin/bash::Version=3 ${expectedTuple}`, ].sort(), ); expect(aptCommands.join("\n")).not.toContain(retainedSpec); @@ -216,7 +214,7 @@ installed_version() { if [[ "$1" == "libc6" ]]; then printf '2.39-0ubuntu8'; fi; package_is_exact() { return 0; } create_apt_transaction_guard() { APT_TRANSACTION_GUARD_DIR=/run/nemoclaw-apt-transaction.TEST - APT_TRANSACTION_HOOK="$APT_TRANSACTION_GUARD_DIR/verify-plan" + APT_TRANSACTION_HOOK="/bin/bash $APT_TRANSACTION_GUARD_DIR/verify-plan" } sudo() { printf 'SUDO %s\n' "$*" @@ -358,7 +356,7 @@ install_packages } }); - it("emits an executable root-hook payload bound to its target manifest", () => { + it("emits a noexec-safe root-hook command bound to its target manifest", () => { const { result, output } = runSourced( ` PACKAGE_TRANSACTION_SPECS=('${DOCKER_CE_SPEC}') @@ -378,12 +376,18 @@ sudo() { cat >"$HOME/generated-guard/\${2##*/}" ;; chmod) - command chmod "$2" "$HOME/generated-guard/\${3##*/}" + printf 'SUDO %s\n' "$*" + if [[ "$3" == /run/nemoclaw-apt-transaction.GENERATED ]]; then + command chmod "$2" "$HOME/generated-guard" + else + command chmod "$2" "$HOME/generated-guard/\${3##*/}" + fi ;; esac } create_apt_transaction_guard -"$HOME/generated-guard/verify-plan" <<<"$APT_PLAN" +/bin/bash "$HOME/generated-guard/verify-plan" <<<"$APT_PLAN" +printf 'APT_HOOK=%s\n' "$APT_TRANSACTION_HOOK" printf 'GENERATED_HOOK_ACCEPTED\n' `, { @@ -396,6 +400,11 @@ printf 'GENERATED_HOOK_ACCEPTED\n' expect(result.status, output).toBe(0); expect(output).toContain("GENERATED_HOOK_ACCEPTED"); + expect(output).toContain( + "APT_HOOK=/bin/bash /run/nemoclaw-apt-transaction.GENERATED/verify-plan", + ); + expect(output).toContain("SUDO chmod 0700 /run/nemoclaw-apt-transaction.GENERATED/verify-plan"); + expect(output).toContain("SUDO chmod 0600 /run/nemoclaw-apt-transaction.GENERATED/targets"); }); it("cleans the root-owned transaction guard when the caller exits", () => { @@ -404,7 +413,7 @@ sudo() { printf 'SUDO %s\n' "$*"; } setup_log() { :; } run_apply() { APT_TRANSACTION_GUARD_DIR=/run/nemoclaw-apt-transaction.EXITTEST - APT_TRANSACTION_HOOK="$APT_TRANSACTION_GUARD_DIR/verify-plan" + APT_TRANSACTION_HOOK="/bin/bash $APT_TRANSACTION_GUARD_DIR/verify-plan" } main --apply `); From 4ea0f4b59143000d69e6446d330f14d8c1981766 Mon Sep 17 00:00:00 2001 From: Aaron Erickson Date: Sat, 18 Jul 2026 23:40:03 -0700 Subject: [PATCH 2/2] test(installer): enforce package quiescence order Signed-off-by: Aaron Erickson --- test/install-station-package-transaction.test.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/install-station-package-transaction.test.ts b/test/install-station-package-transaction.test.ts index c435fd1b6e6..94786bf1e8d 100644 --- a/test/install-station-package-transaction.test.ts +++ b/test/install-station-package-transaction.test.ts @@ -89,7 +89,7 @@ apt-get() { done fi } -require_docker_restart_quiescence() { printf 'RECHECK_DOCKER_RESTART\n'; } +require_docker_restart_quiescence() { printf 'RECHECK_DOCKER_RESTART %s\n' "$1"; } package_state() { printf 'missing\n'; } package_is_exact() { return 0; } create_apt_transaction_guard() { @@ -130,7 +130,10 @@ cat "$HOME/apt-cache-calls" expect(output).toContain( "SUDO env DEBIAN_FRONTEND=noninteractive LC_ALL=C apt-get -s install --no-install-recommends --no-remove", ); - expect(output).toContain("RECHECK_DOCKER_RESTART"); + const quiescenceMarker = "RECHECK_DOCKER_RESTART Station prerequisite package installation"; + const installMarker = "SUDO env DEBIAN_FRONTEND=noninteractive LC_ALL=C apt-get install -y"; + expect(output).toContain(quiescenceMarker); + expect(output.indexOf(installMarker)).toBeGreaterThan(output.indexOf(quiescenceMarker)); expect(output).toContain("CLEANUP_GUARD"); expect(output).toContain("pinned_packages=installed"); });