Last active
August 10, 2016 14:28
-
-
Save vMarkusK/24e94c6daf77b38dec7e to your computer and use it in GitHub Desktop.
Reports vSphere VM disks related to Datastores and Max IOPs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.NOTES | |
=========================================================================== | |
Created by: Markus Kraus | |
Twitter: @vMarkus_K | |
Private Blog: mycloudrevolution.com | |
Organization: Vater Operations GmbH | |
Organization Site: vater-cloud.de | |
=========================================================================== | |
Changelog: | |
2016.03 ver 1.0 Base Release | |
2016.03 ver 1.1 Added VM Limit-Exclusion by Name | |
2016.04 ver 1.2 Added Disk Limit-Exclusion for "Independent Persistent" Disks | |
2016.08 ver 1.3 Added Format and Misconfiguration Report | |
=========================================================================== | |
.DESCRIPTION | |
This will Create a IOPS Report | |
#Requires -Modules VMware.VimAutomation.Core, @{ModuleName="VMware.VimAutomation.Core";ModuleVersion="6.3.0.0"} | |
#> | |
#region: Load VMware Snapin | |
if (!(Get-PSSnapin -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue)) { | |
if (!(Add-PSSnapin -PassThru VMware.VimAutomation.Core)) { | |
# Error out if loading fails | |
Write-Error "`nERROR: Cannot load the VMware Snapin. Is the PowerCLI installed?" | |
Exit | |
} | |
} | |
#endregion | |
#region: Global Definitions | |
$VIServer = "your-vCenter.lan.local" | |
[int]$TimeRange = "-10080" ## -10080 is one Week | |
[int]$B_Limit = "250" | |
[int]$S_Limit = "1000" | |
[int]$G_Limit = "-1" | |
$Unlimited = "VEEAM*||MON*|" | |
$entity = "Cluster" ## Cluster or Folder | |
$FolderName = "myFolder" | |
$ClusterName = @("Cluster01","Cluster02") | |
#endregion | |
#region: vCenter Connection | |
Write-Output "Starting to Process vCenter Connection to $VIServer ..." | |
$OpenConnection = $global:DefaultVIServers | where { $_.Name -eq $VIServer } | |
if($OpenConnection.IsConnected) { | |
Write-Output "vCenter is Already Connected..." | |
$VIConnection = $OpenConnection | |
} else { | |
Write-Output "Connecting vCenter..." | |
$VIConnection = Connect-VIServer -Server $VIServer | |
} | |
if (-not $VIConnection.IsConnected) { | |
Write-Error "`nError: vCenter Connection Failed" | |
Exit | |
} | |
#endregion | |
#region: Creating VM Array | |
Write-Output "Starting to Create VM Array by Entity $entity..." | |
if ($entity -eq "Folder") { | |
$VMs = get-folder -Name $FolderName | Get-VM | where {$_.PowerState -eq "PoweredOn" -and ($_ | Get-HardDisk).count -gt 0 -and ($_ | Get-HardDisk).ExtensionData.Controllerkey -ne 200} | |
} | |
elseif ($entity -eq "Cluster") { | |
$VMs = get-Cluster -Name $ClusterName | Get-VM | where {$_.PowerState -eq "PoweredOn" -and ($_ | Get-HardDisk).count -gt 0 -and ($_ | Get-HardDisk).ExtensionData.Controllerkey -ne 200} | |
} | |
else { | |
Write-Error "Error: No correct Entity Choosen" | |
Exit | |
} | |
#endregion | |
#region: Creating Metrics | |
Write-Output "Starting to Create Metrics..." | |
$metrics = "virtualDisk.numberReadAveraged.average","virtualDisk.numberWriteAveraged.average" | |
$start = (Get-Date).AddMinutes($TimeRange) | |
$stats = Get-Stat -Stat $metrics -Entity $vms -Start $start | |
#endregion | |
#region: Creating HD-Tab | |
Write-Output "Starting to Create HD-Tab..." | |
$hdTab = @{} | |
foreach($hd in (Get-Harddisk -VM $vms)){ | |
$controllerKey = $hd.Extensiondata.ControllerKey | |
$controller = $hd.Parent.Extensiondata.Config.Hardware.Device | where{$_.Key -eq $controllerKey} | |
$hdTab[$hd.Parent.Name + "/scsi" + $controller.BusNumber + ":" + $hd.Extensiondata.UnitNumber] = $hd.FileName.Split(']')[0].TrimStart('[') | |
} | |
#endregion | |
#region: Creating Reports | |
Write-Output "Starting to Process IOPS Report..." | |
$reportPerf = @() | |
$reportPerf = $stats | Group-Object -Property {$_.Entity.Name},Instance | %{ | |
New-Object PSObject -Property @{ | |
VM = $_.Values[0] | |
Disk = $_.Values[1] | |
IOPSMax = ($_.Group | ` | |
Group-Object -Property Timestamp | ` | |
%{$_.Group[0].Value + $_.Group[1].Value} | ` | |
Measure-Object -Maximum).Maximum | |
Datastore = $hdTab[$_.Values[0] + "/"+ $_.Values[1]] | |
} | |
} | |
Write-Output "Starting to Process VM Report..." | |
$report = @() | |
foreach ($Vm in $Vms) { | |
$VmHdds = Get-HardDisk -VM $Vm | select Name, ExtensionData, Filename, CapacityKB | |
foreach ($VmHdd in $VmHdds) { | |
$row = "" | select VmName, ScsiID, Datastore, Tier, CapacityGB, CurrentIOLimit, PlannedIOLimit, IOLimitCorrect, MaxIOPS, HitPlannedIOLimit | |
$row.VmName = $Vm.Name | |
$row.ScsiID = $([string]$VmHdd.extensiondata.controllerkey).substring(3,1) +":"+ $([string]$VmHdd.extensiondata.unitnumber) | |
$row.Datastore = $($VmHdd.Filename.TrimStart("[")).split("]")[0] | |
$row.Tier = $row.Datastore.Split("-")[3] | |
switch ($row.Tier) { | |
"S" {$row.PlannedIOLimit = $S_Limit} | |
"B" {$row.PlannedIOLimit = $B_Limit} | |
"G" {$row.PlannedIOLimit = $G_Limit} | |
default {$row.PlannedIOLimit = "Invalid DS name or tier identifier"} | |
} | |
if ($row.VmName -match $Unlimited) {$row.PlannedIOLimit = -1} | |
elseif ($VmHdd.ExtensionData.Backing.DiskMode -eq "independent_persistent") {$row.PlannedIOLimit = -1} | |
$row.CapacityGB = [Math]::round(($VmHdd.capacitykb / 1024 / 1024),2) | |
$row.CurrentIOlimit = $VmHdd.ExtensionData.StorageIOAllocation.limit | |
if ($row.CurrentIOLimit -eq -1 -and $row.PlannedIOLimit -ne -1 -and $row.VmName -notmatch $Unlimited) {$row.IOLimitCorrect = "No IO Limit Set"} | |
elseif ($row.VmName -match $Unlimited) {$row.IOLimitCorrect = "Fixed Unlimited"} | |
elseif ($VmHdd.ExtensionData.Backing.DiskMode -eq "independent_persistent") {$row.IOLimitCorrect = "Fixed Unlimited"} | |
elseif ($row.CurrentIOLimit -gt $row.PlannedIOLimit) {$row.IOLimitCorrect = "Too High"} | |
elseif ($row.CurrentIOLimit -lt $row.PlannedIOLimit) {$row.IOLimitCorrect = "Too Low"} | |
else {$row.IOLimitCorrect = "Just Right"} | |
$row.MaxIOPS = ($reportPerf | where {$_.VM -eq $row.VmName -and $_.Disk -eq "scsi" + $row.ScsiID}).IOPSMax | |
if ($row.MaxIOPS -ge $row.PlannedIOLimit -and $row.PlannedIOLimit -ne "-1" ) {$row.HitPlannedIOLimit = "YES"} | |
else {$row.HitPlannedIOLimit = "NO"} | |
$report += $row | |
### Uncomment the following Lines and this script will set the IO Limit for VMDKs during execution | |
<# if ($row.IOLimitCorrect -ne "Just Right") { | |
$VMDisk = $VM | Get-HardDisk | where {$_.Name -eq $VmHdd.Name} | |
if ($VM.Name -match $Unlimited) { | |
Write-Output "VM Limit Exclusion Found!" | |
if ($VMDisk.ExtensionData.StorageIOAllocation.limit -ne -1) { | |
Write-Output " Disk IOPS Limit needs to removed..." | |
$Vm | Get-VMResourceConfiguration | Set-VMResourceConfiguration -Disk $VMDisk -DiskLimitIOPerSecond "-1" | |
} | |
else { | |
Write-Output " Disk IOPS Limit already unset..." | |
} | |
} | |
elseif ($VMDisk.Persistence -eq "independentpersistent" ) { | |
Write-Warning "`nWARNING: RAW Device Found!" | |
if ($VMDisk.ExtensionData.StorageIOAllocation.limit -ne -1) { | |
Write-Output " Disk IOPS Limit needs to removed..." | |
$Vm | Get-VMResourceConfiguration | Set-VMResourceConfiguration -Disk $VMDisk -DiskLimitIOPerSecond "-1" | |
} | |
else { | |
Write-Output " Disk IOPS Limit already unset..." | |
} | |
} | |
else { | |
Write-Output "Disk IOPS Limit needs to be set..." | |
$Vm | Get-VMResourceConfiguration | Set-VMResourceConfiguration -Disk $VMDisk -DiskLimitIOPerSecond $row.PlannedIOLimit | |
} | |
} ### Uncomment until here | |
#> | |
} | |
} | |
$VMsHit = @() | |
$VMsHit = ($Report | where {$_.HitPlannedIOLimit -eq "YES"}).VmName | |
$VMsMisC = @() | |
$VMsMisC = ($Report | where {$_.CurrentIOLimit -ne $_.PlannedIOLimit}).VmName | |
$reportHIT = @() | |
foreach ($VMHit in $VMsHit) { | |
$reportHIT += $report | where {$_.VmName -like $VMHit} | |
} | |
$reportMisC = @() | |
foreach ($VMMisC in $VMsMisC) { | |
$reportMisC += $report | where {$_.VmName -like $VMMisC} | |
} | |
Write-Output "`nReport of VMs with possible violation:" | |
$reportHIT | ft -AutoSize | |
Write-Output "`nReport of VMs with Misconfiguration:" | |
$reportMisC | ft -AutoSize | |
Write-Output "`nReport of all VMs:" | |
$Report | ft -AutoSize | |
#endregion |
Author
vMarkusK
commented
Aug 10, 2016
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment