# encoding: ascii # api: powershell # title: VM Performance Report - # description: The script requires an input file, supplied as an argument to the script. The first line of this file contains an email address, subsequent lines contain VM names, one per line. The script connects to vCenter, queries for given performance stats (get-stat) and then generates a HTML report, which is then emailed to the recipient. The script can be scheduled via scheduled tasks (when supplied with a credential file for vCenter created with http://poshcode.org/3487) or run interactively. # version: 1.0 # type: script # author: Samuel Mulhearn # license: CC0 # function: Out-LogFile # x-poshcode-id: 3510 # x-archived: 2012-07-17T20:33:10 # x-published: 2012-07-11T06:52:00 # # Updated for US date/format # <# .SYNOPSIS The script creates an HTML report for given vSphere VM's, that contains VM performance data over a given period. The script then emails the report to a given address. .DESCRIPTION The script requires an input file, supplied as an argument to the script. The first line of this file contains an email address, subsequent lines contain VM names, one per line. The script connects to vCenter, queries for given performance stats (get-stat) and then generates a HTML report, which is then emailed to the recipient. The script can be scheduled via scheduled tasks (when supplied with a credential file for vCenter created with http://poshcode.org/3491) or run interactively. .NOTES File Name : Get-VMPeformanceReport.ps1 Author : Samuel Mulhearn Version History: Version 1.0 28 Jun 2012. Release Version 1.1 11 July 2012 Andy Helsby - Modified for US formatting of date and time .LINK http://poshcode.org/3494 .EXAMPLE Call the script with a single argument which should be the path to the input file .\Get-VMPeformanceReport.ps1 #> #Change These Values $VC = "vc.domain.local" #VirtualCenter $SMTPServer = "192.168.1.100" #SMTP Server $SendersAddress = "noreply@domain.com" #The report comes from this address $SavedCredentialsFile = "C:\path\file.txt" #Make this file using http://poshcode.org/3491 $CompanyLogo = "http://placehold.it/150x50" function Out-LogFile { #Log File Function http://poshcode.org/3232 [CmdletBinding(DefaultParameterSetName='Message')] param( [Parameter(ParameterSetName='Message', Position=0, ValueFromPipeline=$true)] [object[]]$Message, [Parameter(ParameterSetName='Message')] [string]$LogFile = $global:DefaultLogPath, [Parameter(ParameterSetName='Message')] [int]$BlankLine = 0, [switch]$WriteHost = $global:WriteHostPreference, [string]$Severity = "I", [Parameter(ParameterSetName='Message')] [switch]$DontFormat, [Parameter(ParameterSetName='Message')] [string]$DateFormat = "dd-MM-yyyy HH:mm:ss", #[Parameter(ParameterSetName='Title',Position=0,Mandatory=$true)] [string]$Title, [System.ConsoleColor]$ForegroundColor = $host.UI.RawUI.ForegroundColor, [System.ConsoleColor]$BackgroundColor = $host.UI.RawUI.BackgroundColor, [ValidateSet('unicode', 'utf7', 'utf8', 'utf32', 'ascii', 'bigendianunicode', 'default', 'oem')] [string]$Encoding = 'Unicode', [switch]$Force ) begin { Write-Verbose "Log File: $LogFile" if ( -not $LogFile ) { Write-Error "The -LogFile parameter must be defined or $global:LogFile must be set."; break} if ( -not (Test-Path $LogFile) ) { New-Item -Path $LogFile -ItemType File -Force | Out-Null } if ( -not (Test-Path $LogFile) ) { Write-Error "Log file can not be found: $LogFile."; break} if ( $Title ) { $text = $Title $Title = $null Out-LogFile -BlankLine 1 -LogFile $LogFile -WriteHost:$WriteHost -Force:$Force -Encoding $Encoding Out-LogFile -Message $text -BlankLine 1 -DontFormat -LogFile $LogFile -WriteHost:$WriteHost -Force:$Force -Encoding $Encoding } } process { if ( $Message ) { $text = $Message foreach ( $text in $Message ) { if ( -not $DontFormat ) { $text = "$(($Severity).ToUpper()): $(Get-Date -Format `"$DateFormat`")" + ": $text" } if ($WriteHost) { Write-Host $text -BackgroundColor $BackgroundColor -ForegroundColor $ForegroundColor} $text | Out-File -FilePath $LogFile -Force:$Force -Encoding $Encoding -Append } } if ( $BlankLine -gt 0 ){ for ($i = 0; $i -lt $BlankLine; $i++ ) { "" | Out-File -FilePath $LogFile -Force:$Force -Encoding $Encoding -Append if ($WriteHost) { Write-Host "" -BackgroundColor $BackgroundColor -ForegroundColor $ForegroundColor } } } } end { } } #end of logfile function #New Line Variable $nl = [Environment]::NewLine #INTERACTIVE: (Prompt for password) Replace code below with: $VCCred = (Get-Credential) #NONE-INTERACTIVE: Store password in a file (using http://poshcode.org/3491), and retrive as below $key = [byte]57,86,59,11,72,75,18,52,73,46,0,21,56,76,47,12 #Must match key used to save password (http://poshcode.org/3491) $VCCred = Import-Csv $SavedCredentialsFile #Make this file using http://poshcode.org/3491 $VCCred.Password = ($VCCred.Password| ConvertTo-SecureString -Key $key) $VCCred = (New-Object -typename System.Management.Automation.PSCredential -ArgumentList $VCCred.Username,$VCCred.Password) #Get Datafile, this wil contain VM's to report on, and an email address to send the report to #Datafile format: first line is email address, subsequent lines are VM's, one per line) if ($args[0] -eq $null) #Test Datafile was supplied as argument to the script, if not error! { Throw "No datafile supplied, supply path to datafile as an argument to the script! e.g .\SCRIPT.ps1 DATAFILE.txt $nl To create a datafile, the first line of the datafile should be an email address, each subseqenet line should be a VM (one per line)" #$Datafile = "C:\Path\datain.txt" #If debugging uncomment this line and comment above to supply a fixed input file } else { $Datafile = $args[0] } #From Datafile, get a log file, and a $LogFile = (($DataFile).SubString(0,(($Datafile).length - 3))) + "log" $Outfile = (($DataFile).SubString(0,(($Datafile).length - 3))) + "htm" $global:WriteHostPreference = $true $global:DefaultLogPath = $LogFile Out-LogFile -Message "Starting script with $datafile" #Load PowerCLI if ( (Get-PSSnapin -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue) -eq $null ) { Add-PsSnapin VMware.VimAutomation.Core } If (!(Get-PSSnapin -Name VMware.VimAutomation.Core)) {Out-LogFile -Message "Failed to load PowerCLI Snap-in. Check PowerCLI is installed." -Severity "E" Exit(1) } #Static HTML $HTMLPreString=@" Virtual Machine Performance statistics "@ $HTMLPreString += "$nl" $HTMLBodyBegin =" $nl" $HTMLBodyBegin += "`"Company $nl" $HTMLBodyBegin += "

