feat(verlauf): Filter, Wiederholen und Aufräumen

Verlauf filterbar (URL, API, proxdeploy history); Wiederholen füllt den Assistenten aus einem alten Auftrag; Aufräumen löscht nach Fehlschlag oder Abbruch den halb angelegten Gast – nur, wenn dessen Beschreibung auf den Auftrag verweist. Deshalb setzt das Klonen die Beschreibung jetzt sofort. Auf pve-demo geprüft (CT 109).

Closes #014

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-12 16:39:58 +02:00
co-authored by Claude Opus 5.5
parent 8dca30e254
commit 7f6cf00a0e
32 changed files with 1488 additions and 53 deletions
+59
View File
@@ -0,0 +1,59 @@
import { phasenAusfuehren } from "@/engine/ablauf/ablauf";
import { aufraeumSchritte, type AufraeumStand } from "@/engine/ablaeufe/aufraeumen";
import { ProxmoxClient } from "@/engine/proxmox/client";
import { prisma } from "@/lib/db";
import { z } from "@/lib/validierung";
import { melden } from "@/server/ereignisse/senke";
import { verbindungAus } from "@/server/services/server";
import { ablaufRegistrieren } from "../ausfuehren";
import { aufrufLogger } from "../aufruf-log";
const Anfrage = z.object({
auftrag: z.string(),
typ: z.enum(["VM", "LXC"]),
vmid: z.number().int(),
knoten: z.string().nullable(),
});
ablaufRegistrieren("AUFRAEUMEN", async ({ auftrag, senke, abbruchGewuenscht }) => {
const anfrage = Anfrage.parse(auftrag.anfrage);
const server = await prisma.server.findUniqueOrThrow({ where: { id: auftrag.serverId } });
await prisma.auftrag.update({
where: { id: auftrag.id },
data: {
vmid: anfrage.vmid,
kopf: `Server ${server.name}${anfrage.knoten ? ` · Node ${anfrage.knoten}` : ""} · ${
anfrage.typ === "LXC" ? "CT" : "VM"
} ${anfrage.vmid} aus ${anfrage.auftrag}`,
},
});
await melden(auftrag.id);
const client = new ProxmoxClient(verbindungAus(server), { beobachter: aufrufLogger(senke) });
const stand: AufraeumStand = {};
try {
const ergebnis = await phasenAusfuehren(
aufraeumSchritte(
{
client,
typ: anfrage.typ,
vmid: anfrage.vmid,
knoten: anfrage.knoten,
auftragKurzId: anfrage.auftrag,
},
stand,
),
senke,
{ abbruchGewuenscht },
);
if (!ergebnis.ok) return ergebnis;
// Der ursprüngliche Auftrag ist damit erledigt – im Verlauf als „aufgeräumt“ sichtbar.
if (auftrag.bezugId) {
await prisma.auftrag.update({ where: { id: auftrag.bezugId }, data: { status: "AUFGERAEUMT" } });
await melden(auftrag.bezugId);
}
return { ok: true, ergebnis: { vmid: anfrage.vmid, ...(stand.knoten ? { knoten: stand.knoten } : {}) } };
} finally {
await client.schliessen();
}
});