Skip to content

feat(agent): report Linux host capacity on the MetalNode - #2541

Open
cnuss wants to merge 1 commit into
defilantech:mainfrom
cnuss:split/2518-linux-host-capacity
Open

cnuss wants to merge 1 commit into
defilantech:mainfrom
cnuss:split/2518-linux-host-capacity

Conversation

@cnuss

@cnuss cnuss commented Nov 13, 2026

Copy link
Copy Markdown
Collaborator

What

DetectHostCapacity now has a Linux implementation in pkg/agent/hostcapacity_linux.go. The chip is /proc/device-tree/model with its trailing NUL stripped when the board has a device tree, otherwise the first model name or Model line in /proc/cpuinfo, otherwise empty. It goes through the same printable-prefix filter and 128-byte limit as the darwin reader, so the controller accepts whatever it reports. Memory comes from NewHostMemoryProvider().TotalMemory(), the LinuxMemoryProvider from #2531, so a cgroup limit below MemTotal is what the MetalNode shows, the same figure the memory budget uses.

To keep the dead-code guard passing with GOOS=linux, hostCapacityFromSysctl and its test move from the shared files into hostcapacity_darwin.go and hostcapacity_darwin_test.go. The stub for other OSes (!darwin && !linux) now returns an empty HostCapacity directly. macOS behaviour is unchanged.

On main the agent still exits at the Metal check on Linux, so for now this code runs only in tests. #2520 makes it reachable.

Why

Off macOS, DetectHostCapacity reports nothing, so a Linux host's MetalNode would show no chip and no memory in its capacity.

Part of #2481.

Fixes #2518

How

hostChipFromProc takes a readFile function, so the tests can use a fake /proc. They cover a device-tree model with its trailing NUL, the cpuinfo fallback when there is no device tree, and no /proc at all, which gives an empty chip rather than a guess. TestDetectHostCapacityOnLinux runs the real reader and checks that memory is non-zero and no Metal fields are set.

On a real board: a Raspberry Pi 5 (Debian 13, arm64) ran the agent built from the epic branch (7df0d2b9, which carries this slice). Its MetalNode capacity showed chip: "Raspberry Pi 5 Model B Rev 1.1", which matches /proc/device-tree/model, and memory: 8255824Ki, which matches MemTotal. That systemd user unit has no MemoryMax, so nothing capped it.

Under a cgroup limit: a small program calling agent.DetectHostCapacity() in a golang:1.27.4 container under --memory 3g printed MemoryBytes:3221225472, which is the cgroup's memory.max, while /proc/meminfo showed MemTotal: 8122332 kB (about 8 GB). The chip was empty there, because that VM has no device-tree model and its cpuinfo has no model name line.

What I ran on this branch:

  • go build ./... and GOOS=linux go build ./...: both build.
  • GOOS=linux bin/golangci-lint run ./... and GOOS=darwin bin/golangci-lint run ./...: 0 issues. for each.
  • make lint-deadcode and GOOS=linux make lint-deadcode: 0 issues. for each.
  • go test -count=1 ./pkg/agent/ ./api/... and go test -count=1 ./cmd/metal-agent/ on macOS: all ok.
  • In a golang:1.27.4 container, go test -count=1 ./pkg/agent/ -run 'TestHostChipFromProc|TestDetectHostCapacityOnLinux|TestMetalVersionString|TestLinuxMemory': all pass.
  • make chart-crds and make docs-reference: running them a second time changed nothing more, and make check-docs-reference exits 0.
  • make gate BASE_REF=origin/main: regen, drift, fmt, copyright, vet and lint passed. The test step's only failure was TestOMLXBindHostOverrideReachesDaemon, a known flake in a path this PR doesn't touch, which passed 3/3 rerun alone.

Checklist

  • Tests added/updated
  • make test passes locally
  • make lint passes locally
  • Commit messages follow conventional commits
  • All commits are signed off (git commit -s) per DCO
  • AI assistance (if any) is disclosed above, per CONTRIBUTING.md
  • Documentation updated (if user-facing change)

Miscellaneous fixes

  • The MetalNodeCapacity field comments in api/v1alpha1/metalnode_types.go described only a Mac. They now describe any host. memoryBytes is unified memory on a Mac and RAM under the agent's cgroup limit on Linux. chip is the CPU brand string on macOS and the device-tree model or cpuinfo model name on Linux. gpuCores and metalVersion are reported on macOS only. The regenerated CRD, the chart's copy and docs/site/reference/crds.md carry the new descriptions.

Assisted-by: Claude Code (Claude Opus 5.5) split this out of #2482, wrote the description and ran the checks above in my session.

DetectHostCapacity on Linux reads the chip from /proc/device-tree/model
with its trailing NUL stripped, else the first "model name" or "Model"
line in /proc/cpuinfo, else leaves it empty. It goes through the same
printable-prefix and 128-byte limit as on darwin. Memory is
NewHostMemoryProvider().TotalMemory(), so a cgroup limit below MemTotal
is what the capacity reports.

hostCapacityFromSysctl and its test move into the darwin files, and the
stub for other OSes returns an empty HostCapacity, so the sysctl parser
is not dead code on Linux.

The MetalNodeCapacity field comments are now host-neutral: memory is
unified memory on a Mac and RAM under the agent's cgroup limit on
Linux, the chip is the CPU brand string on macOS and the device-tree or
cpuinfo model name on Linux, and GPU cores and the Metal version are
reported on macOS only. The generated CRDs, the chart's CRD and the
CRD reference page carry the new descriptions.

Fixes defilantech#2518

Signed-off-by: Christian Nuss <cnuss@users.noreply.github.com>
@cnuss
cnuss requested a review from Defilan as a code owner November 13, 2026 23:54
@codecov

codecov Bot commented Nov 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.23529% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
pkg/agent/hostcapacity_linux.go 88.23% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Raspberry Pi] Report Linux host capacity on the MetalNode

1 participant