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
Edukate
Contributor
Contributor

I'm having problems downloading the newer version of this file. Version 2.1

Could somebody please add it as an attachment to a reply. OneDrive is just saying the file has been moved or doesn't exist.

Reply
0 Kudos
Rajeev8080
Contributor
Contributor

Hello Marcus,

I read your blogs for vSphere Capacity planning PowerCLI script.  I was trying to download it but it seems that URL is moved out or no longer exist.

I have urgent requirements for vSphere Capacity planning in my environment and running through hard time to get something handy.

Does this script work any kind of environment?

if yes, pls help me to share the script and make it workable for me too. It would be highly appreciated !

I have 10 different VCenters and i have read only access to my ID.

any help would be highly appreciated !

Reply
0 Kudos
AlbertWT
Virtuoso
Virtuoso

Hi,

I'm running it on Windows 10 Powershell ISE but somehow I cannot get the email not even finding the C:\Windows\Reports.html file ?

Creating chart...

Exception calling "SaveImage" with "2" argument(s): "Access to the path 'C:\WINDOWS\Cluster_Production-2_Datastore_Usage.png' is denied."

At line:652 char:2

+     $Chart.SaveImage($FullPath,"png")

+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : UnauthorizedAccessException

           Calculating Virtual Machine Average Usage Statistics for Cluster Production 2

           Gathering Cluster Resilience Information for Cluster Production 2

           Creating chart...

Exception calling "SaveImage" with "2" argument(s): "Access to the path 'C:\WINDOWS\Cluster_Production-2_Resilience_Report.png' is denied."

At line:652 char:2

+     $Chart.SaveImage($FullPath,"png")

+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : UnauthorizedAccessException

Out-File : Access to the path 'C:\WINDOWS\report.html' is denied.

At line:912 char:13

+ $HTMLPage | Out-File ((Get-Location).Path + "\report.html") # Export  ...

+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : OpenError: (:) [Out-File], UnauthorizedAccessException

    + FullyQualifiedErrorId : FileOpenFailure,Microsoft.PowerShell.Commands.OutFileCommand

Report has exported to HTML file  + C:\WINDOWS\report.html

Send-Mailmessage : Could not find file 'C:\WINDOWS\vCenter_CPU_Usage.png'.

At line:914 char:1

+ Send-Mailmessage -From $FromAddress -To $ToAddress -Subject $Subject  ...

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [Send-MailMessage], FileNotFoundException

    + FullyQualifiedErrorId : System.IO.FileNotFoundException,Microsoft.PowerShell.Commands.SendMailMessage

what's wrong with the script above ?

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

Hi Albert,

I've always updated the latest version in the original post of this thread.

If I update it any further, I will probably post it on my blog : Nuvoli Systems – Nuvoli means Cloud.

wowitsdave
Enthusiast
Enthusiast

Marcus316,

This script is amazing (especially for the price)! Thank you so much of putting it together for us.

It's given me visibility into our environment where I had none.

Reply
0 Kudos
Matt_B1
Enthusiast
Enthusiast

Really excited to use the script. Can someone post v2.1? The short URL in the original post doesn't work for me and the long URL LucD shared points to v2.0. I have tried the short URL with both my corporate and home systems. I also checked the Nuvoli blog and didn't see it.

Reply
0 Kudos
LucD
Leadership
Leadership

The link is broken for me as well Smiley Sad


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

Reply
0 Kudos
vMarkusK1985
Expert
Expert

Still a good idea! And so much Views...

Maybe you could start a GitHub project?

https://mycloudrevolution.com | https://twitter.com/vMarkus_K | https://github.com/vMarkusK
Reply
0 Kudos
AlbertWT
Virtuoso
Virtuoso

Here's the v 2.1

############################# INFORMATION #######################################

# VMWare Capacity & Performance Report

# Marc Vincent Davoli (Find me on LinkedIn! http://ca.linkedin.com/in/marcvincentdavoli/)

# PREREQUISITES for this script: Powershell V2, PowerCLI 5.0, Microsoft Chart Controls for .NET Framework (download from this link:

# http://www.microsoft.com/en-us/download/details.aspx?id=14422)

# INPUT for this script: vCenter server IP/hostname, vCenter server credentials, SMTP server IP/hostname

# OUTPUT for this script: E-mailed Report, Report.HTML and Attachments, 1 for each chart (in the working directory)

# Notice 1 : CPU and Memory provisioning potential is calculated by removing 1 host

# Notice 2 : Datastore space provisioning potential is calculated by removing 5%

############################# CHANGELOG #######################################

# February 2013 First version

# April 2013 Bugfixes, Added Per Cluster report

# July 2013 Bugfixes, Added Cluster Resilience & Provisionning Potential reports, other minor code adjustements

# January 2014 Added Consolidation ratio, ESXi Hardware & Software Information table, vCenter version, Print Computer name and script version

# May 2015 Fixed issue with Cluster charts not appearing in e-mail report, cause by a space in the cluster name

################################ CONSTANTS ######################################

Write-Host Loading...

#-------------------------CHANGE THESE VALUES--------------------------------

$SMTPServer = "smtp.domain.com"

$vCenterServerName = "PRODVCENTER01-VM"

$ToAddress = "admin@domain.com"

#-----------------------------------------------------------------------------

$ScriptVersion = "v2.1 - Community Edition" # Included in the Runtime info in $HTMLFooter

$Subject = "VMware Capacity & Performance Report for " + $vCenterServerName

$FromAddress = $vCenterServerName + "@domain.com"

$ColorArray = "Red", "Orange", "Purple", "Blue", "Olive", "SlateGrey", "Orange", "Purple", "Blue", "Olive"

$ColorArrayIndex = 0

$HTMLHeader = "<HTML><TITLE> VMware Capacity & Performance Report for " + $vCenterServerName + "</TITLE>"

$HTMLFooter = "Made with CPReport Script Version " + $ScriptVersion + " running on server " + $env:COMPUTERNAME + "</HTML>"

############################# GLOBAL VARIABLES ####################################

$global:ArrayOfNames = @()

$global:ArrayOfValues = @()

$Attachments = @()

############################## PREPROCESSING ####################################

Write-Host Preprocessing...

# Create a folder for temporary image files

#IF ((Test-Path -path .\Temp) -ne $True) {$TempFolder = New-Item .\Temp -type directory} else {$TempFolder = ".\Temp"}

Add-PSSnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue

Connect-VIServer $vCenterServerName

$DC = Get-Datacenter | Sort-Object -Property Name #| Select-Object -First 2

$Clusters = Get-Cluster | Sort-Object -Property Name #| Select-Object -First 1

$VMHosts = Get-VMHost | Sort-Object -Property Name #| Select-Object -First 1

$VM = Get-VM | Sort-Object -Property Name #| Select-Object -First 2

$Datastores = Get-Datastore | Sort-Object -Property Name #| Select-Object -First 1

$Templates = Get-Template | Sort-Object -Property Name #| Select-Object -First 2

$ResourcePools = Get-ResourcePool | Sort-Object -Property Name #| Select-Object -First 2

$Snapshots = $VM | Get-Snapshot #| Select-Object -First 2

$Date = Get-Date | Sort-Object -Property Name #| Select-Object -First 2

################################ FUNCTIONS ######################################

Function GetTotalCPUCyclesInGhz ($VMHostsTemp) {

  $TotalCPUCyclesInGHz = $VMHostsTemp | Measure-Object -Property CpuTotalMhz -Sum # Count total CPU in Mhz

  $TotalCPUCyclesInGHz = $TotalCPUCyclesInGHz.Sum -as [int] # Convert from String to Int

  $TotalCPUCyclesInGHz = $TotalCPUCyclesInGHz / 1000 # Divide by 1000 to convert from MHz to GHz

  $TotalCPUCyclesInGHz = [system.math]::ceiling($TotalCPUCyclesInGHz) # Round down

  return $TotalCPUCyclesInGHz

}

Function GetTotalNumberofCPUs ($VMHostsTemp){

  $TotalCPU = $VMHostsTemp | Measure-Object -Property NumCpu -Sum # Count total RAM in MB

  $TotalCPU = $TotalCPU.Sum

  return $TotalCPU

}

Function GetTotalMemoryInGB ($VMHostsTemp){

  $TotalRAMinGB = $VMHostsTemp | Measure-Object -Property MemoryTotalMB -Sum # Count total RAM in MB

  $TotalRAMinGB = $TotalRAMinGB.Sum -as [int] # Convert from String to Int

  $TotalRAMinGB = $TotalRAMinGB / 1024 # Divide by 1024 to convert from MB to GB

  $TotalRAMinGB = [system.math]::ceiling($TotalRAMinGB) # Round down

  return $TotalRAMinGB

}

