gioser

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

TOML 1572Shell 203Rust 109Markdown 993728 Definitions

⎇ 7a0c1b7eae74e07b0b701ca8f674fc75884c6c3c scripts/product-boot-test.sh Shell · 80 lines · 4.7 KB History raw

takana etapa 5c: comentarios de scripts, MOTD, y un BUG que introdujo la etapa 4 476168bb0 · Sergio ·

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