Files
takana/scripts/hammer-install.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

103 lines
6.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# takana-install.sh — Etapa E2: instalador a disco. Vuelca el `product-rootfs` (lean: 4/4 + userland
# Rust + sshd) sobre un DISCO destino (block device real `/dev/sdX`, o un fichero pre-dimensionado para
# pruebas) con el mismo layout GPT + GRUB BIOS de la imagen E1, pero IN-PLACE sobre el target. Tras
# instalar, el disco arranca solo (SeaBIOS → GRUB → kernel → arje-zero PID1 → hammerd+getty+sshd).
#
# Es la contraparte "a disco real" de scripts/product-image.sh (que produce un fichero imagen portátil):
# la lógica de particionado/format/GRUB es la misma (delegada a install-image.sh); sólo cambia el target.
#
# Uso:
# sudo PRODUCT=<hash> AUTHKEYS=~/.ssh/id_ed25519.pub FORCE=1 ./scripts/hammer-install.sh /dev/sdX
# # prueba sin hardware (fichero pre-dimensionado, se valida el camino in-place + boot SSH):
# PRODUCT=<hash> TESTKEY=1 BOOT=1 ./scripts/hammer-install.sh work/target.img
#
# Variables:
# PRODUCT product-rootfs sellado (hash/prefijo; default: el más reciente del store)
# AUTHKEYS fichero authorized_keys a instalar para root (recomendado en instalación real)
# TESTKEY 1 ⇒ genera un par efímero y usa su pubkey como authorized_keys (para validar por SSH)
# FORCE 1 ⇒ requerido para escribir sobre un BLOCK DEVICE (seguridad anti-pisada)
# KERNEL bzImage a embeber (default store/*-linux/boot/bzImage)
# ROOT_SIZE/STORE_SIZE/STATE_SIZE MiB de cada partición (default 1024/512/512)
# BOOT 1 ⇒ tras instalar, arranca el target con QEMU (útil sólo para fichero/imagen) + handshake
# KVM/MEM/PORT/DEADLINE passthrough del arranque de prueba
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"; cd "$ROOT"
TARGET="${1:-}"
[ -n "$TARGET" ] || { echo "uso: $0 <device|imagen> (p.ej. /dev/sdX o work/target.img)"; exit 2; }
WORK="$ROOT/work/hammer-install"; RFS="$WORK/rootfs"
# --- resolver product-rootfs sellado ---
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; }
echo "==> product-rootfs: $PDIR"
echo "==> target: $TARGET"
# --- guardas de seguridad para un disco real ---
PREALLOC=0
if [ -b "$TARGET" ]; then
[ "${FORCE:-0}" = 1 ] || { echo "!! $TARGET es un BLOCK DEVICE — exijo FORCE=1 para escribirlo (borra datos)"; exit 1; }
if mount | grep -q "^$TARGET"; then echo "!! $TARGET (o una partición) está MONTADO — desmontá antes"; exit 1; fi
echo "==> escritura sobre block device REAL (FORCE=1)"
elif [ -e "$TARGET" ]; then
PREALLOC=1 # fichero existente ⇒ in-place (no truncar): exactamente el camino de un device
echo "==> target fichero pre-dimensionado ⇒ instalación in-place (PREALLOC)"
else
echo "==> target fichero nuevo ⇒ install-image lo crea (truncate)"
fi
# --- copia escribible del product-rootfs + provisión de authorized_keys ---
rm -rf "$WORK"; mkdir -p "$WORK"
cp -a "$PDIR"/. "$RFS"/; chmod -R u+w "$RFS"; rm -rf "$RFS/.hammer"
install -d -m 0700 "$RFS/root/.ssh"
if [ "${TESTKEY:-0}" = 1 ]; then
"$(ls store/*-openssh/usr/bin/ssh-keygen | head -1)" -t ed25519 -N '' -f "$WORK/clientkey" -q
cat "$WORK/clientkey.pub" > "$RFS/root/.ssh/authorized_keys"
echo "==> authorized_keys: llave de prueba efímera ($WORK/clientkey)"
elif [ -n "${AUTHKEYS:-}" ] && [ -f "$AUTHKEYS" ]; then
cat "$AUTHKEYS" > "$RFS/root/.ssh/authorized_keys"
echo "==> authorized_keys: $AUTHKEYS"
else
echo "==> (sin authorized_keys: nadie podrá entrar por SSH hasta provisionarlas; usá AUTHKEYS= o TESTKEY=1)"
fi
chmod 0600 "$RFS/root/.ssh/authorized_keys" 2>/dev/null || true
# --- delegar particionado/format/GRUB a install-image.sh, apuntando al target (IN-PLACE si aplica) ---
echo "==> instalando sobre $TARGET (GPT + ext4 + GRUB BIOS, in-place=$PREALLOC)"
ROOTFS="$RFS" IMG="$TARGET" PREALLOC="$PREALLOC" BOOT=0 \
ROOT_SIZE="${ROOT_SIZE:-1024}" STORE_SIZE="${STORE_SIZE:-512}" STATE_SIZE="${STATE_SIZE:-512}" \
sh ./scripts/install-image.sh
echo "==> instalado. El disco arranca solo (SeaBIOS → GRUB → arje-zero)."
[ "${BOOT:-0}" = 1 ] || { echo " (set BOOT=1 para arrancar el target y probar SSH)"; exit 0; }
[ "${TESTKEY:-0}" = 1 ] || { echo " BOOT=1 sin TESTKEY=1: no tengo llave para el handshake; omito."; exit 0; }
# --- arranque de prueba del target (sólo fichero/imagen) + handshake SSH ---
KVM="${KVM:-1}"; MEM="${MEM:-2048}"; PORT="${PORT:-2225}"; DEADLINE="${DEADLINE:-150}"
accel=(-cpu Broadwell); { [ "$KVM" = 1 ] && [ -w /dev/kvm ]; } && accel=(-enable-kvm -cpu host)
echo "==> AUTO-BOOT del target (sin -kernel) + hostfwd :$PORT->:22"
qemu-system-x86_64 -m "$MEM" -no-reboot -nographic "${accel[@]}" \
-drive file="$TARGET",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 desde el disco instalado (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 INSTALLED_DISK_SSH_OK uid=$(id -u); uname -sr; ls --version 2>&1|head -1; df -h /store /var/lib/hammer 2>/dev/null|tail -2' 2>/dev/null); then
echo "========= RESPUESTA DEL DISCO INSTALADO ========="; echo "$out"; echo "================================================="
echo "$out" | grep -q INSTALLED_DISK_SSH_OK && ok=1; break
fi
sleep 3
done
echo "---- consola (cola) ----"; tail -12 "$WORK/console.log" 2>/dev/null
[ "$ok" = 1 ] && { echo; echo "*** HAMMER INSTALL OK — disco instalado in-place arranca solo y sirve SSH ***"; exit 0; }
echo; echo "*** HAMMER INSTALL FALLÓ — ver $WORK/console.log ***"; exit 1