Function GetTotalDatastoreDiskSpaceinGB ($DatastoresTemp) {

  $TotalDatastoreDiskSpaceinGB = $DatastoresTemp | Measure-Object -Property FreeSpaceMB -Sum # Count total  MB

  $TotalDatastoreDiskSpaceinGB = $TotalDatastoreDiskSpaceinGB.Sum -as [int] # Convert from String to Int

  $TotalDatastoreDiskSpaceinGB = $TotalDatastoreDiskSpaceinGB / 1024 # Divide by 1024 to convert from MB to GB

  $TotalDatastoreDiskSpaceinGB = [system.math]::ceiling($TotalDatastoreDiskSpaceinGB) # Round down

  return $TotalDatastoreDiskSpaceinGB

}

Function GetVMHostMemoryinGB ($vmhosttemp){

  $TempVMHostRAMinGB = $vmhosttemp.MemoryTotalMB -as [int] # Convert from String to Int

  $TempVMHostRAMinGB = $TempVMHostRAMinGB / 1024 # Divide by 1024 to convert from MB to GB

  $TempVMHostRAMinGB = [system.math]::ceiling($TempVMHostRAMinGB) # Round down

  return $TempVMHostRAMinGB

}

Function GetVMHostAverageCPUUsagePercentage ($vmhosttemp) { #For the last 30 days

  $AverageCPUUsagePercentage = Get-Stat -Entity ($vmhosttemp)-start (get-date).AddDays(-30) -Finish (Get-Date)-MaxSamples 31 -stat cpu.usage.average

  $AverageCPUUsagePercentage = $AverageCPUUsagePercentage | Measure-Object -Property value -Average

  $AverageCPUUsagePercentage = $AverageCPUUsagePercentage.Average

  $AverageCPUUsagePercentage = [system.math]::ceiling($AverageCPUUsagePercentage) # Round up

  return $AverageCPUUsagePercentage

}

Function GetVMHostAverageMemoryUsagePercentage ($vmhosttemp) { #For the last 30 days

  $AverageMemoryUsagePercentage = Get-Stat -Entity ($vmhosttemp)-start (get-date).AddDays(-30) -Finish (Get-Date)-MaxSamples 31 -stat mem.usage.average

  $AverageMemoryUsagePercentage = $AverageMemoryUsagePercentage | Measure-Object -Property value -Average

  $AverageMemoryUsagePercentage = $AverageMemoryUsagePercentage.Average

  $AverageMemoryUsagePercentage = [system.math]::ceiling($AverageMemoryUsagePercentage) # Round up

  return $AverageMemoryUsagePercentage

}

Function GetDatastoreCurrentDiskSpaceUsagePercentage ($DatastoreTemp) {

  $DatastoreFreeSpaceinMB = $DatastoreTemp.FreeSpaceMB -as [int]

  $DatastoreCapacityinMB= $DatastoreTemp.CapacityMB -as [int]

  $DatastoreCurrentDiskSpaceUsagePercentage = 100 - ($DatastoreFreeSpaceinMB / $DatastoreCapacityinMB *100)

  $DatastoreCurrentDiskSpaceUsagePercentage = [system.math]::ceiling($DatastoreCurrentDiskSpaceUsagePercentage) # Round up

  return $DatastoreCurrentDiskSpaceUsagePercentage

}

Function GetDatastoreCapacityinGB ($DatastoreTemp) {

  $DatastoreCapacityinGB = $DatastoreTemp.CapacityMB -as [int]

  $DatastoreCapacityinGB = $DatastoreCapacityinGB / 1024 # Divide by 1024 to convert from MB to GB

  $DatastoreCapacityinGB = [system.math]::ceiling($DatastoreCapacityinGB) # Round up

  return $DatastoreCapacityinGB

}

Function GetNumberofVMsInDatastore ($DatastoreTemp) {

  $DatastoreTemp = $DatastoreTemp | Get-VM | Measure-Object | Select-Object Count

  return $DatastoreTemp.Count

}

