Table of Contents
Hyper-V Disks Load and Performance
Summary: How to measure Hyper-V 2 disk load and performance.
Date: Around 2020
Refactor: 1 March 2025: Checked links and formatting.
For a project I need how much bandwidth was required considering hoe much data was written to disk (All VMs were to be replicated to a different location). As I soon find out is that hyper-V does not keep this kind of data stored somewhere as vCenter does in a vSphere environment. Since Hyper-V 2 there are a few commands available to see the disk load end measure this. However, I found that the commands are unreliable, and especially in a Virtual Machine Manager environment where you run into name collision problems between VMM and Hyper-V commandlets (note that you sometimes can prefix commands like Hyper-V\get-VM).
The script
# Script Variables $scriptname = [System.IO.Path]::GetFilenameWithoutExtension($MyInvocation.MyCommand.Path.ToString()) $scriptlocation = Split-Path $myinvocation.mycommand.path # Start transcript for full logging capabilities start-transcript -path "$scriptlocation\logtranscript.txt" # Mail settings #$weekdate = Get-Date -uformat %V #$weekdate = get-date -Format yyyyMMdd-HHmm $mailserver = "smtpserver" $toemail = "sjoerd_getshifting.com" $ccmail = "sjoerd_getshifting.com" $fromemail = "$scriptname_getshifting.com" #$monthreport = "$scriptlocation\$weekdate-$scriptname.csv" # Run this script from a server with Virtual Machine Manager installed as well as the RSAT tools $vmmserver = "vmm.getshifting.local" Get-SCVMMServer $vmmserver # Because the VMM server has both Hyper-V and VMM commandlets installed, and these commandlets can have the same name (or an alias), use all Hyper-V commands as 'Hyper-V\commandlet' ## For example: Hyper-V\Get-VM Function Send-Email ($subject, $info){ # Send high prio email without attachment if ($priority -eq "high" -and $monthreport -eq $null){ Send-MailMessage -To $toemail -From $fromemail -cc $ccmail -SmtpServer $mailserver -Subject $subject -Body $info -BodyAsHtml -Priority High } # Send mail without attachment (some Controls do not need attachments) elseif ($monthreport -eq $null){ Send-MailMessage -To $toemail -From $fromemail -cc $ccmail -SmtpServer $mailserver -Subject $subject -Body $info -BodyAsHtml } else{ Send-MailMessage -To $toemail -From $fromemail -cc $ccmail -SmtpServer $mailserver -Subject $subject -Body $info -BodyAsHtml -Attachments "$monthreport" } } Function Show-Menu{ param ( [string]$Title = 'Hyper-V Performance' ) #Clear-Host Write-Host "================ $Title ================" Write-Host "1: Press '1' to enable and reset resourcemonitoring in cluster1 (PRD)" Write-Host "2: Press '2' to collect disk resourcemonitoring in cluster1 (PRD)" Write-Host "3: Press '3' to enable and reset resourcemonitoring in cluster2 (Test)" Write-Host "4: Press '4' to collect disk resourcemonitoring in cluster2 (Test)" Write-Host " " Write-Host "5: Press '5' to disable resourcemonitoring in cluster1 and cluster2" Write-Host " " Write-Host "The report will be send to $toemail " Write-Host "Q: Press 'Q' to quit." } Function Enable-Metering{ foreach($node in $nodes) { Write-host "Node: $node" #Set-VMHost -ComputerName $node -ResourceMeteringSaveInterval 24:00:00 Set-VMHost -ComputerName $node -ResourceMeteringSaveInterval 5:00:00 Get-VMHost -ComputerName $node | select ResourceMeteringSaveInterval $vms = Hyper-V\Get-VM -ComputerName $node foreach ($vm in $vms){ $name = $vm.name write-host "VMname: $name" $vm | Enable-VMResourceMetering $vm | Reset-VMResourceMetering } } } Function Disable-Metering{ foreach($node in $nodes) { Write-host "Node: $node" $vms = Hyper-V\Get-VM -ComputerName $node foreach ($vm in $vms){ $name = $vm.name write-host "VMname: $name" $vm | Disable-VMResourceMetering } } } Function Collect-Metering{ $allvms = @() foreach($node in $nodes) { Write-host "Node: $node" $vms = Hyper-V\Get-VM -ComputerName $node $measures = Hyper-V\Get-VM -ComputerName $node | Measure-VM | select vmname,meteringduration,AggregatedAverageNormalizedIOPS,AggregatedDiskDataRead,AggregatedDiskDataWritten,AggregatedNormalizedIOCount foreach ($vm in $vms){ $vminfo = "" | select Name,State,MonitoringEnabled,MeteringDuration,AggregatedAverageNormalizedIOPS,AggregatedDiskDataRead,AggregatedDiskDataWritten,AggregatedNormalizedIOCount #write-host "VM: $vm" #$vmobject = Hyper-V\Get-VM -ComputerName $node | where {$_.Name -like "*$vm*"} #write-host "VMobject: $vmobject" $name = $vm.name write-host "VMname: $name" $vminfo.name = $name $vminfo.state = $vm.state $vminfo.monitoringenabled = $vm.ResourceMeteringEnabled $measure = $measures | where {$_.vmname -eq $name} #foreach ($measure in $measures) $vminfo.meteringduration = $measure.meteringduration $vminfo.AggregatedAverageNormalizedIOPS = $measure.AggregatedAverageNormalizedIOPS $vminfo.AggregatedDiskDataRead = $measure.AggregatedDiskDataRead $vminfo.AggregatedDiskDataWritten = $measure.AggregatedDiskDataWritten $vminfo.AggregatedNormalizedIOCount = $measure.AggregatedNormalizedIOCount $allvms += $vminfo } } $allvms | export-csv -NoTypeInformation $monthreport $subject = $Cluster + " Hyper-V Performance Report" $body = "See the attached report" Send-Email $subject $body } # Start menu do { Show-Menu $selection = Read-Host "Please make a selection" switch ($selection) { '1' { $cluster = "cluster1.prd.shift.com" $nodes = Get-ClusterNode -cluster $cluster Enable-Metering } '2' { $cluster = "cluster1.prd.shift.com" $nodes = Get-ClusterNode -cluster $cluster $weekdate = get-date -Format yyyyMMdd-HHmm $monthreport = "$scriptlocation\$weekdate-$scriptname.csv" Collect-Metering } '3' { $cluster = "cluster2.test.shift.com" $nodes = Get-ClusterNode -cluster $cluster Enable-Metering } '4' { $cluster = "ccluster2.test.shift.com" $nodes = Get-ClusterNode -cluster $cluster $weekdate = get-date -Format yyyyMMdd-HHmm $monthreport = "$scriptlocation\$weekdate-$scriptname.csv" Collect-Metering } '5' { $cluster = "cluster1.prd.shift.com" $nodes = Get-ClusterNode -cluster $cluster Disable-Metering $cluster = "cluster2.test.shift.com" $nodes = Get-ClusterNode -cluster $cluster Disable-Metering } } pause } until ($selection -eq 'q') # Stop transcript stop-transcript
Resources
- Start and collect resourcemonitoring for all VMs in Hyper-V Cluster