From 36081cf1cfeb9901778d710c8950819f81c9beee Mon Sep 17 00:00:00 2001 From: sergio Date: Sun, 9 Aug 2026 08:11:57 -0400 Subject: [PATCH] =?UTF-8?q?farm-up:=20DOS=20bombas=20de=20p=C3=A9rdida=20d?= =?UTF-8?q?e=20datos=20=E2=80=94=20una=20ya=20explot=C3=B3=20y=20se=20llev?= =?UTF-8?q?=C3=B3=20~900=20artefactos=20del=20volumen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- scripts/farm/farm-up.sh | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) 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\"