fix: lecture disques hôte via lsblk + filtrage montages Docker

This commit is contained in:
perco
2026-06-28 09:06:58 +02:00
parent 9c1e45a7bc
commit 7738430807
+71 -48
View File
@@ -116,60 +116,83 @@ def _host_path(p: str) -> str:
return HOST_ROOT + p if HOST_ROOT else p return HOST_ROOT + p if HOST_ROOT else p
def _read_host_mounts() -> list[dict]: def _flatten_lsblk(dev: dict, result: list | None = None) -> list:
"""Lit /proc/mounts depuis le système hôte (via HOST_ROOT/proc/mounts).""" if result is None:
mounts_file = _host_path("/proc/mounts") result = []
parts = [] result.append(dev)
for child in dev.get("children", []):
_flatten_lsblk(child, result)
return result
def _read_host_disks() -> list[dict]:
"""Enumère les vrais disques via lsblk (lit /sys) et accède aux montages via /rootfs."""
try: try:
with open(mounts_file) as f: raw = _run(["lsblk", "-J", "-b", "-o",
for line in f: "NAME,SIZE,TYPE,MOUNTPOINT,MOUNTPOINTS,FSTYPE,LABEL"])
cols = line.split() data = json.loads(raw)
if len(cols) < 3: except Exception:
return []
result = []
seen_mp: set = set()
for dev in data.get("blockdevices", []):
for item in _flatten_lsblk(dev):
if item.get("type") not in ("part", "lvm", "disk", "raid1", "md"):
if item.get("type") == "disk" and not item.get("children"):
pass # disque sans partition (rare, garder)
elif item.get("type") != "disk":
pass
# on garde tout sauf loop/rom/etc
if item.get("type") in ("loop", "rom", "sr"):
continue continue
device, mountpoint, fstype = cols[0], cols[1], cols[2]
if fstype in SKIP_FS: mps = item.get("mountpoints") or []
continue mp = item.get("mountpoint")
if not device.startswith("/dev/"): if mp and mp not in mps:
continue mps.insert(0, mp)
# accéder au point de montage via le chemin hôte mps = [m for m in mps if m and m not in ("[SWAP]", "")]
real_path = _host_path(mountpoint)
try: fstype = item.get("fstype") or ""
u = psutil.disk_usage(real_path) if fstype in SKIP_FS:
if u.total == 0: continue
for mountpoint in mps:
# ne garder que les montages hôtes (commencent par HOST_ROOT si défini)
if HOST_ROOT:
if not mountpoint.startswith(HOST_ROOT + "/") and mountpoint != HOST_ROOT:
continue continue
parts.append({ display_mp = mountpoint[len(HOST_ROOT):] or "/"
"device": device, real_path = mountpoint
"mountpoint": mountpoint, else:
display_mp = mountpoint
real_path = mountpoint
if display_mp in seen_mp:
continue
try:
st = os.statvfs(real_path)
total = st.f_blocks * st.f_frsize
if total == 0:
continue
free = st.f_bavail * st.f_frsize
used = total - st.f_bfree * st.f_frsize
pct = round(used / total * 100, 1) if total else 0
seen_mp.add(display_mp)
result.append({
"device": "/dev/" + item["name"],
"mountpoint": display_mp,
"fstype": fstype, "fstype": fstype,
"total": u.total, "label": item.get("label") or "",
"used": u.used, "total": total,
"free": u.free, "used": used,
"percent": u.percent, "free": free,
"percent": pct,
}) })
except Exception: except Exception:
continue continue
except Exception:
# fallback : partitions vues par le container
for p in psutil.disk_partitions(all=False):
if p.fstype in SKIP_FS:
continue
try:
u = psutil.disk_usage(p.mountpoint)
parts.append({
"device": p.device, "mountpoint": p.mountpoint,
"fstype": p.fstype,
"total": u.total, "used": u.used, "free": u.free, "percent": u.percent,
})
except Exception:
pass
# dédupliquer par device+mountpoint
seen = set()
result = []
for p in parts:
key = (p["device"], p["mountpoint"])
if key not in seen:
seen.add(key)
result.append(p)
return result return result
@@ -181,7 +204,7 @@ def get_live() -> dict:
mem = psutil.virtual_memory() mem = psutil.virtual_memory()
swap = psutil.swap_memory() swap = psutil.swap_memory()
disks = _read_host_mounts() disks = _read_host_disks()
# réseau — avec network_mode:host on lit directement les stats hôte # réseau — avec network_mode:host on lit directement les stats hôte
net_now = psutil.net_io_counters() net_now = psutil.net_io_counters()