Performance Statistics

$nl" $HTMLPostString=@" "@ #Functions for dynamic HTML Function Get-DataTable ($Statistics, $UID, $Summation = $false, $Title) { #https://developers.google.com/chart/interactive/docs/examples#custom_table_example $mystring = "$nl" return $mystring } function Get-DivHTML ($UID, $Notes) { $tempHTML = "
$nl" $tempHTML += "
$nl" $tempHTML += "
$nl" $tempHTML += "
Information: $Notes
$nl" $tempHTML += "
$nl" $tempHTML += "
$nl" return $tempHTML } #Main Code #Process datafile, get VM's to report on, and an email address to send the report to $DataTable = @(Get-Content $Datafile) $email = $DataTable[0] $VMs = @($DataTable[1..($DataTable.Count)]) #Connect to VC Set-PowerCLIConfiguration -InvalidCertificateAction:Ignore -DefaultVIServerMode:Single -Confirm:$false|Out-Null if ((Connect-VIServer $VC -Credential $VCCred) -eq $null) #Connect to vCenter, exit if fails. { Out-LogFile -Message "Failed to connect to vCenter ($VC)" -Severity "E" -WriteHost Exit (1) } else {Out-LogFile -Message "Connected to vCenter ($VC)"} #Validate VM's exist $VCVMs = (get-vm -name $VMs -ErrorAction SilentlyContinue) $VMs | % { $tmpvm = $_ $Exists = $false $VCVMs | % { if ($_.Name -eq $tmpvm) {$Exists = $true}} If ($Exists){ Out-LogFile -Message "$_ found in vCenter inventory" } Else { Out-LogFile -Message "$_ not found in vCenter inventory" -Severity "W" $VMs = $VMs |? {$_ -ne $tmpvm} } } #To add new Stat #1. Add stat to $metrics (use Get-VM | GetStatType to find new metrics) #2. Create a Variable To hold new stats, $MyVariabe = ($Stats | Where-Object {$_.MetricId -eq $metrics[X]} | Sort-Object TimeStamp |Group-Object -Property Timestamp) #3. Invent a new UID - MyUID ? #4. Build Datatable, add code: $HTMLOut += (Get-DataTable -Statistics $MyVariable -UID "MyUID" -Title "Graph Title") #5. Edit static Tabs HTML below, within