Hello everyone!
After recent discussion on vSphere Capacity planning, I thought I would share one of the tools I use for this purpose. This is a side project I've been working on for few months.
I present to you, my very own "VMware Capacity & Performance Report PowerCLI script (v2.1 Community edition)"
(Click here then click on "Download")
This is a complex PowerCLI script I wrote, that generates an e-mail report that gives you insight into the current state of your VMware vSphere environment's capacity. It generates tables, pie charts and line charts with information about CPU, Memory & Storage capacity, VM Provisioning Potential, Cluster Resilience and more. Check the script's #INFORMATION block for more information about prerequisites, script input and output.
Have a look at the report it generates and let me know what you think of it!
Please share your thoughts and comments!
Marc Davoli
http://ca.linkedin.com/in/marcvincentdavoli/
Edited on May 25 : Changed OneDrive link to updated script v2.1 with bugfix (for cluster names with a space in it)
Hi Punnet,
You have to install MS charts on machine where ur running script. download it from http://www.microsoft.com/en-us/download/details.aspx?id=14422.
For saving file to local system change below lines in script
# Create a folder for temporary image files
$Date = Get-Date -UFormat "%Y-%m-%d-%H-%M"
$FLocation = "D:\scripts\Test_Scripts\CPReport\Mod" + $vCenterServerName + $Date #replace path with actual location on the server ex: C:\CPReports\VC01\
IF ((Test-Path -path $FLocation) -ne $True) {$TempFolder = New-Item $FLocation -type directory} else {$TempFolder = $FLocation}
Set-Location $FLocation # create directory
Regards,
Ankoji
Hi Ankoji,
Thanks a lot for the response, It helped.
Thanks,
Puneet
Added a check to remove 'powered off' VMs while taking CPU average. The script was throwing error for 'powered off VMs'
Function GetVMAverageCPUUsage ($VMsTemp) {
$AverageVMCPUUsage = Get-Stat -Entity ($VMsTemp | Where-Object {$_.PowerState -eq "PoweredOn"}) -MaxSamples 10 -Stat cpu.usagemhz.average
$AverageVMCPUUsage = $AverageVMCPUUsage | Measure-Object -Property value -Average
$AverageVMCPUUsage = $AverageVMCPUUsage.Average
#$AverageVMCPUUsage = $AverageVMCPUUsage / 1000 # Divide by 1000 to convert from MHz to GHz # VALUE NOT HIGH ENOUGH
$AverageVMCPUUsage = [system.math]::ceiling($AverageVMCPUUsage) # Round up
return $AverageVMCPUUsage
}
Please include this change in the original script if you feel good to accomodate
Fyi, you can get the same result by adding "-ErrorAction SilentlyContinue" on the Get-Stat cmdlet.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Add a check to remove 'Local Datastore' while taking cluster report . The script was throwing error fo local datastore
# Get inventory objects for this cluster only
$VMHostsTemp = Get-Cluster $ClusterTemp.Name | Get-VMHost | Sort-Object -Property Name #| Select-Object -First 1
$DatastoresTemp = Get-Cluster $ClusterTemp.Name | Get-VMHost | Get-Datastore -VM$ | Sort-Object -Property Name #| Select-Object -First 1
$VMTemp = Get-Cluster $ClusterTemp.Name | Get-VM | Sort-Object -Property Name #| Select-Object -First 1
$ResourcePoolsTemp = Get-Cluster $ClusterTemp.Name | Get-ResourcePool | Sort-Object -Property Name #| Select-Object -First 1
Thanks in Advance,
Ankoji
Hi Guys,
When I run the script, I get average monthly usage as 0 for both cpu and memory. Also I get following errors while running the script.
Step 1/6 - Collecting inventory...
Attempted to divide by zero.
At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\CapacityReport2.ps1:304 char:60
+ $InventoryTemp += [String][system.math]::floor($VM.Count / <<<< $VMHosts.Count) + ":1" + " Consolidation ratio <br>"
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException
Gathering ESXi Hardware and Software Information...
Step 2/6 - Collecting CPU statistics...
Gathering x.x.x.x CPU usage statistics...
Creating chart...
Step 3/6 - Collecting Memory information...
Gathering x.x.x.x Memory usage statistics...
Creating chart...
Step 4/6 - Collecting Datastore information...
Gathering datastore1 (3) Datastore usage statistics...
Creating chart...
Step 5/6 - Collecting Virtual Machine information...
Collecting Virtual Machine Guest OS information...
Creating chart...
Step 6/6 - Collecting Cluster information...
Get-VMHost : Cannot validate argument on parameter 'Datastore'. The argument is null or empty. Supply an argument that is not null or empty and then try the command again.
At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\CapacityReport2.ps1:781 char:55
+ $NumberOfVMHostsInCluster = $ClusterTemp | Get-VMHost <<<< | Measure-Object
+ CategoryInfo : InvalidData: (:) [Get-VMHost], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetVMHost
New-Item : The device is not ready.
At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\CapacityReport2.ps1:922 char:68
+ IF ((Test-Path -path $FLocation) -ne $True) {$TempFolder = New-Item <<<< $FLocation -type directory} else {$TempFolder = $FLocation}
+ CategoryInfo : WriteError: (D:\scripts\Test...015-12-02-12-16:String) [New-Item], IOException
+ FullyQualifiedErrorId : CreateDirectoryIOError,Microsoft.PowerShell.Commands.NewItemCommand
Set-Location : Cannot find path 'D:\scripts\Test_Scripts\CPReport\Mod x.x.x.x 2015-12-02-12-16' because it does not exist.
At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\CapacityReport2.ps1:923 char:13
+ Set-Location <<<< $FLocation # create directory
+ CategoryInfo : ObjectNotFound: (D:\scripts\Test...015-12-02-12-16:String) [Set-Location], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.SetLocationCommand
Attaching the script I used.
I am also having issues where I get average monthly usage as 0 for both cpu and memory. I have been using this for a few months without any issues, but now this is happening. Appears that the usage is only on a few clusters, and if I run the script it is consistent in reporting usage as 0 for those clusters.
Any ideas?
Thanks
Kudos for the wonderful script Marc. Using it often now
Just a small advice - next time you publish anything put terms & conditions for all Indian guys expecting new features and training on how to use the script.
There is a faster way for filtering the local datastores out. In the script wherever there is:
Get-Datastore
Replace it with:
Get-Datastore | Where-Object {$_.extensiondata.summary.MultipleHostAccess -eq $true}
Cheers
Many thanks Marcus316 for sharing the great script here.
How do we know if there is latest update on your script ?
Great Script! Thanks for Sharing.
The only thing I miss is a little bit of error handling, e.g.:
vCenter Connection
# Start vCenter Connection
Write-Host "Starting to Process vCenter Connection to " $VIServer " ..."-ForegroundColor Magenta
$OpenConnection = $global:DefaultVIServers | where { $_.Name -eq $VIServer }
if($OpenConnection.IsConnected) {
Write-Host "vCenter is Already Connected..." -ForegroundColor Yellow
$VIConnection = $OpenConnection
} else {
Write-Host "Connecting vCenter..."
$VIConnection = Connect-VIServer -Server $VIServer
}
if (-not $VIConnection.IsConnected) {
Write-Error "Error: vCenter Connection Failed"
Exit
}
# End vCenter Connection
Load Plugin
# Start Load VMware Snapin (if not already loaded)
if (!(Get-PSSnapin -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue)) {
if (!(Add-PSSnapin -PassThru VMware.VimAutomation.Core)) {
# Error out if loading fails
Write-Error "ERROR: Cannot load the VMware Snapin. Is the PowerCLI installed?"
Exit
}
}
# End Load VMware Snapin (if not already loaded)
Ressources
Get-Datastore | where {$_.State -eq "Available" -and $_.Accessible -eq "True"})
Get-VMHost | Where-Object { ($_.ConnectionState -eq 'Connected')}
I'm seeing error messages for one of my clusters during the resiliency report.
Gathering Cluster Resilience Information for Cluster
Method invocation failed because [System.Object[]] does not contain a method named 'op_Subtraction'.
At C:\Scripts\CPReport-v2.1-Community-Edition.ps1:496 char:4
+ $ClusterFreeMemory = $ClusterTotalMemory - $ClusterUsedMemory - $ACPolicyInte ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (op_Subtraction:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
Method invocation failed because [System.Object[]] does not contain a method named 'op_Subtraction'.
At C:\Scripts\CPReport-v2.1-Community-Edition.ps1:499 char:4
+ $ClusterFreeMemoryPercentage = $ClusterFreeMemoryPercentage - $ACPolicyIntege ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (op_Subtraction:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
Method invocation failed because [System.Object[]] does not contain a method named 'op_Division'.
At C:\Scripts\CPReport-v2.1-Community-Edition.ps1:512 char:4
+ $HAReservedMemory = ($ACPolicyInteger/100) * ($ClusterTemp | Get-VMHost | Mea ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (op_Division:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
Creating chart...
Exception calling "DataBindXY" with "2" argument(s): "Data points insertion error. Number of X values is less than Y values
Parameter name: xValue"
At C:\Scripts\CPReport-v2.1-Community-Edition.ps1:608 char:2
+ $Chart.Series["Data"].Points.DataBindXY($NameArray, $ValueArray) #Modified by M ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ArgumentOutOfRangeException
I saw someone had a similar issue, but did not see a resolution. It only happens with one cluster. Any ideas as to why?
Excellent script very useful to automate some report for management.
Has anyone been able to edit the script to include totals for the monthly average memory/CPU usage per cluster? Something like below the table below?
Host Name | RAM Quantity (in GB) | Current Memory Usage % | Monthly Average Memory Usage % |
esx01 | 192 GB | 53% | 53% |
esx02 | 192 GB | 40% | 42% |
esx03 | 192 GB | 40% | 35% |
esx04 | 192 GB | 45% | 45% |
esx05 | 192 GB | 43% | 46% |
esx06 | 192 GB | 41% | 40% |
esx07 | 192 GB | 55% | 55% |
Total | 1344 GB | 45% | 45% |
Thanks for the script it ran fine with charts but it does gives an error everytime I ran the script, Tried to figure it out myself as $VMsTemp is not been set with any value yet even though script set it.
Script:
Function GetVMAverageCPUUsage ($VMsTemp) {
$AverageVMCPUUsage = Get-Stat -Entity ($VMsTemp) -MaxSamples 1 -stat cpu.usagemhz.average
$AverageVMCPUUsage = $AverageVMCPUUsage | Measure-Object -Property value -Average
$AverageVMCPUUsage = $AverageVMCPUUsage.Average
#$AverageVMCPUUsage = $AverageVMCPUUsage / 1000 # Divide by 1000 to convert from MHz to GHz # VALUE NOT HIGH ENOUGH
$AverageVMCPUUsage = [system.math]::ceiling($AverageVMCPUUsage) # Round up
return $AverageVMCPUUsage
Error:
Get-Stat : 8-3-2016 14:45:30 | Get-Stat | Object reference not set to an instance of an object. |
At line:171 char:31
+ | $AverageVMCPUUsage = Get-Stat <<<< -Entity ($VMsTemp) -MaxSamples 1 -stat cpu.usagemhz.average | |
+ CategoryInfo | : NotSpecified: (:) [Get-Stat], VimException | |
+ FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetViStats |
Get-Stat : 8-3-2016 14:47:36 | Get-Stat | Object reference not set to an instance of an object. |
At line:171 char:31
+ | $AverageVMCPUUsage = Get-Stat <<<< -Entity ($VMsTemp) -MaxSamples 1 -stat cpu.usagemhz.average | |
+ CategoryInfo | : NotSpecified: (:) [Get-Stat], VimException | |
+ FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetViStats |
Tried multiple things to get rid of this error even by changing the value and removing too but still gets error. If you can help on this.
Hi Ankojin,
Do I need MS Office to be installed on the machine while creating this report. I installed the mschart on machine and I see the png files also created in the powercli folder but the images are not included in the report.
Thanks,
Puneet
Thanks very much for the script,
This script is really useful to capture information to the management, but i just hit into the problem that the average CPU and Mem can not be show on the report, it used to work before,
The error show the resources is not available, but it should be only one VM,
Get-Stat : 4/13/2016 12:04:41 PM Get-Stat The metric counter "cpu.usagemhz.average" doesn't exist for entity "Asterisk1-clone".
At C:\Users\lingt\Desktop\PowerCLI\CPReport-v2.1-Community-Edition.ps1:181 char:23
+ $AverageVMCPUUsage = Get-Stat -Entity ($VMsTemp) -MaxSamples 1 -stat cpu.usagem ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceUnavailable: (cpu.usagemhz.average:String) [Get-Stat], VimException
+ FullyQualifiedErrorId : Client20_RuntimeDataServiceImpl_CheckUserMetrics_MetricDoesntExist,VMware.VimAutomation.ViCore.Cmdlets.Commands.
GetViStats
Anyone can help on this?
Thanks,
BR,
Tommy
I was actually able to resolve my issue. Here's what I did in case anyone has a similar problem.
Within the CreateClusterResilienceTable Function, I changed this:
$ClusterView = Get-View -ViewType "ClusterComputeResource" -Filter @{"Name" = $ClusterTemp.Name}
to this:
$ClusterView = Get-View -ViewType "ClusterComputeResource" | Where {$_.Name -eq $clusterTemp.Name}
After the change, I had no more errors and the resiliency part reported correctly.
Hi,
Wondering if there is a way to include Average CPU Ready to the CPU table?
I am not the best at powershell so gonna try changing the Average CPU Function to -stat cpu.ready.summation to see what the results are.
Would be good if there was another column for average CPU ready int table and possibly a graph created with highlighted red if passed the threshold.
Hello All,
Unable to download the script over the shared URL, can anybody help us with the same.
HI
First thing, this is a great piece of work and thanks for sharing it.
I wanted to ask if it was possible to have the output to a csv file.
Thanks
Vincenzo