VMware Cloud Community
carias593
Contributor
Contributor
Jump to solution

PowerCLI Script to capture Cluster Utilization with Performance Averages (v2)

Hi,

Id like to take the script used for quickly analyzing and exporting cluster utilization data to include historical average as well using Get-Stat as recommended by LucD.  I've modified the final script version from the previous thread located https://communities.vmware.com/thread/596563 to the following:

$hosts = "192.168.0.1"

$a = "<style>"

$a = $a + "BODY{background-color:white;}"

$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"

$a = $a + "TH{border-width: 1px;padding: 1px;border-style: solid;border-color: black;background-color:PaleGoldenrod}"

$a = $a + "TD{border-width: 1px;padding: 1px;border-style: solid;border-color: black;background-color:white}"

$a = $a + "</style>"

if($global:defaultviservers){

    Disconnect-VIServer -Server $global:defaultviservers -Force -Confirm:$false

}

$output = foreach($vc in $hosts){

    Write-Host "Getting Cluster Information from $vc"

    Connect-VIServer -Server $vc | Out-Null

    Get-Cluster -Server $vc | where{$_.ExtensionData.Host.Count -ne 0} | ForEach-Object -Process {

        Write-Host "Looking at cluster $($_.Name)"

        #$ds = Get-Datastore -RelatedObject $_ | where{$_.ExtensionData.Summary.MultipleHostAccess}

        $esx = Get-VMHost -Location $_

        $vm = Get-VM -Location $_ | where{$_.PowerState -eq "PoweredOn"}

        $cpuTot = ($esx | Measure-Object -Property CpuTotalMhz -Sum).Sum

        $cpuUse = ($esx | Measure-Object -Property CpuUsageMhz -Sum).Sum

        $memTot = ($esx | Measure-Object -Property MemoryTotalGB -Sum).Sum

        $memUse = ($esx | Measure-Object -Property MemoryUsageGB -Sum).Sum

        $obj = [ordered]@{

            #vCenter = $global:defaultviserver.Name

            Cluster = $_.Name

            'Total CPU Ghz' = [math]::Round($cpuTot/1000,0)

            'CPU Usage' = "{0:P0}" -f ($cpuUse/$cpuTot)

            'CPU Free' = "{0:P0}" -f (($cpuTot - $cpuUse)/$cpuTot)

            'Total RAM GB' = [math]::Round($memTot,0)

            'RAM Usage' = "{0:P0}" -f ($memUse/$memTot)

            'RAM Free GB' = "{0:P0}" -f (($memTot - $memUse)/$memTot)

            #'Total Capacity GB' = [math]::Round(($ds.CapacityGB | Measure-Object -Sum).Sum,0)

            #'Used Capacity GB' = [math]::Round(($ds | %{$_.CapacityGB - $_.FreeSpaceGB} | Measure-Object -Sum).Sum,0)

            #'Free Capacity GB' = [math]::Round(($ds.FreeSpaceGB | Measure-Object -Sum).Sum,0)

            'N° Hosts' = $_.ExtensionData.Host.Count

            'N°VMs' = &{

                $esxVM = Get-View -Id $_.ExtensionData.Host -Property VM

                $vm = @()

                if($esxVM.VM){

                    $vm = Get-View -Id $esxVM.VM -Property Summary.Config.Template |

                    where{-not $_.Summary.Config.Template}

                }

                $vm.Count

                }

            'vCPU' = ($vm.NumCpu | Measure-Object -Sum).Sum

            'pCPU' = ($esx.NumCpu | Measure-Object -Sum).Sum

            'vCPU/pCPU' = "{0:P0}" -f (($vm.NumCpu | Measure-Object -Sum).Sum / ($esx.NumCpu | Measure-Object -Sum).Sum)

            'vMem' = [math]::Round(($vm.MemoryGB | Measure-Object -Sum).Sum)

            'pMem' = [math]::Round(($esx.MemoryTotalGB | Measure-Object -Sum).Sum)

            'vMem/pMem' = "{0:P0}" -f (($vm.MemoryGB | Measure-Object -Sum).Sum / ($esx.MemoryTotalGB | Measure-Object -Sum).Sum)

        }

        New-Object PSObject -Property $obj

   }

   Disconnect-VIServer $vc -confirm:$false

}

