From 91998921154eb64c13bc34fa1b0695b9e00a3ee6 Mon Sep 17 00:00:00 2001 From: rcourtman Date: Fri, 7 Nov 2025 12:27:11 +0000 Subject: [PATCH] Fix Windows VM disk accumulation bug by normalizing drive letters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Related to #656 Windows guest agents can return multiple directory mountpoints (C:\, C:\Users, C:\Windows) all on the same physical drive. When the QEMU guest agent omits disk[] metadata, commit 5325ef481 falls back to using the mountpoint string as the disk identifier. This causes every Windows directory to be treated as a separate disk, accumulating to inflated totals (e.g., 1TB reported for a 250GB drive). Root cause: The fallback logic in pkg/proxmox/client.go:1585-1594 assigns fs.Disk = fs.Mountpoint when disk[] is missing. On Windows, every directory path is unique, so the deduplication guard in internal/monitoring/monitor_polling.go: 619-635 never triggers, causing all directories to be summed. Changes: - Detect Windows-style mountpoints (drive letter + colon + backslash) - Normalize to drive root when disk[] is missing (e.g., C:\Users → C:) - Preserve existing behavior for Linux/BSD and VMs with disk[] metadata - Add debug logging for synthesized Windows drive identifiers This fix maintains backward compatibility with commit 5325ef481 while preventing the Windows directory accumulation issue. LXC containers are unaffected as they use a different code path. --- pkg/proxmox/client.go | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/pkg/proxmox/client.go b/pkg/proxmox/client.go index 307784c..99cfe88 100644 --- a/pkg/proxmox/client.go +++ b/pkg/proxmox/client.go @@ -1588,8 +1588,24 @@ func (c *Client) GetVMFSInfo(ctx context.Context, node string, vmid int) ([]VMFi if fs.Mountpoint == "/" { fs.Disk = "root-filesystem" } else { - // Use mountpoint as unique identifier - fs.Disk = fs.Mountpoint + // For Windows, normalize drive letters to prevent duplicate counting + // Windows guest agent can return multiple directory entries (C:\, C:\Users, C:\Windows) + // all on the same physical drive. Without disk[] metadata, we must deduplicate by drive letter. + isWindowsDrive := len(fs.Mountpoint) >= 2 && fs.Mountpoint[1] == ':' && strings.Contains(fs.Mountpoint, "\\") + if isWindowsDrive { + // Use drive letter as identifier (e.g., "C:" for C:\, C:\Users, etc.) + driveLetter := strings.ToUpper(fs.Mountpoint[:2]) + fs.Disk = driveLetter + log.Debug(). + Str("node", node). + Int("vmid", vmid). + Str("mountpoint", fs.Mountpoint). + Str("synthesized_disk", driveLetter). + Msg("Synthesized Windows drive identifier from mountpoint") + } else { + // Use mountpoint as unique identifier for non-Windows paths + fs.Disk = fs.Mountpoint + } } } }