PowerShell script used in the Windows Server 2016 TP2 Storage QoS demo at MSIgnite


This is the Windows PowerShell script I used in the Microsoft Ignite 2015 session on Storage QoS: Hyper-V Storage Performance with Storage Quality of Service. You can also find that demo video by itself at Windows Server 2016 TP2 Storage QoS: Managing with a PowerShell script.


The script is fairly straightforward, but there a few interesting points to make about what it does:

  • The script is designed to run from a separate management computer, so all Storage QoS cmdlets use the –CimSession option to point to the Scale-Out File Server.
  • There is a handy function called “Get-PolicyName” that translates a PolicyID into a PolicyName by using Get-StorageQosPolicy.
  • It shows how to filter output of Get-StorageQosFlow. It remove the default policy entries from the list and and sorts the list by VM name (InitiatorName).
  • It offers a good example of how to use Expressions to format the output of Get-StorageQosFlow.
  • It uses the $LastChange variable to later show the time passed since the QoS policies were changed with Set-StorageQosPolicy, since the Get-StorageQosFlow is an average for the last 5 minutes.


Here’s the script:

# QosDemo.ps1 – Storage QoS demo script for Microsoft Ignite 2015

Function Get-PolicyName([string] $PolicyID)
$Policy = Get-StorageQosPolicy -CimSession JOSEBDA-FS -PolicyID $PolicyID
Return $Policy.Name

$LastChange = Get-Date
$Option = "R"

While ($Option -ne "Q") {


    Write-Host -ForegroundColor Yellow "C:> Get-StorageQosFlow |”
Write-Host -ForegroundColor Yellow “FT InitiatorNodeName, InitiatorName, FilePath, MinimumIOPS, MaximumIOPS, InitiatorIOPS, InitiatorLatency, PolicyID"

    Get-StorageQosFlow -CimSession JOSEBDA-FS | ? InitiatorName -ne "" | Sort InitiatorName |
FT @{Expression={$_.InitiatorNodeName.Split(".")[0]}; Label="Node"},
@{Expression={$_.InitiatorName}; Label="VM"},
@{Expression={$_.FilePath.Split("")[4]}; Label="File"},
@{Expression={$_.MinimumIOPS}; Label="MinIOPS"},
@{Expression={$_.MaximumIOPS}; Label="MaxIOPS"},
@{Expression={$_.InitiatorIOPS}; Label="VM IOPS"},
@{Expression={[int] $_.InitiatorLatency}; Label="Latency"},
@{Expression={(Get-PolicyName $_.PolicyID)}; Label="Policy"},
PolicyID -AutoSize

    $TimeDiff = (Get-Date) - $LastChange
$Minutes = [System.Math]::Round($TimeDiff.TotalMinutes, 2)
$Seconds = [System.Math]::Round($TimeDiff.TotalSeconds, 2)

    Write-Host "IOPS and Latency are 5-minute averages. Last policy change $Seconds seconds ago ($Minutes minutes ago)."

    Write-Host -ForegroundColor Yellow "C:> Get-StorageQosPolicy | FT Name, PolicyType, MinimumIOPS, MaximumIOPS, PolicyID"
Get-StorageQosPolicy -CimSession JOSEBDA-FS | FT Name, PolicyType, MinimumIOPS, MaximumIOPS, PolicyID -AutoSize

    Write-Host -NoNewline "Command: Quit, Refresh, Zero, Low, High: "
$Option = Read-Host
$Option = $Option.ToUpper()[0]

    Switch ($Option) {

    "Z" {
Set-StorageQosPolicy -CimSession JOSEBDA-FS -Name SilverVM -MinimumIops 0 -MaximumIops 0
Set-StorageQosPolicy -CimSession JOSEBDA-FS -Name GoldVM -MinimumIops 0 -MaximumIops 0
$LastChange = Get-Date

    "L" {
Set-StorageQosPolicy -CimSession JOSEBDA-FS -Name SilverVM -MinimumIops 200 -MaximumIops 500
Set-StorageQosPolicy -CimSession JOSEBDA-FS -Name GoldVM -MinimumIops 500 -MaximumIops 1000
$LastChange = Get-Date

    "H" {
Set-StorageQosPolicy -CimSession JOSEBDA-FS -Name SilverVM -MinimumIops 500 -MaximumIops 1000
Set-StorageQosPolicy -CimSession JOSEBDA-FS -Name GoldVM -MinimumIops 1000 -MaximumIops 5000
$LastChange = Get-Date

    } #end switch

} #end while