Add dynamic DNS and show the running kernel on the overview
router.ddns keeps provider records on the uplink's addresses with ddclient, run by a timer and by a watcher that starts it when an address changes. The Dynamic DNS page edits it; the secret is a private file on the router. The overview shows the running kernel and says when the current system boots a different one. PLAN.md records why the A/B image approach was not pursued. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AeFqV9dZrK6nipHkPfyM4F
This commit is contained in:
@@ -16,6 +16,7 @@ import (
|
||||
"net/netip"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -67,6 +68,8 @@ type UplinkStatus struct {
|
||||
type SystemStatus struct {
|
||||
Uptime time.Duration
|
||||
Load string
|
||||
Kernel string // the running kernel
|
||||
KernelNext string // the kernel of the current system when it differs: a reboot is due
|
||||
CPU float64 // percent; NaN until the second sample
|
||||
MemUsed uint64
|
||||
MemTotal uint64
|
||||
@@ -253,6 +256,12 @@ func systemStatus() SystemStatus {
|
||||
s.Uptime = time.Duration(secs) * time.Second
|
||||
}
|
||||
}
|
||||
if data, err := os.ReadFile("/proc/sys/kernel/osrelease"); err == nil {
|
||||
s.Kernel = strings.TrimSpace(string(data))
|
||||
}
|
||||
if dest, err := filepath.EvalSymlinks("/run/current-system/kernel"); err == nil {
|
||||
s.KernelNext = pendingKernel(s.Kernel, dest)
|
||||
}
|
||||
if data, err := os.ReadFile("/proc/loadavg"); err == nil {
|
||||
if f := strings.Fields(string(data)); len(f) >= 3 {
|
||||
s.Load = strings.Join(f[:3], " ")
|
||||
@@ -282,6 +291,18 @@ func systemStatus() SystemStatus {
|
||||
return s
|
||||
}
|
||||
|
||||
var kernelDirRe = regexp.MustCompile(`-linux-([0-9][^/]*)/`)
|
||||
|
||||
// pendingKernel is the version of the kernel image the current system boots
|
||||
// (a path like /nix/store/…-linux-6.12.5/bzImage) if it is not the running one.
|
||||
func pendingKernel(running, image string) string {
|
||||
m := kernelDirRe.FindStringSubmatch(image)
|
||||
if m == nil || running == "" || m[1] == running || strings.HasPrefix(running, m[1]+"-") {
|
||||
return ""
|
||||
}
|
||||
return m[1]
|
||||
}
|
||||
|
||||
// Sensor is one temperature the machine reports.
|
||||
type Sensor struct {
|
||||
Key string // stable name of its series
|
||||
|
||||
Reference in New Issue
Block a user