Files
takana/scripts/product-boot-test.sh
T
Sergio 476168bb07 takana etapa 5c: comentarios de scripts, MOTD, y un BUG que introdujo la etapa 4
250 líneas de comentario en 151 scripts. Control verificado: el diff no toca
NI UNA línea que no empiece por #, y la sintaxis de los 151 pasa.

El barrido saltea heredocs y cadenas triples, y el guardián DISPARÓ 3 veces:
las tres eran el MOTD que el script escribe DENTRO de la imagen construida —
texto del producto, no comentario del script. Se cambiaron aparte y a
propósito, que es rebranding, no limpieza.

Y el hallazgo caro:  casaba contra ,
que es el TARGET de tracing — o sea el module_path!, o sea el nombre del crate.
La etapa 4 lo movió a  y el script quedó casando NADA. No fallaba:
imprimía cero atribuciones, indistinguible de un log sin problemas. Comprobado
con el binario (RUST_LOG=info sobre zlib), no deducido. Ahora acepta las dos, y
tiene que seguir aceptándolas porque los logs viejos en disco dicen la vieja.

Además 14 rutas de módulo  en docs, que el barrido anterior no tocó
porque  no es frontera de palabra.
2026-09-09 19:28:48 +00:00

81 lines
4.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# product-boot-test.sh — valida que el `product-rootfs` ENSAMBLADO POR LA RUTA REAL
# (`takana bootstrap product`) bootea en QEMU y sirve SSH. A diferencia de ssh-e2e-test.sh (spike
# que arma un rootfs sucio a mano), acá NO se ensambla nada: se toma el artefacto sellado tal cual
# (seed de producto, passwd, sshd_config, /var/empty, sshd como card — todo ya inyectado por la capa
# de servicios) y sólo se provisiona una authorized_keys de prueba (lo que en deploy haría el admin).
#
# Prueba el axioma de la consolidación: el mismo árbol que produce el pipeline arranca el daemon SSH
# bajo arje sin tocar el núcleo verificado.
#
# Uso: PRODUCT=<hash-o-prefijo> ./scripts/product-boot-test.sh
# (PRODUCT = el que imprimió `takana bootstrap product`; default: el más reciente del store)
# Vars: KERNEL MEM (def 2048) KVM (def 1) PORT (def 2223) DEADLINE (def 150)
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"; cd "$ROOT"
KERNEL="${KERNEL:-$(ls store/*-linux/boot/bzImage 2>/dev/null | head -1)}"
MEM="${MEM:-2048}"; KVM="${KVM:-1}"; PORT="${PORT:-2223}"; DEADLINE="${DEADLINE:-150}"
WORK="$ROOT/work/product-boot"; RFS="$WORK/rootfs"; LOG="$WORK/console.log"
# localizar el product-rootfs sellado (por prefijo, o el más reciente)
if [ -n "${PRODUCT:-}" ]; then
PDIR=$(ls -d store/"${PRODUCT#b3:}"*-product-rootfs 2>/dev/null | head -1)
else
PDIR=$(ls -dt store/*-product-rootfs 2>/dev/null | head -1)
fi
[ -n "$PDIR" ] && [ -d "$PDIR" ] || { echo "no encuentro product-rootfs (corré 'hammer bootstrap product')"; exit 1; }
[ -n "$KERNEL" ] && [ -e "$KERNEL" ] || { echo "no encuentro kernel"; exit 1; }
echo "==> product-rootfs: $PDIR"
echo "==> kernel: $KERNEL"
# copia escribible del artefacto sellado (read-only); NO modificamos el store
rm -rf "$WORK"; mkdir -p "$WORK"
cp -a "$PDIR"/. "$RFS"/
chmod -R u+w "$RFS"
rm -rf "$RFS/.hammer"
# provisión de admin: una authorized_keys de prueba (única cosa que el producto NO trae horneada)
"$(ls store/*-openssh/usr/bin/ssh-keygen | head -1)" -t ed25519 -N '' -f "$WORK/clientkey" -q
install -d -m 0700 "$RFS/root/.ssh"
cat "$WORK/clientkey.pub" > "$RFS/root/.ssh/authorized_keys"
chmod 0600 "$RFS/root/.ssh/authorized_keys"
# sanity: el árbol de producto trae lo que esperamos (sin ensamblarlo acá)
echo "==> chequeo de contenido del artefacto:"
for f in usr/sbin/sshd usr/bin/netup usr/bin/coreutils usr/bin/find usr/bin/rg etc/ssh/sshd_config etc/passwd ente/seed.card.json; do
[ -e "$RFS/$f" ] && echo " ok $f" || { echo " FALTA $f"; exit 1; }
done
grep -q '"label": "sshd"' "$RFS/ente/seed.card.json" && echo " ok card sshd en la seed" || { echo " FALTA card sshd"; exit 1; }
# adelgazar busybox: /usr/bin/ls debe apuntar a coreutils (Rust), no a busybox
lstgt=$(readlink "$RFS/usr/bin/ls" 2>/dev/null || true)
[ "$lstgt" = coreutils ] && echo " ok /usr/bin/ls → coreutils (ensombrece busybox)" || echo " !! /usr/bin/ls → ${lstgt:-?}"
# empaquetar (root-owned) y bootear
( cd "$RFS" && find . -print0 | cpio --null -o -H newc -R 0:0 2>/dev/null | gzip -1 ) > "$WORK/initramfs.cpio.gz"
accel=(-cpu Broadwell); { [ "$KVM" = 1 ] && [ -w /dev/kvm ]; } && accel=(-enable-kvm -cpu host)
echo "==> boot QEMU (mem ${MEM}), hostfwd :$PORT->:22"
qemu-system-x86_64 -m "$MEM" -no-reboot -nographic "${accel[@]}" \
-kernel "$KERNEL" -initrd "$WORK/initramfs.cpio.gz" -append "console=ttyS0 rdinit=/sbin/init" \
-netdev "user,id=n0,hostfwd=tcp::$PORT-:22" -device e1000,netdev=n0 > "$LOG" 2>&1 &
QPID=$!; trap 'kill $QPID 2>/dev/null || true' EXIT
SSHOPTS=(-p "$PORT" -i "$WORK/clientkey" -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
-o GlobalKnownHostsFile=/dev/null -o PasswordAuthentication=no -o ConnectTimeout=4 -o LogLevel=ERROR)
echo "==> esperando handshake (deadline ${DEADLINE}s)…"
start=$(date +%s); ok=0
while [ $(( $(date +%s) - start )) -lt "$DEADLINE" ]; do
kill -0 $QPID 2>/dev/null || { echo "!! QEMU murió"; break; }
if out=$(ssh "${SSHOPTS[@]}" root@localhost \
'echo PRODUCT_SSH_OK uid=$(id -u); uname -sr;
printf "ls: "; command -v ls; ls --version 2>&1 | head -1;
printf "find: "; find --version 2>&1 | head -1;
printf "rg: "; rg --version 2>&1 | head -1' 2>/dev/null); then
echo "============== RESPUESTA DEL GUEST =============="; echo "$out"; echo "================================================"
echo "$out" | grep -q PRODUCT_SSH_OK && ok=1; break
fi
sleep 3
done
echo "---- consola (cola) ----"; tail -18 "$LOG" 2>/dev/null
[ "$ok" = 1 ] && { echo; echo "*** PRODUCT SSH OK — el product-rootfs de la ruta real bootea y sirve SSH ***"; exit 0; }
echo; echo "*** PRODUCT SSH FALLÓ — ver $LOG ***"; exit 1