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 1471Shell 173Rust 105Markdown 943545 Definiciones

imagen↔repo: end-to-end — producto booteable con userland del repo firmado

scripts/product-image-from-repo.sh cierra el lazo Etapa F+G entero:
base product-rootfs (arje-zero PID1 + musl/busybox) → hidrata userland rico vía
`hammer install --require-signed` del repo firmado → imagen GRUB auto-booteable →
boot en QEMU + handshake SSH que CORRE los tools del repo.

VALIDADO e2e: booteó, arje-zero PID1, hammerd+netup+sshd, y por SSH corrieron
bat 0.26.1 / fd 10.4.2 / jq 1.8.1 / eza — userland farmeado, servido desde el
repo firmado, no del bootstrap hardcodeado. 240 bins en /usr/bin (base+repo).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

404bfc497099f86900b0c416682f05730a23ded2 · por sergio · (hace 3 meses) · padre d41f1705e · ver el árbol en este commit

Delta semántico

Ninguna definición cambió: el cambio es de texto, documentación o datos.

1 archivos · +65 −0

diff --git a/scripts/product-image-from-repo.sh b/scripts/product-image-from-repo.sh
new file mode 100755
index 00000000..3bd4e976
--- /dev/null
+++ b/scripts/product-image-from-repo.sh
@@ -0,0 +1,65 @@
+#!/usr/bin/env bash
+# product-image-from-repo.sh — CIERRE DEL LAZO Etapa F+G: arma una imagen de producto AUTO-BOOTEABLE
+# cuyo USERLAND CLI se hidrata desde el REPO FIRMADO (no del bootstrap hardcodeado). Pipeline:
+#   1. base = product-rootfs del store (init arje-zero + musl/busybox + servicios).
+#   2. hidrata el userland rico vía `hammer install --repo --prefix --require-signed` (product-userland-from-repo.sh).
+#   3. arma el disco GRUB-booteable (install-image.sh) y, con BOOT=1, lo arranca en QEMU + handshake SSH.
+#
+# Uso:   ./scripts/product-image-from-repo.sh                 # crea work/hammer-product-repo.img
+#        BOOT=1 ./scripts/product-image-from-repo.sh          # además auto-bootea + prueba SSH (los tools del repo)
+# Vars:  PRODUCT (hash base; def el más reciente del store)  PKGS (set de userland; def el de la script)
+#        KERNEL (def store/*-linux/boot/bzImage)  IMG  KVM(1)  MEM(2048)  PORT(2225)  DEADLINE(180)
+set -euo pipefail
+ROOT="$(cd "$(dirname "$0")/.." && pwd)"; cd "$ROOT"
+IMG="${IMG:-work/hammer-product-repo.img}"; KVM="${KVM:-1}"; MEM="${MEM:-2048}"; PORT="${PORT:-2225}"
+DEADLINE="${DEADLINE:-180}"; WORK="$ROOT/work/product-from-repo"; RFS="$WORK/rootfs"
+KERNEL="${KERNEL:-$(ls store/*-linux/boot/bzImage 2>/dev/null | head -1)}"
+
+# 1. base
+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 base (corré 'hammer bootstrap product')"; exit 1; }
+echo "==> base product-rootfs: $PDIR"
+rm -rf "$WORK"; mkdir -p "$WORK"
+cp -a "$PDIR" "$RFS"; chmod -R u+w "$RFS"; rm -rf "$RFS/.hammer"
+
+# 2. userland rico desde el repo firmado, hidratado SOBRE la base
+OVER="$RFS" scripts/product-userland-from-repo.sh
+echo "==> rootfs ensamblado: $(ls "$RFS"/usr/bin | wc -l) binarios en /usr/bin (base + repo)"
+
+# 3. admin key de prueba (lo único no horneado)
+KG=$(ls store/*-openssh/usr/bin/ssh-keygen | head -1)
+"$KG" -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"
+[ -d "$RFS/store" ] || mkdir -p "$RFS/store"   # install-image puebla la partición store desde acá
+
+# 4. disco GRUB-booteable (sin auto-boot acá; lo hacemos nosotros con red)
+echo "==> armando imagen GRUB-booteable"
+ROOTFS="$RFS" IMG="$IMG" KERNEL="$KERNEL" BOOT=0 ROOT_SIZE="${ROOT_SIZE:-1280}" STORE_SIZE="${STORE_SIZE:-256}" \
+  STATE_SIZE="${STATE_SIZE:-256}" sh ./scripts/install-image.sh
+echo "==> imagen: $IMG"
+[ "${BOOT:-0}" = 1 ] || { echo "(set BOOT=1 para auto-bootear + probar los tools del repo por SSH)"; exit 0; }
+
+# 5. auto-boot (GRUB del disco, sin -kernel) + red + handshake que CORRE los tools del repo
+accel=(-cpu Broadwell); { [ "$KVM" = 1 ] && [ -w /dev/kvm ]; } && accel=(-enable-kvm -cpu host)
+echo "==> AUTO-BOOT + hostfwd :$PORT->:22"
+qemu-system-x86_64 -m "$MEM" -no-reboot -nographic "${accel[@]}" \
+  -drive file="$IMG",format=raw,if=virtio \
+  -netdev "user,id=n0,hostfwd=tcp::$PORT-:22" -device e1000,netdev=n0 > "$WORK/console.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_REPO_OK; bat --version 2>/dev/null | head -1; fd --version 2>/dev/null; jq --version 2>/dev/null; eza --version 2>/dev/null | head -1' 2>/dev/null); then
+    echo "===== TOOLS DEL REPO CORRIENDO EN EL PRODUCTO ====="; echo "$out"; echo "==================================================="
+    echo "$out" | grep -q PRODUCT_REPO_OK && ok=1; break
+  fi
+  sleep 3
+done
+tail -12 "$WORK/console.log" 2>/dev/null
+[ "$ok" = 1 ] && { echo; echo "*** LAZO CERRADO — producto auto-booteable corre userland del REPO FIRMADO ***"; exit 0; }
+echo; echo "*** boot/SSH falló — ver $WORK/console.log ***"; exit 1