feat(templates): Template-Bau für VMs mit eingebautem Guest-Agent
Cloud-Image laden (download-url mit Prüfsumme, ab PVE 8.4 per API, davor per SSH), VM mit q35/UEFI/virtio-scsi-single anlegen, Disk per import-from importieren, Guest-Agent mit einem einmaligen Vorbereitungsstart einbauen und als Template markieren. Auf pve-demo (PVE 9.2.2) gebaut: Template 9000 aus Debian 13 in 5 min 26 s, Snippet und cicustom danach entfernt. Der Weg ohne SSH über eine Bau-Adresse ist als #021 ausgegliedert. Templates-Seite mit Liste (Proxmox ist maßgeblich, Tag proxdeploy-template) und Formular; Abfrageschleifen erscheinen im Detail-Log nur noch bei Fehlern. Closes #007 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,2 @@
|
||||
/**
|
||||
* Meldet alle Abläufe beim worker an. Template-Bau (#007), Ausrollen (#008) und Aufräumen folgen.
|
||||
*/
|
||||
export {};
|
||||
/** Meldet alle Abläufe beim worker an. Ausrollen (#008) und Aufräumen folgen. */
|
||||
import "./ablaeufe/template";
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
import { phasenAusfuehren } from "@/engine/ablauf/ablauf";
|
||||
import { templateBauSchritte, templateName, type TemplateBauStand } from "@/engine/ablaeufe/template-bau";
|
||||
import type { Distribution } from "@/engine/katalog/schema";
|
||||
import { ProxmoxClient } from "@/engine/proxmox/client";
|
||||
import { prisma } from "@/lib/db";
|
||||
import { TemplateBauAnfrage } from "@/lib/schemas/template";
|
||||
import { melden } from "@/server/ereignisse/senke";
|
||||
import { verbindungAus } from "@/server/services/server";
|
||||
import { nodeBefehlFuer } from "@/server/services/ssh-zugang";
|
||||
import { vmidReservieren } from "@/server/services/vmid";
|
||||
import { ablaufRegistrieren } from "../ausfuehren";
|
||||
import { aufrufLogger } from "../aufruf-log";
|
||||
|
||||
ablaufRegistrieren("TEMPLATE_BAUEN", async ({ auftrag, senke, abbruchGewuenscht, angelegt }) => {
|
||||
const anfrage = TemplateBauAnfrage.parse(auftrag.anfrage);
|
||||
const server = await prisma.server.findUniqueOrThrow({ where: { id: auftrag.serverId } });
|
||||
const zeile = await prisma.distribution.findUniqueOrThrow({ where: { id: anfrage.distribution } });
|
||||
const distribution = zeile.definition as Distribution;
|
||||
|
||||
await prisma.auftrag.update({
|
||||
where: { id: auftrag.id },
|
||||
data: { kopf: `Server ${server.name} · Node ${anfrage.knoten} · Template ${distribution.name}` },
|
||||
});
|
||||
await melden(auftrag.id);
|
||||
|
||||
const client = new ProxmoxClient(verbindungAus(server), { beobachter: aufrufLogger(senke) });
|
||||
const stand: TemplateBauStand = {};
|
||||
try {
|
||||
const ergebnis = await phasenAusfuehren(
|
||||
templateBauSchritte(
|
||||
{
|
||||
client,
|
||||
distribution,
|
||||
knoten: anfrage.knoten,
|
||||
storage: anfrage.storage,
|
||||
bridge: anfrage.bridge,
|
||||
vlan: anfrage.vlan,
|
||||
ssh: nodeBefehlFuer(server, anfrage.knoten),
|
||||
auftragKurzId: auftrag.kurzId,
|
||||
vmidReservieren: async (belegt) => {
|
||||
const vmid = await vmidReservieren({
|
||||
serverId: server.id,
|
||||
auftragId: auftrag.id,
|
||||
belegt,
|
||||
von: server.templateVmidVon,
|
||||
bis: server.templateVmidBis,
|
||||
});
|
||||
await prisma.auftrag.update({ where: { id: auftrag.id }, data: { vmid } });
|
||||
await angelegt({ vmid, knoten: anfrage.knoten, typ: "VM" });
|
||||
return vmid;
|
||||
},
|
||||
},
|
||||
stand,
|
||||
),
|
||||
senke,
|
||||
{ abbruchGewuenscht },
|
||||
);
|
||||
if (!ergebnis.ok) return ergebnis;
|
||||
await prisma.template.create({
|
||||
data: {
|
||||
serverId: server.id,
|
||||
knoten: anfrage.knoten,
|
||||
vmid: stand.vmid!,
|
||||
distributionId: distribution.id,
|
||||
storage: anfrage.storage,
|
||||
imageDatei: stand.imageDatei!,
|
||||
pruefsumme: stand.pruefsumme!,
|
||||
gebautVonAuftragId: auftrag.id,
|
||||
},
|
||||
});
|
||||
return {
|
||||
ok: true,
|
||||
ergebnis: { vmid: stand.vmid, template: templateName(distribution), knoten: anfrage.knoten },
|
||||
};
|
||||
} finally {
|
||||
await client.schliessen();
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user