takana etapa 4: los 10 crates de librería y el CLI pasan a takana-*
hammer-{core,build,bootstrap,overlay,journal,mirror,upgrade,agent,recover,cli}
→ takana-*, con sus deps de workspace, sus identificadores en el fuente y las
referencias -p de los scripts.
VERIFICADO que no mueve nada del corpus: `takana hash recipes/zlib.toml`
devuelve b3:dc363f26… , idéntico a antes del renombre. Los nombres de crate no
entran en hash_inputs, pero eso se comprueba, no se supone. 600 tests en verde.
DOS BINARIOS SE CONGELAN, y no por prolijidad:
- `hammerd` — paquete Y binario. Es componente de Stage 1 de la distro (musl,
busybox, hammerd, arje-zero), lo supervisa arje-zero en el sistema arrancado,
`PRESEED=hammerd` lo nombra en selfhost-verify y sus bytes anclan el baseline
of_tree. El nombre del crate va en los símbolos ⇒ renombrarlo mueve los bytes.
- `hammer-recover` — el PAQUETE se renombra a takana-recover, el BINARIO no.
hammer-live-install.sh lo copia a /usr/sbin/hammer-recover en sistemas ya
instalados y hornea un hook de arranque que lo invoca por ese nombre:
renombrarlo rompe máquinas instaladas, no el repo.
Consecuencia que hay que anotar igual: al renombrar hammer-core, los bytes de
hammerd cambian de todos modos porque linkea contra un crate con otro nombre.
El baseline of_tree del selfhost hay que rehacerlo — es efecto de la etapa 4,
no de un cambio de hammerd.
Las referencias en comentarios de recetas y docs (rutas hammer-core/src/…)
quedan para la etapa 5: son texto, no mueven hash.
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
[package]
|
||||
name = "takana-recover"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
authors.workspace = true
|
||||
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
|
||||
# invoca por ese nombre. Renombrar el binario rompe máquinas instaladas. Etapa 6.
|
||||
[[bin]]
|
||||
name = "hammer-recover"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
takana-upgrade.workspace = true
|
||||
takana-journal.workspace = true
|
||||
@@ -0,0 +1,73 @@
|
||||
//! `hammer-recover` — auto-recuperación de upgrades al **arranque** (E4 / refinamiento #4b).
|
||||
//!
|
||||
//! El producto NO lleva el CLI `hammer` completo; este mini-binario (estático musl) es lo único que el
|
||||
//! sistema instalado necesita para auto-sanar un upgrade interrumpido. El wrapper `/sbin/init` lo corre
|
||||
//! **tras montar `/store` y `/var/lib/hammer`** y **antes** de incarnar arje-zero:
|
||||
//!
|
||||
//! - Sin intento pendiente ⇒ no-op (el caso normal).
|
||||
//! - Con un `pending.json` (un `hammer upgrade apply` cortado por un apagón/reinicio): intenta
|
||||
//! **completar** (roll-forward, re-ejecuta el plan idempotente + commitea); si no puede (p.ej. el árbol
|
||||
//! ya no está en `/store`), **deshace** (roll-back) para dejar el FHS consistente. En cualquier caso el
|
||||
//! sistema arranca en un estado coherente, no a medias.
|
||||
//!
|
||||
//! Encaja con el modelo de generaciones **in-place** (el FHS es la generación viva): no hay menú de
|
||||
//! generaciones tipo NixOS que seleccionar, sino una reparación determinista del estado a medias.
|
||||
//!
|
||||
//! Paths del producto (overridables por entorno para tests):
|
||||
//! `HAMMER_RECOVER_ROOT=/` `HAMMER_RECOVER_STORE=/store`
|
||||
//! `HAMMER_RECOVER_STATE=/var/lib/hammer/upgrades` `HAMMER_RECOVER_JOURNAL=/var/lib/hammer/journal`
|
||||
//! Flag: `--rollback` fuerza deshacer en vez de completar.
|
||||
//!
|
||||
//! NUNCA sale con código ≠0 por un fallo de recuperación: es un hook de arranque, no debe abortar el
|
||||
//! boot. Reporta por consola y deja que arje-zero siga (con el estado más consistente que logró).
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn env_path(key: &str, default: &str) -> PathBuf {
|
||||
std::env::var(key).map(PathBuf::from).unwrap_or_else(|_| PathBuf::from(default))
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let force_rollback = std::env::args().skip(1).any(|a| a == "--rollback");
|
||||
let root = env_path("HAMMER_RECOVER_ROOT", "/");
|
||||
let store = env_path("HAMMER_RECOVER_STORE", "/store");
|
||||
let state = env_path("HAMMER_RECOVER_STATE", "/var/lib/hammer/upgrades");
|
||||
let journal_dir = env_path("HAMMER_RECOVER_JOURNAL", "/var/lib/hammer/journal");
|
||||
|
||||
match takana_upgrade::pending(&state) {
|
||||
Ok(None) => {
|
||||
println!("hammer-recover: sin upgrade interrumpido");
|
||||
return;
|
||||
}
|
||||
Ok(Some(p)) => {
|
||||
println!("hammer-recover: upgrade interrumpido (generación {}) — recuperando", p.id);
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("hammer-recover: no pude leer el estado de upgrades: {e}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let journal = takana_journal::Journal::open(&journal_dir).ok();
|
||||
let j = journal.as_ref();
|
||||
|
||||
if force_rollback {
|
||||
match takana_upgrade::recover(&store, &root, &state, j, true) {
|
||||
Ok(r) => println!("hammer-recover: DESHECHO (generación {} descartada)", r.generation),
|
||||
Err(e) => eprintln!("hammer-recover: rollback falló: {e}"),
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Optimista: completar el upgrade. Si el roll-forward falla, deshacer ⇒ FHS consistente igual.
|
||||
match takana_upgrade::recover(&store, &root, &state, j, false) {
|
||||
Ok(r) => println!("hammer-recover: COMPLETADO (generación {})", r.generation),
|
||||
Err(e) => {
|
||||
eprintln!("hammer-recover: roll-forward falló ({e}); deshaciendo para dejar el FHS consistente");
|
||||
match takana_upgrade::recover(&store, &root, &state, j, true) {
|
||||
Ok(r) => println!("hammer-recover: DESHECHO tras fallo (generación {})", r.generation),
|
||||
Err(e2) => eprintln!("hammer-recover: rollback de respaldo también falló: {e2}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user