Enterprise-Backup-, Recovery-, Verification-, Security- und Monitoring-Plattform fuer Proxmox VE, Windows, Linux und Dateisysteme. Der Leitsatz, der fast jede Entscheidung erklaert: Ein Backup gilt erst als vertrauenswuerdig, wenn Integritaet geprueft und Wiederherstellbarkeit nachgewiesen wurde. Deshalb steigt ein Wiederherstellungspunkt erst nach einem tatsaechlich durchgefuehrten Restore-Test auf "recoverable", und Unbekanntes geht in keine Bewertung als "gut" ein. Umfang (Phasen 0-23): - Repository Engine: inhaltsadressierte Bloecke, atomares Commit-Protokoll, Katalogaufbau allein aus den Manifesten — ohne Datenbank - Backup Engine: inhaltsabhaengiges Chunking, Deduplizierung trotz Verschluesselung, zstd, AES-256-GCM, Streaming mit Gegendruck - Agenten fuer Windows und Linux mit Auftragsabholung (Pull-Modell) - Proxmox-Provider mit beiden Zugriffswegen auf die Sicherungsarchive - Scheduler, Recovery Engine mit Pruefpunkt, Verification, Unveraenderlichkeit - Weboberflaeche, Kennzahlen, Meldungen, Berichte, Security Center, Ransomware-Heuristik (meldet, handelt nie) - Disaster Recovery, Haertung, Leistungsmessung, Chaos Testing - Eingefrorene Vertraege fuer API, Migrationen, Backup-Format und Repository - Auslieferungspaket fuer linux/amd64, linux/arm64 und windows/amd64 Nicht enthalten und als solches gekennzeichnet: Kapazitaetsprognose, Backup Copy, Changed Block Tracking bei Proxmox, erweiterte Attribute und ACLs. Gebaut, aber nie auf echter Hardware gefahren: der Windows-Dienst, die systemd-Einheit und der verpflichtende Proxmox-Meilenstein — ob eine wiederhergestellte VM startet, ist ungeprueft. Einzelheiten in CHANGELOG.md und docs/release-candidate.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
134 lines
6.4 KiB
Markdown
134 lines
6.4 KiB
Markdown
# Auftragsübermittlung an Agenten (Phase 5)
|
|
|
|
Bis zu dieser Phase war der Agent ein **angemeldeter Beobachter**: Er meldete
|
|
sich an und gab Lebenszeichen, aber der Server konnte ihm nichts zu tun geben.
|
|
Zentral gesteuerte Sicherungen liefen nur für Quellen, die der Control-Server
|
|
selbst erreicht.
|
|
|
|
Jetzt läuft die Kette durch:
|
|
|
|
```text
|
|
Server stellt Auftrag ein
|
|
→ Agent holt ihn ab
|
|
→ Agent sichert über die Engine
|
|
→ Agent meldet Fortschritt und Ergebnis
|
|
→ Server trägt den Wiederherstellungspunkt ein
|
|
```
|
|
|
|
## Der Agent holt ab, der Server drückt nicht
|
|
|
|
Das ist keine Bequemlichkeit, sondern die einzige Wahl, die in echten Netzen
|
|
funktioniert. Ein Agent steht hinter einer Firewall, oft hinter NAT, und ist vom
|
|
Server aus nicht erreichbar — jedenfalls nicht ohne eine eingehende Portfreigabe
|
|
auf **jedem** gesicherten System. Die Verbindung geht deshalb immer vom Agenten
|
|
aus, in genau der Richtung, die auch seine Lebendmeldung nimmt.
|
|
|
|
Drei Endpunkte, alle am **Betriebstoken des Agenten**:
|
|
|
|
```bash
|
|
POST /api/v1/agents/tasks/claim # holt den nächsten Auftrag (204 = nichts zu tun)
|
|
POST /api/v1/agents/tasks/{id}/progress # Fortschritt und Lebenszeichen
|
|
POST /api/v1/agents/tasks/{id}/result # Ergebnis
|
|
```
|
|
|
|
Jeder prüft, dass der Auftrag dem anfragenden Agenten gehört. Ohne diese Prüfung
|
|
könnte ein übernommener Agent die Aufträge aller anderen Systeme abholen — samt
|
|
Quell- und Repositorypfaden, also einer Landkarte der gesamten Anlage.
|
|
|
|
Ein fremder und ein bereits abgeschlossener Auftrag ergeben **dieselbe** Antwort:
|
|
Die Unterscheidung verriete, welche Auftragskennungen es gibt.
|
|
|
|
## Der Fund: Der Server sperrte das Repository für seinen eigenen Agenten
|
|
|
|
Beim ersten Durchlauf meldete der Agent:
|
|
|
|
```
|
|
REPOSITORY_UNREACHABLE — Das Repository unter "…/p5/repo" ist von diesem
|
|
Agenten aus nicht erreichbar
|
|
```
|
|
|
|
Das Repository lag einwandfrei da. Gesperrt hatte es der **Server**: Phase 8
|
|
öffnet das Repository einmal je Lauf und hält dabei die Schreibsperre — eine
|
|
richtige Entscheidung, solange der Server selbst sichert. Bei einer Delegation
|
|
wartete er nun mit gehaltener Sperre darauf, dass der Agent in dasselbe
|
|
Repository schreibt.
|
|
|
|
Der Server öffnet das Repository jetzt nur noch, wenn mindestens eine Quelle des
|
|
Laufs **serverseitig** gesichert wird. Ein Lauf mit ausschließlich
|
|
Agentenquellen löst den Datensatz auf — der Agent braucht den Pfad —, öffnet das
|
|
Repository aber nicht.
|
|
|
|
## Wie der Agent an das Repository kommt
|
|
|
|
Der Auftrag enthält den Repositorypfad; der Agent öffnet ihn unmittelbar. Daraus
|
|
folgt eine Betriebsanforderung, die klar benannt sein muss:
|
|
|
|
**Der Agent braucht Schreibzugriff auf das Repository.** Auf einem gemeinsamen
|
|
Server ist das der lokale Pfad. Bei getrennten Maschinen braucht es eine
|
|
Freigabe (NFS, SMB) oder ein eingehängtes Verzeichnis. Erreicht der Agent das
|
|
Ziel nicht, meldet er `REPOSITORY_UNREACHABLE` mit dem Hinweis auf die Freigabe —
|
|
statt einen technischen Pfadfehler weiterzureichen oder eine leere Sicherung
|
|
abzuliefern.
|
|
|
|
Ein Streaming-Protokoll, bei dem der Agent seine Blöcke an den Server schickt und
|
|
dieser sie ablegt, wäre die Alternative. Es ist bewusst **nicht** gebaut: Es
|
|
verdoppelt den Datenweg, macht den Control-Server zum Engpass jeder Sicherung
|
|
und verlangt ein eigenes Übertragungsprotokoll samt Wiederaufnahme. Für einen
|
|
ersten funktionierenden Weg ist die Freigabe die ehrlichere Lösung.
|
|
|
|
## Regeln, die auch hier gelten
|
|
|
|
- **Ein Auftrag je Agent.** Ein Teilindex auf `(agent_id) WHERE status IN
|
|
('claimed','running')` erzwingt es. Zwei gleichzeitige Sicherungen desselben
|
|
Systems konkurrierten um dieselben Dateien und dieselbe Schreibsperre.
|
|
- **Ein Teilfehler bleibt ein Teilfehler.** Der Agent meldet ihn als solchen, der
|
|
Server berichtigt ein widersprüchliches Ergebnis, und die Datenbank lehnt
|
|
„erfolgreich mit übergangenen Objekten" per CHECK ab. Drei Ebenen für dieselbe
|
|
Regel — weil sie die wichtigste ist (verbindliche Regel 1).
|
|
- **Ein Fehler ist eine Antwort.** Der Agent meldet auch im Fehlerfall zurück.
|
|
Ein Agent, der bei einem Fehler schweigt, lässt den Lauf bis zum Ablauf der
|
|
Frist hängen.
|
|
- **Verschlüsselung wird nie stillschweigend weggelassen.** Verlangt der Auftrag
|
|
sie und hat der Agent kein Schlüsselmaterial, wird der Auftrag abgelehnt. Ein
|
|
Backup, das der Server für verschlüsselt hält und das es nicht ist, wäre eine
|
|
Zusicherung ins Leere.
|
|
- **Der Lauf wartet synchron auf den Agenten.** Würde der Server den Auftrag nur
|
|
einstellen und den Lauf als erfolgreich vermerken, stünde ein grüner Lauf in
|
|
der Übersicht, während der Agent noch arbeitet — oder bereits gescheitert ist.
|
|
- **Verwaiste Aufträge werden freigegeben, nicht wiederholt.** Stirbt ein Agent
|
|
mitten im Lauf, gilt sein Auftrag nach Fristablauf als gescheitert
|
|
(`AGENT_LOST`, Klasse `transient`). Nicht erneut eingereiht: Er könnte bereits
|
|
Blöcke geschrieben haben.
|
|
- **Der Fortschritt ist zugleich die Lebendmeldung** und wird gedrosselt (alle
|
|
fünf Sekunden). Die Engine ruft ihren Rückruf sehr häufig auf; ungedrosselt
|
|
erzeugte eine Sicherung mit einer Million Dateien eine Million HTTP-Anfragen.
|
|
|
|
## Nachweis
|
|
|
|
Auf einer Maschine, auf der Server und Agent laufen:
|
|
|
|
```text
|
|
Agent aufgenommen dev-agent
|
|
Auftrag mit agent_id angelegt Quelle ist Agent zugewiesen ✓
|
|
Lauf angestoßen HTTP 202
|
|
Agent holt ab und führt aus "auftrag wird ausgefuehrt"
|
|
Ergebnis succeeded, 3.500.014 Byte, 4 Objekte
|
|
Wiederherstellungspunkt in der DB complete, 3.500.014 Byte
|
|
Quelle gelöscht, wiederhergestellt ✓ alle Prüfsummen stimmen
|
|
```
|
|
|
|
## Was noch fehlt
|
|
|
|
- **Der Windows-Dienst ist weiterhin ungeprüft.** `service_windows.go` ist
|
|
geschrieben, aber auf macOS nicht ausführbar. Der Kommandozeilenweg und die
|
|
Auftragsausführung sind plattformunabhängig; der Dienstwrapper ist der letzte
|
|
ungeprüfte Teil von Phase 5.
|
|
- **Wiederherstellung über den Agenten.** Der Auftragstyp `restore` ist im Modell
|
|
vorgesehen und nicht umgesetzt: Eine Wiederherstellung schreibt auf ein fremdes
|
|
System und braucht dieselben drei Hürden wie die serverseitige (Phase 9). Sie
|
|
wird als eigener Schritt gebaut, nicht nebenbei.
|
|
- **Kein Streaming zum Server.** Siehe oben — der Agent braucht Zugriff auf das
|
|
Repository.
|
|
- **Keine Abbruchmöglichkeit von außen.** Ein laufender Agentenauftrag lässt sich
|
|
derzeit nicht über die API abbrechen; er läuft zu Ende oder in die Frist.
|