If a Hyper-V virtual machine has a checkpoint, then it is that checkpoint delta file that is mounted to the VM. When SolarWinds checks the disk size of these VMs, it most often reports a size of 0 GB, because it's only considering this checkpoint delta file. SolarWinds should be able to query the Hyper-V server for the entire chain and report that.
Here is a PowerShell script I have that runs on my Hyper-V server; this script gets the full chain size from Hyper-V, then uploads it so my SolarWinds server as a custom property, and I use the custom property to report the VM size.
This script also has to sum VMs with duplicate names together as a single VM, because SolarWinds gets confused about duplicate named VMs and actually adds them together and double reports them, so this script fixes that.
I don't know why the format is all wonky.
function Get-VHDChainSize {
param([string]$Path)
$total = 0
$current = $Path
while ($current) {
$vhd = Get-VHD -Path $current -ErrorAction SilentlyContinue
if ($vhd) {
$total += $vhd.FileSize
$current = $vhd.ParentPath
} else {
break
}
}
return $total
}
Find all replica VMs
$vms = Get-VM -Name "replica" -ErrorAction SilentlyContinue
$results = @()
Group by VM name and sum GB
$groupedVms = $vms | Group-Object Name
foreach ($group in $groupedVms) {
$vmName = $group.Name
$totalBytes = 0
foreach ($vm in $group.Group) {
$drives = $vm | Get-VMHardDiskDrive -ErrorAction SilentlyContinue
foreach ($drive in $drives) {
if ($drive.Path -and (Test-Path $drive.Path)) {
$totalBytes += Get-VHDChainSize -Path $drive.Path
}
}
}
$gb = if ($totalBytes -gt 0) { [math]::Round($totalBytes / 1GB, 1) } else { 0 }
if ($gb -eq 0) {
Write-Host "Skipped $vmName → 0 GB (no disks attached to any instance)"
continue
}
$results += [pscustomobject]@{
VMName = $vmName
TotalGB = $gb
Timestamp = Get-Date
}
# Update Orion - update ALL matching records with summed GB
$query = "SELECT Uri FROM Orion.VIM.VirtualMachines WHERE Name = '$vmName'"
$uris = Get-SwisData $swis $query
if ($uris.Count -eq 0) {
Write-Warning "VM $vmName not found in Orion"
} else {
foreach ($uri in $uris) {
if ($uri -and $uri -ne "") {
$customUri = "$uri/CustomProperties"
try {
Set-SwisObject $swis $customUri -Properties @{ $CustomPropertyName = $gb }
Write-Host "Updated $vmName → $gb GB (Uri: $customUri)"
} catch {
Write-Error "Failed to update $vmName at $customUri : $($_.Exception.Message)"
}
} else {
Write-Warning "Empty/invalid Uri for $vmName - skipping"
}
}
if ($uris.Count -gt 1) {
Write-Warning "Duplicates found for $vmName ($($uris.Count) records) - all updated; clean stale via Veeam"
}
}
}