Function GetDatastoreAllocationPercentage ($DatastoreTemp) {

  $DatastoreTemp = $DatastoreTemp | Get-View

  $DSAllocationTemp = [math]::round(((($DatastoreTemp.Summary.Capacity - $DatastoreTemp.Summary.FreeSpace)`

  + $DatastoreTemp.Summary.Uncommitted)*100)/$DatastoreTemp.Summary.Capacity,0)

  return $DSAllocationTemp

}

Function GetVMHostCurrentMemoryUsagePercentage ($vmhosttemp) {

  $MemoryUsageinMhz = $vmhosttemp.MemoryUsageMB -as [int]

  $MemoryTotalinMhz = $vmhosttemp.MemoryTotalMB -as [int]

  $MemoryUsagePercentage = $MemoryUsageinMhz / $MemoryTotalinMhz *100

  $MemoryUsagePercentage = [system.math]::ceiling($MemoryUsagePercentage) # Round up

  return $MemoryUsagePercentage

}

Function GetVMHostCurrentCPUUsagePercentage ($vmhosttemp) {

  $CPUUsageinMhz = $vmhosttemp.CpuUsageMhz -as [int]

  $CPUTotalinMhz = $vmhosttemp.CpuTotalMhz -as [int]

  $CPUUsagePercentage = $CPUUsageinMhz / $CPUTotalinMhz *100

  $CPUUsagePercentage = [system.math]::ceiling($CPUUsagePercentage) # Round up

  return $CPUUsagePercentage

}

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

}

Function GetVMAverageMemoryUsage ($VMsTemp) {

  $TotalVMMemoryinMB = $VMsTemp | Measure-Object -Property MemoryMB -Sum # Count total RAM in MB

  $TotalVMMemoryinMB = $TotalVMMemoryinMB.Sum -as [int] # Convert from String to Int

  #$TotalVMMemoryinGB = $TotalVMMemoryinMB / 1024 # Divide by 1024 to convert from MB to GB # VALUE NOT HIGH ENOUGH

  $AverageVMMemoryInGB = $TotalVMMemoryinMB / $VMsTemp.Length # Divide by number of VMs

  $AverageVMMemoryInGB = [system.math]::ceiling($AverageVMMemoryInGB) # Round down

  return $AverageVMMemoryInGB

}

Function GetVMAverageDatastoreUsage ($VMsTemp) {

  $TotalVMProvisionedSpaceinGB = $VMsTemp | Measure-Object -Property ProvisionedSpaceGB -Sum # Count total RAM in MB

  $TotalVMProvisionedSpaceinGB = $TotalVMProvisionedSpaceinGB.Sum -as [int] # Convert from String to Int

  $VMAverageDatastoreUsage = $TotalVMProvisionedSpaceinGB / $VMsTemp.Length # Divide by number of VMs

  $VMAverageDatastoreUsage = [system.math]::ceiling($VMAverageDatastoreUsage) # Round up

  return $VMAverageDatastoreUsage

}

Function GetVMTotalMemory ($VMsTemp) {

  $VMTotalMemory = $VMsTemp | Measure-Object -Property MemoryMB -Sum

  $VMTotalMemory = $VMTotalMemory.Sum / 1024 # Divide by 1024 to convert from MB to GB

  $VMTotalMemory = [system.math]::ceiling($VMTotalMemory)

  return $VMTotalMemory

}

Function GetVMTotalCPUs ($VMsTemp) {

  $VMTotalCPUs = $VMsTemp  | Measure-Object -Property NumCpu -Sum

  return $VMTotalCPUs.Sum

}

Function GetCPUSlotsAvailable ($VMHostsInClusterTemp, $ClusterVMAverageCPUUsageTemp) {

  $VMHostsTotalCPUMhz = $VMHostsInClusterTemp | Measure-Object -Property CpuTotalMhz -Sum

  $VMHostsUsedCPUMhz = $VMHostsInClusterTemp | Measure-Object -Property CpuUsageMhz -Sum

  $VMHostsTotalCPUMhz = $VMHostsTotalCPUMhz.Sum * 0.90 # Keep 10% available for best practice

  $VMHostsUsedCPUMhz = $VMHostsUsedCPUMhz.Sum

  $VMHostsAvailableCPUMhz = $VMHostsTotalCPUMhz - $VMHostsUsedCPUMhz

  $ClusterCPUSlots = $VMHostsAvailableCPUMhz / $ClusterVMAverageCPUUsageTemp # The rest divided by 1 CPU Slot

  $ClusterCPUSlots = [system.math]::floor($ClusterCPUSlots) # Round down

  return $ClusterCPUSlots

}

Function GetMemorySlotsAvailable ($VMHostsInClusterTemp, $ClusterVMAverageMemoryUsageTemp) {

  $VMHostsTotalMemoryMB = $VMHostsInClusterTemp | Measure-Object -Property MemoryTotalMB -Sum

  $VMHostsUsedMemoryMB = $VMHostsInClusterTemp | Measure-Object -Property MemoryUsageMB -Sum

  $VMHostsTotalMemoryMB = $VMHostsTotalMemoryMB.Sum * 0.90 # Keep 10% available for best practice

  $VMHostsUsedMemoryMB = $VMHostsUsedMemoryMB.Sum

  $VMHostsAvailableMemoryMB = $VMHostsTotalMemoryMB - $VMHostsUsedMemoryMB

  $ClusterMemorySlots = $VMHostsAvailableMemoryMB / $ClusterVMAverageMemoryUsageTemp # The rest divided by 1 Memory Slot

  $ClusterMemorySlots = [system.math]::floor($ClusterMemorySlots) # Round down

  return $ClusterMemorySlots

}

Function GetDatastoreSlotsAvailable ($DatastoresInClusterTemp, $ClusterVMAverageMemoryUsageTemp) {

  # Remove 5% of Datastore capacity for Best Practices

  $DatastoreCapacityTemp = $DatastoresInClusterTemp | Measure-Object -Property CapacityMB -Sum

  $DatastoreCapacityMinus5Percent = $DatastoreCapacity.Sum * 0.95

  $5PercentOfDatastoreCapacity = $DatastoreCapacity.Sum - $DatastoreCapacityMinus5Percent

  $DatastoreFreeSpaceMB = $DatastoreFreeSpaceMB - $5PercentOfDatastoreCapacity

  $DatastoreFreeSpaceMB = $DatastoresInClusterTemp | Measure-Object -Property FreeSpaceMB -Sum

  $DatastoreFreeSpaceMB = $DatastoreFreeSpaceMB.Sum / 1024 # Divide by 1024 to convert from MB to GB

  $DatastoreFreeSpaceMB = $DatastoreFreeSpaceMB - $5PercentOfDatastoreCapacity # Keep 5% available for best practice

  $ClusterDatastoreSlots = $DatastoreFreeSpaceMB / $ClusterVMAverageMemoryUsageTemp # Divided by 1 Memory Slot

  $ClusterDatastoreSlots = [system.math]::floor($ClusterDatastoreSlots) # Round down

  return $ClusterDatastoreSlots

}

Function GetVMProvisioningPotential ($CPUSLOTS, $MEMORYSLOTS, $DATASTORESLOTS) {

  if ($CPUSLOTS -le $MEMORYSLOTS -and  $CPUSLOTS -le $DATASTORESLOTS){ return ([String]$CPUSLOTS + ". CPU is your limiting factor.")}

  if ($MEMORYSLOTS -le $CPUSLOTS -and  $MEMORYSLOTS -le $DATASTORESLOTS){ return ([String]$MEMORYSLOTS + ". Memory is your limiting factor.")}

  if ($DATASTORESLOTS -le $CPUSLOTS -and  $DATASTORESLOTS -le $MEMORYSLOTS){ return ([String]$DATASTORESLOTS + ". Datastore Disk Space is your limiting factor.")}

}

Function CreateHeader ($text) {

  $HeaderTemp = "<hr>"

  $HeaderTemp += "<h2><b><center>" + $text + "</center></b></h2>"

  $HeaderTemp += "<hr>"

  $HeaderTemp += "<br>"

  return $HeaderTemp

}

Function ListVCenterInventory () {

  $InventoryTemp = "<h4>"

  $HostTemp = Get-VMHost | Select-Object -First 1

  $InventoryTemp += "vCenter version " + (($HostTemp | Select-Object @{N="vCenterVersion";E={$global:DefaultVIServers | where {$_.Name.ToLower() -eq ($HostTemp.ExtensionData.Client.ServiceUrl.Split('/')[2]).ToLower()} | %{"$($_.Version) Build $($_.Build)"}   }}).vCenterVersion) + "<br>"

  $InventoryTemp += [String]$DC.Count + " Datacenters <br>"

  $InventoryTemp += [String]$Clusters.Count + " Clusters <br>"

  $InventoryTemp += [String]$VMHosts.Count + " ESXi Hosts with a total of " + (GetTotalCPUCyclesInGhz ($VMHosts)) + " GHz on " + `

  (GetTotalNumberofCPUs ($VMHosts)) + " CPUs and " + (GetTotalMemoryInGB ($VMHosts)) + " GB of RAM <br>"

  $InventoryTemp += [String]$Datastores.Count + " Datastores with a total of " + (GetTotalDatastoreDiskSpaceinGB ($Datastores)) + " GB of disk space <br>"

  $InventoryTemp += [String]$VM.Count + " Virtual Machines <br>"

  $InventoryTemp += [String]$Templates.Count + " Templates <br>"

  $InventoryTemp += [String]$ResourcePools.Count + " Resource Pools <br>"

  $InventoryTemp += [String][system.math]::floor($VM.Count / $VMHosts.Count) + ":1" + " Consolidation ratio <br>"

  $InventoryTemp += "<br>"

  $InventoryTemp += BuildESXiSoftwareAndHardwareInfoTable ($VMHosts)

  $InventoryTemp += "</h4>"

  return $InventoryTemp

}

Function BuildESXiSoftwareAndHardwareInfoTable ($VMHostsTemp) {

  $ESXiSoftwareAndHardwareInfoTemp = "<table border=1>"

  $ESXiSoftwareAndHardwareInfoTemp += "<tr><th colspan=6><b><center> ESXi Software and Hardware Information </center></b></th></tr>"

  $ESXiSoftwareAndHardwareInfoTemp += "<tr><td width=200><b>Host Name</b></td><td width=200><b>Server Model</b></td><td width=130><b>Number of CPUs</b></td>" `

  + "<td width=180><b>RAM Quantity (in GB)</b></td><td width=170><b>ESXi Version</b></td><td width=80><b>Uptime</b></td></tr>"

  Write-Host "          " Gathering ESXi Hardware and Software Information...

  $ESXiSoftwareAndHardwareInfoTemp += $VMHostsTemp | Sort-Object name | ForEach-Object {

  "<tr><td>" + $_.Name + "</td><td>" + $_.Manufacturer + " " + $_.Model + "</td><td>" + $_.NumCpu + " CPUs </td><td>" `

  + (GetTotalMemoryInGB ($_)) + " GB </td><td>" + $_.Version + " Build " + $_.Build + "</td><td>" `

  + ($_ | Get-View | select @{N="Uptime"; E={(Get-Date) - $_.Summary.Runtime.BootTime}}).Uptime.Days + " days </td>"

  }

  $ESXiSoftwareAndHardwareInfoTemp += "</table><br>"

  return $ESXiSoftwareAndHardwareInfoTemp

}

Function ListClusterInventory ($ClusterTemp) {

  Write-Host "          " Gathering $ClusterTemp.Name "inventory..."

  # 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 | 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

  $InventoryTemp = "<h4>"

  $InventoryTemp += [String]$VMHostsTemp.Count + " ESXi Hosts with a total of " + (GetTotalCPUCyclesInGhz ($VMHostsTemp)) + " GHz on " + `

  (GetTotalNumberofCPUs ($VMHostsTemp)) + " CPUs and " + (GetTotalMemoryInGB ($VMHostsTemp)) + " GB of RAM <br>"

  $InventoryTemp += [String]$DatastoresTemp.Count + " Datastores with a total of " + (GetTotalDatastoreDiskSpaceinGB ($DatastoresTemp)) + " GB of disk space <br>"

  $InventoryTemp += [String]$VMTemp.Count + " Virtual Machines <br>"

  $NbOfResourcePoolsTemp = $ResourcePoolsTemp | Measure-Object;

  $InventoryTemp += [String]$NbOfResourcePoolsTemp.Count + " Resource Pools <br>"

  $InventoryTemp += [String][system.math]::floor($VMTemp.Count / $VMHostsTemp.Count) + ":1" + " Consolidation ratio <br>"

  $InventoryTemp += "<br>"

  $InventoryTemp += BuildESXiSoftwareAndHardwareInfoTable ($VMHostsTemp)

  $InventoryTemp += "</h4>"

  return $InventoryTemp

}

Function ReinitializeArrays (){ #Reinitialize variables for reuse

  Clear-Variable -Name ArrayOfNames

  Clear-Variable -Name ArrayOfValues

  $global:ArrayOfNames = @()

  $global:ArrayOfValues = @()

}

Function CreateVMHostCPUUsageTable ($VMHostsTemp){ # Builds CPU HTML Table and populates Arrays used to create chart

  $CPUTableTemp = "<table border=1>"

  $CPUTableTemp += "<tr><th colspan=4><b><center> ESXi Host CPU Usage Statistics </center></b></th></tr>"

  $CPUTableTemp += "<tr><td width=200><b>Host Name</b></td><td width=130><b>Number of CPUs</b></td><td width=200><b>Current CPU Usage %</b></td>" `

  + "<td width=250><b>Monthly Average CPU Usage %</b></td></tr>"

  $CPUTableTemp += $VMHostsTemp | Sort-Object name | ForEach-Object {

  Write-Host "          " Gathering $_.Name "CPU usage statistics..."

  $tempVMHostAverageCPUUsagePercentage = (GetVMHostAverageCPUUsagePercentage $_)

  "<tr><td>" + $_.name + " </td><td>" + $_.NumCpu + " CPUs </td><td> " + (GetVMHostCurrentCPUUsagePercentage $_) `

  + "% </td><td>" + ($tempVMHostAverageCPUUSagePercentage) + "% </td>"

  $global:ArrayOfNames += $_.Name

  $global:ArrayOfValues += ($tempVMHostAverageCPUUSagePercentage)

  }

  $CPUTableTemp += "</table>"

  return $CPUTableTemp

}

Function CreateVMHostMemoryUsageTable ($VMHostsTemp){ # Builds Memory HTML Table and populates Arrays used to create chart

  $MemoryTableTemp = "<table border=1>"

  $MemoryTableTemp += "<tr><th colspan=4><b><center> ESXi Host Memory Usage Statistics </center></b></th></tr>"

  $MemoryTableTemp += "<tr><td width=200><b>Host Name</b></td><td width=200><b>RAM Quantity (in GB)</b></td><td width=200><b>Current Memory Usage % " `

  + "</b></td><td width=250><b>Monthly Average Memory Usage %</b></td></tr>"

  $MemoryTableTemp += $VMHostsTemp | Sort-Object name | ForEach-Object {

  Write-Host "          " Gathering $_.Name "Memory usage statistics..."

  $tempVMHostAverageMemoryUsagePercentage = (GetVMHostAverageMemoryUsagePercentage $_)

  "<tr><td>" + $_.name + " </td><td>" + (GetVMHostMemoryinGB $_) + " GB </td><td> " + (GetVMHostCurrentMemoryUsagePercentage $_) `

  + "% </td><td>" + ($tempVMHostAverageMemoryUsagePercentage) + "% </td>"

  $global:ArrayOfNames += $_.Name

  $global:ArrayOfValues += ($tempVMHostAverageMemoryUsagePercentage)

  }

  $MemoryTableTemp += "</table>"

  return $MemoryTableTemp

}

Function CreateDatastoreUsageTable ($DatastoresTemp){ # Builds Datastore HTML Table and populates Arrays used to create chart

  $DatastoreTableTemp += "<table border=1>"

  $DatastoreTableTemp += "<tr><th colspan=5><b><center> Datastore Usage Statistics </center></b></th></tr>"

  $DatastoreTableTemp += "<tr><td width=300><b>Datastore Name</b></td><td width=200><b>Total Disk Space (in GB)</b></td>" `

  + "<td><b>Current Usage % </b></td><td><b>Number of VMs contained</b></td><td><b>Commitment %</b></td></tr>"

  $DatastoreTableTemp += $DatastoresTemp | Sort-Object name | ForEach-Object {

  Write-Host "          " Gathering $_.Name "Datastore usage statistics..."

  "<tr><td>" + $_.name + " </td><td>" + (GetDatastoreCapacityinGB $_) + " GB </td><td> " + `

  (GetDatastoreCurrentDiskSpaceUsagePercentage $_) + "% </td><td>" + (GetNumberofVMsInDatastore $_)+  "</td>" `

  + "<td>" + (GetDatastoreAllocationPercentage $_) + "% </tr>"

  $global:ArrayOfNames += $_.Name

  $global:ArrayOfValues += (GetDatastoreCurrentDiskSpaceUsagePercentage $_)

  }

  $DatastoreTableTemp += "</table>"

  return $DatastoreTableTemp

}

Function CreateClusterProvisioningPotentialTables ($ClusterTemp) {

  $VMsInClusterTemp = $ClusterTemp | Get-VM

  # Remove biggest host from collection

  $BiggestHostInCluster = $ClusterTemp | Get-VMHost | Sort-Object MemoryTotalMB -Descending | Select-Object -First 1

  $VMHostsInClusterMinusBiggest = $ClusterTemp | Get-VMHost | Where-Object {$_.Name -ne $BiggestHostInCluster.Name}

  $DatastoresInClusterMinusBiggestHosts = $VMHostsInClusterMinusBiggest | Get-Datastore

  $ClusterVMAverageCPUUsage = (GetVMAverageCPUUsage ($VMsInClusterTemp))

  $ClusterVMAverageMemoryUsage = (GetVMAverageMemoryUsage ($VMsInClusterTemp))

  $ClusterVMAverageDatastoreUsage = (GetVMAverageDatastoreUsage ($VMsInClusterTemp))

  $AvailableCPUSlotsInCluster = (GetCPUSlotsAvailable $VMHostsInClusterMinusBiggest $ClusterVMAverageCPUUsage)

  $AvailableMemorySlotsInCluster = (GetMemorySlotsAvailable $VMHostsInClusterMinusBiggest $ClusterVMAverageMemoryUsage)

  $AvailableDatastoreSlotsInCluster  = (GetDatastoreSlotsAvailable $DatastoresInClusterMinusBiggestHosts $ClusterVMAverageDatastoreUsage)

  # Average Usage Statistics Table

  $ClusterProvisioningTableTemp += "<table border=1 width=1000>"

  $ClusterProvisioningTableTemp += "<tr><th colspan=4><b><center> Virtual Machine Average Usage Statistics </center></b></th></tr>"

  $ClusterProvisioningTableTemp += "<tr><td><b>Total Number of VMs</b></td><td><b>Average VM CPU Usage</b></td><td><b>Average VM Memory Usage</b></td><td><b>Average VM Datastore Usage</b></td></tr>"

  $ClusterProvisioningTableTemp += "<tr><td>" + $VMsInCluster.Length + "</td><td>" + $ClusterVMAverageCPUUsage + " MHz </td><td>" + $ClusterVMAverageMemoryUsage + " MB </td><td>" + `

  $ClusterVMAverageDatastoreUsage + " GB </td></tr>"

  $ClusterProvisioningTableTemp += "</table>"

  $ClusterProvisioningTableTemp += "<br>"

  # Available Resource Slots Table

  $ClusterProvisioningTableTemp += "<table border=1 width=1000>"

  $ClusterProvisioningTableTemp += "<tr><th colspan=4><b><center> Available Virtual Machine Resource Slots </center></b></th></tr>"

  $ClusterProvisioningTableTemp += "<tr><td>1 Slot = Average VM allocation</td><td><b>CPU Slots Available</b></td><td><b>Memory Slots Available</b></td><td><b>Datastore Slots Available</b></td></tr>"

  $ClusterProvisioningTableTemp += "<tr><td></td><td>" + $AvailableCPUSlotsInCluster + "</td><td>" + $AvailableMemorySlotsInCluster `

    + "</td><td>" + $AvailableDatastoreSlotsInCluster + "</td></tr>"

  $ClusterProvisioningTableTemp += "</table>"

  $ClusterProvisioningTableTemp += "<br>"

  # Provisioning potential Table

  $ClusterProvisioningTableTemp += "<table border=1 width=1000>"

  $ClusterProvisioningTableTemp += "<tr><th colspan=4><b><center> Virtual Machine Provisioning Potential </center></b></th></tr>"

  $ClusterProvisioningTableTemp += "<tr><th colspan=4><center> <font color=red>The <u>approximate</u> number of Virtual Machines you can provision safely in this cluster is " + `

  (GetVMProvisioningPotential $AvailableCPUSlotsInCluster $AvailableMemorySlotsInCluster $AvailableDatastoreSlotsInCluster) +  "</font>*</center></th></tr>"

  $ClusterProvisioningTableTemp += "<tr><th colspan=4><center>*<i>Calculations are according to CPU, Memory and Datastore disk space VM average statistics. Statistics are calculated conservatively.</i></center></th></tr>"

  $ClusterProvisioningTableTemp += "</table><br>"

  return $ClusterProvisioningTableTemp

}

Function CreateClusterResilienceTable ($ClusterTemp) {

  Write-Host "          " Gathering Cluster Resilience Information for Cluster $ClusterTemp.Name

  # Get HA info

  $HAEnabled = $ClusterTemp | Select-Object HAEnabled; $HAEnabled = $HAEnabled.HAEnabled

  $ACEnabled = $ClusterTemp | Select-Object HAAdmissionControlEnabled; $ACEnabled = $ACEnabled.HAAdmissionControlEnabled

  $ACPolicy = "N/A"

  $HostLossTolerance = 0

  # GET HA Admission Control Policy

  if ($HAEnabled -and $ACEnabled){

  if ((($ClusterTemp | Select-Object HAFailoverlevel).HAFailoverLevel) -eq 0){ # If protection setting is NOT a # of hosts

  $ClusterView = Get-View -ViewType "ClusterComputeResource" -Filter @{"Name" = $ClusterTemp.Name}

  $ACPolicyInteger = $ClusterView.configuration.dasConfig.admissionControlpolicy.cpuFailoverResourcesPercent

  $ACPolicy = [String]$ACPolicyInteger  + " % of resources reserved"

  # CHART VALUE PREPARATIONS

  $ClusterUsedMemory = ($ClusterTemp | Get-VMHost | Measure-Object MemoryUsageMB -Sum).sum

  $ClusterTotalMemory = ($ClusterTemp | Get-VMHost | Measure-Object MemoryTotalMB -Sum).sum

  $ClusterFreeMemory = $ClusterTotalMemory - $ClusterUsedMemory - $ACPolicyInteger

  $ClusterUsedMemoryPercentage = [system.math]::floor($ClusterUsedMemory * 100 / $ClusterTotalMemory)

  $ClusterFreeMemoryPercentage = [system.math]::floor($ClusterFreeMemory * 100 / $ClusterTotalMemory)

  $ClusterFreeMemoryPercentage = $ClusterFreeMemoryPercentage - $ACPolicyInteger

  $global:ArrayOfNames += "Used"

  $global:ArrayOfValues += $ClusterUsedMemoryPercentage

  $global:ArrayOfNames += "Free"

  $global:ArrayOfValues += $ClusterFreeMemoryPercentage

  $global:ArrayOfNames += "HA Admission Control Reservation"

  $global:ArrayOfValues += $ACPolicyInteger

  # Host Loss Tolerance Calculation

  $BiggestHostInCluster = $ClusterTemp | Get-VMHost | Sort-Object MemoryTotalMB -Descending | Select-Object -First 1

  $HAReservedMemory = ($ACPolicyInteger/100) * ($ClusterTemp | Get-VMHost | Measure-Object MemoryTotalMB -Sum).sum

  $HostLossTolerance = $HAReservedMemory / $BiggestHostInCluster.MemoryTotalMB

  $HostLossTolerance = [System.Math]::Round($HostLossTolerance,2)

  }else{ # If protection setting is a # of hosts

  $ACPolicy =  ($ClusterTemp | Select-Object HAFailoverlevel).HAFailoverLevel

  $ACPolicy = [String]$ACPolicy  + " host(s) reserved"

  $HostLossTolerance = ($ClusterTemp | Select-Object HAFailoverlevel).HAFailoverLevel

  }

  }

  # Build HTML Table

  $ClusterResilienceTableTemp += "<table border=1>"

  $ClusterResilienceTableTemp += "<tr><th colspan=3><b><center> Cluster Resilience Report </center></b></th></tr>"

  $ClusterResilienceTableTemp += "<tr><td width=300><b>HA Enabled</b></td><td width=300><b>Admission Control Enabled</b></td><td width=300><b>Admission Control Policy</b></td></tr>"

  $ClusterResilienceTableTemp += "<tr><td>" + $HAEnabled + " </td><td>" + $ACEnabled + " </td><td>" + $ACPolicy + " </td></tr>"

  $ClusterResilienceTableTemp += "<tr><th colspan=3><b><font color=red><center> This cluster can survive the loss of approximately " + $HostLossTolerance + " host(s)</center></font></b></th></tr>"

  $ClusterResilienceTableTemp += "</table><br>"

  return $ClusterResilienceTableTemp

}

Function CreateVirtualMachineOSTable ($VMsTemp){ # Builds VM HTML Table and populates Arrays used to create chart

  Write-Host "          " Collecting Virtual Machine Guest OS information...

  # Calculate how many of each Guest OS

  $NumberOfWindowsVMs = $VMsTemp | Where-Object {$_.Guest -like "*Windows*"} | Measure-Object

  $NumberOfWindowsVMs = $NumberOfWindowsVMs.Count

  $NumberOfLinuxVMs = $VMsTemp | Where-Object {$_.Guest -like "*inux*" -OR $_.Guest -like "*nix*"} | Measure-Object

  $NumberOfLinuxVMs = $NumberOfLinuxVMs.Count

  $NumberOfOtherVMs = [int]$VMsTemp.Length - ([int]$NumberOfWindowsVMs + [int]$NumberOfLinuxVMs)

  # Build HTML Table

  $VMTableTemp += "<table border=1>"

  $VMTableTemp += "<tr><th colspan=2><b><center> Virtual Machine Guest OS Breakdown </center></b></th></tr>"

  $VMTableTemp += "<tr><td width=200><b>Operating System Type</b></td><td width=200><b>Number of VMs</b></td></tr>"

  $VMTableTemp += "<tr><td> Windows </td><td>" + $NumberOfWindowsVMs + " </td></tr>"

  $VMTableTemp += "<tr><td> Linux/Unix </td><td>" + $NumberOfLinuxVMs + " </td></tr>"

  $VMTableTemp += "<tr><td> Other </td><td>" + $NumberOfOtherVMs + " </td></tr>"

  $VMTableTemp += "<tr><td> TOTAL </td><td>" + $VMsTemp.Length + " </td></tr>"

  $VMTableTemp += "</table><br>"

  # Populate Arrays to create Chart

  $global:ArrayOfNames += "Windows"

  $global:ArrayOfNames += "Linux/Unix"

  $global:ArrayOfNames += "Other"

  $global:ArrayOfValues += $NumberOfWindowsVMs

  $global:ArrayOfValues += $NumberOfLinuxVMs

  $global:ArrayOfValues += $NumberOfOtherVMs

  return $VMTableTemp

}

# Credit to Sean from Shogun Tech :

#http://www.shogan.co.uk/vmware/generating-graphical-charts-with-vmware-powercli-powershell/

Function Create-Chart() {

  Param(

     [String]$ChartType,

  [String]$ChartTitle,

     [String]$FileName,

  [String]$XAxisName,

     [String]$YAxisName,

  [Int]$ChartWidth,

  [Int]$ChartHeight,

  [String[]]$NameArray, #Added by MVD

  [Int[]]$ValueArray #Added by MVD

  )

  [void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

  [void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms.DataVisualization")

  Write-Host "          " Creating chart...

  #Create our chart object

  $Chart = New-object System.Windows.Forms.DataVisualization.Charting.Chart

  $Chart.Width = $ChartWidth

  $Chart.Height = $ChartHeight

  $Chart.Left = 10

  $Chart.Top = 10

  #Create a chartarea to draw on and add this to the chart

  $ChartArea = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea

  $Chart.ChartAreas.Add($ChartArea)

  [void]$Chart.Series.Add("Data")

  $Chart.ChartAreas[0].AxisX.Interval = "1" #Set this to 1 (default is auto) and allows all X Axis values to display correctly

  $Chart.ChartAreas[0].AxisX.IsLabelAutoFit = $false;

  $Chart.ChartAreas[0].AxisX.LabelStyle.Angle = "-45"

  #Add the Actual Data to our Chart

  $Chart.Series["Data"].Points.DataBindXY($NameArray, $ValueArray) #Modified by MVD

  if (($ChartType -eq "Pie") -or ($ChartType -eq "pie")) {

  $ChartArea.AxisX.Title = $XAxisName

  $ChartArea.AxisY.Title = $YAxisName

  $Chart.Series["Data"].ChartType = [System.Windows.Forms.DataVisualization.Charting.SeriesChartType]::Pie

  $Chart.Series["Data"]["PieLabelStyle"] = "Outside"

  $Chart.Series["Data"]["PieLineColor"] = "Black"

  $Chart.Series["Data"]["PieDrawingStyle"] = "Concave"

  #($Chart.Series["Data"].Points.FindMaxByValue())["Exploded"] = $true

  $Chart.Series["Data"].Label = "#VALX = #VALY\n" # Give an X & Y Label to the data in the plot area (useful for Pie graph)

  #(Display both axis labels, use: Y = #VALY\nX = #VALX)

  }

  elseif (($ChartType -eq "Bar") -or ($ChartType -eq "bar")) {

  #$Chart.Series["Data"].Sort([System.Windows.Forms.DataVisualization.Charting.PointSortOrder]::Descending, "Y")

  $ChartArea.AxisX.Title = $XAxisName

  $ChartArea.AxisY.Title = $YAxisName

  # Find point with max/min values and change their colour

  $maxValuePoint = $Chart.Series["Data"].Points.FindMaxByValue()

  $maxValuePoint.Color = [System.Drawing.Color]::Red

  $minValuePoint = $Chart.Series["Data"].Points.FindMinByValue()

  $minValuePoint.Color = [System.Drawing.Color]::Green

  # make bars into 3d cylinders

  $Chart.Series["Data"]["DrawingStyle"] = "Cylinder"

  $Chart.Series["Data"].Label = "#VALY" # Give a Y Label to the data in the plot area (useful for Bar graph)

  }

  else {

  Write-Host "No Chart Type was defined. Try again and enter either Pie or Bar for the ChartType Parameter. " `

  "The chart will be created as a standard Bar Graph Chart for now." -ForegroundColor Cyan

  }

  #Set the title of the Chart to the current date and time

  $Title = new-object System.Windows.Forms.DataVisualization.Charting.Title

  $Chart.Titles.Add($Title)

  $Chart.Titles[0].Text = $ChartTitle

  #Save the chart to a file

  $FullPath = ((Get-Location).Path + "\" + $FileName + ".png")

  $Chart.SaveImage($FullPath,"png")

  #Write-Host "Chart saved to $FullPath" -ForegroundColor Green

  #return $FullPath

}

################################################# OUTPUT ##########################################################

######################## INVENTORY ############################

Write-Host Step 1/6 - Collecting inventory...

$HTMLBody = "<BODY>"

$HTMLBody += "$Date<br>"

$HTMLBody += "<h1><b><center>VMWare Capacity & Performance Report for " + $vCenterServerName + "</center></b></h1>"

$HTMLBody += CreateHeader ("INVENTORY FOR <font color=green><b> vCENTER " + $vCenterServerName + "</font></b>")

$HTMLBody += ListVCenterInventory

$HTMLBody +=

######################## vCenter CPU CAPACITY REPORT ############################

Write-Host Step 2/6 - Collecting CPU statistics...

# HEADER

$HTMLBody += CreateHeader ("CPU CAPACITY REPORT FOR <font color=green><b> vCENTER " + $vCenterServerName + "</font></b>")

# INTRO TEXT

$HTMLBody += "<b>" + [String]$VMHosts.Count + " ESXi Hosts with a total of " + (GetTotalCPUCyclesInGhz ($VMHosts)) + " GHz on " +

  (GetTotalNumberofCPUs ($VMHosts)) + " CPUs </b><br><br>"

# TABLE

$HTMLBody += CreateVMHostCPUUsageTable ($VMHosts)

# CHART

Create-Chart -ChartType Bar -ChartTitle "Monthly Average Host CPU Usage Percentage" -FileName ("vCenter_CPU_Usage") -ChartWidth 750 `

-ChartHeight 650 -NameArray $global:ArrayOfNames -ValueArray $global:ArrayOfValues

$HTMLBody += "<IMG SRC=vCenter_CPU_Usage.png>"

$Attachments += "vCenter_CPU_Usage.png"

# CLEANUP

ReinitializeArrays

######################## vCenter MEMORY CAPACITY REPORT ############################

Write-Host Step 3/6 - Collecting Memory information...

# HEADER

$HTMLBody += CreateHeader ("MEMORY CAPACITY REPORT FOR <font color=green><b> vCENTER " + $vCenterServerName + "</font></b>")

# INTRO TEXT

$HTMLBody += "<b>" + [String]$VMHosts.Count + " ESXi Hosts with a total of " + (GetTotalMemoryInGB ($VMHosts)) + " GB of RAM </b><br><br>"

# TABLE

$HTMLBody += CreateVMHostMemoryUsageTable ($VMHosts)

# CHART

Create-Chart -ChartType Bar -ChartTitle "Monthly Average Host Memory Usage Percentage" -FileName ("vCenter_Memory_Usage") -ChartWidth 750 `

-ChartHeight 650 -NameArray $global:ArrayOfNames -ValueArray $global:ArrayOfValues

$HTMLBody += "<IMG SRC=vCenter_Memory_Usage.png>"

$Attachments += "vCenter_Memory_Usage.png"

# CLEANUP

ReinitializeArrays

######################## vCenter DATASTORE CAPACITY REPORT ############################

Write-Host Step 4/6 - Collecting Datastore information...

# HEADER

$HTMLBody += CreateHeader ("DATASTORE CAPACITY REPORT FOR <font color=green><b> vCENTER " + $vCenterServerName + "</font></b>")

# INTRO TEXT

$HTMLBody += "<b>" + [String]$Datastores.Count + " Datastores with a total of " + (GetTotalDatastoreDiskSpaceinGB ($Datastores)) + `

  " GB of disk space</b><br><br>"

# TABLE

$HTMLBody += CreateDatastoreUsageTable ($Datastores)

# CHART

Create-Chart -ChartType Bar -ChartTitle "Datastore Usage Percentage " -FileName ("vCenter_Datastore_Usage") -ChartWidth 1200 `

-ChartHeight 650 -NameArray $global:ArrayOfNames -ValueArray $global:ArrayOfValues

$HTMLBody += "<IMG SRC=vCenter_Datastore_Usage.png>"

$Attachments += "vCenter_Datastore_Usage.png"

# CLEANUP

ReinitializeArrays

######################## vCenter VIRTUAL MACHINE REPORT ############################

Write-Host Step 5/6 - Collecting Virtual Machine information...

# HEADER

$HTMLBody += CreateHeader ("VIRTUAL MACHINE REPORT FOR <font color=green><b> vCENTER " + $vCenterServerName + "</font></b>")

# INTRO TEXT

$HTMLBody += "<b>" + [String]$VM.Count + " Virtual Machines</b><br><br>"

  

# TABLE

$HTMLBody += CreateVirtualMachineOSTable ($VM)

# CHART

Create-Chart -ChartType Pie -ChartTitle "VM Operating System Report" -FileName ("vCenter_VM_OS_Report") -ChartWidth 750 `

-ChartHeight 650 -NameArray $global:ArrayOfNames -ValueArray $global:ArrayOfValues

$HTMLBody += "<IMG SRC=vCenter_VM_OS_Report.png>"

$Attachments += "vCenter_VM_OS_Report.png"

# CLEANUP

ReinitializeArrays

########################  PER CLUSTER REPORT ############################

Write-Host Step 6/6 - Collecting Cluster information...

# Loop through all clusters

ForEach ($ClusterTemp in ($Clusters)){

  $NumberOfVMHostsInCluster = $ClusterTemp | Get-VMHost | Measure-Object

  $NumberOfVMHostsInCluster = $NumberOfVMHostsInCluster.Count

  If ($NumberOfVMHostsInCluster -gt 1){ #Ignore Clusters with no ESXi hosts in it

  Write-Host "          " Gathering $ClusterTemp.Name "usage statistics..."

  $VMHostsInCluster = $ClusterTemp | Get-VMHost

  $DatastoresInCluster = $ClusterTemp | Get-VMHost | Get-Datastore

  $VMsInCluster = $ClusterTemp | Get-VM

  ################################# PER CLUSTER INVENTORY  ##########################

  # HEADER

  $HTMLBody += CreateHeader ("INVENTORY FOR <font color=" + $ColorArray[$ColorArrayIndex] + "><b> CLUSTER " + $ClusterTemp.Name + "</b></font>")

  # INVENTORY

  $HTMLBody += ListClusterInventory ($ClusterTemp)

  ################################# PER CLUSTER CPU REPORT ##########################

  # HEADER

  $HTMLBody += CreateHeader ("CPU CAPACITY REPORT FOR <font color=" + $ColorArray[$ColorArrayIndex] + "><b> CLUSTER " + $ClusterTemp.Name + "</b></font>")

  # INTRO TEXT

  $HTMLBody += "<b>" + [String]$VMHostsInCluster.Count + " ESXi Hosts with a total of " + (GetTotalCPUCyclesInGhz ($VMHostsInCluster)) + " GHz on " +

  (GetTotalNumberofCPUs ($VMHostsInCluster)) + " CPUs </b><br><br>"

  # TABLE

  $HTMLBody += CreateVMHostCPUUsageTable ($VMHostsInCluster)

  # CHART

  Create-Chart -ChartType Bar -ChartTitle "Monthly Average Host CPU Usage Percentage" -FileName ("Cluster_" + `

  ($ClusterTemp.Name -replace " ", "-") + "_CPU_Usage") -ChartWidth 750 -ChartHeight 650 -NameArray $global:ArrayOfNames -ValueArray $global:ArrayOfValues

  $HTMLBody += "<IMG SRC=Cluster_" + ($ClusterTemp.Name -replace " ", "-") + "_CPU_Usage.png>"

  $Attachments += "Cluster_" + ($ClusterTemp.Name -replace " ", "-") + "_CPU_Usage.png"

  # CLEANUP

  ReinitializeArrays

  ################################# PER CLUSTER MEMORY REPORT ##########################

  # HEADER

  $HTMLBody += CreateHeader ("MEMORY CAPACITY REPORT FOR <font color=" + $ColorArray[$ColorArrayIndex] + "><b> CLUSTER " + $ClusterTemp.Name + "</b></font>")

  # INTRO TEXT

  $HTMLBody += "<b>" + [String]$VMHostsInCluster.Count + " ESXi Hosts with a total of " + (GetTotalMemoryInGB ($VMHostsInCluster)) + " GB of RAM </b><br><br>"

  # TABLE

  $HTMLBody += CreateVMHostMemoryUsageTable ($VMHostsInCluster)

  # CHART

  Create-Chart -ChartType Bar -ChartTitle "Monthly Average Host Memory Usage Percentage" -FileName ("Cluster_" + `

  ($ClusterTemp.Name -replace " ", "-") + "_Memory_Usage") -ChartWidth 750 -ChartHeight 650 -NameArray $global:ArrayOfNames -ValueArray $global:ArrayOfValues

  $HTMLBody += "<IMG SRC=Cluster_" + ($ClusterTemp.Name -replace " ", "-") + "_Memory_Usage.png>"

  $Attachments += "Cluster_" + ($ClusterTemp.Name -replace " ", "-") + "_Memory_Usage.png"

  # CLEANUP

  ReinitializeArrays

  ################################# PER CLUSTER DATASTORE REPORT ##########################

  # HEADER

  $HTMLBody += CreateHeader ("DATASTORE CAPACITY REPORT FOR <font color=" + $ColorArray[$ColorArrayIndex] + "><b> CLUSTER " + $ClusterTemp.Name + "</b></font>")

  # INTRO TEXT

  $HTMLBody += "<b>" + [String]$DatastoresInCluster.Count + " Datastores with a total of " + (GetTotalDatastoreDiskSpaceinGB ($DatastoresInCluster)) + `

  " GB of disk space</b><br><br>"

  # TABLE

  $HTMLBody += CreateDatastoreUsageTable ($DatastoresInCluster)

  # CHART

  Create-Chart -ChartType Bar -ChartTitle "Datastore Usage Percentage " -FileName ("Cluster_" + ($ClusterTemp.Name -replace " ", "-") + `

  "_Datastore_Usage") -ChartWidth 850 -ChartHeight 650 -NameArray $global:ArrayOfNames -ValueArray $global:ArrayOfValues

  $HTMLBody += "<IMG SRC=Cluster_" + ($ClusterTemp.Name -replace " ", "-") + "_Datastore_Usage.png>"

  $Attachments += "Cluster_" + ($ClusterTemp.Name -replace " ", "-") + "_Datastore_Usage.png"

  # CLEANUP

  ReinitializeArrays

  ################################# PER CLUSTER PROVISONING POTENTIAL REPORT ##########################

  # HEADER

  $HTMLBody += CreateHeader ("PROVISIONING POTENTIAL REPORT FOR <font color=" + $ColorArray[$ColorArrayIndex] + "><b> CLUSTER " + $ClusterTemp.Name + "</b></font>")

  # INTRO TEXT

  $HTMLBody += "<b>" + [String]$VMsInCluster.Length + " Virtual Machines with a total of " + (GetVMTotalCPUs ($VMsInCluster)) + " vCPUs and " + `

  (GetVMTotalMemory ($VMsInCluster)) + " GB of vRAM</b><br><br>"

  Write-Host "          " Calculating Virtual Machine Average Usage Statistics for Cluster $ClusterTemp.Name

  # TABLE

  $HTMLBody += CreateClusterProvisioningPotentialTables ($ClusterTemp)

  ################################# PER CLUSTER RESILIENCE REPORT ##########################

  # HEADER

  $HTMLBody += CreateHeader ("CLUSTER RESILIENCE REPORT FOR <font color=" + $ColorArray[$ColorArrayIndex] + "><b> CLUSTER " + $ClusterTemp.Name + "</b></font>")

  # INTRO TEXT

  $HTMLBody += "<b>" + [String]$VMHostsInCluster.Count + " ESXi Hosts with a total of " + (GetTotalCPUCyclesInGhz ($VMHostsInCluster)) + " GHz on " +

  (GetTotalNumberofCPUs ($VMHostsInCluster)) + " CPUs and " + (GetTotalMemoryInGB ($VMHostsInCluster)) + " GB of RAM </b><br>"

  $HTMLBody += "<b>" + [String]$DatastoresInCluster.Count + " Datastores with a total of " + (GetTotalDatastoreDiskSpaceinGB ($DatastoresInCluster)) + `

  " GB of disk space</b><br><br>"

  #TABLE

  $HTMLBody += CreateClusterResilienceTable ($ClusterTemp)

  # CHART

  if ($global:ArrayOfNames.count -gt 0){ # If HA Admission Control is set to a %, create a pie chart

  Create-Chart -ChartType Pie -ChartTitle "Cluster Resilience Report" -FileName ("Cluster_" + ($ClusterTemp.Name -replace " ", "-") + `

  "_Resilience_Report") -ChartWidth 850 -ChartHeight 750 -NameArray $global:ArrayOfNames -ValueArray $global:ArrayOfValues

  $HTMLBody += "<IMG SRC=Cluster_" + ($ClusterTemp.Name -replace " ", "-") + "_Resilience_Report.png>"

  $Attachments += "Cluster_" + ($ClusterTemp.Name -replace " ", "-") + "_Resilience_Report.png"

  }

  # CLEANUP

  ReinitializeArrays

  #-----------------------------------------------------------------------------------------------

  # Change the color of the Header for the next Cluster

  $ColorArrayIndex++

  }

}

########################### SEND REPORT BY E-MAIL #################################

$HTMLBody += "</BODY>" # Close HTML Body

$HTMLPage = $HTMLHeader + $HTMLBody + $HTMLFooter

$HTMLPage | Out-File ((Get-Location).Path + "\report.html") # Export locally to html file

Write-Host "Report has exported to HTML file " + ((Get-Location).Path + "\report.html")

Send-Mailmessage -From $FromAddress -To $ToAddress -Subject $Subject -Attachments $Attachments -BodyAsHTML -Body $HTMLPage -Priority Normal -SmtpServer $SMTPServer

Write-Host "Report has been sent by E-mail to " $ToAddress " from " $FromAddress

Exit

/* Please feel free to provide any comments or input you may have. */
LucD
Leadership
Leadership

AlbertWT
Virtuoso
Virtuoso

Marcus

The script does not work on the latest Windows 10 laptop running the latest PowerCLI from VMware:

PS C:\WINDOWS> Get-PowerCLIVersion

PowerCLI Version

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

   VMware vSphere PowerCLI 6.3 Release 1 build 3639347

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

Component Versions

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

   VMware Cloud Infrastructure Suite PowerCLI Component 6.3 build 3639341

   VMWare AutoDeploy PowerCLI Component 6.0 build 3511413

   VMWare ImageBuilder PowerCLI Component 6.0 build 3511413

   VMware vSphere PowerCLI Component 6.3 build 3639341

PS C:\WINDOWS> $PSVersionTable

Name                           Value                                                                                                                                                                      

----                           -----                                                                                                                                                                      

PSVersion                      5.0.10586.494                                                                                                                                                              

PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}                                                                                                                                                    

BuildVersion                   10.0.10586.494                                                                                                                                                             

CLRVersion                     4.0.30319.42000                                                                                                                                                            

WSManStackVersion              3.0                                                                                                                                                                        

PSRemotingProtocolVersion      2.3                                                                                                                                                                        

SerializationVersion           1.1.0.1   

Here's the output from the console:

Name                           Port  User                         

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

PRODVCENTER01-VM                      443   DOMAIN\Administrator           

Step 1/6 - Collecting inventory...

           Gathering ESXi Hardware and Software Information...

Step 2/6 - Collecting CPU statistics...

           Gathering PRODESXi01.DOMAIN.com CPU usage statistics...

           Gathering PRODESXi02.DOMAIN.com CPU usage statistics...

           Creating chart...

Exception calling "SaveImage" with "2" argument(s): "Access to the path 'C:\WINDOWS\vCenter_CPU_Usage.png' is denied."

At line:649 char:2

+     $Chart.SaveImage($FullPath,"png")

+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : UnauthorizedAccessException

Step 3/6 - Collecting Memory information...

           Gathering PRODESXi01.DOMAIN.com Memory usage statistics...

           Gathering PRODESXi02.DOMAIN.com Memory usage statistics...

           Creating chart...

Exception calling "SaveImage" with "2" argument(s): "Access to the path 'C:\WINDOWS\vCenter_Memory_Usage.png' is denied."

At line:649 char:2

+     $Chart.SaveImage($FullPath,"png")

+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : UnauthorizedAccessException

Step 4/6 - Collecting Datastore information...

           Gathering VMFS-SSD01_vol_01 Datastore usage statistics...

           Gathering VMFS-SSD01_vol_02 Datastore usage statistics...

           Creating chart...

Exception calling "SaveImage" with "2" argument(s): "Access to the path 'C:\WINDOWS\vCenter_Datastore_Usage.png' is denied."

At line:649 char:2

+     $Chart.SaveImage($FullPath,"png")

+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : UnauthorizedAccessException

Step 5/6 - Collecting Virtual Machine information...

           Collecting Virtual Machine Guest OS information...

           Creating chart...

Exception calling "SaveImage" with "2" argument(s): "Access to the path 'C:\WINDOWS\vCenter_VM_OS_Report.png' is denied."

At line:649 char:2

+     $Chart.SaveImage($FullPath,"png")

+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : UnauthorizedAccessException

Step 6/6 - Collecting Cluster information...

           Gathering Production usage statistics...

           Gathering Production inventory...

           Gathering ESXi Hardware and Software Information...

           Gathering PRODESXi01.DOMAIN.com CPU usage statistics...

           Gathering PRODESXi02.DOMAIN.com CPU usage statistics...

           Creating chart...

Exception calling "SaveImage" with "2" argument(s): "Access to the path 'C:\WINDOWS\Cluster_Production_CPU_Usage.png' is denied."

At line:649 char:2

+     $Chart.SaveImage($FullPath,"png")

+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : UnauthorizedAccessException

           Gathering PRODESXi01.DOMAIN.com Memory usage statistics...

           Gathering PRODESXi02.DOMAIN.com Memory usage statistics...

           Creating chart...

Exception calling "SaveImage" with "2" argument(s): "Access to the path 'C:\WINDOWS\Cluster_Production_Memory_Usage.png' is denied."

At line:649 char:2

+     $Chart.SaveImage($FullPath,"png")

+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : UnauthorizedAccessException

           Gathering VMFS-SSD01_vol_01 Datastore usage statistics...

           Gathering VMFS-SSD01_vol_02 Datastore usage statistics...

           Creating chart...

Exception calling "SaveImage" with "2" argument(s): "Access to the path 'C:\WINDOWS\Cluster_Production_Datastore_Usage.png' is denied."

At line:649 char:2

+     $Chart.SaveImage($FullPath,"png")

+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : UnauthorizedAccessException

           Calculating Virtual Machine Average Usage Statistics for Cluster Production

           Gathering Cluster Resilience Information for Cluster Production

Method invocation failed because [System.Object[]] does not contain a method named 'op_Subtraction'.

At line:497 char:4

+             $ClusterFreeMemory = $ClusterTotalMemory - $ClusterUsedMe ...

+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidOperation: (op_Subtraction:String) [], RuntimeException

    + FullyQualifiedErrorId : MethodNotFound

Method invocation failed because [System.Object[]] does not contain a method named 'op_Subtraction'.

At line:500 char:4

+             $ClusterFreeMemoryPercentage = $ClusterFreeMemoryPercenta ...

+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidOperation: (op_Subtraction:String) [], RuntimeException

    + FullyQualifiedErrorId : MethodNotFound

Method invocation failed because [System.Object[]] does not contain a method named 'op_Division'.

At line:513 char:4

+             $HAReservedMemory = ($ACPolicyInteger/100) * ($ClusterTem ...

+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + 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 line:609 char:2

+     $Chart.Series["Data"].Points.DataBindXY($NameArray, $ValueArray)  ...

+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : ArgumentOutOfRangeException

Exception calling "SaveImage" with "2" argument(s): "Access to the path 'C:\WINDOWS\Cluster_Production_Resilience_Report.png' is denied."

At line:649 char:2

+     $Chart.SaveImage($FullPath,"png")

+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : UnauthorizedAccessException

           Gathering Production 2 usage statistics...

           Gathering Production 2 inventory...

           Gathering ESXi Hardware and Software Information...

           Gathering PRODESXi08.DOMAIN.com CPU usage statistics...

           Gathering PRODESXi09.DOMAIN.com CPU usage statistics...

           Creating chart...

Exception calling "SaveImage" with "2" argument(s): "Access to the path 'C:\WINDOWS\Cluster_Production-2_CPU_Usage.png' is denied."

At line:649 char:2

+     $Chart.SaveImage($FullPath,"png")

+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : UnauthorizedAccessException

           Gathering PRODESXi08.DOMAIN.com Memory usage statistics...

           Gathering PRODESXi09.DOMAIN.com Memory usage statistics...

           Creating chart...

Exception calling "SaveImage" with "2" argument(s): "Access to the path 'C:\WINDOWS\Cluster_Production-2_Memory_Usage.png' is denied."

At line:649 char:2

+     $Chart.SaveImage($FullPath,"png")

+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : UnauthorizedAccessException

           Gathering VMFS-SSD01_vol_01 Datastore usage statistics...

           Gathering VMFS-SSD01_vol_02 Datastore usage statistics...

           Creating chart...

Exception calling "SaveImage" with "2" argument(s): "Access to the path 'C:\WINDOWS\Cluster_Production-2_Datastore_Usage.png' is denied."

At line:649 char:2

+     $Chart.SaveImage($FullPath,"png")

+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : UnauthorizedAccessException

           Calculating Virtual Machine Average Usage Statistics for Cluster Production 2

Get-Stat : 11/08/2016 10:34:04 AM    Get-Stat        The metric counter "cpu.usagemhz.average" doesn't exist for entity "PRODSSP01-CLONE".

At line:182 char:23

+ ... MCPUUsage = Get-Stat -Entity ($VMsTemp) -MaxSamples 1 -stat cpu.usage ...

+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : ResourceUnavailable: (cpu.usagemhz.average:String) [Get-Stat], VimException

    + FullyQualifiedErrorId : Client20_RuntimeDataServiceImpl_CheckUserMetrics_MetricDoesntExist,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetViStats

           Gathering Cluster Resilience Information for Cluster Production 2

           Creating chart...

Exception calling "SaveImage" with "2" argument(s): "Access to the path 'C:\WINDOWS\Cluster_Production-2_Resilience_Report.png' is denied."

At line:649 char:2

+     $Chart.SaveImage($FullPath,"png")

+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : UnauthorizedAccessException

Out-File : Access to the path 'C:\WINDOWS\report.html' is denied.

At line:909 char:13

+ $HTMLPage | Out-File ((Get-Location).Path + "\report.html") # Export  ...

+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : OpenError: (:) [Out-File], UnauthorizedAccessException

    + FullyQualifiedErrorId : FileOpenFailure,Microsoft.PowerShell.Commands.OutFileCommand

Report has exported to HTML file  + C:\WINDOWS\report.html

Send-Mailmessage : Could not find file 'C:\WINDOWS\vCenter_CPU_Usage.png'.

At line:911 char:1

+ Send-Mailmessage -From $FromAddress -To $ToAddress -Subject $Subject  ...

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [Send-MailMessage], FileNotFoundException

    + FullyQualifiedErrorId : System.IO.FileNotFoundException,Microsoft.PowerShell.Commands.SendMailMessage

Report has been sent by E-mail to  admin@DOMAIN.com  from  PRODVCENTER01-VM@DOMAIN.com

The email did not sent at all ?

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

There seems to be an issue with PowerCLI 6.3R1 and the Windows Anniversary Update!


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

AlbertWT
Virtuoso
Virtuoso

LucD‌ Ah no wonder,

The script was executed using the DOMAIN\Administrator privillege but still it cannot give the result.

It used to be working on Windows 8.1 and earlier version of Windows 10.

Thanks for the confirmation Luc.

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

Check $env:PSModulePath, mine only had the PowerShell modules folder after the upgrade.


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

AlbertWT
Virtuoso
Virtuoso

Here's the result LucD‌:

PS C:\WINDOWS> $env:PSModulePath

C:\Users\Administrator\Documents\WindowsPowerShell\Modules;

C:\Program Files\WindowsPowerShell\Modules;

C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\;

C:\Program Files (x86)\Microsoft SQL Server\120\Tools\PowerShell\Modules\;

C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\Modules

so is tehre anything that is missing from yours ?

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

Yes, I only seem to have C:\Program Files\WindowsPowerShell\Modules in there after the update.


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

AlbertWT
Virtuoso
Virtuoso

LucD‌, So I wonder if the script above is working for you or not ?

Because I wonder what is not working from the script above which have caused the graphics and temporary files to be written to C:\Windows directory ?

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

Don't have access to my lab right now, will check this evening.


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

Reply
0 Kudos
AlbertWT
Virtuoso
Virtuoso

Thanks LucD‌.

Let us know how it goes on your lab.

/* Please feel free to provide any comments or input you may have. */
Reply
0 Kudos
nicholas1982
Hot Shot
Hot Shot

Hey All,

Just wondering if this script has been tuned for 6.3R1, I tried it can got errors?

PowerCLI C:\powercli scripts> .\capacity-check.ps1

At C:\powercli scripts\capacity-check.ps1:195 char:107

+ ... mary.FreeSpace)`

+                    ~

Missing closing ')' in expression.

At C:\powercli scripts\capacity-check.ps1:193 char:60

+ Function GetDatastoreAllocationPercentage ($DatastoreTemp) {

+                                                            ~

Missing closing '}' in statement block.

At C:\powercli scripts\capacity-check.ps1:196 char:79

+   +

$DatastoreTemp.Summary.Uncommitted)*100)/$DatastoreTemp.Summary.Capacity,0)

+

~

Unexpected token ')' in expression or statement.

At C:\powercli scripts\capacity-check.ps1:198 char:1

+ }

+ ~

Unexpected token '}' in expression or statement.

At C:\powercli scripts\capacity-check.ps1:739 char:70

+   "The chart will be created as a standard Bar Graph Chart for now."

-Foreground ...

+

~~~~~~~~~~~

Unexpected token '-ForegroundColor' in expression or statement.

At C:\powercli scripts\capacity-check.ps1:739 char:87

+ ... oregroundColor Cyan

+                    ~~~~

Unexpected token 'Cyan' in expression or statement.

    + CategoryInfo          : ParserError: (:) [], ParseException

    + FullyQualifiedErrorId : MissingEndParenthesisInExpression

PowerCLI C:\powercli scripts>

Nicholas