mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-10 02:25:56 +00:00
Apply agent LXC filesystem data on the cluster/resources poll path
The host agent's node-local pct df inventory was only applied by the per-node container poll fallback. Cluster instances are served by the efficient cluster/resources path, which never called the enrichment, so installs on that path showed rootfs-only container filesystems (and, since the config-mount restoration, config-listed mounts with unknown usage) no matter how healthy the linked agent was. Reported on #1477 after the reporter installed agents specifically to get per-mount usage. Reproduced end to end against a live PVE cluster: the agent shipped the full inventory, the server linked the agent and populated the filesystem cache every report, and the poll path never read it. With the enrichment applied after metadata enrichment, mirroring the per-node path's ordering, the same rig surfaces real per-mount usage. Refs #1477 Contract-Neutral: behavioral fix: cluster/resources poll path now applies agent pct df enrichment like the per-node path (#1477), no public contract delta
This commit is contained in:
@@ -179,6 +179,12 @@ func (m *Monitor) buildContainerFromClusterResource(
|
||||
}
|
||||
|
||||
m.enrichContainerMetadata(ctx, client, instanceName, res.Node, &container, statusSnapshot)
|
||||
// The per-node fallback path applies node-local pct df data after metadata
|
||||
// enrichment (monitor_polling_containers.go); the efficient cluster/resources
|
||||
// path must do the same or installs served by it never surface the host
|
||||
// agent's per-mount usage and fall back to config-listed mounts with
|
||||
// unknown usage (#1477).
|
||||
m.enrichContainerWithAgentLXCFilesystems(instanceName, res.Node, &container, sampleTime)
|
||||
|
||||
// For non-running containers, zero out resource usage metrics to prevent false alerts.
|
||||
// Proxmox may report stale or residual metrics for stopped containers.
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/rcourtman/pulse-go-rewrite/internal/models"
|
||||
agentshost "github.com/rcourtman/pulse-go-rewrite/pkg/agents/host"
|
||||
"github.com/rcourtman/pulse-go-rewrite/pkg/proxmox"
|
||||
)
|
||||
|
||||
@@ -393,3 +394,69 @@ func TestIssue1477ConfigOnlyMountsSurviveIntoContainerDisks(t *testing.T) {
|
||||
t.Fatalf("config-only mount must keep device and mp key, got %+v", archive)
|
||||
}
|
||||
}
|
||||
|
||||
// The efficient cluster/resources path must apply the host agent's node-local
|
||||
// pct df data the same way the per-node fallback path does. Before the #1477
|
||||
// fix it skipped that enrichment entirely, so cluster-served installs never
|
||||
// surfaced per-mount usage regardless of a healthy linked agent.
|
||||
func TestBuildContainerFromClusterResource_AppliesAgentLXCFilesystems(t *testing.T) {
|
||||
monitor := newTestMonitor(t)
|
||||
monitor.state.UpdateNodesForInstance("cluster-a", []models.Node{{
|
||||
ID: "cluster-a-pve-a",
|
||||
Name: "pve-a",
|
||||
Instance: "cluster-a",
|
||||
Status: "online",
|
||||
}})
|
||||
|
||||
now := time.Now()
|
||||
monitor.applyAgentLXCFilesystems("cluster-a-pve-a", "agent-1", &agentshost.ProxmoxLXCInventory{
|
||||
Containers: []agentshost.ProxmoxLXCContainer{{
|
||||
VMID: 202,
|
||||
Name: "cache-ct",
|
||||
Disks: []agentshost.Disk{
|
||||
{Device: "local:202/vm-202-disk-0.raw", Mountpoint: "/", Type: "rootfs", TotalBytes: 32 << 30, UsedBytes: 8 << 30, FreeBytes: 24 << 30, Usage: 25},
|
||||
{Device: "/mnt/tank/cache", Mountpoint: "/data", Type: "mp0", TotalBytes: 100 << 30, UsedBytes: 50 << 30, FreeBytes: 50 << 30, Usage: 50},
|
||||
},
|
||||
}},
|
||||
CollectedAt: now.UTC(),
|
||||
}, now, 30)
|
||||
|
||||
client := &stubPVEClientLXCStatus{
|
||||
containerStatus: &proxmox.Container{Status: "running"},
|
||||
}
|
||||
resource := proxmox.ClusterResource{
|
||||
Type: "lxc",
|
||||
Node: "pve-a",
|
||||
Name: "cache-ct",
|
||||
Status: "running",
|
||||
VMID: 202,
|
||||
MaxCPU: 2,
|
||||
MaxMem: 4096,
|
||||
Mem: 2048,
|
||||
MaxDisk: 32 << 30,
|
||||
Disk: 8 << 30,
|
||||
}
|
||||
|
||||
container, _, _, _, ok := monitor.buildContainerFromClusterResource(
|
||||
context.Background(),
|
||||
"cluster-a",
|
||||
resource,
|
||||
client,
|
||||
map[int]bool{},
|
||||
)
|
||||
if !ok {
|
||||
t.Fatal("expected container to be built")
|
||||
}
|
||||
if len(container.Disks) != 2 {
|
||||
t.Fatalf("expected 2 disks from agent pct df enrichment, got %d: %+v", len(container.Disks), container.Disks)
|
||||
}
|
||||
var dataMount *models.Disk
|
||||
for i := range container.Disks {
|
||||
if container.Disks[i].Mountpoint == "/data" {
|
||||
dataMount = &container.Disks[i]
|
||||
}
|
||||
}
|
||||
if dataMount == nil || dataMount.Total != 100<<30 || dataMount.Used != 50<<30 {
|
||||
t.Fatalf("expected /data mount with real usage from agent data, got %+v", container.Disks)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user