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:
2026-10-12 10:57:11 +02:00
co-authored by Claude Opus 5.5
parent 76bc0e4269
commit 4285785a4c
14 changed files with 1252 additions and 17 deletions
@@ -0,0 +1,24 @@
import { NextResponse } from "next/server";
import { aufruferAdresse } from "@/lib/adressen";
import { api, jsonLesen } from "@/server/api";
import { rechtErforderlich } from "@/server/auth/zugang";
import { templateBauStarten, templatesListe } from "@/server/services/templates";
type Kontext = { params: Promise<{ name: string }> };
export const GET = api(async (anfrage: Request, { params }: Kontext) => {
await rechtErforderlich(anfrage, "lesen");
return NextResponse.json(await templatesListe((await params).name));
});
/** Template bauen → Auftrag; Fortschritt unter /api/v1/auftraege/<kurzId>/ereignisse. */
export const POST = api(async (anfrage: Request, { params }: Kontext) => {
const aufrufer = await rechtErforderlich(anfrage, "ausrollen");
const auftrag = await templateBauStarten(
(await params).name,
await jsonLesen(anfrage),
aufrufer,
aufruferAdresse(anfrage.headers),
);
return NextResponse.json({ id: auftrag.id, kurzId: auftrag.kurzId }, { status: 202 });
});