$output | ConvertTo-Html -Head $a | Out-File C:\ClusterReport.htm -width 400

I've commented out various storage related items, and added columns for the vCPU, pCPU, vMem, and pMem components, as well as changed the original script to only count poweredOn VMs where relevant.  Is it possible to change CPU usage and RAM usage to display the clusters overall average usage for 7 days or even a month? Can anyone think of a way to subtract the largest host from the values calculated for pCPU?

Thanks in advance,

carias593

Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

The cluster avg CPU & mem usage can be done as follows.
I trust you can incorporate that in your script

$clusterName = 'cluster'

$sStat = @{

   Entity = Get-Cluster -Name $clusterName

   Stat = 'cpu.usage.average', 'mem.usage.average'

   Start = (Get-Date).AddDays(-7)

   # Start = (Get-Date).AddHours(-1)

   Instance = '*'

   ErrorAction = 'SilentlyContinue'

}


$stat = Get-Stat @sStat


New-Object -TypeName PSObject -Property @{

   Cluster = $clusterName

   ClusterAvgCpu = (($stat | where { $_.MetricId -eq 'cpu.usage.average' }).Value | Measure-Object -Average).Average

   ClusterAvgMem = (($stat | where { $_.MetricId -eq 'mem.usage.average' }).Value | Measure-Object -Average).Average

}

To skip the host with the most pCPU, you could do

'pCPU' = ($esx.NumCpu | Sort-Object -Descending | Select -Skip 1 | Measure-Object -Sum).Sum

---------------------------------------------------------------------------------------------------------

Was it helpful? Let us know by completing this short survey here.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

View solution in original post

Reply
0 Kudos
13 Replies
LucD
Leadership
Leadership
Jump to solution

I'm not sure how the line you added

$vm = Get-VM -Location $_ | where{$_.PowerState -eq "PoweredOn"}

has any impact on the script?

Or am I missing something?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
carias593
Contributor
Contributor
Jump to solution

Its purpose was to only count the powered on VMs when calculating provisioned memory/cpu (vCPU/vMem).  In our environment, we only count powered on VMs for capacity planning.

carias593

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

The cluster avg CPU & mem usage can be done as follows.
I trust you can incorporate that in your script

$clusterName = 'cluster'

$sStat = @{

   Entity = Get-Cluster -Name $clusterName

   Stat = 'cpu.usage.average', 'mem.usage.average'

   Start = (Get-Date).AddDays(-7)

   # Start = (Get-Date).AddHours(-1)

   Instance = '*'

   ErrorAction = 'SilentlyContinue'

}


$stat = Get-Stat @sStat


New-Object -TypeName PSObject -Property @{

   Cluster = $clusterName

   ClusterAvgCpu = (($stat | where { $_.MetricId -eq 'cpu.usage.average' }).Value | Measure-Object -Average).Average

   ClusterAvgMem = (($stat | where { $_.MetricId -eq 'mem.usage.average' }).Value | Measure-Object -Average).Average

}

To skip the host with the most pCPU, you could do

'pCPU' = ($esx.NumCpu | Sort-Object -Descending | Select -Skip 1 | Measure-Object -Sum).Sum

---------------------------------------------------------------------------------------------------------

Was it helpful? Let us know by completing this short survey here.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
carias593
Contributor
Contributor
Jump to solution

Here's my final:

$hosts = "192.168.0.1"

$a = "<style>"

$a = $a + "BODY{background-color:white;}"

$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"

$a = $a + "TH{border-width: 1px;padding: 1px;border-style: solid;border-color: black;background-color:PaleGoldenrod}"

$a = $a + "TD{border-width: 1px;padding: 1px;border-style: solid;border-color: black;background-color:white}"

$a = $a + "</style>"

if($global:defaultviservers){

    Disconnect-VIServer -Server $global:defaultviservers -Force -Confirm:$false

}

