Dedicated hardware poller + read-only consumers #4

Open
adamksmith wants to merge 13 commits from feat/dedicated-poller into main
2 changed files with 44 additions and 2 deletions
Showing only changes of commit 5032c58f7d - Show all commits

View File

@@ -22,7 +22,7 @@ import time
from services import store from services import store
from services.cache import close_cache, init_cache, redis_available from services.cache import close_cache, init_cache, redis_available
from services.host import get_host_drives from services.host import get_host_drives
from services.host_sensors import read_coretemp, read_ipmi_temps from services.host_sensors import read_coretemp, read_hwmon_env, read_ipmi_temps
logging.basicConfig( logging.basicConfig(
level=logging.INFO, level=logging.INFO,
@@ -47,7 +47,7 @@ async def sweep_env() -> None:
except Exception as e: except Exception as e:
errors.append(f"ipmi:{e}") errors.append(f"ipmi:{e}")
ipmi = [] ipmi = []
env = [s for s in ipmi if s.get("kind") == "env"] env = [s for s in ipmi if s.get("kind") == "env"] + read_hwmon_env()
cpu = read_coretemp() or [s for s in ipmi if s.get("kind") == "cpu"] cpu = read_coretemp() or [s for s in ipmi if s.get("kind") == "cpu"]
await store.set_host_sensors({ await store.set_host_sensors({

View File

@@ -7,7 +7,9 @@ coretemp is a cheap sysfs read.
""" """
import asyncio import asyncio
import logging import logging
import os
import re import re
from collections import Counter
from pathlib import Path from pathlib import Path
from services.hwgate import gate from services.hwgate import gate
@@ -67,6 +69,46 @@ def _parse_ipmi(text: str) -> list[dict]:
return sensors return sensors
def read_hwmon_env() -> list[dict]:
"""Read labelled temps from extra hwmon chips as env sensors.
For boxes without IPMI (e.g. Dell workstations), the BIOS SMM interface
(`dell_smm`) exposes CPU/ambient/SODIMM/board temps. Chips are configurable
via HOST_HWMON_CHIPS (comma list; default "dell_smm"); set to "" to disable.
Names are "<chip> <label>", with the temp index appended when a label
repeats within a chip (e.g. dell_smm's multiple "Other" sensors).
"""
chips = [c.strip() for c in os.environ.get("HOST_HWMON_CHIPS", "dell_smm").split(",") if c.strip()]
if not chips or not HWMON.is_dir():
return []
out: list[dict] = []
for hw in sorted(HWMON.iterdir()):
try:
chip = (hw / "name").read_text().strip()
except OSError:
continue
if chip not in chips:
continue
entries: list[tuple[str, str, int]] = [] # (idx, label, temp)
for label_f in sorted(hw.glob("temp*_label")):
try:
label = label_f.read_text().strip()
except OSError:
continue
input_f = label_f.with_name(label_f.name.replace("_label", "_input"))
try:
temp = round(int(input_f.read_text().strip()) / 1000)
except (OSError, ValueError):
continue
idx = label_f.name[len("temp"):-len("_label")]
entries.append((idx, label, temp))
dup = {lbl for lbl, n in Counter(l for _, l, _ in entries).items() if n > 1}
for idx, label, temp in entries:
name = f"{chip} {label}" + (f" {idx}" if label in dup else "")
out.append({"name": name, "temperature_c": temp, "status": "ok", "kind": "env"})
return out
def read_coretemp() -> list[dict]: def read_coretemp() -> list[dict]:
"""CPU package temps from coretemp hwmon → [{name, temperature_c, kind}].""" """CPU package temps from coretemp hwmon → [{name, temperature_c, kind}]."""
cpus: list[dict] = [] cpus: list[dict] = []