farm-up: DOS bombas de pérdida de datos — una ya explotó y se llevó ~900 artefactos del volumen
Investigando por qué el worker nuevo arrancó con 2 artefactos en vez de ~900, apareció esto.
BOMBA 1 — `rm -rf $REMOTE/store` sin comprobar si es punto de montaje.
La guarda era `[ -d ] && [ ! -L ]`: basta en un server creado desde la golden ORIGINAL, donde
/opt/hammer/store es un directorio normal. Pero al re-snapshotear un worker (ayer, para meterle
Rust y Go) la imagen se llevó también LA CONFIGURACIÓN DE MONTAJE ⇒ el server nuevo monta el
volumen en esa ruta AL ARRANCAR, antes de que corra el «rescate». Entonces el `rm -rf` borra A
TRAVÉS DEL MONTAJE y se lleva el store del volumen entero — justo lo que el volumen existe para
proteger.
Evidencia: el volumen pasó de ~900 artefactos a 2, pero NO se perdió el filesystem (lost+found
de julio, 17 montajes, .dmerge intacto). Se borró el CONTENIDO, no el disco. Ahora hay
`mountpoint -q`: si ya está montado no hay nada que rescatar ni que borrar.
BOMBA 2 — `mount … || { mkfs.ext4 -F …; }`. Formatear ante CUALQUIER fallo de montaje, incluida
la carrera normal entre `volume attach` y la aparición del dispositivo. Un hipo de segundos
destruía el volumen. Ahora sólo formatea si `blkid` dice que NO tiene filesystem; si lo tiene y
no montó, aborta y lo dice.
Las dos comparten la misma forma: un fallback destructivo que asume la causa benigna. `mv -n`
está bien elegido (no pisa), pero el `rm -rf` que lo sigue anulaba esa prudencia.
Y una consecuencia que hay que asumir: re-snapshotear un worker NO conserva el store — los
artefactos viven en el volumen, que no entra en la imagen. La golden aporta toolchain y sistema;
la caché la aporta el volumen. Hoy la imagen decía traer store y no lo trae.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Semántico sayk'uy
Mana ima sutichaypas t'ikrakurqanchu: qillqalla, yachachiylla utaq willaylla t'ikrakurqan.
1 qillqakuna · +22 −2
- scripts/farm/farm-up.sh +22 −2
diff --git a/scripts/farm/farm-up.sh b/scripts/farm/farm-up.sh
index 7e1ed347..7fd929dc 100755
--- a/scripts/farm/farm-up.sh
+++ b/scripts/farm/farm-up.sh
@@ -97,7 +97,16 @@ for k in $(seq 1 "$N"); do
hcloud volume attach --server "$name" "$VOL_NAME" >/dev/null 2>&1 || true
dev="/dev/disk/by-id/scsi-0HC_Volume_$vid"
$SSH root@"$ip" "mkdir -p /mnt/cosecha
- mount $dev /mnt/cosecha 2>/dev/null || { mkfs.ext4 -q -F $dev && mount $dev /mnt/cosecha; }
+ # ⚠ El `mkfs.ext4 -F` de rescate SÓLO si el dispositivo no tiene filesystem. La versión previa
+ # formateaba ante CUALQUIER fallo de montaje —incluida la carrera normal entre `volume attach`
+ # y la aparición del dispositivo— o sea que un hipo de segundos destruía el volumen entero.
+ # `blkid` distingue «vacío» de «no pude montarlo ahora».
+ if ! mount $dev /mnt/cosecha 2>/dev/null; then
+ if blkid $dev >/dev/null 2>&1; then
+ echo " ✗ el volumen TIENE filesystem y no montó — NO lo formateo. Revisá a mano." >&2; exit 1
+ fi
+ mkfs.ext4 -q -F $dev && mount $dev /mnt/cosecha
+ fi
mkdir -p /mnt/cosecha/store /mnt/cosecha/verdicts /mnt/cosecha/logs
# el store del worker ES el del volumen: sellar YA es persistir.
# PERO antes hay que RESCATAR el store HORNEADO en la golden (2026-07-21): esto hacía
@@ -106,7 +115,18 @@ for k in $(seq 1 "$N"); do
# deuda contra un store casi vacío y se pone a reconstruir media distro: en la tanda del
# 2026-07-21 dio 716 recetas de deuda donde el hub medía 37. Es CAS (nombre = hash) ⇒
# fusionar es seguro por construcción: \`mv -n\` no pisa lo que el volumen ya tiene.
- if [ -d $REMOTE/store ] && [ ! -L $REMOTE/store ]; then
+ # ⚠ `mountpoint -q` NO ES OPCIONAL — sin él este bloque BORRA EL VOLUMEN.
+ # La guarda original sólo comprobaba «es directorio y no es symlink». Eso basta en un server
+ # recién creado desde la golden ORIGINAL, donde /opt/hammer/store es un directorio normal.
+ # Pero al re-snapshotear un worker (2026-08-08) la imagen se llevó también la CONFIGURACIÓN DE
+ # MONTAJE: el server nuevo monta el volumen en /opt/hammer/store al arrancar, ANTES de que
+ # corra este rescate. Entonces `rm -rf $REMOTE/store` borra A TRAVÉS DEL MONTAJE y se lleva el
+ # store del volumen entero — que es justo lo que el volumen existe para proteger.
+ # Medido: el volumen pasó de ~900 artefactos a 2. No se perdió el filesystem (lost+found es de
+ # julio, 17 montajes): se borró el CONTENIDO.
+ # ⇒ Si ya es punto de montaje, no hay nada que rescatar ni que borrar: el store ya está donde
+ # tiene que estar.
+ if [ -d $REMOTE/store ] && [ ! -L $REMOTE/store ] && ! mountpoint -q $REMOTE/store; then
n=\$(ls $REMOTE/store 2>/dev/null | wc -l)
[ \"\$n\" -gt 0 ] && mv -n $REMOTE/store/* /mnt/cosecha/store/ 2>/dev/null
echo \" ✓ rescatados \$n artefactos horneados de la golden al volumen\"