$output = foreach($vc in $hosts){

    Write-Host "Getting Cluster Information from $vc"

    Connect-VIServer -Server $vc | Out-Null

    Get-Cluster -Server $vc | where{$_.ExtensionData.Host.Count -ne 0} | ForEach-Object -Process {

        Write-Host "Looking at cluster $($_.Name)"

        #$ds = Get-Datastore -RelatedObject $_ | where{$_.ExtensionData.Summary.MultipleHostAccess}

        $sStat = @{

            Entity = Get-Cluster -Name $_.Name

            Stat = 'cpu.usage.average', 'mem.usage.average'

            Start = (Get-Date).AddDays(-7)

            # Start = (Get-Date).AddHours(-1)

            Instance = '*'

            ErrorAction = 'SilentlyContinue'

            }

        $stat = Get-Stat @sStat

        $esx = Get-VMHost -Location $_

        #$hostthreads = ($esx.extensiondata.hardware.cpuinfo.numcputhreads | Measure-Object -Sum).Sum

        $vm = Get-VM -Location $_ | where{$_.PowerState -eq "PoweredOn"}

        $cpuTot = ($esx | Measure-Object -Property CpuTotalMhz -Sum).Sum

        $cpuUse = ($esx | Measure-Object -Property CpuUsageMhz -Sum).Sum

        $memTot = ($esx | Measure-Object -Property MemoryTotalGB -Sum).Sum

        $memUse = ($esx | Measure-Object -Property MemoryUsageGB -Sum).Sum

        $obj = [ordered]@{

            #vCenter = $global:defaultviserver.Name

            Cluster = $_.Name

            'Total CPU Ghz' = [math]::Round($cpuTot/1000,0)

            'CPU Usage' = "{0:P0}" -f ($cpuUse/$cpuTot)

            'CPU 7-day' = "{0:P2}" -f (((($stat | where { $_.MetricId -eq 'cpu.usage.average' }).Value | Measure-Object -Average).Average)/100)

            'CPU Free' = "{0:P0}" -f (($cpuTot - $cpuUse)/$cpuTot)

            'Total RAM GB' = [math]::Round($memTot,0)

            'RAM Usage' = "{0:P0}" -f ($memUse/$memTot)

            'RAM 7-day' = "{0:P2}" -f (((($stat | where { $_.MetricId -eq 'mem.usage.average' }).Value | Measure-Object -Average).Average)/100)

            'RAM Free GB' = "{0:P0}" -f (($memTot - $memUse)/$memTot)

            #'Total Capacity GB' = [math]::Round(($ds.CapacityGB | Measure-Object -Sum).Sum,0)

            #'Used Capacity GB' = [math]::Round(($ds | %{$_.CapacityGB - $_.FreeSpaceGB} | Measure-Object -Sum).Sum,0)

            #'Free Capacity GB' = [math]::Round(($ds.FreeSpaceGB | Measure-Object -Sum).Sum,0)

            'N° Hosts' = $_.ExtensionData.Host.Count

            'N°VMs' = &{

                $esxVM = Get-View -Id $_.ExtensionData.Host -Property VM

                $vm = @()

                if($esxVM.VM){

                    $vm = Get-View -Id $esxVM.VM -Property Summary.Config.Template |

                    where{-not $_.Summary.Config.Template}

                }

                $vm.Count

                }

            'vCPU' = ($vm.NumCpu | Measure-Object -Sum).Sum

            'pCPU' = ($esx.NumCpu | Sort-Object -Descending | Select -Skip 1 | Measure-Object -Sum).Sum

            'vCPU/pCPU' = "{0:P0}" -f (($vm.NumCpu | Measure-Object -Sum).Sum / ($esx.NumCpu | Measure-Object -Sum).Sum)

            'vMem' = [math]::Round(($vm.MemoryGB | Measure-Object -Sum).Sum)

            'pMem' = [math]::Round(($esx.MemoryTotalGB | Measure-Object -Sum).Sum)

            'vMem/pMem' = "{0:P0}" -f (($vm.MemoryGB | Measure-Object -Sum).Sum / ($esx.MemoryTotalGB | Measure-Object -Sum).Sum)

        }

        New-Object PSObject -Property $obj

   }

   Disconnect-VIServer $vc -confirm:$false

}

$output | ConvertTo-Html -Head $a | Out-File C:\ClusterReport.htm -width 400

