fix (containers): gebruik PODMAN_SYSTEMD_UNIT label als ground truth voor Managed By

De oude logica miste .kube quadlets volledig: het zocht alleen naar .container
bestanden op naam en gebruikte een fragiele pod-naam heuristiek als fallback.
Containers gestart via mediaserver.kube en bookstack.kube werden daardoor
als 'podman' geclassificeerd terwijl ze systemd-beheerd zijn.

PODMAN_SYSTEMD_UNIT label wordt door Podman/systemd automatisch gezet op elke
container gestart via een quadlet (.container, .kube, .pod). Dit is de enige
betrouwbare bron.

Verwijderd: _unit_is_active(), unit_active_cache, _map_pod_to_unit import.
Behouden: find_defined_containers() voor section C (offline containers) en
action routing (start/stop/restart via systemd unit).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-24 11:14:50 +01:00
parent fba9b59445
commit 7d2f19f81f
+9 -27
View File
@@ -14,7 +14,6 @@ from fastapi.responses import StreamingResponse
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from common import ( from common import (
_helper_call, _helper_call,
_map_pod_to_unit,
_podman_action_post, _podman_action_post,
_podman_get_json, _podman_get_json,
_podman_get_text, _podman_get_text,
@@ -412,21 +411,8 @@ def init_containers_router(
dashboard = [] dashboard = []
defined = find_defined_containers() defined = find_defined_containers()
# Cache zodat we niet voor elke container opnieuw systemctl doen
unit_active_cache = {}
stats_by_name = _STATS_CACHE_BY_NAME stats_by_name = _STATS_CACHE_BY_NAME
def _unit_is_active(unit):
if not unit:
return False
if unit in unit_active_cache:
return unit_active_cache[unit]
code, out = systemctl_func(["systemctl", "--user", "is-active", unit])
ok = (code == 0) or ((out or "").strip() == "active")
unit_active_cache[unit] = ok
return ok
# A) echte containers (runtime) # A) echte containers (runtime)
real = _podman_get_json(session, f"{podman_api_base}/libpod/containers/json?all=true") real = _podman_get_json(session, f"{podman_api_base}/libpod/containers/json?all=true")
for c in real: for c in real:
@@ -448,23 +434,19 @@ def init_containers_router(
c["_dashboard_mem_usage"] = st.get("mem_usage") c["_dashboard_mem_usage"] = st.get("mem_usage")
c["_dashboard_mem_perc"] = st.get("mem_perc") c["_dashboard_mem_perc"] = st.get("mem_perc")
# 1) Managed: systemd als er een .container definitie bestaat # Classificatie: PODMAN_SYSTEMD_UNIT label is ground truth
if rname in defined: labels = c.get("Labels") or {}
podman_unit = labels.get("PODMAN_SYSTEMD_UNIT") or ""
if podman_unit:
c["_dashboard_source"] = "systemd" c["_dashboard_source"] = "systemd"
c["_dashboard_unit"] = f"{rname}.service" c["_dashboard_unit"] = podman_unit
c["_dashboard_def_path"] = defined[rname]
else:
# 2) Extra: zit container in een pod die via systemd (kube/quadlet) draait?
podname = (c.get("PodName") or "").strip()
pod_unit = _map_pod_to_unit(podname) if podname else None
if pod_unit and _unit_is_active(pod_unit):
c["_dashboard_source"] = "systemd"
c["_dashboard_unit"] = pod_unit
# geen _dashboard_def_path, want dit is geen .container definitie
else: else:
c["_dashboard_source"] = "podman" c["_dashboard_source"] = "podman"
# Definitiepad: onafhankelijk van classificatie
if rname in defined:
c["_dashboard_def_path"] = defined[rname]
dashboard.append(c) dashboard.append(c)
# B) Dedup set: ook genormaliseerd (voorkomt /name vs name doublures) # B) Dedup set: ook genormaliseerd (voorkomt /name vs name doublures)