Commit Graph

3 Commits (6de7bf9db8ed14f31e071952fa063bfe95c279cf)

Author SHA1 Message Date
nexxo 19a770e1eb Kuendigung B1, Fix-Welle: der Platz wird frei, und das Loeschen ist vollzogen
K1 — abgebaute Instanzen zaehlten weiter als belegend. `scopeOccupyingHost`
filtert jetzt `torn_down_at`: eine abgebaute Instanz behaelt `ended`, `vmid`
und `disk_gb` als Nachweis, `status != 'failed'` war fuer sie also wahr. Der
Knoten wurde physisch leer und die Buchhaltung blieb voll — die naechste
bezahlte Bestellung derselben Groesse waere geparkt und verworfen worden.

K2 — `deleteVm()` gibt die UPID zurueck, der Abbau wartet den qmdestroy-Auftrag
ab und schreibt `torn_down_at` erst danach. Ein 200 heisst nur, dass Proxmox
den Auftrag angenommen hat; scheitert die Zerstoerung danach, stand bisher eine
laufende Maschine mit einem Datensatz da, der "abgebaut" sagte — und niemand
sah sie je wieder an. Die Attrappe bildet die Asynchronitaet ab
(`destroyedVmids`, `destroyExitStatus`, `destroyHangs`). Die Fristen des
Auftrags wandern mit: Sichern 900 s, Zerstoeren 300 s, Summe unveraendert 1800 s
unter der Uhr des Arbeiters.

K3 — vor `shutdownVm()` steht derselbe `vmStatus()`-Riegel wie im
Nachbarschritt. Eine wegen offener Zahlung gesperrte Cloud und jeder
Wiederholungslauf nach einem Teilfehlschlag treffen einen gestoppten Gast; der
Wurf haette die Instanz unheilbar gemacht und den echten Grund am Datensatz
ueberschrieben. Die Attrappe weist eine Bitte gegen eine stehende Maschine
jetzt ab, und ein Test faehrt erstmals einen zweiten Lauf nach einem
Fehlschlag durch.

W2 — der rote Kasten "Abbau haengt" filtert `status = 'ended'`. Eine
wiederbelebte Instanz waere sonst fuer immer darin stehengeblieben.

Neun Pruefungen im Mahnwesen lassen ihre Cloud jetzt laufen, bevor sie gesperrt
wird — die geschaerfte Attrappe legt offen, dass `SuspendInstance` denselben
fehlenden Riegel hat (Folgepunkt im Bericht).

Zu jedem der vier Punkte eine Zusicherung, die ohne den Fix rot ist; die
Rotproben stehen im Bericht.
2026-08-04 12:39:06 +02:00
nexxo 51ec6ebed2 Kuendigung B1, Task 3 — Fix-Runde: der Nachtrag braucht ein Lebenszeichen
Vier Befunde aus der Pruefung.

Der schwerste: der Nachtrags-Zweig konnte eine LAUFENDE Kundenmaschine als
abgebaut verbuchen. vmExists() ist ->get(...)->successful() ohne ->throw(), und
Proxmox antwortet auf die Konfiguration einer nicht vorhandenen VM mit 500 —
demselben Code wie ein hakender Knoten. "Gibt es nicht" und "ich konnte nicht
fragen" sahen damit gleich aus, und der Zustand entsteht im Regelbetrieb: ein
Lauf sichert, scheitert am Loeschen, und der naechste findet archive_volid
gesetzt und einen Knoten, der nichts beantwortet. Die Ablagenpruefung steht
deshalb jetzt VOR dem Zweig: nodeStorage() ruft ->throw(), laeuft sie durch, hat
der Knoten geantwortet, und erst dann ist ein "nein" aus vmExists() ein Befund
statt einer Vermutung.

Drei Ausnahmen lagen ausserhalb des try und haetten im Zeitplan die uebrigen
Instanzen mitgerissen: das Anlegen der Sperre (im Betrieb Redis), das Vermerken
des Grundes im catch, und die Freigabe im finally — die sogar am Erfolgsfall
vorbei. Alle drei abgesichert.

Die Sperrfrist war mit backupWaitSeconds + 600 knapper als der laengste Lauf
(Herunterfahren UND Sichern) und konnte kurz vor dem Loeschen auslaufen. Jetzt
shutdownWaitSeconds + backupWaitSeconds + Puffer — und sie hat endlich eine
eigene Pruefung.

Ein einzelnes Archiv ohne Zeitpunkt bleibt gueltig, mehrere nicht: sie lassen
sich nicht ordnen, und vermerkt wuerde womoeglich die Sicherung von vorgestern.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 11:36:18 +02:00
nexxo 24a0f64128 Kuendigung B1, Task 3: archivieren, nachsehen, und erst dann abbauen
Gekuendigte Kundenmaschinen wurden nie abgebaut. EndInstanceService nimmt der
Instanz am Laufzeitende die Adresse weg und laesst die Maschine ausdruecklich
stehen; danach kam nichts mehr, und sie belegte fuer immer einen Platz auf dem
Host. ArchiveAndTearDown ist der Schritt danach: vierzehn Tage nach dem Ende
wird die Maschine archiviert und geloescht.

Die eine Regel: niemals loeschen, bevor das Archiv nachweislich existiert. Ein
vzdump kann mit einer Auftragskennung enden und trotzdem nichts hinterlassen —
volle Ablage, abgebrochener Lauf, ein Fehler im Gast. Deshalb steht zwischen
Sichern und Loeschen eine echte Nachschau auf der Ablage (backupsFor), und der
juengste Eintrag muss nach dem Beginn dieses Laufes entstanden sein: eine
naechtliche Sicherung von gestern ist kein Archiv, dem der letzte Tag fehlen
darf.

Beide Proxmox-Aufrufe liefern nur eine Kennung, keine Zusage, also wird auf den
Auftrag gewartet und danach nachgesehen — beim Herunterfahren, ob der Gast
wirklich steht, beim Sichern, ob die Datei liegt. Unmittelbar vor dem Loeschen
wird der Datensatz neu gelesen: eine Instanz, die in der Zwischenzeit
wiederbelebt wurde, wird nicht geloescht. Keine Ausnahme entkommt — ein
Fehlschlag ist false und ein Grund in teardown_error, weil dieser Ablauf spaeter
im Zeitplan ueber viele Instanzen laeuft.

Die Ablage kommt aus einer Einstellung (provisioning.proxmox.archive_storage,
Vorgabe local wie bei den naechtlichen Sicherungen) UND wird gegen die Ablagen
des Knotens geprueft. Fehlt sie oder nimmt sie keine Sicherungen auf, bricht der
Abbau ab, bevor eine Kundenmaschine dafuer heruntergefahren wurde.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 11:15:52 +02:00