Here's its output:

Output.jpg

I'm probably going to remove the pMem column since the data is duplicated from Total RAM GB, but all the rest of the data looks great at this point!

Thanks for your help LucD!

carias593

Reply
0 Kudos
lucknowdinesh
Contributor
Contributor
Jump to solution

I am looking for similar data by script out but when i use it is not working.

I just copy paste this script and only change the name of my VC server at  $hosts = "192.168.0.1" but nothing work.

Can you please help me how to use it in the environment.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

I suspect the connection is not working.

Can you change

Connect-VIServer -Server $vc | Out-Null

to

Connect-VIServer -Server $vc

and check if there is an error message?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
lucknowdinesh
Contributor
Contributor
Jump to solution

Thanks.

After changes script is working but output is not as expected.

$hosts = "10.10.10.xx"

$a = "<style>"

$a = $a + "BODY{background-color:white;}"

$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"

$a = $a + "TH{border-width: 1px;padding: 1px;border-style: solid;border-color: black;background-color:PaleGoldenrod}"

$a = $a + "TD{border-width: 1px;padding: 1px;border-style: solid;border-color: black;background-color:white}"

$a = $a + "</style>"

if($global:defaultviservers){

    Disconnect-VIServer -Server $global:defaultviservers -Force -Confirm:$false

}

$output = foreach($vc in $hosts){

    Write-Host "Getting Cluster Information from $vc"

    Connect-VIServer -Server $vc

    Get-Cluster -Server $vc | where{$_.ExtensionData.Host.Count -ne 0} | ForEach-Object -Process {

        Write-Host "Looking at cluster $($_.Name)"

        #$ds = Get-Datastore -RelatedObject $_ | where{$_.ExtensionData.Summary.MultipleHostAccess}

        $sStat = @{

            Entity = Get-Cluster -Name $_.Name

            Stat = 'cpu.usage.average', 'mem.usage.average'

            Start = (Get-Date).AddDays(-7)

            # Start = (Get-Date).AddHours(-1)

            Instance = '*'

            ErrorAction = 'SilentlyContinue'

            }

        $stat = Get-Stat @sStat

        $esx = Get-VMHost -Location $_

        #$hostthreads = ($esx.extensiondata.hardware.cpuinfo.numcputhreads | Measure-Object -Sum).Sum

        $vm = Get-VM -Location $_ | where{$_.PowerState -eq "PoweredOn"}

        $cpuTot = ($esx | Measure-Object -Property CpuTotalMhz -Sum).Sum

        $cpuUse = ($esx | Measure-Object -Property CpuUsageMhz -Sum).Sum

        $memTot = ($esx | Measure-Object -Property MemoryTotalGB -Sum).Sum

        $memUse = ($esx | Measure-Object -Property MemoryUsageGB -Sum).Sum

        $obj = [ordered]@{

            #vCenter = $global:defaultviserver.Name

            Cluster = $_.Name

            'Total CPU Ghz' = [math]::Round($cpuTot/1000,0)

            'CPU Usage' = "{0:P0}" -f ($cpuUse/$cpuTot)

            'CPU 7-day' = "{0:P2}" -f (((($stat | where { $_.MetricId -eq 'cpu.usage.average' }).Value | Measure-Object -Average).Average)/100)

            'CPU Free' = "{0:P0}" -f (($cpuTot - $cpuUse)/$cpuTot)

            'Total RAM GB' = [math]::Round($memTot,0)

            'RAM Usage' = "{0:P0}" -f ($memUse/$memTot)

            'RAM 7-day' = "{0:P2}" -f (((($stat | where { $_.MetricId -eq 'mem.usage.average' }).Value | Measure-Object -Average).Average)/100)

            'RAM Free GB' = "{0:P0}" -f (($memTot - $memUse)/$memTot)

            #'Total Capacity GB' = [math]::Round(($ds.CapacityGB | Measure-Object -Sum).Sum,0)

            #'Used Capacity GB' = [math]::Round(($ds | %{$_.CapacityGB - $_.FreeSpaceGB} | Measure-Object -Sum).Sum,0)

            #'Free Capacity GB' = [math]::Round(($ds.FreeSpaceGB | Measure-Object -Sum).Sum,0)

            'N° Hosts' = $_.ExtensionData.Host.Count

            'N°VMs' = &{

                $esxVM = Get-View -Id $_.ExtensionData.Host -Property VM

                $vm = @()

                if($esxVM.VM){

                    $vm = Get-View -Id $esxVM.VM -Property Summary.Config.Template |

                    where{-not $_.Summary.Config.Template}

                }

                $vm.Count

                }

            'vCPU' = ($vm.NumCpu | Measure-Object -Sum).Sum

            'pCPU' = ($esx.NumCpu | Sort-Object -Descending | Select -Skip 1 | Measure-Object -Sum).Sum

            'vCPU/pCPU' = "{0:P0}" -f (($vm.NumCpu | Measure-Object -Sum).Sum / ($esx.NumCpu | Measure-Object -Sum).Sum)

            'vMem' = [math]::Round(($vm.MemoryGB | Measure-Object -Sum).Sum)

            'pMem' = [math]::Round(($esx.MemoryTotalGB | Measure-Object -Sum).Sum)

            'vMem/pMem' = "{0:P0}" -f (($vm.MemoryGB | Measure-Object -Sum).Sum / ($esx.MemoryTotalGB | Measure-Object -Sum).Sum)

        }

        New-Object PSObject -Property $obj

   }

   Disconnect-VIServer $vc -confirm:$false

}

