VMware Cloud Community
Marcus316
Enthusiast
Enthusiast

PowerCLI script for vSphere capacity planning

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)"

http://1drv.ms/1J00vkq

(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)

160 Replies
Ankojin
Contributor
Contributor

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

punjain
Contributor
Contributor

Hi Ankoji,

Thanks a lot for the response, It helped. Smiley Happy

Thanks,

Puneet

Reply
0 Kudos
devkumars
Contributor
Contributor

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

Reply
0 Kudos
LucD
Leadership
Leadership

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

Reply
0 Kudos
Ankojin
Contributor
Contributor


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

Reply
0 Kudos
punjain
Contributor
Contributor

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.

Reply
0 Kudos
esekula
Contributor
Contributor

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

Reply
0 Kudos
snonchev
Contributor
Contributor

Kudos for the wonderful script Marc. Using it often now Smiley Happy

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.

Reply
0 Kudos
snonchev
Contributor
Contributor

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

Reply
0 Kudos
AlbertWT
Virtuoso
Virtuoso

Many thanks Marcus316‌ for sharing the great script here.

How do we know if there is latest update on your script ?

/* Please feel free to provide any comments or input you may have. */
Reply
0 Kudos
vMarkusK1985
Expert
Expert

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')}

https://mycloudrevolution.com | https://twitter.com/vMarkus_K | https://github.com/vMarkusK
Reply
0 Kudos
elihuj
Enthusiast
Enthusiast

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?

Reply
0 Kudos
MarkRapp
Contributor
Contributor

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 NameRAM Quantity (in GB)Current Memory Usage % Monthly Average Memory Usage %
esx01192 GB53%53%
esx02192 GB40%42%
esx03192 GB40%35%
esx04192 GB45%45%
esx05192 GB43%46%
esx06192 GB41%40%
esx07192 GB55%55%
Total1344 GB45%45%
Reply
0 Kudos
RahulVmware1985
Enthusiast
Enthusiast

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:30Get-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:36Get-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.

Reply
0 Kudos
punjain
Contributor
Contributor

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

Reply
0 Kudos
tuvtommy
Contributor
Contributor

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,

ScreenHunter_06 Apr. 13 14.17.png

BR,

Tommy

Reply
0 Kudos
elihuj
Enthusiast
Enthusiast

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.

PeterOHara
Contributor
Contributor

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.

Reply
0 Kudos
GowdaAnand7012
Contributor
Contributor

Hello All,

Unable to download the script over the shared URL, can anybody help us with the same.

Reply
0 Kudos
supportblueit
Contributor
Contributor

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

Reply
0 Kudos