📜 ⬆️ ⬇️

Script to calculate the space occupied by Hyper-V virtual machines

Recently, I discovered a discrepancy in the data about the virtual disk space occupied by the virtual machines displayed in the System Center Virtual Machine Manager console with data obtained using Get-SCVirtualMachine and decided to find out what was wrong. I obtained the data on disk space using the popular Get-SCVirtualMachine cmdlet . To do this, I used a cycle in which I went through all the virtual machines and accumulated the size of their disks in a variable:

$totalhdd = 0 $vms = Get-SCVirtualMachine #| where {$_.Name -eq "VM Name"} #   foreach ($vm in $vms) { $totalhdd += ($vm.VirtualHardDisks.Size -as [double]) / 1TB} } 

Similar designs are replicated many times on the technet forums and in all sorts of blogs , so I had no doubts about their correctness. After detecting discrepancies, I added debug information to the loop: $ vm.VirtualHardDisks.Size for each VM and its name. The output of the modified script showed that some VMs had a volume of 0. I was sure that $ vm.VirtualHardDisks.Size shows the sum, but this turned out to be wrong - the team returned two numbers (for two vhd). Obviously, powershell was not able to divide the array into 1TB, and therefore gave 0:

 PS D:\Scripts\IT_git> $vm.VirtualHardDisks.Size 3547332608 4194304 PS D:\Scripts\IT_git> ($vm.VirtualHardDisks.Size -as [double]) / 1TB 0 

I do not even know in this case, to say thanks to the flexibility of the version for not being ERROR , or to say to him anti-thank you for such a disservice. Forgives a lot of mistakes.
')
Then I decided to loop through all the disks and changed the original construction to a slightly more complicated, but also more correct:

 foreach ($vm in $vms) { $vhds = $vm.VirtualHardDisks foreach ($vhd in $vhds) { $totalhdd += ($vhd.Size -as [double]) / 1TB} } 

Fine! Now VMs with two or more virtual disks were counted correctly, BUT! The amount of all the virtuals still did not match, although it was close to the readings of the console.
I drove my script and so on. I looked, aligned, and saw that for some VMs the amount coincides to a penny, and for some there is a significant discrepancy. Climbed into the properties, and there ... snapshots! We didn’t count them.
Then again, Google, again questionable scripts, down to very exotic methods with file search by mask.
Hidden text
The method with the search * avhdx , at the same time, is fundamentally wrong, since the current data is written to avhd, and the snapshot is in vhdx. However, I met him with other authors.

I had to write myself. At first, I tried to select all disks using Get-SCVirtualHardDisk without going through virtual machines, but I managed to list only those disks that I received using $ vm.VirtualHardDisks . So I had to dig a little deeper. The virtual machine has a VMCheckpoints property, which lists all control points. From this property, you can get, in fact, the VMSnapshot object (I did not understand how Snapshot differs from Checkpoint in terms of SCVMM). This object also has the VirtualDiskDrives property, but for some reason it does not have the Size property, so we had to insert a crutch: from VirtualDiskDrives we take the VirtualHardDiskID property and with this ID we make Get-SCVirtualHardDisk :

 ... # Snapshots search foreach ($vmc in $vm.VMCheckpoints) { foreach ($vdd in $vmc.VirtualDiskDrives) { $vhd = Get-SCVirtualHardDisk -ID $vdd.VirtualHardDiskID $snapshotshdd += ($vhd.Size -as [double]) / 1TB } } ... 

After that, a small discrepancy still remained, and a colleague prompted me to also calculate the service files .bin and .vsv , in which the service information is stored like memory dump. Once again, looking through the list of available virtual machine options, I came across ... $ vm.TotalSize . Who would have thought that all the work for me had already been done and you just need to sum up this parameter for all virtual machines!
So, through thorns, crutches and rakes, I found a really beautiful solution:

 $totalsize = 0 $vms = Get-SCVirtualMachine #| where {$_.Name -eq "VM Name"} #   foreach ($vm in $vms) { $totalsize += ($vm.TotalSize -as [double]) / 1TB } 

It was so funny that I decided not to delete snapshot data obtained from such a script from the script.
Filled gallery.technet.microsoft.com/scriptcenter/Script-to-calculate-the-36a9314f here .
Maths are joking

Source: https://habr.com/ru/post/266097/


All Articles