$output | ConvertTo-Html -Head $a | Out-File C:\ClusterReport.htm -width 400

My script out is not like this.

Output.jpg

IsConnectedIdServiceUriSessionSecretNamePortSessionIdUserUidVersionBuildProductLineInstanceUuidRefCountExtensionData
Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

That is why the Out-Null was there.
Place it back, since it looks as if the Connect-VIServer is working.

You are sure Get-Cluster is returning anything?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
lucknowdinesh
Contributor
Contributor
Jump to solution

Excellent!!

It is working now and output is also perfect.

Thanks once again..

Reply
0 Kudos
vmk2014
Expert
Expert
Jump to solution

LucD,

If i want to pull report for all the cluster in vCenter instead of specific cluster i.e. $clusterName = 'cluster'  will be replaced by $Cluster = Get-Cluster $ClusterName ?

$Cluster = Get-Cluster $ClusterName

$sStat = @{

   Entity = Get-Cluster -Name $clusterName

   Stat = 'cpu.usage.average', 'mem.usage.average'

   Start = (Get-Date).AddDays(-7)

   # Start = (Get-Date).AddHours(-1)

   Instance = '*'

   ErrorAction = 'SilentlyContinue'

}

$stat = Get-Stat @sStat

New-Object -TypeName PSObject -Property @{

   Cluster = $clusterName

   ClusterAvgCpu = (($stat | where { $_.MetricId -eq 'cpu.usage.average' }).Value | Measure-Object -Average).Average

   ClusterAvgMem = (($stat | where { $_.MetricId -eq 'mem.usage.average' }).Value | Measure-Object -Average).Average

}

Thanks

V

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Are you going to keep on piggy-backing on answered old threads?

That is not very polite to people doing a search in this community.
If you have a new question, open a new thread.

You can always refer to an existing thread


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
Mmanjunath
Contributor
Contributor
Jump to solution

$output | ConvertTo-Html -Head $a | Out-File C:\temp\VMware Daily report\ClusterReport.htm -width 400

 

this fails with below error 

Out-File : Cannot validate argument on parameter 'Encoding'. The argument "Daily" does not belong to the set "unknown,string,unicode,bigendianunicode,utf8,utf7,utf32,ascii,default,oem"
specified by the ValidateSet attribute. Supply an argument that is in the set and then try the command again.
At line:135 char:61
+ ... put | ConvertTo-Html -Head $a | Out-File C:\temp\VMware Daily report\ ...
+ ~~~~~
+ CategoryInfo : InvalidData: (:) [Out-File], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.OutFileCommand

 

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

If you have blanks in the filepath, enclose it in quotes

Out-File 'C:\temp\VMware Daily report\ClusterReport.html'


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos