From 35f58aa75be2f5dedf0b60754977b68f81dd7569 Mon Sep 17 00:00:00 2001 From: sergio Date: Thu, 16 Jul 2026 07:47:36 -0400 Subject: [PATCH] harkaq: granja con volumen + auto-shutdown VALIDADA end-to-end MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test real (worker + volumen + helper), no en el papel. Las 3 piezas: 1. worker midió lz4+bzip2 → volumen 2. tras 1 ciclo idle SE AUTO-ELIMINÓ (verificado: el server desapareció solo) 3. volumen SOBREVIVIÓ con los 2 verdicts; helper efímero ccx13 los recogió al hub y se auto-destruyó 3 bugs cazados EN EL TEST (no adivinados): - falta --exclude /work: work/=69GB colgó el rsync del up horas - cpx11 'unsupported' en hel1 (AMD sin stock) → ccx13 - collect llamaba harvest con 'local' (rsync a un worker inexistente): ahora sólo recoge; clasificar es paso aparte (worker mide, hub clasifica) + auto-delete por API REST (curl+metadata), NO hcloud CLI (la golden no lo trae). El ID propio sale del metadata service, no del nombre. Cierra los 2 huecos de la 1ª campaña: idle cobrando (ahora auto-delete) y dependencia de que yo esté viva (ahora el volumen persiste). Runbook: docs/runbooks/harkaq-granja-volumen.md. Volumen clausurado tras el test (€0). Co-Authored-By: Claude Opus 4.8 --- docs/runbooks/harkaq-granja-volumen.md | 42 ++++++++++++++++++++++++++ scripts/farm/harkaq-vol.sh | 19 ++++++++---- 2 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 docs/runbooks/harkaq-granja-volumen.md diff --git a/docs/runbooks/harkaq-granja-volumen.md b/docs/runbooks/harkaq-granja-volumen.md new file mode 100644 index 00000000..d7106887 --- /dev/null +++ b/docs/runbooks/harkaq-granja-volumen.md @@ -0,0 +1,42 @@ +# Granja harkaq con volumen persistente + auto-shutdown + +La arquitectura que la 1ª campaña pidió (quedó idle ~4h cobrando). El worker no depende de que yo +esté viva y no se queda idle. **Validado end-to-end 2026-07-16** (worker se auto-eliminó, volumen +sobrevivió con las cosechas, helper efímero las recogió). + +## Ciclo + +```sh +scripts/farm/harkaq-vol.sh up 2 # 2 workers midiendo → volumen; se auto-eliminan al agotar cola +# ... (muelen la noche, se destruyen solos) ... +scripts/farm/harkaq-vol.sh collect # (cuando esté viva) helper efímero baja las cosechas al hub +scripts/farm/harkaq-vol.sh close # clausura el volumen (deja de cobrar) +scripts/farm/harkaq-vol.sh status +``` + +## Cómo funciona (y por qué así) + +- **Volumen `harkaq-cosecha`**: los workers escriben verdicts a `/mnt/cosecha`, que **sobrevive a + su destrucción**. No dependo de estar viva para no perder el trabajo. +- **Auto-shutdown**: tras `IDLE_CICLOS` ciclos con 0 mediciones nuevas, el worker **se auto-elimina + vía API REST** (`curl` + metadata service; NO hcloud CLI, que la golden no trae). En Hetzner un + server apagado **sigue cobrando** ⇒ apagar de verdad es `delete`. +- **collect**: monta el volumen en un helper efímero barato (o un worker vivo), rsync al hub, lo + destruye. Clasificar los verdicts es un paso aparte (el worker MIDE, el hub CLASIFICA con el + store completo). + +## Rastrillos que ya se pagaron (todos verificados en vivo) + +- **`--exclude /work` es crítico**: `work/` son 69GB; sin excluirlo el rsync del `up` cuelga horas. +- **Tipo de server**: en hel1 los AMD `cpx*` dan "unsupported/stock"; `ccx13`/`ccx23` sí van. +- **El token va al worker** (para auto-delete): riesgo acotado — efímero, sin servicios entrantes. +- **`${1:?...}` sin llaves** en el mensaje: una `}` interna cierra la expansión. +- El bucle **borra el artefacto `-hkm` tras medir** (envenenaba la caché en la 1ª campaña) y gatea + por ABI≥7 + binario-con-jaula (no medir ciego). + +## Parar de emergencia +```sh +hcloud server list | grep hkw # ver workers +hcloud server delete hkw-N # matar uno +scripts/farm/harkaq-vol.sh close # y el volumen +``` diff --git a/scripts/farm/harkaq-vol.sh b/scripts/farm/harkaq-vol.sh index b61264b2..a7a28f09 100755 --- a/scripts/farm/harkaq-vol.sh +++ b/scripts/farm/harkaq-vol.sh @@ -26,7 +26,7 @@ cd "$HUB" VOL="${VOL:-harkaq-cosecha}" IMAGE="${IMAGE:-408909310}" # golden con kernel 6.17 (Landlock ABI 7) TYPE="${TYPE:-ccx23}" -HELPER_TYPE="${HELPER_TYPE:-cx22}" # para collect: el más barato que monte el volumen +HELPER_TYPE="${HELPER_TYPE:-ccx13}" # para collect: el más barato que monte el volumen LOCATION="${LOCATION:-hel1}" SSHKEY="${SSHKEY:-desarrollo@jlsoltech.com}" SSH_KEY="${SSH_KEY:-$HOME/.ssh/github5}" @@ -75,8 +75,11 @@ EOF ip=$(hcloud server ip "$name") wait_ssh "$ip" || { echo " $name no responde"; continue; } # Provisión: código + harkaq + montaje del volumen + servicio con auto-shutdown. - rsync -az -e "$SSH" --exclude /store --exclude '/store-*' --exclude /target --exclude /dist \ - --exclude /.dev-fs --exclude /.git --exclude /.scratch --exclude '*.png' --exclude '/content*' \ + # --exclude /work es CRÍTICO: work/ son 69GB (sources, tandas). Sin él el rsync manda + # decenas de GB y el up cuelga horas — pasó. farm-up.sh ya lo excluye; se perdió al copiar. + rsync -az -e "$SSH" --exclude /work --exclude /store --exclude '/store-*' --exclude /target \ + --exclude /dist --exclude /tandas --exclude /.dev-fs --exclude /.git --exclude /.scratch \ + --exclude '*.png' --exclude '/content*' \ ./ "root@$ip:$REMOTE/" >/dev/null $SSH "root@$ip" "MNT=/mnt/cosecha; mkdir -p \$MNT; mount $DEV \$MNT 2>/dev/null || (mkfs.ext4 -q -F $DEV && mount $DEV \$MNT); mkdir -p \$MNT/verdicts \$MNT/logs" scripts/farm/harkaq-farm-setup.sh "$ip" >/dev/null 2>&1 || echo " (setup con avisos, sigo)" @@ -120,9 +123,13 @@ collect) mkdir -p work/harkaq-campana rsync -az -e "$SSH" "root@$ip:/mnt/cosecha/verdicts/" work/harkaq-campana/ 2>/dev/null || true [ -n "$helper" ] && { echo "== destruyo el helper"; hcloud server delete "$helper" >/dev/null; } - echo "== corriendo el harvest sobre lo recogido" - scripts/farm/harvest-harkaq.sh "local" 2>/dev/null || \ - echo " (harvest necesita un worker; recogido a work/harkaq-campana/, clasificá con harvest-harkaq)" + # NO se corre el harvest acá: harvest-harkaq.sh rsync-ea de un WORKER, y en este punto los + # verdicts ya están locales (los trajo el rsync del volumen). Clasificarlos es un paso aparte + # —lo hace el hub con el store COMPLETO (el worker mide, el hub clasifica)— y su edición de + # recetas + commit no debe colgar de un `collect`. Se reporta y se deja al operador/harvest. + n=$(ls work/harkaq-campana/*.verdicts 2>/dev/null | wc -l) + echo "== recogidos $n verdicts a work/harkaq-campana/. Clasificar/declarar:" + echo " scripts/farm/harkaq-suggest.py ~/.cache/harkaq/base.policy \$PWD/store \$PWD/recipes" ;; close)