docs: infrastructura din dashboard si /infra, acces agenti pe statia de birou si 10.0.20.36

Lantul de pornire nou: JuiceSSH -> 10.0.20.36 -> C:\wolcluster.bat. Cheia moltbot
in docs/chei-publice.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KddsXCqEbKMhdFJDYbAsx8
This commit is contained in:
Claude Agent
2026-09-13 10:19:06 +00:00
parent c87fa06b55
commit ab9dbef998
6 changed files with 186 additions and 1 deletions

View File

@@ -124,7 +124,81 @@ Inapoi la token: scoate `DASHBOARD_AUTH=off` din `~/.claude-discord/env` si
reporneste serviciul. Doar `off`, `none`, `0` si `false` scot login-ul; orice alta
valoare il pastreaza.
## Instalare
## Tab Infrastructură
Al treilea tab (lângă Punte și Maria), aceeași logică folosită și de comanda
Discord `/infra` — un singur registru de acțiuni, `infra_actions.py`, cu doi
consumatori.
### Registrul de acțiuni — `infra_actions.py`
`ACTIONS: dict[str, dict]` e sursa unică de adevăr: id, `label`/`desc`, `host`
(`local`/`pvemini`/`pveelite`/`vm109`/`oracle-prod-admin`), `cmd`/`dry` (comanda
reală și, dacă există, varianta `--dry-run`), `job` (True → lansată prin
`systemd-run`, detașată; False → ssh sincron, timeout 120s), `confirm` (cere
confirmare explicită în UI/Discord) și `pre` (text descriptiv al precondiției).
Adăugarea unei acțiuni noi înseamnă o singură intrare aici — dashboard-ul și
botul o preiau automat (dashboard prin id, bot prin `app_commands.choices`
generat din `ACTIONS`).
Funcțiile publice: `status(fresh=False)` (stare cluster, cache 30s), `check(id,
st, dry_run)` (precondiții, funcție pură), `run(id, dry_run)`, `stop(id)`,
`log_tail(id, n=60)`, `maintenance_pending(st)`, `post_startup_instructions()`.
### Rute dashboard
| Metodă | Rută | Ce face |
|---|---|---|
| GET | `/api/infra/status?fresh=1` | `infra_actions.status()`; `fresh=1` ocolește cache-ul de 30s |
| GET | `/api/infra/log?id=<action>&n=<N>` | ultimele linii din jurnalul acțiunii (`log_tail`) |
| POST | `/api/infra/run` | `{"id": "...", "dry_run": bool}` → `infra_actions.run()` |
| POST | `/api/infra/stop` | `{"id": "..."}` → oprește job-ul systemd-run al acțiunii |
Fiecare `run`/`stop` scrie o linie în `infra.log` (`[actiune] infra <id>
dry=<bool>, cerut de <who>`) — identitatea vine din antetul Tailscale, ca la
restul dashboard-ului. **Citirea de stare ocolește `security/infra`** (ssh
direct, read-only, ca să nu umple jurnalul de acțiuni la fiecare 30 de
secunde); **acțiunile** trec toate prin `security/infra <host> "<cmd>"`, deci
apar în `infra.log` cu jurnalizarea obișnuită a wrapper-ului.
### Joburi lungi — `systemd-run` pe nod, nu tmux
tmux nu e instalat pe niciun nod Proxmox, așa că o acțiune cu `job: True`
pornește prin `security/infra <host> "systemd-run --unit=infra-<id> --collect
... /bin/bash -c '<cmd>'"` — detașată de conexiunea ssh, cu stdout/stderr
redirectate în `/var/log/infra-actions/<id>-<timestamp>.log`. `status()`
listează job-urile active (`systemctl list-units 'infra-*'`) și jurnalele
recente din acel director; tab-ul Infra le arată într-un banner cu buton
Jurnal (poll la 3s) și Oprește (`systemctl stop infra-<id>`).
### Precondiții
Fiecare acțiune reală (nu `stare`/`sarcini`) are o precondiție verificată de
`check()` înainte de executare — de exemplu `oprire` cere cele 3 noduri
online + cvorum + niciun job activ; `backup-pe-pvemini` cere pveelite offline
și failover-ul încă neactiv. Un `run()` cu precondiția nefăcută întoarce
`412` fără să atingă rețeaua. `status()` include deja rezultatul `check()`
pentru fiecare id (`actions: {id: {ok, reason}}`), ca butoanele să se
dezactiveze direct din prima cerere de stare.
### Fără oprire UPS reală
Acțiunea `ups-simulare` rulează scriptul de shutdown la panică UPS cu
`--dry-run --force` — nimic nu se oprește cu adevărat. Nu există în registru
nicio acțiune care să declanșeze un test de baterie cu oprire efectivă a
clusterului; `ups-test` (testul lunar) descarcă bateria controlat, dar nu
oprește noduri.
### Permisiunea Discord „Pin Messages" — momentan lipsă
La `oprire` (nu în dry-run), `post_startup_instructions()` postează mesajul cu
instrucțiunile de pornire în primul canal configurat și încearcă să-l fixeze
(pin). Botul **nu are** azi permisiunea `Pin Messages` pe canal: mesajul se
postează oricum, dar `PUT .../pins/<id>` întoarce 403, iar eșecul devine doar
un `warning` în răspunsul acțiunii (nu blochează oprirea). De dat botului
permisiunea `Pin Messages` pe canalul respectiv ca fixarea să funcționeze.
### Instalare
`ops/install.sh` face totul (leaga unitul, genereaza `DASHBOARD_TOKEN` daca lipseste,
porneste serviciul). Manual: