Find out how much space is used / can be used by a virtual machines virtual hard disks [script]

Find out how much space is used / can be used by a virtual machines virtual hard disks [script]

  • Comments 2

After writing the script to find all virtual hard disks associated with a virtual machine – the next logical step was to answer some questions about these virtual hard disks.  The two obvious questions that I could think of were:

  • How much space is this virtual machine currently using?
  • How much space can this virtual machine use if it “goes crazy” and starts trying to write out as much data as possible?

So I modified yesterdays script to answer these questions:

# Prompt for the Hyper-V Server to use
$HyperVServer = Read-Host "Specify the Hyper-V Server to use (enter '.' for the local computer)"
 
# Prompt for the virtual machine to use
$VMName = Read-Host "Specify the name of the virtual machine"
 
# Get Storage management service
$ImgService = gwmi Msvm_ImageManagementService -namespace "root\virtualization" -computername $HyperVServer -locale MS_409
 
# Get the virtual machine object
$VM = gwmi MSVM_ComputerSystem -namespace "root\virtualization" -computername $HyperVServer -locale MS_409 | where {$_.ElementName -eq $VMName}
 
# Create an empty hashtable
$table = @{}
 
# Set size variables
$totalSize = 0
 
# Go over each of the virtual machines "system setting data" objects.  There will be a system setting data
# for each snapshot associated with the virtual machine, and one for the active virtual machine.
foreach ($VSSD in @($VM.getRelated("Msvm_VirtualSystemSettingData"))) 
  {
   # Get all the VHDs associated with the current system setting data
   $VHDs = [array]($VSSD.getRelated("Msvm_ResourceAllocationSettingData") | where {$_.ResourceType -eq 21} | where {$_.ResourceSubType -eq "Microsoft Virtual Hard Disk"})
 
   # Only continue if the system setting data actually had virtual hard disks
   if ($VHDs)
      {
      # Intialize index, and get the VHD and VHDPath for the first virtual hard disk      
      $index = 0
      $VHD = $VHDs[$index]
      $VHDPath = $VHD.Connection | select -first 1
 
      # loop through all virtual hard disks
      do      
         {
         # Get the detailed information for the current virtual hard disk
         $xml = [xml]($ImgService.GetVirtualHardDiskInfo($VHDPath)).info
      
         # Only continue if the current virtual hard disk is not in the hashtable
         if (!$table.ContainsKey($VHDPath)) 
            {
            # Store the file size for the virtual hard disk in the table - and add it to $totalSize
            $table[$VHDPath] = [uint64]($xml.Instance.Property | ?{$_.Name -eq "fileSize"}).value
            $totalSize = $totalSize + [uint64]($xml.Instance.Property | ?{$_.Name -eq "fileSize"}).value
            
            # Check to see if the current virtual hard disk has a parent virtual hard disk
            if (($xml.Instance.Property | ?{$_.Name -eq "ParentPath"}).value)
               {
               # if it does - make the parent the next virtual hard disk that we look at
               $VHDPath = ($xml.Instance.Property | ?{$_.Name -eq "ParentPath"}).value
               }
            # If the current virtual hard disk does not have a parent - just move onto the next virtual
            # hard disk in the system settings data object
            else
               {
               # Increase the index - and make sure that we have not gone past the last virtual hard disk
               $index = $index + 1
               if ($index -ne $VHDs.count)
                  {
                  # Setup new values for next time through
                  $VHD = $VHDs[$index]
                  $VHDPath = $VHD.Connection | select -first 1}
                  }
         
               }
 
         # If the current virtual hard disk is already in the hashtable - move onto the next virtual
         # hard disk in the system settings data object         
         else
            {
            # Increase the index - and make sure that we have not gone past the last virtual hard disk
            $index = $index + 1
            if ($index -ne $VHDs.count)
               {
               # Setup new values for next time through
               $VHD = $VHDs[$index]
               $VHDPath = $VHD.Connection | select -first 1
               }
            }
         }
      
      # loop until we have covered all virtual hard disks
      until ($index -eq $VHDs.count)
      }
   }
 
# Get the VSSD and VHD array for the currently active virtual machine
$activeVSSD = $VM.getRelated("Msvm_VirtualSystemSettingData") | ?{$_.SettingType -eq 3}
$activeVHDs = [array]($activeVSSD.getRelated("Msvm_ResourceAllocationSettingData") | where {$_.ResourceType -eq 21} | where {$_.ResourceSubType -eq "Microsoft Virtual Hard Disk"})
 
# Setup some blank varibles
$activeVMSize = 0
$activeVMCapacity = 0
 
# Calculate the total file size and internal capacity only for the active virtual machine
foreach ($VHD in $activeVHDs) 
  {
  $VHDPath = $VHD.Connection | select -first 1
  $xml = [xml]($ImgService.GetVirtualHardDiskInfo($VHDPath)).info
  $activeVMSize = $activeVMSize + [uint64]($xml.Instance.Property | ?{$_.Name -eq "fileSize"}).value
  $activeVMCapacity = $activeVMCapacity + [uint64]($xml.Instance.Property | ?{$_.Name -eq "MaxInternalSize"}).value
  }
 
# Do some math and formatting to get from bytes to gigagytes
$totalPossibleSize = "{0:N2}" -f (($totalSize - $activeVMSize + $activeVMCapacity) / 1073741824)
$totalSize = "{0:N2}" -f ($totalSize / 1073741824)
 
# Display the results
write-host "Total disk space used by the virtual machine:" $totalSize "GB"
write-host "Most disk space that can be used by the virtual machine:" $totalPossibleSize "GB"

This script starts by just adding up the file size of all virtual hard disks associated with the virtual machine (this is the value that is stored in $totalSize).  Then it takes this “total size” and removes the file size of the currently active disks – and replaces that with the maximum possible size of the currently active disks.  This second value (stored in $totalPossibleSize) represents the largest amount of disk space that the virtual machine could use – in its current configuration.

Cheers,
Ben

Attachment: FindVHDSize.zip
Leave a Comment
  • Please add 3 and 7 and type the answer here:
  • Post
  • One step better would be a script that would list ALL the VMs on a given Hyper-V server...  :-)

  • I agree with Robert. The total storage needed if all the VMs maxed out their disks would be great.

Page 1 of 1 (2 items)