sites: Inventar und Zielbild an echte Knoten (pve44–pve61) angepasst; ADR-0001/0002/0006 ergänzt
ci / test (push) Successful in 25s
ci / test (push) Successful in 25s
Aufbauplan Task 0.4: - inventory.yaml: pve44/46/48/52/61 und GODE-PC-05/06 (Ada, Windows, cpu_roles: false) - proxmox.yaml: eine GPU-VM pro Knoten mit allen Karten (D2), local-lvm/tank (D1 B), 192.168.100.0/24 ohne VLAN, Gast-IPs .220–.239 (ANNAHME bis Task 0.2) - registry.yaml/prometheus.yml: ops-Labels auf gpu-pve44/46/48, Ada ohne pve_node/vmid - tofu: dynamische hostpci, Speicher je Gast; Ansible: pve_gpu_hosts/pve_kiosk, Replikation auf mehrere Ziele - Placement: cpu_roles=false schließt Arbeitsplätze/Kiosk von CPU-Rollen aus - PLAN §1.3/§1.4/§9 und ADR-Nachträge (D1 entschieden, D2/D3 Bestätigung offen) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -24,7 +24,7 @@ def test_healer_labels_available_on_alerts():
|
||||
"""Labels, die Healer-Regeln brauchen, müssen von Metrik oder Scrape-Target kommen."""
|
||||
prom = yaml.safe_load((DEPLOY / "prometheus/prometheus.yml").read_text())
|
||||
jobs = {j["job_name"]: j for j in prom["scrape_configs"]}
|
||||
for job in ("node", "gpu", "vllm"):
|
||||
for job in ("node", "gpu", "llamacpp"):
|
||||
for sc in jobs[job]["static_configs"]:
|
||||
assert {"slot", "pve_node", "vmid"} <= set(sc["labels"]), (job, sc)
|
||||
from knaster.canary import OPS_LABELS
|
||||
@@ -46,13 +46,17 @@ def test_compose_files_parse(role):
|
||||
|
||||
|
||||
def test_ops_labels_consistent_between_registry_and_prometheus():
|
||||
"""Das erste Scrape-Ziel eines Slots trägt dieselben ops-Labels wie die Registry (Healer-Ziel)."""
|
||||
reg = yaml.safe_load((REPO_ROOT / "sites/knaster/registry.yaml").read_text())
|
||||
prom = yaml.safe_load((DEPLOY / "prometheus/prometheus.yml").read_text())
|
||||
vllm = {sc["labels"]["slot"]: sc["labels"] for sc in
|
||||
next(j for j in prom["scrape_configs"] if j["job_name"] == "vllm")["static_configs"]}
|
||||
for slot, labels in vllm.items():
|
||||
first: dict[str, dict] = {}
|
||||
for sc in next(j for j in prom["scrape_configs"] if j["job_name"] == "llamacpp")["static_configs"]:
|
||||
first.setdefault(sc["labels"]["slot"], sc["labels"])
|
||||
assert first
|
||||
for slot, labels in first.items():
|
||||
ops = reg["slots"][slot]["ops"]
|
||||
assert ops["vmid"] == labels["vmid"] and ops["container"] == labels["container"]
|
||||
assert {k: ops[k] for k in ("docker_host", "container", "pve_node", "vmid")} == \
|
||||
{k: labels[k] for k in ("docker_host", "container", "pve_node", "vmid")}, slot
|
||||
|
||||
|
||||
WORKFLOWS = sorted((REPO_ROOT / "n8n/workflows").glob("*.json"))
|
||||
@@ -160,19 +164,27 @@ def test_proxmox_site_consistent_with_registry_and_prometheus():
|
||||
reg = yaml.safe_load((REPO_ROOT / "sites/knaster/registry.yaml").read_text())
|
||||
vms = site["vms"]
|
||||
for vm in vms.values():
|
||||
assert vm["gpu"] in site["pci_mappings"]
|
||||
assert site["pci_mappings"][vm["gpu"]]["node"] == vm["node"] # Mapping liegt auf dem Host der VM
|
||||
for gpu in vm["gpus"]:
|
||||
assert gpu in site["pci_mappings"]
|
||||
assert site["pci_mappings"][gpu]["node"] == vm["node"] # Mapping liegt auf dem Host der VM
|
||||
assert vm["driver_generation"] in {"legacy", "modern"}
|
||||
gpus = [vm["gpu"] for vm in vms.values()]
|
||||
assert vm["node"] in site["nodes"] and site["nodes"][vm["node"]]["gpu_host"]
|
||||
gpus = [g for vm in vms.values() for g in vm["gpus"]]
|
||||
assert len(gpus) == len(set(gpus)) # keine GPU doppelt durchgereicht
|
||||
assert set(gpus) == set(site["pci_mappings"]) # jede gemappte Karte steckt in einer VM
|
||||
by_vmid = {str(vm["vmid"]): (name, vm) for name, vm in {**vms, **site["containers"]}.items()}
|
||||
for slot, spec in reg["slots"].items():
|
||||
ops = spec.get("ops")
|
||||
if not ops:
|
||||
ops = spec.get("ops") or {}
|
||||
if "vmid" not in ops: # z. B. Ada-Worker unter Windows (D3), kein Proxmox-Gast
|
||||
assert "pve_node" not in ops, slot
|
||||
continue
|
||||
name, vm = by_vmid[ops["vmid"]]
|
||||
assert vm["node"] == ops["pve_node"], slot
|
||||
assert ops["docker_host"].startswith(name.split("-")[0]), slot
|
||||
assert ops["docker_host"] == name, slot
|
||||
for c in site["containers"].values():
|
||||
if c.get("ha"):
|
||||
assert site["nodes"][c["node"]]["zfs_tank"] and c["storage"] == "tank"
|
||||
assert all(site["nodes"][t]["zfs_tank"] for t in c["replicate_to"])
|
||||
vmids = [str(v["vmid"]) for v in vms.values()] + [str(c["vmid"]) for c in site["containers"].values()]
|
||||
assert len(vmids) == len(set(vmids))
|
||||
# vLLM nur auf modernen Karten
|
||||
|
||||
Reference in New Issue
Block a user