diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a8005c..465f23f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## v0.59.0 — report backing device + capacity for a registry-sourced drive in /disks (2026-07-01) + +Completes the `/disks` representation for a registry-sourced (raw, no-PVE-storage) drive: the agent-view +showed "—" for the device and no size bar, because the union row never populated `backing_device` or +`total_bytes`/`used_bytes` (Observe drives get those from `pvesm status`, which a raw drive has none of). + +- **`internal/localapi/disks.go` handleDisks registry union:** resolve `BackingDevice` from the fs-UUID + (`storage.ByUUIDDevicePath`) and read capacity via `statfsCapacity` (new build-tagged + `capacity_linux.go` = `syscall.Statfs` on the mount; `capacity_other.go` = no-op for dev builds). +- `go build/vet/test ./...` clean (Linux + Windows dev). Live: the registry drive now shows its device + + size in the agent-view, matching the Observe-sourced drives. + ## v0.58.0 — report GuestPath/BoundUnderParent for a registry-sourced drive in /disks (2026-07-01) Last piece of first-class raw-drive support: the `/disks` union row for a registry-sourced drive (Impl-2a diff --git a/cmd/felhom-agent/main.go b/cmd/felhom-agent/main.go index aec85d4..9dfc19f 100644 --- a/cmd/felhom-agent/main.go +++ b/cmd/felhom-agent/main.go @@ -45,7 +45,7 @@ import ( // version is the agent version. Overridable at build time with // -ldflags "-X main.version="; defaults to the in-repo CHANGELOG version. -var version = "0.58.0" +var version = "0.59.0" // runGuestHook is the PVE pre-start hook body (`felhom-agent guest-hook `). On the // pre-start phase it creates placeholder dirs for any absent bind-mount source so the guest always boots diff --git a/internal/localapi/capacity_linux.go b/internal/localapi/capacity_linux.go new file mode 100644 index 0000000..c043233 --- /dev/null +++ b/internal/localapi/capacity_linux.go @@ -0,0 +1,26 @@ +//go:build linux + +package localapi + +import "syscall" + +// statfsCapacity returns the total + used bytes of the filesystem mounted at path (Linux statvfs). A +// registry-sourced drive (no PVE storage) has no `pvesm status` usage, so /disks reads capacity here +// instead. ok=false on any error → the caller leaves the size fields zero. +func statfsCapacity(path string) (total, used int64, ok bool) { + var st syscall.Statfs_t + if err := syscall.Statfs(path, &st); err != nil { + return 0, 0, false + } + bs := int64(st.Bsize) + total = int64(st.Blocks) * bs + if total <= 0 { + return 0, 0, false + } + free := int64(st.Bfree) * bs + used = total - free + if used < 0 { + used = 0 + } + return total, used, true +} diff --git a/internal/localapi/capacity_other.go b/internal/localapi/capacity_other.go new file mode 100644 index 0000000..09455db --- /dev/null +++ b/internal/localapi/capacity_other.go @@ -0,0 +1,6 @@ +//go:build !linux + +package localapi + +// statfsCapacity is Linux-only (syscall.Statfs); on other platforms (dev builds) it reports nothing. +func statfsCapacity(string) (total, used int64, ok bool) { return 0, 0, false } diff --git a/internal/localapi/disks.go b/internal/localapi/disks.go index c7394e9..9c2c0aa 100644 --- a/internal/localapi/disks.go +++ b/internal/localapi/disks.go @@ -235,6 +235,18 @@ func (s *Server) handleDisks(w http.ResponseWriter, r *http.Request, vmid int) { di.GuestPath = gp di.BoundUnderParent = s.boundUnderParent(r.Context(), vmid, gp) } + // A registry drive has no PVE `pvesm status` snapshot, so fill backing device + capacity + // from the host directly: resolve the device by fs-UUID, and statfs the mount for size — + // else the agent-view shows "—" for the device and no size bar. + if d.UUID != "" { + if dev, err := storage.ByUUIDDevicePath(d.UUID); err == nil { + di.BackingDevice = dev + } + } + if total, used, okc := statfsCapacity(d.MountPath); okc { + di.TotalBytes, di.UsedBytes = total, used + di.UsedFraction = float64(used) / float64(total) + } out = append(out, di) } } else {