renombre: los instaladores pasan a takana-* — y el peligro no era el fichero, era el PROTOCOLO
ADR 0016 los listaba entre los CONGELADOS; el usuario pidió descongelarlos al abrir el SDD 28. La
enmienda queda escrita en el propio ADR, que si no la etiqueta deja de describir el hecho.
`hammer-install.sh` → `takana-install.sh`, `hammer-live-install.sh` → `takana-live-install.sh`,
`hammer-banner.txt` → `takana-banner.txt`, `BRIEFING-hammer.md` → `BRIEFING-takana.md`.
**Lo que hacía caro esto no es el nombre del fichero.** El instalador se inyecta en el ISO como
`/usr/bin/hammer-install` y su éxito se detecta con un `grep` de `HAMMER-INSTALL-OK` desde TRES
scripts de prueba. Renombrar un solo lado los deja casando NADA — sin fallar —, que es literalmente
el modo en que `atribuir-fallos.py` quedó mudo cuando el renombre movió el target de `tracing`.
Se renombraron las dos puntas en el mismo commit (`/usr/bin/takana-install`,
`TAKANA-INSTALL-OK/FAIL`, `TAKANA_INSTALL_*`, `work/takana-install.img`, `/run/takana-install`),
se comprobó por `grep` que no quede ningún token viejo fuera del ADR, y —lo que decide— se CORRIÓ
`install-tui-test.sh`: 4/4 casos verdes.
Las tres `TAKANA_INSTALL_*` caen al nombre viejo (`${TAKANA_INSTALL_X:-${HAMMER_INSTALL_X:-}}`):
el llamador puede ser un ISO anterior al renombre. Misma convención que `TAKANA_ROOT_PW` unas
líneas más arriba en ese mismo script.
NO se tocó `/usr/sbin/hammer-recover` ni su hook de arranque —renombrarlo rompe máquinas YA
INSTALADAS, no el repo—: sobrevive intacto dentro del script renombrado, verificado por conteo
antes y después (8 ocurrencias). Tampoco `hammerd`, `hammer-edit` (su `name` está en la ruta del
store), `/var/lib/hammer`, `HAMMER_LIVE` ni los siete literales de hash.
De paso: `scripts/.hammer-banner.txt.kate-swp` era un swap de editor commiteado por error. Fuera.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RomoxEGZUhaT4pob1QSX5x
This commit is contained in:
@@ -8,7 +8,7 @@ repository.workspace = true
|
||||
description = "Mini-binario de auto-recuperación de upgrades al arranque (E4 #4b): el /sbin/init lo corre para completar/deshacer un apply interrumpido antes de incarnar."
|
||||
|
||||
# El PAQUETE se renombra, el BINARIO no: `/usr/sbin/hammer-recover` está copiado en
|
||||
# sistemas ya instalados y `hammer-live-install.sh` hornea un hook de arranque que lo
|
||||
# sistemas ya instalados y `takana-live-install.sh` hornea un hook de arranque que lo
|
||||
# invoca por ese nombre. Renombrar el binario rompe máquinas instaladas. Etapa 6.
|
||||
[[bin]]
|
||||
name = "hammer-recover"
|
||||
|
||||
@@ -96,7 +96,7 @@ kernel en `/boot`, los módulos GRUB en `/boot/grub/i386-pc` y los pasos `grub-m
|
||||
generaciones es **in-place** (el FHS es la generación viva), así que NO hay menú de generaciones tipo
|
||||
NixOS que ofrecer en GRUB; lo que encaja es **auto-sanar** un upgrade interrumpido al boot. El producto
|
||||
no lleva el CLI `takana` completo ⇒ `hammer-recover` es lo único que el sistema instalado necesita: el
|
||||
wrapper `/sbin/init` (de `hammer-live-install.sh`) lo corre **tras montar `/store` y `/var/lib/hammer`**
|
||||
wrapper `/sbin/init` (de `takana-live-install.sh`) lo corre **tras montar `/store` y `/var/lib/hammer`**
|
||||
y **antes** de incarnar arje-zero. Sin `pending.json` es no-op; con uno, **completa** (roll-forward) o,
|
||||
si no puede, **deshace** (roll-back) ⇒ el FHS siempre arranca consistente. Nunca aborta el boot. El
|
||||
instalador lo bundlea desde el payload a `/usr/sbin/hammer-recover`. Validado in-VM
|
||||
@@ -133,8 +133,8 @@ kernel en `/boot`, los módulos GRUB en `/boot/grub/i386-pc` y los pasos `grub-m
|
||||
LINUX_EFI_INITRD_MEDIA_GUID" → arje-zero → sshd) y por BIOS (SeaBIOS, El Torito). **Refinamiento #3
|
||||
CERRADO.** (Falta como pulido: rama EFI del INSTALADOR a disco — GPT+ESP en `takana-install`, hoy el
|
||||
instalado es MBR-BIOS.)
|
||||
- **Instalar DESDE el live ✅** (`scripts/iso-image.sh INSTALLER=1` + `scripts/hammer-live-install.sh`
|
||||
→ `/usr/bin/hammer-install` + `scripts/iso-install-test.sh`). Cierra el lazo **ISO live → disco
|
||||
- **Instalar DESDE el live ✅** (`scripts/iso-image.sh INSTALLER=1` + `scripts/takana-live-install.sh`
|
||||
→ `/usr/bin/takana-install` + `scripts/iso-install-test.sh`). Cierra el lazo **ISO live → disco
|
||||
instalado → bootea solo**. El ISO instalador bundlea un *payload de disco* en el initramfs bajo
|
||||
`/usr/lib/hammer/install/` (kernel + GRUB `boot.img`/`core.img` MBR-prefix `(hd0,msdos1)/boot/grub`
|
||||
+ módulos, armado en build-time con `grub-mkimage`). `takana-install <dev>` corre **dentro del live
|
||||
@@ -150,5 +150,5 @@ kernel en `/boot`, los módulos GRUB en `/boot/grub/i386-pc` y los pasos `grub-m
|
||||
binario del caso GPT de E1. (c) copiar el top-level de `/` ENUMERÁNDOLO (no una lista fija) o se
|
||||
escapa `/ente/seed.card.json` ⇒ arje-zero aborta "seed.card no encontrada". `AUTO_INSTALL=<dev>`
|
||||
hace el `/init` desatendido (install + poweroff) = instalación unattended + scaffolding del test.
|
||||
Validado E2E in-VM: boot ISO+disco en blanco → HAMMER-INSTALL-OK → boot del disco solo → GRUB→kernel
|
||||
Validado E2E in-VM: boot ISO+disco en blanco → TAKANA-INSTALL-OK → boot del disco solo → GRUB→kernel
|
||||
→arje-zero→sshd, /store y /var/lib/hammer montadas. **Refinamiento #1 CERRADO.**
|
||||
|
||||
@@ -196,7 +196,7 @@ BUILD (sandbox, N en paralelo, cero locks)
|
||||
(overlay-src de deps: el mecanismo reutilizado; tabla de fases a corregir en F1) · SDD 16 (patrón
|
||||
"inerte sin flag"; canario D9 → IF-2) · CLAUDE.md regla 3 (marker contra vacíos) · CLAUDE.md
|
||||
regla 1 (retiro del flock en R11) · `build-farm.sh` Fase 1b (carrera B; se borra en F3) ·
|
||||
`docs/BRIEFING-hammer.md` §14.4 (los modos de fallo estructurales que R3 e IF-6 citan).*
|
||||
`docs/BRIEFING-takana.md` §14.4 (los modos de fallo estructurales que R3 e IF-6 citan).*
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ muerto antes del takeover).
|
||||
- **host-side** `scripts/install-image-efi.sh` — GPT+ESP+root/store/state, ESP con mtools de takana,
|
||||
ext4 con `mke2fs -d` bajo `unshare -r`; **validado VERDE en OVMF** (`scripts/efi-disk-boot-test.sh`:
|
||||
firmware → BOOTX64.EFI → pivote → arje-zero PID1).
|
||||
- **live-side** `scripts/hammer-live-install.sh` rama EFI — detecta `/sys/firmware/efi` y hace
|
||||
- **live-side** `scripts/takana-live-install.sh` rama EFI — detecta `/sys/firmware/efi` y hace
|
||||
**MBR con ESP tipo 0xEF** (UEFI arranca una ESP MBR igual que GPT ⇒ alcanza busybox
|
||||
fdisk/mkfs.vfat/mount, sin GPT-tool ni mtools en el live). El kernel EFI-stub viaja en el payload
|
||||
(`iso-image.sh INSTALLER=1` bundlea `bzImage-efi`). **Validación 2-stage VERDE en OVMF**
|
||||
|
||||
@@ -223,9 +223,32 @@ simplemente deja de cosechar. El directorio es lo **último** que se toca, y con
|
||||
reescribir historia es peor que un mensaje incompleto. El detalle vive acá.)*
|
||||
|
||||
**Congelados y verificados con controles:** `/opt/hammer`, `/var/lib/hammer`, `/usr/bin/hammer`,
|
||||
`/mnt/vvv/hammer`, la URL de gitea, `hammer-farm.service`, `hammer-live-install.sh`,
|
||||
`BRIEFING-hammer.md`, `hammerd`, `hammer-recover`, `HAMMER_LIVE`, `.hammer-zig-cc`,
|
||||
`/mnt/vvv/hammer`, la URL de gitea, `hammer-farm.service`, ~~`hammer-live-install.sh`~~,
|
||||
~~`BRIEFING-hammer.md`~~, `hammerd`, `hammer-recover`, `HAMMER_LIVE`, `.hammer-zig-cc`,
|
||||
`.hammer-cargo-vendor` y dos identificadores más que aparecieron al barrer:
|
||||
|
||||
> **ENMIENDA 2026-09-09 — dos de esos congelados se descongelaron por decisión del usuario**
|
||||
> («renombrá todos los `hammer` que vayas encontrando, como ese `hammer-install`»), al abrir el
|
||||
> frente del [SDD 28](../28-servidor-de-produccion.md). Renombrados:
|
||||
> `hammer-install.sh` → `takana-install.sh`, `hammer-live-install.sh` → `takana-live-install.sh`,
|
||||
> `hammer-banner.txt` → `takana-banner.txt`, `BRIEFING-hammer.md` → `BRIEFING-takana.md`.
|
||||
>
|
||||
> **Lo que hacía peligroso este renombre no era el fichero: era el PROTOCOLO.** El instalador se
|
||||
> inyecta en el ISO como `/usr/bin/hammer-install` y su éxito se detecta con un `grep` de
|
||||
> `HAMMER-INSTALL-OK` desde **tres** scripts de prueba (`iso-install-test.sh`,
|
||||
> `efi-install-test.sh`, `install-tui-test.sh`). Renombrar un solo lado deja los tests casando
|
||||
> **nada** — sin fallar, exactamente el modo en que `atribuir-fallos.py` quedó mudo al renombrar
|
||||
> el target de `tracing`. Se renombraron **las dos puntas** en el mismo commit
|
||||
> (`/usr/bin/takana-install`, `TAKANA-INSTALL-OK/FAIL`, `TAKANA_INSTALL_*`), se comprobó por
|
||||
> `grep` que no quedara ningún token viejo, y se **corrió** `install-tui-test.sh`: 4/4 verdes.
|
||||
>
|
||||
> **Lo que NO se tocó, y sigue congelado por la misma razón de antes**: el binario
|
||||
> `/usr/sbin/hammer-recover` y su hook de arranque (renombrarlo rompe **máquinas ya instaladas**,
|
||||
> no el repo) — sobrevive intacto dentro del script renombrado, verificado por conteo antes y
|
||||
> después. Tampoco `hammerd`, `hammer-edit`, `/var/lib/hammer`, `HAMMER_LIVE` ni los siete
|
||||
> literales de hash. Y las tres variables `TAKANA_INSTALL_*` **caen al nombre viejo**
|
||||
> (`${TAKANA_INSTALL_X:-${HAMMER_INSTALL_X:-}}`), porque el llamador puede ser un ISO anterior al
|
||||
> renombre — la misma convención que `TAKANA_ROOT_PW` unas líneas más arriba en ese script.
|
||||
- `hammer-build-state/1` — el `schema` del estado generado. Nadie lo valida, pero el valor de un
|
||||
identificador de esquema **es** ser estable; renombrarlo no gana nada.
|
||||
- `hammer-edit` — es una **receta con artefacto sellado**: su `name` está en la ruta del store
|
||||
|
||||
Binary file not shown.
@@ -47,13 +47,13 @@ timeout "$INSTALL_DEADLINE" qemu-system-x86_64 -m "$MEM" -no-reboot -nographic "
|
||||
-drive if=pflash,unit=0,format=raw,readonly=on,file="$OVMF_CODE" \
|
||||
-drive if=pflash,unit=1,format=raw,file="$WORK/vars-install.fd" \
|
||||
-drive file="$TGT",format=raw,if=virtio -cdrom "$ISO" -boot d > "$ILOG" 2>&1 || true
|
||||
if ! grep -aq "HAMMER-INSTALL-OK" "$ILOG"; then
|
||||
if ! grep -aq "TAKANA-INSTALL-OK" "$ILOG"; then
|
||||
echo "✗ la instalación EFI NO terminó OK — ver $ILOG" >&2
|
||||
sed 's/\x1b\[[0-9;]*[a-zA-Z]//g; s/\r//g' "$ILOG" | grep -iE "HAMMER-INSTALL-FAIL|hammer-install|no apareció|UEFI|EFI-stub soberano|error" | head; exit 1
|
||||
sed 's/\x1b\[[0-9;]*[a-zA-Z]//g; s/\r//g' "$ILOG" | grep -iE "TAKANA-INSTALL-FAIL|takana-install|no apareció|UEFI|EFI-stub soberano|error" | head; exit 1
|
||||
fi
|
||||
echo " ✓ HAMMER-INSTALL-OK (rama EFI corrió en el live UEFI)"
|
||||
echo " ✓ TAKANA-INSTALL-OK (rama EFI corrió en el live UEFI)"
|
||||
# Confirmar que fue la rama EFI (no la BIOS)
|
||||
sed 's/\x1b\[[0-9;]*[a-zA-Z]//g; s/\r//g' "$ILOG" | grep -aqiE 'hammer-install \(UEFI\)|EFI-stub soberano' \
|
||||
sed 's/\x1b\[[0-9;]*[a-zA-Z]//g; s/\r//g' "$ILOG" | grep -aqiE 'takana-install \(UEFI\)|EFI-stub soberano' \
|
||||
&& echo " ✓ tomó la rama EFI (MBR+ESP-0xEF)" || echo " ! no vi el marcador de rama EFI (¿fue por BIOS?)" >&2
|
||||
|
||||
echo "==> (3) boot del DISCO instalado EN OVMF (sin ISO, sin -kernel) — deadline ${BOOT_DEADLINE}s"
|
||||
@@ -77,7 +77,7 @@ reject 'HAMMER-EFI-FALLO|Kernel panic' "sin fallo de pivot
|
||||
|
||||
echo
|
||||
if [ "$fail" = 0 ]; then
|
||||
echo "✓✓ EFI-INSTALL VERDE: ISO live UEFI → hammer-install rama EFI → disco EFI-stub SOBERANO bootea solo en OVMF"
|
||||
echo "✓✓ EFI-INSTALL VERDE: ISO live UEFI → takana-install rama EFI → disco EFI-stub SOBERANO bootea solo en OVMF"
|
||||
else
|
||||
echo "✗ efi-install-test FALLÓ — logs: $ILOG · $BLOG" >&2; exit 1
|
||||
fi
|
||||
|
||||
@@ -15,18 +15,18 @@
|
||||
# de GRUB + el kernel van en /boot de la root, que mke2fs -d puebla desde un directorio.
|
||||
#
|
||||
# Uso:
|
||||
# ./scripts/install-image.sh # crea work/hammer-install.img
|
||||
# ./scripts/install-image.sh # crea work/takana-install.img
|
||||
# BOOT=1 KVM=1 ./scripts/install-image.sh # además lo arranca (auto-boot, sin -kernel)
|
||||
#
|
||||
# Target IN-PLACE (Etapa E2): si IMG es un block device (o PREALLOC=1 sobre un fichero pre-dimensionado),
|
||||
# se instala EN SITIO — no se trunca ni se borra el nodo, sólo se valida capacidad. Esa es la base de
|
||||
# `takana install /dev/sdX` (ver scripts/hammer-install.sh): misma lógica, apuntando a un disco real.
|
||||
# `takana install /dev/sdX` (ver scripts/takana-install.sh): misma lógica, apuntando a un disco real.
|
||||
#
|
||||
# Variables:
|
||||
# ROOTFS dir rootfs a empaquetar (default work/builder-rootfs)
|
||||
# PREALLOC 1 ⇒ trata IMG como target pre-dimensionado in-place (no trunca; prueba el camino device)
|
||||
# KERNEL bzImage a embeber en /boot (default el del store: store/*-linux/boot/bzImage)
|
||||
# IMG imagen de salida (default work/hammer-install.img)
|
||||
# IMG imagen de salida (default work/takana-install.img)
|
||||
# ROOT_SIZE MiB de / (default 4096)
|
||||
# STORE_SIZE MiB de /store (default 2048)
|
||||
# STATE_SIZE MiB de /var/lib/hammer (default 2048)
|
||||
@@ -38,7 +38,7 @@ ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
cd "$ROOT"
|
||||
|
||||
ROOTFS="${ROOTFS:-work/builder-rootfs}"
|
||||
IMG="${IMG:-work/hammer-install.img}"
|
||||
IMG="${IMG:-work/takana-install.img}"
|
||||
ROOT_SIZE="${ROOT_SIZE:-4096}"
|
||||
STORE_SIZE="${STORE_SIZE:-2048}"
|
||||
STATE_SIZE="${STATE_SIZE:-2048}"
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
# install-tui-test.sh — valida la capa NUEVA del instalador interactivo (hammer-live-install.sh) SIN
|
||||
# tocar disco: usa el gancho HAMMER_INSTALL_DRYRUN=1, un /sys/block falso y un rootfs de scratch.
|
||||
# install-tui-test.sh — valida la capa NUEVA del instalador interactivo (takana-live-install.sh) SIN
|
||||
# tocar disco: usa el gancho TAKANA_INSTALL_DRYRUN=1, un /sys/block falso y un rootfs de scratch.
|
||||
# Ejercita (1) el modo interactivo (detección de discos + prompts + confirmación fuerte) y (2) el modo
|
||||
# desatendido por env; en ambos verifica que apply_post_install_config escribe hostname/hosts/shadow/
|
||||
# authorized_keys/localtime/install.conf correctamente. Las ramas EFI/BIOS reales (particionado) las
|
||||
# cubre iso-install-test.sh / efi-install-test.sh en QEMU; acá validamos la lógica de UI + config.
|
||||
set -euo pipefail
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"; cd "$ROOT"
|
||||
INST="$ROOT/scripts/hammer-live-install.sh"
|
||||
INST="$ROOT/scripts/takana-live-install.sh"
|
||||
W="$(mktemp -d)"; trap 'rm -rf "$W"' EXIT
|
||||
fail() { echo "✗ FALLO: $*" >&2; exit 1; }
|
||||
|
||||
@@ -34,7 +34,7 @@ echo "== test 1: modo INTERACTIVO (TUI dry-run) =="
|
||||
# zona America/La_Paz · teclado (default us) · confirmación "/dev/vdb"
|
||||
OUT1="$W/out1.txt"
|
||||
BB=/nonexistent SYS_BLOCK="$SB" MOUNTS="$MOUNTS" ZONEINFO="$ZI" \
|
||||
HAMMER_INSTALL_INTERACTIVE=1 HAMMER_INSTALL_DRYRUN=1 HAMMER_INSTALL_TESTROOT="$R1" \
|
||||
TAKANA_INSTALL_INTERACTIVE=1 TAKANA_INSTALL_DRYRUN=1 TAKANA_INSTALL_TESTROOT="$R1" \
|
||||
sh "$INST" >"$OUT1" 2>&1 <<'ANSWERS' || { cat "$OUT1"; fail "el instalador salió con error"; }
|
||||
2
|
||||
2048
|
||||
@@ -65,7 +65,7 @@ echo " ✓ interactivo: disco elegido + confirmado, config escrita (hostname/ho
|
||||
echo "== test 2: confirmación ERRÓNEA cancela sin tocar nada =="
|
||||
OUT2="$W/out2.txt"
|
||||
if BB=/nonexistent SYS_BLOCK="$SB" MOUNTS="$MOUNTS" ZONEINFO="$ZI" \
|
||||
HAMMER_INSTALL_INTERACTIVE=1 HAMMER_INSTALL_DRYRUN=1 HAMMER_INSTALL_TESTROOT="$W/root-none" \
|
||||
TAKANA_INSTALL_INTERACTIVE=1 TAKANA_INSTALL_DRYRUN=1 TAKANA_INSTALL_TESTROOT="$W/root-none" \
|
||||
sh "$INST" >"$OUT2" 2>&1 <<'ANSWERS'
|
||||
2
|
||||
2048
|
||||
@@ -84,7 +84,7 @@ echo "== test 3: modo DESATENDIDO por env (device + HAMMER_ROOT_HASH) =="
|
||||
R3="$W/root3"; mkdir -p "$R3/etc"
|
||||
printf 'root:!:19000:0:99999:7:::\n' > "$R3/etc/shadow"
|
||||
OUT3="$W/out3.txt"
|
||||
BB=/nonexistent HAMMER_INSTALL_DRYRUN=1 HAMMER_INSTALL_TESTROOT="$R3" \
|
||||
BB=/nonexistent TAKANA_INSTALL_DRYRUN=1 TAKANA_INSTALL_TESTROOT="$R3" \
|
||||
HAMMER_HOSTNAME=srv01 HAMMER_ROOT_HASH='$6$salt$deadbeefHASH' HAMMER_TZ=UTC HAMMER_KEYMAP=es \
|
||||
sh "$INST" /dev/vdb 3000 700 >"$OUT3" 2>&1 || { cat "$OUT3"; fail "desatendido salió con error"; }
|
||||
grep -q 'DEV=/dev/vdb ROOT_MB=3000 STORE_MB=700' "$OUT3" || { cat "$OUT3"; fail "no respetó device/tamaños posicionales"; }
|
||||
|
||||
@@ -74,15 +74,15 @@ cp -al "$ROOTFS" "$RFS/root"
|
||||
echo 'echo "HAMMER-ISO-LIVE-OK: medio live arrancado desde El Torito"'
|
||||
if [ -n "${AUTO_INSTALL:-}" ]; then
|
||||
echo "echo 'HAMMER-AUTO-INSTALL: instalando a ${AUTO_INSTALL}'"
|
||||
echo "if /usr/bin/hammer-install '${AUTO_INSTALL}'; then echo 'HAMMER-INSTALL-OK'; else echo 'HAMMER-INSTALL-FAIL'; fi"
|
||||
echo "if /usr/bin/takana-install '${AUTO_INSTALL}'; then echo 'TAKANA-INSTALL-OK'; else echo 'TAKANA-INSTALL-FAIL'; fi"
|
||||
echo '/bin/busybox sync'
|
||||
echo '/bin/busybox poweroff -f'
|
||||
elif [ "${INSTALLER:-0}" = 1 ] && [ "${INSTALLER_INTERACTIVE:-1}" = 1 ]; then
|
||||
# ISO instalador SIN AUTO_INSTALL ⇒ recibir al usuario con la TUI del instalador en la consola.
|
||||
# Tras instalar (o cancelar) ofrece reiniciar o caer al live. HAMMER_INSTALL_INTERACTIVE fuerza el
|
||||
# Tras instalar (o cancelar) ofrece reiniciar o caer al live. TAKANA_INSTALL_INTERACTIVE fuerza el
|
||||
# modo aunque /dev/console no pase el test -t (a esta altura stdin puede no ser un tty).
|
||||
echo '[ -e /dev/console ] && exec 0</dev/console 1>/dev/console 2>/dev/console'
|
||||
echo 'HAMMER_INSTALL_INTERACTIVE=1 /usr/bin/hammer-install || true'
|
||||
echo 'TAKANA_INSTALL_INTERACTIVE=1 /usr/bin/takana-install || true'
|
||||
echo 'echo; echo "Instalación finalizada. [r] reiniciar · [Enter] shell en vivo"'
|
||||
echo 'read -r _a || _a=""'
|
||||
echo 'case "$_a" in r|R) /bin/busybox reboot -f ;; *) exec /sbin/init ;; esac'
|
||||
@@ -94,10 +94,10 @@ chmod +x "$RFS/root/init"
|
||||
|
||||
# --- INSTALLER=1: payload de instalación a disco DESDE el live (refinamiento #1) ---
|
||||
# Bundle kernel + GRUB (boot.img + core.img MBR-prefix + módulos) bajo /usr/lib/hammer/install/ y el
|
||||
# instalador en /usr/bin/hammer-install. El core.img se arma acá (build-time, el host tiene
|
||||
# instalador en /usr/bin/takana-install. El core.img se arma acá (build-time, el host tiene
|
||||
# grub-mkimage); el live NO lo necesita — sólo dd's. core prefix (hd0,msdos1)/boot/grub para boot MBR.
|
||||
if [ "${INSTALLER:-0}" = 1 ]; then
|
||||
echo "==> INSTALLER=1: bundling payload de instalación a disco (kernel + GRUB MBR + hammer-install)"
|
||||
echo "==> INSTALLER=1: bundling payload de instalación a disco (kernel + GRUB MBR + takana-install)"
|
||||
IPL="$RFS/root/usr/lib/hammer/install"
|
||||
mkdir -p "$IPL/grub/i386-pc" "$IPL/kernel"
|
||||
cp "$KERNEL" "$IPL/kernel/bzImage"; chmod 0644 "$IPL/kernel/bzImage"
|
||||
@@ -116,7 +116,7 @@ if [ "${INSTALLER:-0}" = 1 ]; then
|
||||
# core.img para disco MBR: prefix a la 1ª partición msdos, módulos de disco (biosdisk/part_msdos/ext2).
|
||||
grub-mkimage -O i386-pc -p '(hd0,msdos1)/boot/grub' -o "$IPL/grub/core.img" \
|
||||
biosdisk part_msdos ext2 normal configfile linux echo ls boot search
|
||||
install -m 0755 "$ROOT/scripts/hammer-live-install.sh" "$RFS/root/usr/bin/hammer-install"
|
||||
install -m 0755 "$ROOT/scripts/takana-live-install.sh" "$RFS/root/usr/bin/takana-install"
|
||||
# hammer-recover (static musl): auto-sana un upgrade interrumpido al arranque del sistema instalado.
|
||||
RECOVER_BIN="$ROOT/target/x86_64-unknown-linux-musl/release/hammer-recover"
|
||||
if [ ! -x "$RECOVER_BIN" ]; then
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# iso-install-test.sh — valida el lazo COMPLETO de instalación desde el medio live (refinamiento #1):
|
||||
# (1) arma un ISO instalador (iso-image.sh INSTALLER=1 AUTO_INSTALL=/dev/vda) con el payload de disco
|
||||
# (kernel + GRUB MBR + /usr/bin/hammer-install) bundleado;
|
||||
# (kernel + GRUB MBR + /usr/bin/takana-install) bundleado;
|
||||
# (2) lo bootea con un disco EN BLANCO ⇒ el /init desatendido corre takana-install y apaga;
|
||||
# (3) bootea ESE disco SOLO (sin ISO, sin -kernel) ⇒ el producto instalado arranca y sirve SSH.
|
||||
# Cierra el lazo "ISO live → disco instalado → bootea solo", lo que hace la distro distribuible.
|
||||
@@ -36,11 +36,11 @@ echo "==> (2) boot del instalador con disco EN BLANCO ${DISK_MB}M (auto-instala
|
||||
rm -f "$TGT"; truncate -s "${DISK_MB}M" "$TGT"
|
||||
timeout "$INSTALL_DEADLINE" qemu-system-x86_64 -m "$MEM" -no-reboot -nographic "${accel[@]}" \
|
||||
-drive file="$TGT",format=raw,if=virtio -cdrom "$ISO" -boot d > "$ILOG" 2>&1 || true
|
||||
if ! grep -q "HAMMER-INSTALL-OK" "$ILOG"; then
|
||||
if ! grep -q "TAKANA-INSTALL-OK" "$ILOG"; then
|
||||
echo "✗ la instalación NO terminó OK — ver $ILOG" >&2
|
||||
grep -iE "HAMMER-INSTALL-FAIL|hammer-install:|no apareció|error" "$ILOG" | head; exit 1
|
||||
grep -iE "TAKANA-INSTALL-FAIL|takana-install:|no apareció|error" "$ILOG" | head; exit 1
|
||||
fi
|
||||
echo " ✓ HAMMER-INSTALL-OK"
|
||||
echo " ✓ TAKANA-INSTALL-OK"
|
||||
|
||||
echo "==> (3) boot del DISCO instalado (sin ISO, sin -kernel)"
|
||||
timeout "$BOOT_DEADLINE" qemu-system-x86_64 -m "$MEM" -no-reboot -nographic "${accel[@]}" \
|
||||
@@ -58,7 +58,7 @@ reject "ARRANQUE FALLIDO|seed.card no encontrada" "arje-zero arrancó sin fallo
|
||||
reject "no pude montar" "particiones dedicadas /store y /var/lib/hammer montadas"
|
||||
|
||||
if [ "$fail" = 0 ]; then
|
||||
echo; echo "✓✓ INSTALL-FROM-LIVE VERDE: ISO live → hammer-install → disco que bootea solo y sirve SSH"
|
||||
echo; echo "✓✓ INSTALL-FROM-LIVE VERDE: ISO live → takana-install → disco que bootea solo y sirve SSH"
|
||||
else
|
||||
echo; echo "✗ install-from-live FALLÓ — ver $ILOG / $BLOG" >&2; exit 1
|
||||
fi
|
||||
|
||||
@@ -79,7 +79,7 @@ chmod +x "$AUG/usr/bin/wifi-connect"
|
||||
|
||||
# 5) banner de marca para el login de consola (icono martillo+# + acrónimo + uso WiFi)
|
||||
mkdir -p "$AUG/etc"
|
||||
cp scripts/hammer-banner.txt "$AUG/etc/motd"
|
||||
cp scripts/takana-banner.txt "$AUG/etc/motd"
|
||||
|
||||
# 6) armar el ISO híbrido con iso-image.sh:
|
||||
# - rama UEFI por EFI-STUB DIRECTO (EFI_STUB=1): bzImage=BOOTX64.EFI, esquiva el GRUB 2.14 roto.
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
# 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
|
||||
# sudo PRODUCT=<hash> AUTHKEYS=~/.ssh/id_ed25519.pub FORCE=1 ./scripts/takana-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
|
||||
# PRODUCT=<hash> TESTKEY=1 BOOT=1 ./scripts/takana-install.sh work/target.img
|
||||
#
|
||||
# Variables:
|
||||
# PRODUCT product-rootfs sellado (hash/prefijo; default: el más reciente del store)
|
||||
@@ -25,7 +25,7 @@ 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"
|
||||
WORK="$ROOT/work/takana-install"; RFS="$WORK/rootfs"
|
||||
|
||||
# --- resolver product-rootfs sellado ---
|
||||
if [ -n "${PRODUCT:-}" ]; then
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
# takana-install — instalador a disco DESDE el medio live (Etapa E5 / refinamiento #1).
|
||||
#
|
||||
# Se inyecta en el rootfs del producto como /usr/bin/hammer-install (ver scripts/iso-image.sh
|
||||
# Se inyecta en el rootfs del producto como /usr/bin/takana-install (ver scripts/iso-image.sh
|
||||
# INSTALLER=1). Corre DENTRO del live, como root real (arje-zero es PID1) ⇒ NO necesita unshare -r
|
||||
# ni los rodeos rootless de install-image.sh: particiona, formatea, monta y copia con privilegios
|
||||
# reales, usando sólo herramientas que el producto ya trae (busybox fdisk/mke2fs/mount/dd + uutils cp).
|
||||
@@ -124,7 +124,7 @@ apply_post_install_config() {
|
||||
fi
|
||||
_ts=$(bb date -u +%FT%TZ 2>/dev/null || echo unknown)
|
||||
{
|
||||
echo "# escrito por hammer-install en $_ts"
|
||||
echo "# escrito por takana-install en $_ts"
|
||||
echo "HOSTNAME=${CFG_HOSTNAME:-}"
|
||||
echo "TIMEZONE=${CFG_TZ:-}"
|
||||
echo "KEYMAP=${CFG_KEYMAP:-}" # best-effort: el producto aún no trae kbd/loadkeys
|
||||
@@ -241,10 +241,10 @@ interactive_setup() {
|
||||
|
||||
# --- resolución del modo: interactivo (sin device + TTY) vs desatendido (device dado) ---
|
||||
if [ -z "$DEV" ]; then
|
||||
if [ -t 0 ] || [ "${HAMMER_INSTALL_INTERACTIVE:-}" = 1 ]; then
|
||||
if [ -t 0 ] || [ "${TAKANA_INSTALL_INTERACTIVE:-${HAMMER_INSTALL_INTERACTIVE:-}}" = 1 ]; then
|
||||
interactive_setup
|
||||
else
|
||||
echo "uso: hammer-install <device> [ROOT_MB] [STORE_MB] (o sin args con un TTY para el modo interactivo)" >&2
|
||||
echo "uso: takana-install <device> [ROOT_MB] [STORE_MB] (o sin args con un TTY para el modo interactivo)" >&2
|
||||
exit 2
|
||||
fi
|
||||
fi
|
||||
@@ -255,21 +255,22 @@ if [ -z "$CFG_ROOT_HASH" ] && [ -n "${TAKANA_ROOT_PW:-${HAMMER_ROOT_PW:-}}" ] &&
|
||||
CFG_ROOT_HASH=$(printf '%s' "${TAKANA_ROOT_PW:-$HAMMER_ROOT_PW}" | bb cryptpw -m sha512 2>/dev/null || true)
|
||||
fi
|
||||
|
||||
# --- gancho de prueba: valida TUI + config sin tocar disco (HAMMER_INSTALL_DRYRUN=1) ---
|
||||
if [ "${HAMMER_INSTALL_DRYRUN:-}" = 1 ]; then
|
||||
# --- gancho de prueba: valida TUI + config sin tocar disco (TAKANA_INSTALL_DRYRUN=1) ---
|
||||
if [ "${TAKANA_INSTALL_DRYRUN:-${HAMMER_INSTALL_DRYRUN:-}}" = 1 ]; then
|
||||
echo "== DRYRUN: plan de instalación =="
|
||||
echo " DEV=$DEV ROOT_MB=$ROOT_MB STORE_MB=$STORE_MB"
|
||||
echo " HOSTNAME=$CFG_HOSTNAME TZ=${CFG_TZ:-UTC} KEYMAP=$CFG_KEYMAP"
|
||||
echo " ROOT_HASH=$([ -n "$CFG_ROOT_HASH" ] && echo set || echo -) AUTHKEYS=$([ -n "$CFG_ROOT_AUTHKEYS" ] && echo set || echo -)"
|
||||
if [ -n "${HAMMER_INSTALL_TESTROOT:-}" ]; then
|
||||
apply_post_install_config "$HAMMER_INSTALL_TESTROOT"
|
||||
echo " config aplicada a $HAMMER_INSTALL_TESTROOT"
|
||||
_testroot="${TAKANA_INSTALL_TESTROOT:-${HAMMER_INSTALL_TESTROOT:-}}"
|
||||
if [ -n "$_testroot" ]; then
|
||||
apply_post_install_config "$_testroot"
|
||||
echo " config aplicada a $_testroot"
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
[ -b "$DEV" ] || { echo "hammer-install: $DEV no es un block device" >&2; exit 1; }
|
||||
[ -d "$PAYLOAD" ] || { echo "hammer-install: falta el payload $PAYLOAD (¿ISO sin INSTALLER=1?)" >&2; exit 1; }
|
||||
[ -b "$DEV" ] || { echo "takana-install: $DEV no es un block device" >&2; exit 1; }
|
||||
[ -d "$PAYLOAD" ] || { echo "takana-install: falta el payload $PAYLOAD (¿ISO sin INSTALLER=1?)" >&2; exit 1; }
|
||||
|
||||
# --- Detección de firmware: UEFI ⇒ rama EFI-stub SOBERANA (ADR 0010 paso 5); BIOS ⇒ MBR+GRUB (abajo) ---
|
||||
# La rama EFI usa una ESP tipo 0xEF en tabla MBR (UEFI arranca \EFI\BOOT\BOOTX64.EFI de una ESP MBR igual
|
||||
@@ -277,9 +278,9 @@ fi
|
||||
# binario EFI (EFI-stub, cmdline horneada carga el initrd); un initramfs mínimo pivota por LABEL. Mismos
|
||||
# artefactos que scripts/install-image-efi.sh (validado en OVMF), armados desde dentro del live.
|
||||
if [ -d /sys/firmware/efi ]; then
|
||||
[ -r "$PAYLOAD/kernel/bzImage-efi" ] || { echo "hammer-install: live en UEFI pero falta $PAYLOAD/kernel/bzImage-efi (ISO sin kernel metal)" >&2; exit 1; }
|
||||
[ -r "$PAYLOAD/kernel/bzImage-efi" ] || { echo "takana-install: live en UEFI pero falta $PAYLOAD/kernel/bzImage-efi (ISO sin kernel metal)" >&2; exit 1; }
|
||||
ESP_MB="${ESP_MB:-64}"
|
||||
echo "==> hammer-install (UEFI): EFI-stub soberano en $DEV (ESP ${ESP_MB}M, root ${ROOT_MB}M, store ${STORE_MB}M, estado=resto)"
|
||||
echo "==> takana-install (UEFI): EFI-stub soberano en $DEV (ESP ${ESP_MB}M, root ${ROOT_MB}M, store ${STORE_MB}M, estado=resto)"
|
||||
echo " ¡esto BORRA $DEV!"
|
||||
|
||||
# MBR, 4 primarias: p1=ESP(0xEF) p2=root p3=store p4=estado. Sectores explícitos (como la rama BIOS).
|
||||
@@ -322,7 +323,7 @@ FDISK
|
||||
"$BB" sync; sleep 1
|
||||
P1="${DEV}1"; P2="${DEV}2"; P3="${DEV}3"; P4="${DEV}4"
|
||||
for p in "$P1" "$P2" "$P3" "$P4"; do
|
||||
[ -b "$p" ] || { echo "hammer-install: no apareció la partición $p tras particionar" >&2; exit 1; }
|
||||
[ -b "$p" ] || { echo "takana-install: no apareció la partición $p tras particionar" >&2; exit 1; }
|
||||
done
|
||||
|
||||
echo "==> formateando (ESP FAT32 + 3 ext2 etiquetadas para el pivote por LABEL)"
|
||||
@@ -377,7 +378,7 @@ INIT
|
||||
|
||||
# Poblar la root (copia del live) — sin wrapper que monte particiones (el pivote ya montó store/estado).
|
||||
echo "==> copiando la raíz del live → $P2 (excluye virtuales/efímeros, /store, /var/lib/hammer, payload)"
|
||||
MNT=/run/hammer-install
|
||||
MNT=/run/takana-install
|
||||
"$BB" mkdir -p "$MNT"
|
||||
"$BB" mount -t ext4 "$P2" "$MNT"
|
||||
for entry in /* /.[!.]*; do
|
||||
@@ -423,15 +424,15 @@ INIT
|
||||
"$BB" sync
|
||||
"$BB" umount "$MNT"
|
||||
|
||||
echo "✓ hammer-install (UEFI): $DEV instalado con EFI-stub SOBERANO (sin GRUB ni systemd-boot). Reiniciá sin el medio live."
|
||||
echo "✓ takana-install (UEFI): $DEV instalado con EFI-stub SOBERANO (sin GRUB ni systemd-boot). Reiniciá sin el medio live."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ===================== rama BIOS (MBR + GRUB) — el firmware NO es UEFI ==============================
|
||||
[ -r "$PAYLOAD/grub/boot.img" ] && [ -r "$PAYLOAD/grub/core.img" ] || { echo "hammer-install: payload GRUB incompleto" >&2; exit 1; }
|
||||
[ -r "$PAYLOAD/kernel/bzImage" ] || { echo "hammer-install: falta el kernel en el payload" >&2; exit 1; }
|
||||
[ -r "$PAYLOAD/grub/boot.img" ] && [ -r "$PAYLOAD/grub/core.img" ] || { echo "takana-install: payload GRUB incompleto" >&2; exit 1; }
|
||||
[ -r "$PAYLOAD/kernel/bzImage" ] || { echo "takana-install: falta el kernel en el payload" >&2; exit 1; }
|
||||
|
||||
echo "==> hammer-install: instalando el sistema live en $DEV (root ${ROOT_MB}M, store ${STORE_MB}M, estado=resto)"
|
||||
echo "==> takana-install: instalando el sistema live en $DEV (root ${ROOT_MB}M, store ${STORE_MB}M, estado=resto)"
|
||||
echo " ¡esto BORRA $DEV!"
|
||||
|
||||
# --- particionar MBR con busybox fdisk (3 primarias; p1 bootable) ---
|
||||
@@ -472,7 +473,7 @@ FDISK
|
||||
|
||||
P1="${DEV}1"; P2="${DEV}2"; P3="${DEV}3"
|
||||
for p in "$P1" "$P2" "$P3"; do
|
||||
[ -b "$p" ] || { echo "hammer-install: no apareció la partición $p tras particionar" >&2; exit 1; }
|
||||
[ -b "$p" ] || { echo "takana-install: no apareció la partición $p tras particionar" >&2; exit 1; }
|
||||
done
|
||||
|
||||
# --- formatear (busybox mke2fs = ext2; el driver ext4 del kernel lo monta) ---
|
||||
@@ -482,7 +483,7 @@ echo "==> formateando particiones (ext2, montables como ext4)"
|
||||
"$BB" mke2fs -F -L hammer-state "$P3" >/dev/null 2>&1
|
||||
|
||||
# --- copiar la raíz del live a la partición root, excluyendo virtuales + el payload ---
|
||||
MNT=/run/hammer-install
|
||||
MNT=/run/takana-install
|
||||
"$BB" mkdir -p "$MNT"
|
||||
"$BB" mount -t ext4 "$P1" "$MNT"
|
||||
echo "==> copiando la raíz del live → $P1 (excluye virtuales/efímeros, /store, /var/lib/hammer y el payload)"
|
||||
@@ -550,4 +551,4 @@ echo "==> instalando GRUB (boot.img→MBR + core.img→hueco post-MBR)"
|
||||
"$BB" dd if="$PAYLOAD/grub/core.img" of="$DEV" bs=512 seek=1 conv=notrunc 2>/dev/null
|
||||
"$BB" sync
|
||||
|
||||
echo "✓ hammer-install: $DEV instalado. Reiniciá sin el medio live para arrancar del disco."
|
||||
echo "✓ takana-install: $DEV instalado. Reiniciá sin el medio live para arrancar del disco."
|
||||
Reference in New Issue
Block a user