feat(lxc): LXC-Container ausrollen, mit oder ohne Node-SSH

Container aus dem Proxmox-Template (neueste passende Version aus
aplinfo), unprivilegiert, nesting automatisch für docker. Weil Proxmox
keine Exec-API für Container hat, läuft die Provisionierung per SSH:
bevorzugt pct exec über den Node, sonst direkt in den Container mit
einem Bereitstellungsschlüssel, der am Ende wieder entfernt wird.

Auf pve-demo beide Wege geprüft: Debian 13 mit docker per pct exec
(hello-world läuft mit nesting allein) und Ubuntu 24.04 per SSH in den
Container. Dabei gefunden: chrony scheitert ohne CAP_SYS_TIME (jetzt
if: vm), sshd -t auf Ubuntu 24.04 ohne /run/sshd.

Closes #009

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-12 13:19:13 +02:00
co-authored by Claude Opus 5.5
parent 9310164bc2
commit d25ec54ef9
18 changed files with 893 additions and 67 deletions
+18 -22
View File
@@ -1,11 +1,15 @@
import { phasenAusfuehren } from "@/engine/ablauf/ablauf";
import { sshBefehl, vmAusrollSchritte, type VmAusrollStand } from "@/engine/ablaeufe/vm-ausrollen";
import { sshBefehl } from "@/engine/ablaeufe/vm-ausrollen";
import { ProxmoxClient } from "@/engine/proxmox/client";
import { prisma } from "@/lib/db";
import { melden } from "@/server/ereignisse/senke";
import { ausrollenVorbereiten, kopfzeile } from "@/server/services/ausrollen";
import {
ausrollenVorbereiten,
ausrollSchritte,
kopfzeile,
type AusrollStand,
} from "@/server/services/ausrollen";
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";
@@ -13,7 +17,7 @@ import { aufrufLogger } from "../aufruf-log";
ablaufRegistrieren("AUSROLLEN", async ({ auftrag, senke, abbruchGewuenscht, angelegt }) => {
// Dieselbe Vorbereitung wie beim Anlegen – der Katalog könnte sich seitdem geändert haben.
const v = await ausrollenVorbereiten(auftrag.anfrage);
const stand: VmAusrollStand = {};
const stand: AusrollStand = {};
const kopfSetzen = async () => {
await prisma.auftrag.update({
where: { id: auftrag.id },
@@ -26,12 +30,10 @@ ablaufRegistrieren("AUSROLLEN", async ({ auftrag, senke, abbruchGewuenscht, ange
const client = new ProxmoxClient(verbindungAus(v.server), { beobachter: aufrufLogger(senke) });
try {
const ergebnis = await phasenAusfuehren(
vmAusrollSchritte(
ausrollSchritte(
v,
{
client,
anfrage: v.anfrage,
distribution: v.distribution,
profile: v.profile,
vmidReservieren: async (belegt, wunsch) => {
const vmid = await vmidReservieren({
serverId: v.server.id,
@@ -44,20 +46,14 @@ ablaufRegistrieren("AUSROLLEN", async ({ auftrag, senke, abbruchGewuenscht, ange
await kopfSetzen();
return vmid;
},
templateBau: v.anfrage.templateBauen
? {
sshFuer: (knoten) => nodeBefehlFuer(v.server, knoten),
auftragKurzId: auftrag.kurzId,
vmidReservieren: (belegt) =>
vmidReservieren({
serverId: v.server.id,
auftragId: auftrag.id,
belegt,
von: v.server.templateVmidVon,
bis: v.server.templateVmidBis,
}),
}
: undefined,
templateVmidReservieren: (belegt) =>
vmidReservieren({
serverId: v.server.id,
auftragId: auftrag.id,
belegt,
von: v.server.templateVmidVon,
bis: v.server.templateVmidBis,
}),
angelegt,
auftragKurzId: auftrag.kurzId,
},