Beim Template-Bau lassen sich Profile wählen (nur solche ohne Pflichtvariablen). Nach dem Vorbereitungsstart laufen sie über den Guest-Agent; danach werden Maschinen-ID, SSH-Host-Keys, Docker-Engine-ID und apt-Cache entfernt. Ausrollen nimmt das Template mit den meisten passenden Profilen und überspringt, was schon eingebacken ist. Auf pve-demo: Provisionierung mit base+docker 141 s ohne, ~30 s mit Template. Dabei gefunden: docker nimmt den Benutzer per guest.user in die Gruppe auf – Profile mit guest.* laufen deshalb beim Deploy noch einmal (idempotent, schnell). Closes #022 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
94 lines
3.3 KiB
TypeScript
94 lines
3.3 KiB
TypeScript
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 { templateProfileAufloesen } from "@/server/services/templates";
|
|
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;
|
|
const profile = await templateProfileAufloesen(anfrage.profile, distribution.family);
|
|
|
|
await prisma.auftrag.update({
|
|
where: { id: auftrag.id },
|
|
data: {
|
|
kopf: `Server ${server.name} · Node ${anfrage.knoten} · Template ${distribution.name}${
|
|
anfrage.profile.length > 0 ? ` mit ${anfrage.profile.join(", ")}` : ""
|
|
}`,
|
|
},
|
|
});
|
|
await melden(auftrag.id);
|
|
|
|
const client = new ProxmoxClient(verbindungAus(server), { beobachter: aufrufLogger(senke) });
|
|
const stand: TemplateBauStand = {};
|
|
try {
|
|
const ergebnis = await phasenAusfuehren(
|
|
templateBauSchritte(
|
|
{
|
|
client,
|
|
distribution,
|
|
profile,
|
|
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!,
|
|
profile: profile.map((p) => p.profil.id),
|
|
gebautVonAuftragId: auftrag.id,
|
|
},
|
|
});
|
|
return {
|
|
ok: true,
|
|
ergebnis: {
|
|
vmid: stand.vmid,
|
|
template: templateName(
|
|
distribution,
|
|
profile.map((p) => p.profil.id),
|
|
),
|
|
knoten: anfrage.knoten,
|
|
},
|
|
};
|
|
} finally {
|
|
await client.schliessen();
|
|
}
|
|
});
|