fix: prefer status-mem over status-freemem for VM memory calculation

Proxmox's FreeMem field reports free memory relative to the balloon's
guest-visible total (total_mem), not relative to MaxMem. When ballooning
is active and the VM's memory has been reduced, subtracting FreeMem from
MaxMem produces wildly inflated usage (e.g. 97% when actual usage is 20%).

Proxmox's Mem field is already calculated as (total_mem - free_mem),
giving the correct used bytes regardless of balloon state. Swap the
priority so Mem is checked before FreeMem.

Related to #1185
This commit is contained in:
rcourtman 2026-02-04 12:08:33 +00:00
parent 8313d66e64
commit 902bdd92c2
2 changed files with 20 additions and 6 deletions

View file

@ -6647,12 +6647,19 @@ func (m *Monitor) pollVMsAndContainersEfficient(ctx context.Context, instanceNam
memAvailable = memTotal
}
memUsed = memTotal - memAvailable
case detailedStatus.Mem > 0:
// Prefer Mem over FreeMem: Proxmox calculates Mem as
// (total_mem - free_mem) using the balloon's guest-visible
// total, which is correct even when ballooning is active.
// FreeMem is relative to the balloon allocation (not MaxMem),
// so subtracting it from MaxMem produces wildly inflated
// usage when the balloon has reduced the VM's memory.
// Refs: #1185
memUsed = detailedStatus.Mem
memorySource = "status-mem"
case detailedStatus.FreeMem > 0 && memTotal >= detailedStatus.FreeMem:
memUsed = memTotal - detailedStatus.FreeMem
memorySource = "status-freemem"
case detailedStatus.Mem > 0:
memUsed = detailedStatus.Mem
memorySource = "status-mem"
}
if memUsed > memTotal {
memUsed = memTotal

View file

@ -364,12 +364,19 @@ func (m *Monitor) pollVMsWithNodes(ctx context.Context, instanceName string, clu
memAvailable = memTotal
}
memUsed = memTotal - memAvailable
case vmStatus.Mem > 0:
// Prefer Mem over FreeMem: Proxmox calculates Mem as
// (total_mem - free_mem) using the balloon's guest-visible
// total, which is correct even when ballooning is active.
// FreeMem is relative to the balloon allocation (not MaxMem),
// so subtracting it from MaxMem produces wildly inflated
// usage when the balloon has reduced the VM's memory.
// Refs: #1185
memUsed = vmStatus.Mem
memorySource = "status-mem"
case vmStatus.FreeMem > 0:
memUsed = memTotal - vmStatus.FreeMem
memorySource = "status-freemem"
case vmStatus.Mem > 0:
memUsed = vmStatus.Mem
memorySource = "status-mem"
default:
memUsed = 0
memorySource = "status-unavailable"