Hi,
I have been tasked to create utilisation report of all the esxi clusters based on cpu ready, cpu usage and memory usage. So I am using the following script to create the utilisation report for each cluster.
Could anyone please advise if I have made any mistake in calculation while measuring the utilisation based on cpu ready, cpu usage and memory usage or kindly advise if there is any better way to do this
Import-Module VMware.VimAutomation.Core
$cwdpath = Split-Path -Parent $MyInvocation.MyCommand.Path
$List = $cwdpath + "\VCList.txt"
$VCList = @(Get-Content $List)
$file = "c:\temp\Cluster-CPU-Mem-Utlisation-" + (Get-Date -Format "dd-MM-yyyy") + ".csv"
$report = @()
foreach($VC in $VCList){
Connect-VIServer $VC -user xxxxxxxx -password 'xxxxxxxxxxxxx' -WarningAction SilentlyContinue
$fol = get-folder | where {$_.Name -eq "PROD" -or $_.Name -eq "DEV"}
$clusters = $fol | Get-Cluster
foreach($cluster in $clusters){
$esxhosts = $cluster | Get-VMHost | where {$_.ConnectionState -eq "connected"}
$vms = $cluster | Get-VM | where {$_.PowerState -eq "PoweredOn"}
if($vms){
[double]$cpuAverage = 0
[double]$memAverage = 0
[double]$cpuReady = 0
foreach ($esx in $esxhosts) {
$stats = Get-Stat -Entity $esx -Stat cpu.ready.summation -Start (Get-Date).Adddays(-1) -Finish (Get-Date)
$readyAvg = $stats | Measure-Object -Property Value -Average | Select -ExpandProperty Average
$readyPerc = ($readyAvg / ($stats[0].IntervalSecs * 1000))*100
$cpuReady = $cpuReady + $readyPerc
[double]$esxiCPUavg = [double]($esx | Select-Object @{N = 'cpuAvg'; E = {[double]([math]::Round(($_.CpuUsageMhz) / ($_.CpuTotalMhz) * 100, 2))}} | Select-Object -ExpandProperty cpuAvg)
$cpuAverage = $cpuAverage + $esxiCPUavg
[double]$esxiMEMavg = [double]($esx | Select-Object @{N = 'memAvg'; E = {[double]([math]::Round(($_.MemoryUsageMB) / ($_.MemoryTotalMB) * 100, 2))}} | select-object -ExpandProperty memAvg)
$memAverage = $memAverage + $esxiMEMavg
}
$cpuAverage = [math]::Round(($cpuAverage / ($esxhosts.count) ), 1)
$memAverage = [math]::Round(($memAverage / ($esxhosts.count) ), 1)
$cpuReady = [math]::Round(($cpuReady / ($esxhosts.count) ), 1)
$row = "" | Select Cluster, "CPURdy(%)", CPUAvg, MEMAvg
$row.Cluster = $Cluster.Name
$row."CPURdy(%)" = $cpuReady
$row.CPUAvg = $cpuAverage
$row.MEMAvg = $memAverage
$report += $row
}
}
Disconnect-VIServer -Confirm:$false
}
$report | Export-Csv $file -NoTypeInformation -UseCulture
Yes, that looks better now, you are using values from the same interval.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
There is a basic flaw in your script in that you are using the Ready value over 24 hours, while the CpuUsageMHz and MemoryUsageMB values are over a recent short internal interval.
I would suggest using the average of the metrics cpu.usagemhz.average and mem.usage.average, also over 24 hours, instead.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks LucD for pointing me to correct direction as always. I have made the necessary amendments to the script as per your suggestion as shown below. Please let me know if it is correct now.
Import-Module VMware.VimAutomation.Core
$cwdpath = Split-Path -Parent $MyInvocation.MyCommand.Path
$List = $cwdpath + "\VCList.txt"
$VCList = @(Get-Content $List)
$file = "c:\temp\Cluster-CPU-Mem-Utlisation-" + (Get-Date -Format "dd-MM-yyyy") + ".csv"
$metrics = 'cpu.ready.summation','cpu.usagemhz.average','mem.usage.average'
$report = @()
foreach($VC in $VCList){
Connect-VIServer $VC -user xxxxxxxxx -password 'xxxxxxxxxx' -WarningAction SilentlyContinue
$fol = get-folder | where {$_.Name -eq "PROD" -or $_.Name -eq "DEV"}
$clusters = $fol | Get-Cluster
foreach($cluster in $clusters){
$esxhosts = $cluster | Get-VMHost | where {$_.ConnectionState -eq "connected"}
$vms = $cluster | Get-VM | where {$_.PowerState -eq "PoweredOn"}
if($vms){
[double]$cpuAverage = 0
[double]$memAverage = 0
[double]$cpuReady = 0
foreach ($esx in $esxhosts) {
$stats = Get-Stat -Entity $esx -Stat $metrics -Start (Get-Date).Adddays(-1) -Finish (Get-Date)
$readyAvg = $stats | where {$_.MetricId -eq 'cpu.ready.summation'} | Measure-Object -Property Value -Average | Select -ExpandProperty Average
$readyPerc = ($readyAvg / ($stats[0].IntervalSecs * 1000))*100
$cpuReady = $cpuReady + $readyPerc
$esxiCPUavg = $stats | where {$_.MetricId -eq 'cpu.usagemhz.average'} | Measure-Object -Property Value -Average | Select -ExpandProperty Average
$cpuAverage = $cpuAverage + $esxiCPUavg
$esxiMEMavg = $stats | where {$_.MetricId -eq 'mem.usage.average'} | Measure-Object -Property Value -Average | Select -ExpandProperty Average
$memAverage = $memAverage + $esxiMEMavg
}
$cpuAverage = [math]::Round(($cpuAverage / ($esxhosts.count) ), 1)
$memAverage = [math]::Round(($memAverage / ($esxhosts.count) ), 1)
$cpuReady = [math]::Round(($cpuReady / ($esxhosts.count) ), 1)
$row = "" | Select Cluster, "CPURdy(%)", CPUAvg, MEMAvg
$row.Cluster = $Cluster.Name
$row."CPURdy(%)" = $cpuReady
$row.CPUAvg = $cpuAverage
$row.MEMAvg = $memAverage
$report += $row
}
}
Disconnect-VIServer -Confirm:$false
}
$report | Export-Csv $file -NoTypeInformation -UseCulture
Yes, that looks better now, you are using values from the same interval.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks a lot.