Script for calculating the space occupied by Hyper-V virtual machines

    Recently, I discovered a discrepancy in the data on the disk space occupied by virtual machines displayed in the System Center Virtual Machine Manager console with the data obtained using Get-SCVirtualMachine and decided to find out what was the matter. I got the data on the occupied disk space using the popular Get-SCVirtualMachine cmdlet . To do this, I used a loop in which I sorted 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 constructions are replicated many times on technet forums and in all kinds of blogs , so I had no doubts about their correctness. After detecting the discrepancies, I added the output of debugging information to the loop: $ vm.VirtualHardDisks.Size for each VM and its name. The output of the modified script showed that for some VMs the volume was 0. I was sure that $ vm.VirtualHardDisks.Size shows the amount, but this turned out to be wrong - the command returned two numbers (for two vhd). Obviously, powershell could not divide the array into 1TB, so it returned 0:

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

    I don’t even know in this case, I would like to say thank you to the flexibility that I’m not ERROR , or to say thank you for such a disservice. A lot of mistakes are forgiving.

    Then I decided to cycle through all the disks and changed the original design to a slightly more complex, but more correct one:

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

    Excellent! Now VMs with two or more virtual disks were considered correctly, BUT! The amount for all virtual machines still did not match, although it approached the console.
    I drove my script both this way and that. I looked, compared and saw that for some VMs the amount coincides to a penny, and for some there is a significant discrepancy. He got into properties, and there ... snapshots! We didn’t count them.
    Then google again, again dubious scripts right down to very exotic methods with searching for files by mask.
    Hidden text
    The method with the search * avhdx , at the same time, is fundamentally wrong, since the current data is written in avhd, and the snapshot lies in vhdx. However, I met him with other authors

    I had to write myself. At first I tried to select all the disks using Get-SCVirtualHardDisk without resorting to enumerating virtual machines, however I managed to list only those disks that I received using $ vm.VirtualHardDisks . Therefore, I had to dig a little deeper. The virtual machine has a VMCheckpoints property , which lists all the breakpoints. From this property, you can actually get the VMSnapshot object (I still don’t understand how Snapshot differs from Checkpoint in terms of SCVMM). This object also has a VirtualDiskDrives property , but for some reason it does not have a Size property , so I had to insert a crutch: from VirtualDiskDriveswe take the VirtualHardDiskID property and use this ID to do 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 slight discrepancy still remained, and a colleague told me to count also the service .bin and .vsv files , which store service information like a RAM dump. Once again, looking at the list of available virtual machine parameters, I came across ... $ vm.TotalSize . Who would have thought that all the work for me has already been done and that you just need to sum 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 the snapshot data obtained by such work from the script.
    Filled here gallery.technet.microsoft.com/scriptcenter/Script-to-calculate-the-36a9314f
    Mathematicians are joking


    Also popular now: