Post-repair hardware validation pipeline for Proxmox cluster hosts. Go orchestrator + in-image agent + mkosi live image + bundled dnsmasq PXE + SQLite + HTMX/SSE UI + notify registry + janitor + full docs.
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
package probes
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ThermalSample is one reading from /sys/class/hwmon. Kind is "temp",
|
||||
// Key is the label (or chip-relative name) and Value is degrees C.
|
||||
type ThermalSample struct {
|
||||
Kind string
|
||||
Key string
|
||||
Value float64
|
||||
Unit string
|
||||
}
|
||||
|
||||
// Thermals walks /sys/class/hwmon looking for temp*_input files. The
|
||||
// kernel reports millidegrees C; we divide by 1000. Labels come from
|
||||
// temp*_label (preferred) or a chip-relative fallback.
|
||||
//
|
||||
// This is also used by the thermal sidecar; it re-reads on each tick
|
||||
// rather than holding open handles so hot-plugged sensors (e.g. a PCIe
|
||||
// card enumerating late) get picked up.
|
||||
func Thermals() []ThermalSample {
|
||||
root := "/sys/class/hwmon"
|
||||
chips, err := os.ReadDir(root)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
var out []ThermalSample
|
||||
for _, c := range chips {
|
||||
base := filepath.Join(root, c.Name())
|
||||
chipName := strings.TrimSpace(readFileStr(filepath.Join(base, "name")))
|
||||
files, err := os.ReadDir(base)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for _, f := range files {
|
||||
name := f.Name()
|
||||
if !strings.HasPrefix(name, "temp") || !strings.HasSuffix(name, "_input") {
|
||||
continue
|
||||
}
|
||||
idx := strings.TrimSuffix(strings.TrimPrefix(name, "temp"), "_input")
|
||||
label := strings.TrimSpace(readFileStr(filepath.Join(base, "temp"+idx+"_label")))
|
||||
if label == "" {
|
||||
label = chipName + "/temp" + idx
|
||||
}
|
||||
raw := strings.TrimSpace(readFileStr(filepath.Join(base, name)))
|
||||
milli, err := strconv.Atoi(raw)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
out = append(out, ThermalSample{Kind: "temp", Key: label, Value: float64(milli) / 1000, Unit: "C"})
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func readFileStr(p string) string {
|
||||
b, err := os.ReadFile(p)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
Reference in New Issue
Block a user