If you have a Hyper-V cluster of just a lot of VM's on a standalone Hyper-V server keeping track of all the virtual hard disks can become difficult. Eventually you will probably end up in a situation where you dont want to delete anything becaase you aren't 100% sure if its in use or not. It's like that everywhere. Trust me. Very few people have a handle on this sort of thing.
This script compares the file system of your VHDX location with the actual config file of the VM's on you hosts and gives you a handy list of any VHDX files that exsist but aren't mounted on a VM.
These can be considered orphans.
$fullFilePaths = @()
$VMpaths = @()
#first we get the file paths of all the VM's in your cluster and pop them in an array
$vmhosts = Get-ClusterNode
foreach ($vmhost in $vmhosts)
{
$VMPath = get-vm -ComputerName $vmhost | Get-VMHardDiskDrive
$VMpaths = $VMpaths + $VMPath.path
}
#Now we get the file paths of all VHDX files in your storage location(s)
$partFilePaths = (Get-ChildItem "C:\ClusterStorage\Volume1" -name *.vhdx -recurse)
foreach ($partFilePath in $partFilePaths)
{
$fullFilePath1 = "C:\ClusterStorage\Volume1\" + $partFilePath
$fullFilePaths = $fullFilePaths + $fullFilePath1
}
$partFilePaths = (Get-ChildItem "C:\ClusterStorage\Volume2" -name *.vhdx -recurse)
foreach ($partFilePath in $partFilePaths)
{
$fullFilePath2 = "C:\ClusterStorage\Volume2\" + $partFilePath
$fullFilePaths = $fullFilePaths + $fullFilePath2
}
$partFilePaths = (Get-ChildItem "C:\ClusterStorage\Volume3" -name *.vhdx -recurse)
foreach ($partFilePath in $partFilePaths)
{
$fullFilePath3 = "C:\ClusterStorage\Volume3\" + $partFilePath
$fullFilePaths = $fullFilePaths + $fullFilePath3
}
$partFilePaths = (Get-ChildItem "C:\ClusterStorage\Volume4" -name *.vhdx -recurse)
foreach ($partFilePath in $partFilePaths)
{
$fullFilePath4 = "C:\ClusterStorage\Volume4\" + $partFilePath
$fullFilePaths = $fullFilePaths + $fullFilePath4
}
$partFilePaths = (Get-ChildItem "C:\ClusterStorage\Volume5" -name *.vhdx -recurse)
foreach ($partFilePath in $partFilePaths)
{
$fullFilePath5 = "C:\ClusterStorage\Volume5\" + $partFilePath
$fullFilePaths = $fullFilePaths + $fullFilePath5
}
#Now we compare the 2 arrays. Anything that is in the Filepath array and not in the VM path array is an orphan
$Orphans = $fullFilePaths | Where {$VMpaths -NotContains $_}