Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
#Requires Version 3
#Requires -PSSnapin VMware.VimAutomation.Core
<#
.SYNOPSIS
Exports VMware host (ESX/ESXi) information to Excel
.DESCRIPTION
Queries one or more ESX/ESXi servers directly and exports all info to an Excel workbook
A new workbook/file will be created for each host
.PARAMETER Server
The name of one or more ESX/ESXi servers to query
.PARAMETER Path
Path to folder where Excel workbook is saved
.EXAMPLE
.\Get-VMHostInfo.ps1 -server myesxhost -path "E:\Reports"
Gathers info from myesxhost and exports info to an Excel workbook saved in E:\Reports
.EXAMPLE
.\Get-VMHostInfo.ps1 -server "myesxhost","myotheresxhost" -path "E:\Reports"
Gathers info from myesxhost and myotheresxhost, exports info to separate Excel workbooks located in E:\Reports
.EXAMPLE
$servers = Get-Content "E:\myhosts.txt";.\Get-VMHostInfo.ps1 -server $servers -path "E:\Reports"
Gathers a list of ESX/ESXi host names from E:\myhosts.txt and gathers\exports info to separate Excel workbooks located in E:\Reports
.NOTES
Author : Shawn Masterson
Export-Xlsx function from Gilbert van Griensven https://www.itpilgrims.com/2013/01/export-xlsx-extended/
Excel is required to be installed on script host
Tested with ESX 4 and ESXi 4.1 thru 5.5
#>
[CmdletBinding()]
Param (
[parameter(Mandatory=$true)]
[String[]]
$server,
[parameter(Mandatory=$true)]
[String]
$path
)
### Supporting function ###
Function Export-Xlsx {
<#
.SYNOPSIS
Exports objects to an Excel workbook
.DESCRIPTION
Exports objects to an Excel workbook and applies cosmetics. Optionally add a title, autofilter, autofit and a chart.
Allows for export to .xls and .xlsx format. If .xlsx is specified but not available (Excel 2003) the data will be exported to .xls.
.PARAMETER InputObject
The data to be exported to Excel
.PARAMETER Path
The path of the Excel file. Defaults to %HomeDrive%\Export.xlsx.
.PARAMETER WorksheetName
The name of the worksheet. Defaults to filename in $Path without extension.
.PARAMETER ExpandArrayValues
Joins an array value to a newline separated list.
.PARAMETER ChartType
Name of an Excel chart to be added.
.PARAMETER TableStyle
Apply a style to the created table. Does not work in Excel 2003.
For an overview of styles see http://msdn.microsoft.com/fr-fr/library/documentformat.openxml.spreadsheet.tablestyle.aspx
The Pivot styles are not used in this function.
.PARAMETER Title
Adds a title to the worksheet.
.PARAMETER SheetPosition
Adds the worksheet either to the 'begin' or 'end' of the Excel file.
.PARAMETER TransposeColumnProperty
Selects a property of the input object which will be moved to the top row of the transposed table.
.PARAMETER ChartOnNewSheet
Adds a chart to a new worksheet instead of to the worksheet containing data.
The Chart will be placed after the sheet containing data.
.PARAMETER AppendWorksheet
Appends a worksheet to an existing Excel file.
.PARAMETER Borders
Adds borders to all cells. Defaults to True.
.PARAMETER HeaderColor
Applies background color to the header row. Defaults to True.
.PARAMETER AutoFit
Apply autofit to columns. Defaults to True.
.PARAMETER AutoFilter
Apply autofilter. Defaults to True.
.PARAMETER PassThru
Returns file object of the generated file.
.PARAMETER Force
Overwrites existing Excel sheet. When this switch is not used but the Excel file already exists, a new file with datestamp will be generated.
.PARAMETER Transpose
Transposes the data in Excel. This will automatically disable AutoFilter and HeaderColor.
.PARAMETER FreezePanes
Freezes the title row.
.EXAMPLE
Get-Process | Export-Xlsx -Path D:\Data\ProcessList.xlsx
Exports a list of running processes to Excel
.EXAMPLE
Get-ADuser -Filter {enabled -ne $True} | Select-Object Name,Surname,GivenName,DistinguishedName | Export-Xlsx -Path 'D:\Data\Disabled Users.xlsx' -Title 'Disabled users of Contoso.com'
Export all disabled AD users to Excel with optional title
.EXAMPLE
Get-Process | Sort-Object CPU -Descending | Export-Xlsx -Path D:\Data\Processes_by_CPU.xlsx
Export a sorted processlist to Excel
.EXAMPLE
Export-Xlsx (Get-Process) -AutoFilter:$False -PassThru | Invoke-Item
Export a processlist to %HomeDrive%\Export.xlsx with AutoFilter disabled, and open the Excel file
.NOTES
Author : Gilbert van Griensven
Based on http://www.lucd.info/2010/05/29/beyond-export-csv-export-xls/
#>
[CmdletBinding(DefaultParametersetName="Default")]
Param (
[Parameter(Position=0,Mandatory=$True,ValueFromPipeline=$True)]
[ValidateNotNullOrEmpty()]
$InputObject,
[ValidateScript({
$ReqExt = [System.IO.Path]::GetExtension($_)
($ReqExt -eq ".xls") -or
($ReqExt -eq ".xlsx")
})]
$Path=(Join-Path $env:HomeDrive "Export.xlsx"),
$WorksheetName = [System.IO.Path]::GetFileNameWithoutExtension($Path),
[Switch] $AppendWorksheet,
[ValidateSet("begin","end")] $SheetPosition="begin",
$Title,
[Switch] $AutoFit=$True,
[Switch] $AutoFilter=$True,
[Switch] $FreezePanes,
[Switch] $Transpose,
[String] $TransposeColumnProperty,
[Switch] $ExpandArrayValues,
[PSObject] $ChartType,
[Switch] $ChartOnNewSheet,
[Parameter(ParameterSetName="CustomStyle")]
[Switch] $Borders=$True,
[Parameter(ParameterSetName="CustomStyle")]
[Switch] $HeaderColor=$True,
[Parameter(ParameterSetName="TableStyle")]
[String] $TableStyle,
[Switch] $Force,
[Switch] $PassThru
)
DynamicParam {
# Adds custom argument completers for 'ChartType' and 'TableStyle' parameters for this function only
If ([Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Interop.Excel") -ne $Null) {
$Completion_xlChartType = {
Param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)
[Enum]::GetValues([Microsoft.Office.Interop.Excel.XlChartType]) | % {
New-Object System.Management.Automation.CompletionResult $_, $_, 'ParameterValue', "$($_)"
}
}
$Completion_xlTableStyle = {
Param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)
1..28 | % {
@("TableStyleMedium$($_)")
If ($_ -le 21) { @("TableStyleLight$($_)") }
If ($_ -le 11) { @("TableStyleDark$($_)") }
} |
Sort-Object | % {
New-Object System.Management.Automation.CompletionResult $_, $_, 'ParameterValue', "$($_)"
}
}
If (!($global:options)) { $global:options = @{CustomArgumentCompleters = @{};NativeArgumentCompleters = @{}} }
$global:options['CustomArgumentCompleters']['Export-Xlsx:ChartType'] = $Completion_xlChartType
$global:options['CustomArgumentCompleters']['Export-Xlsx:TableStyle'] = $Completion_xlTableStyle
$function:tabexpansion2 = $function:tabexpansion2 -replace 'End\r\n{','End { If ($Null -ne $options) {$options += $global:options} Else {$options = $global:options}'
}
}
Begin {
Function Convert-NumberToA1 {
Param([parameter(Mandatory=$true)] [int]$number)
$a1Value = $null
While ($number -gt 0) {
$multiplier = [int][system.math]::Floor(($number / 26))
$charNumber = $number - ($multiplier * 26)
If ($charNumber -eq 0) { $multiplier-- ; $charNumber = 26 }
$a1Value = [char]($charNumber + 96) + $a1Value
$number = $multiplier
}
Write-Verbose "Converted '$($number)' to '$($a1Value)'"
Return $a1Value
}
Function Using-Culture ([System.Globalization.CultureInfo]$Culture, [ScriptBlock]$Script) {
$OldCulture = [System.Threading.Thread]::CurrentThread.CurrentCulture
Trap { [System.Threading.Thread]::CurrentThread.CurrentCulture = $OldCulture }
[System.Threading.Thread]::CurrentThread.CurrentCulture = $Culture
$ExecutionContext.InvokeCommand.InvokeScript($Script)
[System.Threading.Thread]::CurrentThread.CurrentCulture = $OldCulture
}
$Path = [System.IO.Path]::GetFullPath($Path)
$Script:WorkingData = @()
}
Process {
$Script:WorkingData += $InputObject
}
End {
If ($Script:WorkingData.Count -eq 0) {
$ExceptionMessage = New-Object System.FormatException "Input object is empty. Nothing to export to Excel."
Throw $ExceptionMessage
}
$Props = $Script:WorkingData[0].PSObject.properties | % { $_.Name }
Write-Verbose "$($Props.Count) object properties detected"
If ($Transpose) {
Write-Verbose "Setting up for transposed data collection"
If (($TransposeColumnProperty) -and ($Props -contains $TransposeColumnProperty)) {
$Props = $Props | ? {$_ -ne $TransposeColumnProperty}
$Rows = 1
} Else {
$TransposeColumnProperty = $Null
$HeaderColor = $False
}
$Rows += $Props.Count
$Cols = $Script:WorkingData.Count+1
$AutoFilter = $False
} Else {
Write-Verbose "Setting up for data collection"
$Rows = $Script:WorkingData.Count+1
$Cols = $Props.Count
}
Write-Verbose "Input object has $($Rows) rows and $($Cols) columns"
$A1Cols = Convert-NumberToA1 $Cols
$Array = New-Object 'object[,]' $Rows,$Cols
$Col = 0
$Row = 0
Write-Verbose "Storing object properties as data headers into array"
If (($Transpose) -and ($TransposeColumnProperty)) {
$Array[$Row,$Col] = $TransposeColumnProperty
$Row++
}
$Props | % {
$Array[$Row,$Col] = $_.ToString()
If ($Transpose) {
$Row++
} Else {
$Col++
}
}
Write-Verbose "Storing object data into array"
$Row = 1
$Script:WorkingData | % {
$Item = $_
$Col = 0
$Props | % {
If (($Transpose) -and ($TransposeColumnProperty) -and ($Col -eq 0)) {
$Array[$Col,$Row] = $Item.($TransposeColumnProperty).ToString()
$Col++
}
If ($Item.($_) -eq $Null) {
If ($Transpose) {
$Array[$Col,$Row] = ""
} Else {
$Array[$Row,$Col] = ""
}
} Else {
If (($Item.($_) -is [System.Array]) -and ($ExpandArrayValues)) {
$ItemData = [String]::Join("`r`n",$Item.($_))
} Else {
$ItemData = $Item.($_).ToString()
}
If ($Transpose) {
$Array[$Col,$Row] = $ItemData
} Else {
$Array[$Row,$Col] = $ItemData
}
}
$Col++
}
$Row++
}
Using-Culture en-US {
Write-Verbose "Attempting to start Excel as COM object"
Try { $ExcelApplication = New-Object -ComObject Excel.Application }
Catch {
$ExceptionMessage = New-Object System.FormatException "Could not create COM object. Please ensure Microsoft Excel is installed."
Throw $ExceptionMessage
}
$ExcelApplication.DisplayAlerts = $False
$ExcelApplicationFixedFormat = [Microsoft.Office.Interop.Excel.XLFileFormat]::xlWorkbookNormal
If ([System.IO.Path]::GetExtension($Path) -eq '.xlsx') {
Write-Verbose "Selected file format: .xlsx"
If ($ExcelApplication.Version -lt 12) {
Write-Verbose "Current Excel version `($($ExcelApplication.Version)`)does not support .xlsx format. Switching to .xls format"
$Path = [System.IO.Path]::ChangeExtension($Path,".xls")
} Else {
$ExcelApplicationFixedFormat = [Microsoft.Office.Interop.Excel.XLFileFormat]::xlWorkbookDefault
}
} Else {
Write-Verbose "Selected file format: .xls"
}
If (Test-Path -Path $Path -PathType "Leaf") {
Write-Verbose "$($Path) exists"
If ($AppendWorkSheet) {
Write-Verbose "AppendWorkSheet parameter received. Attempting to open $($Path)"
$Workbook = $ExcelApplication.Workbooks.Open($Path)
If ($Workbook.ReadOnly) {
$Workbook.Close()
$ExcelApplication.Quit()
While ([System.Runtime.Interopservices.Marshal]::ReleaseComObject($Workbook)) {}
While ([System.Runtime.Interopservices.Marshal]::ReleaseComObject($ExcelApplication)) {}
[GC]::Collect()
$ExceptionMessage = New-Object System.FormatException "The file $($Path) is marked read-only. Please check NTFS permissions and ensure the file is not open in other applications"
Throw $ExceptionMessage
}
If ($SheetPosition -eq "end") {
Write-Verbose "Setting sheet position to 'end'"
$Workbook.Worksheets.Add([System.Reflection.Missing]::Value,$Workbook.Sheets.Item($Workbook.Sheets.Count)) | Out-Null
} Else {
Write-Verbose "Setting sheet position to 'begin'"
$Workbook.Worksheets.Add($Workbook.Worksheets.Item(1)) | Out-Null
}
} Else {
If (!($Force)) {
$Path = $Path.Insert($Path.LastIndexOf(".")," - $(Get-Date -Format "ddMMyyyy-HHmm")")
Write-Verbose "No Force parameter specified. Target file is changed to: $($Path)"
} Else {
Write-Verbose "Force parameter specified. Overwriting existing file"
}
Write-Verbose "Adding new workbook"
$Workbook = $ExcelApplication.Workbooks.Add()
While ($Workbook.Worksheets.Count -gt 1) { $Workbook.Worksheets.Item(1).Delete() }
}
} Else {
Write-Verbose "$($Path) does not exist. Adding new workbook"
$Workbook = $ExcelApplication.Workbooks.Add()
While ($Workbook.Worksheets.Count -gt 1) { $Workbook.Worksheets.Item(1).Delete() }
}
$Worksheet = $Workbook.ActiveSheet
Try { $Worksheet.Name = $WorksheetName }
Catch {
Write-Verbose "!!! Unable to set worksheet name to $($WorksheetName)"
}
If ($Title) {
Write-Verbose "Adding title"
$Worksheet.Cells.Item(1,1) = $Title
$TitleRange = $Worksheet.Range("a1","$($A1Cols)2")
$TitleRange.Font.Size = 18
$TitleRange.Font.Bold=$True
$TitleRange.Font.Name = "Cambria"
$TitleRange.Font.ThemeFont = 1
$TitleRange.Font.ThemeColor = 4
$TitleRange.Font.ColorIndex = 55
$TitleRange.Font.Color = 8210719
$TitleRange.Merge()
$TitleRange.VerticalAlignment = -4160
While ([System.Runtime.Interopservices.Marshal]::ReleaseComObject($TitleRange)) {}
$UsedRange = $Worksheet.Range("a3","$($A1Cols)$($Rows + 2)")
If ($HeaderColor) {
Write-Verbose "Setting header row background color"
$Worksheet.Range("a3","$($A1Cols)3").Interior.ColorIndex = 48
$Worksheet.Range("a3","$($A1Cols)3").Font.Bold = $True
}
If (($FreezePanes) -and ((($Transpose) -and ($TransposeColumnProperty)) -or (!($Transpose)))) {
Write-Verbose "Freezing panes"
$Worksheet.Range("a4:a4").Select() | Out-Null
$ExcelApplication.ActiveWindow.FreezePanes = $True
}
} Else {
$UsedRange = $Worksheet.Range("a1","$($A1Cols)$($Rows)")
If ($HeaderColor) {
Write-Verbose "Setting header row background color"
$Worksheet.Range("a1","$($A1Cols)1").Interior.ColorIndex = 48
$Worksheet.Range("a1","$($A1Cols)1").Font.Bold = $True
}
If (($FreezePanes) -and ((($Transpose) -and ($TransposeColumnProperty)) -or (!($Transpose)))) {
Write-Verbose "Freezing panes"
$Worksheet.Range("a2:a2").Select() | Out-Null
$ExcelApplication.ActiveWindow.FreezePanes = $True
}
}
Write-Verbose "Transferring array data to selected range in Excel"
$UsedRange.Value2 = $Array
$UsedRange.HorizontalAlignment = -4131
$UsedRange.VerticalAlignment = -4160
If ($Borders) {
Write-Verbose "Adding borders"
$UsedRange.Borders.LineStyle = 1
$UsedRange.Borders.Weight = 2
}
If ($AutoFilter) {
Write-Verbose "Applying autofilter"
$UsedRange.AutoFilter() | Out-Null
}
If ($AutoFit) {
Write-Verbose "Applying autofit"
$Worksheet.UsedRange.EntireColumn.AutoFit() | Out-Null
$Worksheet.UsedRange.EntireRow.AutoFit() | Out-Null
}
If (($TableStyle) -and ($ExcelApplication.Version -ge 12)) {
Write-Verbose "Applying table style '$($TableStyle)'"
$ListObject = $Worksheet.ListObjects.Add([Microsoft.Office.Interop.Excel.XlListObjectSourceType]::xlSrcRange, $UsedRange, $Null, [Microsoft.Office.Interop.Excel.XlYesNoGuess]::xlYes, $Null)
$ListObject.TableStyle = $TableStyle
While ([System.Runtime.Interopservices.Marshal]::ReleaseComObject($ListObject)) {}
}
If ($ChartType) {
Try {
Write-Verbose "Attempting to add chart of type '$($ChartType)'"
[Microsoft.Office.Interop.Excel.XlChartType]$ChartType = $ChartType
If ($ChartOnNewSheet) {
Write-Verbose "Adding chart to new worksheet"
$Workbook.Charts.Add().ChartType = $ChartType
$Workbook.ActiveChart.setSourceData($UsedRange)
Try { $Workbook.ActiveChart.Name = "$($WorksheetName) - Chart" }
Catch { }
$Workbook.ActiveChart.Move([System.Reflection.Missing]::Value,$Workbook.Sheets.Item($Worksheet.Name))
} Else {
Write-Verbose "Adding chart to current sheet"
$Worksheet.Shapes.AddChart($ChartType).Chart.setSourceData($UsedRange) | Out-Null
}
}
Catch {
Write-Verbose "!!! '$($ChartType)' is not a valid Excel chart type. Use tab expansion to choose between valid chart types."
}
}
Write-Verbose "Saving Excel workbook to $($Path)"
$Workbook.Worksheets.Item(1).Select()
Try { $Workbook.SaveAs($Path,$ExcelApplicationFixedFormat) }
Catch { $ExceptionMessage = New-Object System.FormatException "Unable to save to $($Path). Please ensure you have write access." }
Write-Verbose "Closing Excel and cleaning up references"
$Workbook.Close()
$ExcelApplication.Quit()
While ([System.Runtime.Interopservices.Marshal]::ReleaseComObject($UsedRange)) {}
While ([System.Runtime.Interopservices.Marshal]::ReleaseComObject($Worksheet)) {}
While ([System.Runtime.Interopservices.Marshal]::ReleaseComObject($Workbook)) {}
While ([System.Runtime.Interopservices.Marshal]::ReleaseComObject($ExcelApplication)) {}
[GC]::Collect()
If ($ExceptionMessage) { Throw $ExceptionMessage }
}
If ($PassThru) { Return Get-Item $Path }
}
}
### Main script begin ###
# Test path
If (!(Test-Path $path)) {
Write-Host "Path not found - $path" -ForegroundColor Red
Exit
}
# Obtain Credentials
$creds = Get-Credential -Message "Enter ESX/ESXi host credentials used to connect" -UserName root
# Cycle through servers gathering and exporting info
Foreach ($ESX in $Server) {
# Create full path to Excel workbook
$FullPath = $Path.Trimend('\') + "\HostInfo_" + $ESX + "_" + (Get-Date -Format MM-dd-yyyy) + ".xlsx"
# Connect to ESX/ESXi host
$connection = Connect-VIServer $ESX -Credential $creds
# Ensure connection
If ($connection) {
Write-Host "Connected to $ESX"
# Get ESX(i) Host Info
$VMHost = Get-VMHost $ESX
$VMHostProp = [ordered]@{}
$VMHostProp.Name = $VMHost.NetworkInfo.HostName
$VMHostProp."Domain Name" = $VMHost.NetworkInfo.DomainName
$VMHostProp.Hypervisor = $VMHost.Extensiondata.Config.Product.FullName
$VMHostProp.License = $VMHost.LicenseKey
$VMHostProp.Vendor = $VMHost.Manufacturer
$VMHostProp.Model = $VMHost.Model
$VMHostProp."BIOS Version" = $VMHost.Extensiondata.Hardware.BiosInfo.BiosVersion
$VMHostProp."CPU Model" = $VMHost.ProcessorType
$VMHostProp."CPU Count" = $VMHost.ExtensionData.Summary.Hardware.NumCpuPkgs
$VMHostProp."Total Cores" = $VMHost.ExtensionData.Summary.Hardware.numCpuCores
$VMHostProp."Total Threads" = $VMHost.ExtensionData.Summary.Hardware.numCpuThreads
$VMHostProp."Hyperthreading Enabled" = $VMHost.HyperThreadingActive
$VMHostProp."CPU Current Usage (Mhz)" = $VMHost.CpuUsageMhz
$VMHostProp."Memory (GB)" = [Math]::Round($VMHost.MemoryTotalGB,0)
$VMHostProp."Memory Current Usage (GB)" = [Math]::Round($VMHost.MemoryUsageGB,0)
$VMHostProp."FC HBAs" = ($VMHost | Get-VMHostHba | where {$_.Type -eq "FibreChannel"}).Count
$VMHostProp."iSCSI HBAs" = ($VMHost | Get-VMHostHba | where {$_.Type -eq "IScsi"}).Count
$VMHostProp."Physical NICs" = $VMHost.ExtensionData.Config.Network.Pnic.Count
If ($VMHost.NetworkInfo.VMKernelGateway) {
$VMHostProp."VMKernel Gateway" = $VMHost.NetworkInfo.VMKernelGateway
} Else {
$VMHostProp."Console Gateway" = $VMHost.NetworkInfo.ConsoleGateway
}
Try {
$domainStatus = ""
$domainStatus = $VMHost | Get-VMHostAuthentication -ErrorAction Stop
$VMHostProp."Authentication Domain" = If ($domainStatus.Domain){$domainStatus.Domain} Else {"Not Configured"}
$VMHostProp."Authentication Domain Status" = If ($domainStatus.DomainMembershipStatus){$domainStatus.DomainMembershipStatus} Else {"Unknown"}
$VMHostProp."Trusted Domains" = If ($domainStatus.Trusteddomains) {$domainStatus | Select -ExpandProperty TrustedDomains | Out-String} Else {"None"}
} Catch {}
$VMHostProp."DNS Server(s)" = $VMHost.ExtensionData.Config.Network.DnsConfig.Address | Out-String
$VMHostProp."Search Domain(s)" = $VMHost.NetworkInfo.SearchDomain | Out-String
$VMHostProp.TimeZone = $VMHost.TimeZone
$VMHostProp."NTP Server(s)" = $VMHost | Get-VMHostNtpServer | Out-String
Try {
$VMHostProp."Syslog Server(s)" = $VMHost | Get-VMHostSysLogServer -ErrorAction Stop | %{$_.Host + ":" + $_.Port} | Out-String
} Catch {
$VMHostProp."Syslog Server(s)" = "Unavailable"
}
Try {
$VMHostProp."Firewall Default Allow Incoming" = $VMHost | Get-VMHostFirewallDefaultPolicy -ErrorAction Stop | Select -ExpandProperty IncomingEnabled
$VMHostProp."Firewall Default Allow Outgoing" = $VMHost | Get-VMHostFirewallDefaultPolicy -ErrorAction Stop | Select -ExpandProperty OutgoingEnabled
} Catch {}
$VMHostProp."VM Count" = ($VMHost | Get-VM).Count
$VMHostProp."Report Created" = Get-Date
$VMHostInfo = New-Object –TypeName PSObject –Prop $VMHostProp
$VMHostInfo | Export-Xlsx -Path $FullPath -WorksheetName "ESX(i) Info" -Title "VMHost Information" -Transpose -Borders:$false -Force
# Get HBA Info
$HBAInfo = @()
$HBAs = $VMHost | Get-VMHostHba
Foreach ($HBA in $HBAs) {
$HBAProp = [ordered]@{}
$HBAProp.Device = $HBA.Device
$HBAProp."HBA Model" = $HBA.Model
$HBAProp."HBA Type" = $HBA.Type
$HBAProp.Driver = $HBA.Driver
$HBAProp.PCI = $HBA.PCI
$NWWN = $null
$NWWNFormatted = $null
[String] $NWWN = "{0:x}" -f $HBA.NodeWorldWideName
If ($NWWN) {
For ($i=0;$i -lt 8;$i++)
{
$NWWNFormatted += "{0}:" -f $($NWWN.SubString($i * 2, 2))
}
$NWWNFormatted = $NWWNFormatted.SubString(0, $NWWNFormatted.Length - 1)
}
$PWWN = $null
$PWWNFormatted = $null
[String] $PWWN = "{0:x}" -f $HBA.PortWorldWideName
If ($PWWN) {
For ($i=0;$i -lt 8;$i++)
{
$PWWNFormatted += "{0}:" -f $($PWWN.SubString($i * 2, 2))
}
$PWWNFormatted = $PWWNFormatted.SubString(0, $PWWNFormatted.Length - 1)
}
$HBAProp.NWWN = $NWWNFormatted
$HBAProp.PWWN = $PWWNFormatted
$HBAProp."Software Based" = $HBA.IsSoftwareBased
$HBAProp."iSCSI Name" = $HBA.IScsiName
$HBAProp."iSCSI Alias" = $HBA.IScsiAlias
$HBAProp.Status = $HBA.Status
$HBATemp = New-Object –TypeName PSObject –Prop $HBAProp
$HBAInfo += $HBATemp
}
If ($HBAInfo) {
$HBAInfo | Export-Xlsx -Path $FullPath -WorksheetName "HBA Info" -Title "HBA Info" -AppendWorksheet -SheetPosition "end"
}
# Get Host Disks
$diskInfo = @()
$disks = $VMHost | Get-VMHostDisk
ForEach ($disk in $disks) {
$diskProp = [ordered]@{}
$diskProp."Device Name" = $disk.DeviceName
$diskProp."SCSI LUN" = $disk.ScsiLun
$diskProp.Cylinders = $disk.Cylinders
$diskProp.Heads = $disk.Heads
$diskProp.Sectors = $disk.Sectors
$diskProp.TotalSectors = $disk.TotalSectors
$diskTemp = New-Object –TypeName PSObject –Prop $diskProp
$diskInfo += $diskTemp
}
If ($diskInfo) {
$diskInfo | Sort "Device Name" | Export-Xlsx -Path $FullPath -WorksheetName "Disks" -Title "Host Disks" -AppendWorksheet -SheetPosition "end"
}
# Get SCSI LUNs
$lunInfo = @()
$scsiLuns = $VMHost | Get-ScsiLun
ForEach ($scsiLun in $scsiLuns) {
$scsiLunProp = [ordered]@{}
$scsiLunProp."Runtime Name" = $scsiLun.RuntimeName
$scsiLunProp."Canonical Name" = $scsiLun.CanonicalName
$scsiLunProp."Device Path" = $scsiLun.ConsoleDeviceName
$scsiLunProp.Type = $scsiLun.LunType
$scsiLunProp.Vendor = $scsiLun.Vendor
$scsiLunProp.Model = $scsiLun.Model
$scsiLunProp."Serial Number" = $scsiLun.SerialNumber
$scsiLunProp."Capacity (GB)" = [Math]::Round($scsiLun.CapacityGB,2)
$scsiLunProp."Multipath Policy" = $scsiLun.MultipathPolicy
$scsiLunProp.Local = $scsiLun.IsLocal
$scsiLunProp.SSD = $scsiLun.ExtensionData.Ssd
$scsiLunProp.UUID = $scsiLun.ExtensionData.Uuid
$scsiLunTemp = New-Object –TypeName PSObject –Prop $scsiLunProp
$lunInfo += $scsiLunTemp
}
If ($lunInfo) {
$lunInfo | Sort Type | Export-Xlsx -Path $FullPath -WorksheetName "SCSI LUNs" -Title "SCSI LUNs" -AppendWorksheet -SheetPosition "end"
}
# Get Multipathing Info
$pathInfo = @()
$luns = $VMhost.ExtensionData.config.storagedevice.multipathinfo.lun
ForEach ($lun in $luns) {
$lunName = $lun.Id
$lunPolicy = $lun.policy.policy
$lunPaths = $lun.path
Foreach ($lunPath in $lunPaths) {
$pathProp = [ordered]@{}
$pathProp."LUN ID" = $lunName
$pathProp."LUN Policy" = $lunPolicy
$pathProp.State = $lunPath.pathstate
$pathProp."Path Name" = $lunPath.Name
$pathProp."Adapter Name" = ($lunPath.Name).Split("-")[0]
$pathProp."Target Name" = ($lunPath.Name).Split("-")[1]
$pathProp."LUN Name" = ($lunPath.Name).Split("-")[2]
$pathTemp = New-Object –TypeName PSObject –Prop $pathProp
$pathInfo += $pathTemp
}
}
If ($pathInfo) {
$pathInfo | Sort "LUN ID" | Export-Xlsx -Path $FullPath -WorksheetName "Multipath Info" -Title "Multipath Info" -AppendWorksheet -SheetPosition "end"
}
# Get iSCSI HBA Targets
$iscsiTargetInfo = @()
$iscsiTargets = Get-IScsiHbaTarget -Server $ESX
ForEach ($iscsiTarget in $iscsiTargets) {
$iscsiTargetProp = [ordered]@{}
$iscsiTargetProp.Name = $iscsiTarget.Name
$iscsiTargetProp."iSCSI Name" = $iscsiTarget.IScsiName
$iscsiTargetProp.Address = $iscsiTarget.Address
$iscsiTargetProp.Port = $iscsiTarget.Port
$iscsiTargetProp.Authentication = $iscsiTarget.AuthenticationProperties
$iscsiTargetProp.Type = $iscsiTarget.Type
$iscsiTargetProp."iSCSI HBA Name" = $iscsiTarget.IScsiHbaName
$iscsiTargetTemp = New-Object –TypeName PSObject –Prop $iscsiTargetProp
$iscsiTargetInfo += $iscsiTargetTemp
}
If ($iscsiTargetInfo) {
$iscsiTargetInfo | Sort Name | Export-Xlsx -Path $FullPath -WorksheetName "iSCSI Targets" -Title "iSCSI HBA Targets" -AppendWorksheet -SheetPosition "end"
}
# Get Host Diagnostic Partitions
$diagInfo = @()
$diags = $VMHost | Get-VMHostDiagnosticPartition
ForEach ($diag in $diags) {
$diagProp = [ordered]@{}
$diagProp."Canonical Name" = $diag.CanonicalName
$diagProp."Diagnostic Type" = $diag.DiagnosticType
$diagProp."Storage Type" = $diag.StorageType
$diagProp.Slots = $diag.SlotCount
$diagProp.Active = $diag.Active
$diagTemp = New-Object –TypeName PSObject –Prop $diagProp
$diagInfo += $diagTemp
}
If ($diagInfo) {
$diagInfo | Sort Active -Descending | Export-Xlsx -Path $FullPath -WorksheetName "Diagnostic Partitions" -Title "Diagnostic Partitions" -AppendWorksheet -SheetPosition "end"
}
# Get Datastore Info
$DSInfo = @()
$DSs = $VMHost | Get-Datastore
Foreach ($DS in $DSs) {
$DSProp = [ordered]@{}
$DSProp.Name = $DS.Name
$DSProp.Type = $DS.Type
$DSProp."Size (GB)" = [Math]::Round($DS.CapacityGB,2)
$DSProp."Used (GB)" = [Math]::Round($DS.CapacityGB - $DS.FreeSpaceGB,2)
$DSProp."Free (GB)" = [Math]::Round($DS.FreeSpaceGB,2)
$usedPerc = ($DS.CapacityGB - $DS.FreeSpaceGB)/$DS.CapacityGB
$DSProp."Used %" = "{0:P1}" -f $usedPerc
$DSProp."Mount Point" = $DS.ExtensionData.Info.Url
$DSProp.Extents = If ($DS.Type -eq "VMFS"){$DS.ExtensionData.Info.Vmfs.Extent.DiskName}
ElseIf ($DS.Type -eq "NFS"){$DS.ExtensionData.Info.Nas.RemoteHost + ":" + $DS.ExtensionData.Info.Nas.RemotePath}
$DSProp.StorageIOControlEnabled = $DS.StorageIOControlEnabled
$DSProp.FileSystemVersion = $DS.FileSystemVersion
$DSProp.BlockSize = $DS.ExtensionData.Info.Vmfs.BlockSizeMB
$DSProp.SSD = $DS.ExtensionData.Info.Vmfs.Ssd
$DSProp.Local = $DS.ExtensionData.Info.Vmfs.Local
$DSProp."VM Count" = ($DS | Get-VM).Count
$DSProp.State = $DS.State
$DSTemp = New-Object –TypeName PSObject –Prop $DSProp
$DSInfo += $DSTemp
}
If ($DSInfo) {
$DSInfo | Sort Name | Export-Xlsx -Path $FullPath -WorksheetName "Datastores" -Title "Datastores" -AppendWorksheet -SheetPosition "end"
}
# Get Datastore Chart
$DSInfo = @()
Foreach ($DS in $DSs) {
$DSProp = [ordered]@{}
$DSProp.Name = $DS.Name
$DSProp."Used (GB)" = [Math]::Round($DS.CapacityGB - $DS.FreeSpaceGB,2)
$DSProp."Free (GB)" = [Math]::Round($DS.FreeSpaceGB,2)
$DSTemp = New-Object –TypeName PSObject –Prop $DSProp
$DSInfo += $DSTemp
}
If ($DSInfo) {
$DSInfo | Sort Name | Export-Xlsx -Path $FullPath -WorksheetName "Datastores - Chart" -Title "Datastores - Chart" -ChartType xlColumnStacked -AppendWorksheet -SheetPosition "end"
}
# Get Physical NIC Info
$pNICInfo = @()
$NICs = $VMHost | Get-VMHostNetworkAdapter -Physical
Foreach ($NIC in $NICs) {
$NICProp = [ordered]@{}
$NICProp.pNIC = $NIC.DeviceName
$NICProp.Model = ($VMHost.ExtensionData.Hardware.PciDevice | where {$_.Id -eq $NIC.ExtensionData.Pci}).DeviceName
$NICProp.Driver = $NIC.ExtensionData.Driver
$NICProp."Speed (MB)" = $NIC.ExtensionData.LinkSpeed.SpeedMB
$NICProp."Full Duplex" = $NIC.ExtensionData.LinkSpeed.Duplex
$NICProp.MAC = $NIC.Mac
$NICProp."PCI Location" = $NIC.ExtensionData.Pci
$NICProp.vSwitch = ($VMHost | Get-VirtualSwitch | where {$_.Nic -contains $NIC.DeviceName}).Name
$NICTemp = New-Object –TypeName PSObject –Prop $NICProp
$pNICInfo += $NICTemp
}
If ($pNICInfo) {
$pNICInfo | Export-Xlsx -Path $FullPath -WorksheetName "pNIC Info" -Title "Physical NIC Info" -AppendWorksheet -SheetPosition "end"
}
# Get VMKernel Virtual Network Adapter Info
$vNICInfo = @()
$vNICs = $VMHost | Get-VMHostNetworkAdapter -VMKernel
Foreach ($vNIC in $vNICs) {
$vNICProp = [ordered]@{}
$vNICProp.VMKernel = $vNIC.DeviceName
$vNICProp.MAC = $vNIC.Mac
$vNICProp.MTU = $vNIC.Mtu
$vNICProp.IPv6Enabled = $vNIC.IPv6Enabled
$vNICProp.DHCPEnabled = $vNIC.DhcpEnabled
$vNICProp.IP = $vNIC.IP
$vNICProp.SubnetMask = $vNIC.SubnetMask
$vNICProp.PortGroupName = $vNIC.PortGroupName
$vNICProp.MgmtEnabled = $vNIC.ManagementTrafficEnabled
$vNICProp.vMotionEnabled = $vNIC.vMotionEnabled
$vNICProp.FTEnabled = $vNIC.FaultToleranceLoggingEnabled
$vNICProp.VSANEnabled = $vNIC.VsanTrafficEnabled
$vNICTemp = New-Object –TypeName PSObject –Prop $vNICProp
$vNICInfo += $vNICTemp
}
If ($vNICInfo) {
$vNICInfo | Export-Xlsx -Path $FullPath -WorksheetName "VMKernel Info" -Title "VMKernel Info" -AppendWorksheet -SheetPosition "end"
}
# Get Service Console Info
$cNICInfo = @()
$cNICs = $VMHost | Get-VMHostNetworkAdapter -Console
Foreach ($cNIC in $cNICs) {
$cNICProp = [ordered]@{}
$cNICProp.cNIC = $cNIC.DeviceName
$cNICProp.MAC = $cNIC.Mac
$cNICProp.DHCPEnabled = $cNIC.DhcpEnabled
$cNICProp.IP = $cNIC.IP
$cNICProp.SubnetMask = $cNIC.SubnetMask
$cNICProp.PortGroupName = $cNIC.PortGroupName
$cNICTemp = New-Object –TypeName PSObject –Prop $cNICProp
$cNICInfo += $cNICTemp
}
If ($cNICInfo) {
$cNICInfo | Export-Xlsx -Path $FullPath -WorksheetName "Service Console Info" -Title "Service Console Info" -AppendWorksheet -SheetPosition "end"
}
# Get Standard Switch Info
$sSwInfo = @()
$sSwitchs = $VMHost | Get-VirtualSwitch -Standard
Foreach ($sSwitch in $sSwitchs) {
$sSwProp = [ordered]@{}
$sSwProp.Name = $sSwitch.Name
$sSwProp.MTU = $sSwitch.Mtu
$sSwProp."pNIC(s)" = $sSwitch.Nic | Out-String
$sSwProp."Load Balancing" = $sSwitch.ExtensionData.Spec.Policy.NicTeaming.Policy
$sSwProp."Network Failure Detection" = If ($sSwitch.ExtensionData.Spec.Policy.NicTeaming.FailureCriteria.CheckBeacon) {
"Beacon probing"} Else {"Link status only"}
$sSwProp."Notify Switches" = $sSwitch.ExtensionData.Spec.Policy.NicTeaming.NotifySwitches
$sSwProp."Failback" = $sSwitch.ExtensionData.Spec.Policy.NicTeaming.ReversePolicy
$sSwProp."Active pNIC(s)" = $sSwitch.ExtensionData.Spec.Policy.NicTeaming.NicOrder.ActiveNic | Out-String
$sSwProp."Standby pNIC(s)" = $sSwitch.ExtensionData.Spec.Policy.NicTeaming.NicOrder.StandbyNic | Out-String
$sSwProp."Promiscuous Mode" = $sSwitch.ExtensionData.Spec.Policy.Security.AllowPromiscuous
$sSwProp."Mac Address Changes" = $sSwitch.ExtensionData.Spec.Policy.Security.MacChanges
$sSwProp."Forged Transmits" = $sSwitch.ExtensionData.Spec.Policy.Security.ForgedTransmits
$sSwProp."Traffic Shaping Enabled" = $sSwitch.ExtensionData.Spec.Policy.ShapingPolicy.Enabled
$sSwProp."Average Bandwidth" = $sSwitch.ExtensionData.Spec.Policy.ShapingPolicy.AverageBandwidth
$sSwProp."Peak Bandwidth" = $sSwitch.ExtensionData.Spec.Policy.ShapingPolicy.PeakBandwidth
$sSwProp."Burst Size" = $sSwitch.ExtensionData.Spec.Policy.ShapingPolicy.BurstSize
$sSwProp."Portgroup(s)" = $sSwitch | Get-VirtualPortGroup | Select -ExpandProperty Name | Out-String
$sSwTemp = New-Object –TypeName PSObject –Prop $sSwProp
$sSwInfo += $sSwTemp
}
If ($sSwInfo) {
$sSwInfo | Export-Xlsx -Path $FullPath -WorksheetName "Standard Switch Info" -Title "Standard Switch Info" -AppendWorksheet -SheetPosition "end"
}
# Get Distributed Switch Information
$dvSwInfo = @()
$dvSwitchs = $VMHost | Get-VDSwitch
Foreach ($dvSwitch in $dvSwitchs) {
$dvSwProp = [ordered]@{}
$dvSwProp.Name = $dvSwitch.Name
$dvSwProp.MTU = $dvSwitch.Mtu
$dvSwProp."Overall Status" = $dvSwitch.ExtensionData.OverallStatus
$dvSwProp."Config Status" = $dvSwitch.ExtensionData.ConfigStatus
$dvSwProp.Note = "vCenter needed for further info"
$dvSwTemp = New-Object –TypeName PSObject –Prop $dvSwProp
$dvSwInfo += $dvSwTemp
}
If ($dvSwInfo) {
$dvSwInfo | Export-Xlsx -Path $FullPath -WorksheetName "Distributed Switch Info" -Title "Distributed Switch Info" -AppendWorksheet -SheetPosition "end"
}
# Get Standard Portgroup Information
$sPortInfo = @()
$sPortGroups = $VMHost | Get-VirtualPortGroup -Standard
Foreach ($sPortGroup in $sPortGroups) {
$sPortProp = [ordered]@{}
$sPortProp."Virtual Switch" = $sPortGroup.VirtualSwitchName
$sPortProp.Portgroup = $sPortGroup.Name
$sPortProp.VLAN = $sPortGroup.Vlanid
$sPortProp."Load Balancing" = $sPortGroup.ExtensionData.ComputedPolicy.NicTeaming.Policy
$sPortProp."Network Failure Detection" = If ($sPortGroup.ExtensionData.ComputedPolicy.NicTeaming.FailureCriteria.CheckBeacon) {
"Beacon probing"} Else {"Link status only"}
$sPortProp."Notify Switches" = $sPortGroup.ExtensionData.ComputedPolicy.NicTeaming.NotifySwitches
$sPortProp."Failback" = $sPortGroup.ExtensionData.ComputedPolicy.NicTeaming.ReversePolicy
$sPortProp."Active pNIC(s)" = $sPortGroup.ExtensionData.ComputedPolicy.NicTeaming.NicOrder.ActiveNic | Out-String
$sPortProp."Standby pNIC(s)" = $sPortGroup.ExtensionData.ComputedPolicy.NicTeaming.NicOrder.StandbyNic | Out-String
$sPortProp."Promiscuous Mode" = $sPortGroup.ExtensionData.ComputedPolicy.Security.AllowPromiscuous
$sPortProp."Mac Address Changes" = $sPortGroup.ExtensionData.ComputedPolicy.Security.MacChanges
$sPortProp."Forged Transmits" = $sPortGroup.ExtensionData.ComputedPolicy.Security.ForgedTransmits
$sPortProp."Traffic Shaping Enabled" = $sPortGroup.ExtensionData.ComputedPolicy.ShapingPolicy.Enabled
$sPortProp."Average Bandwidth" = $sPortGroup.ExtensionData.ComputedPolicy.ShapingPolicy.AverageBandwidth
$sPortProp."Peak Bandwidth" = $sPortGroup.ExtensionData.ComputedPolicy.ShapingPolicy.PeakBandwidth
$sPortProp."Burst Size" = $sPortGroup.ExtensionData.ComputedPolicy.ShapingPolicy.BurstSize
$sPortProp."VM Count" = ($sPortGroup | Get-VM).Count
$sPortTemp = New-Object –TypeName PSObject –Prop $sPortProp
$sPortInfo += $sPortTemp
}
If ($sPortInfo) {
$sPortInfo | Sort "Virtual Switch", Portgroup | Export-Xlsx -Path $FullPath -WorksheetName "Standard Portgroup Info" -Title "Standard Portgroup Info" -AppendWorksheet -SheetPosition "end"
}
# Get Distributed Portgroup Information
$dvPortInfo = @()
$dvPortGroups = Get-VDPortgroup -Server $ESX
Foreach ($dvPortGroup in $dvPortGroups) {
$dvPortProp = [ordered]@{}
$dvPortProp."Virtual Switch" = $dvPortGroup.VDSwitch
$dvPortProp.Portgroup = $dvPortGroup.Name
$dvPortProp."Port Binding" = $dvPortGroup.PortBinding
$dvPortProp."Overall Status" = $dvPortGroup.ExtensionData.OverallStatus
$dvPortProp."Config Status" = $dvPortGroup.ExtensionData.ConfigStatus
$dvPortProp.Note = "vCenter needed for further info"
$dvPortTemp = New-Object –TypeName PSObject –Prop $dvPortProp
$dvPortInfo += $dvPortTemp
}
If ($dvPortInfo) {
$dvPortInfo | Sort "Virtual Switch", Portgroup | Export-Xlsx -Path $FullPath -WorksheetName "Distributed Portgroup Info" -Title "Distributed Portgroup Info" -AppendWorksheet -SheetPosition "end"
}
# Get Firewall Exceptions
$fwInfo = @()
Try {
$fwExceptions = $VMHost | Get-VMHostFirewallException -ErrorAction Stop
Foreach ($fwException in $fwExceptions) {
$fwProp = [ordered]@{}
$fwProp.Enabled = $fwException.Enabled
$fwProp.Name = $fwException.Name
$fwProp."Incoming Ports" = $fwException.IncomingPorts
$fwProp."Outgoing Ports" = $fwException.OutgoingPorts
$fwProp."Protocol(s)" = $fwException.Protocols
$fwProp."Allow all IPs" = $fwException.ExtensionData.AllowedHosts.AllIp
$fwProp.Service = $fwException.ExtensionData.Service
$fwProp."Service Running" = $fwException.ServiceRunning
$fwTemp = New-Object –TypeName PSObject –Prop $fwProp
$fwInfo += $fwTemp
}
} Catch {}
If ($fwInfo) {
$fwInfo | Sort Enabled, Name | Export-Xlsx -Path $FullPath -WorksheetName "Firewall Exceptions" -Title "Firewall Exceptions" -AppendWorksheet -SheetPosition "end"
}
# Get Services Information
$svcInfo = @()
$services = $VMHost | Get-VMHostService
Foreach ($service in $services) {
$svcProp = [ordered]@{}
$svcProp.Service = $service.Label
$svcProp.Key = $service.Key
$svcProp.Running = $service.Running
switch ($service.Policy)
{
"on" {$svcProp."Startup Policy" = "Start and stop with host"}
"off" {$svcProp."Startup Policy" = "Start and stop manually"}
"automatic" {$svcProp."Startup Policy" = "Start and stop with port usage"}
default {$svcProp."Startup Policy" = "Unknown"}
}
$svcProp.Required = $service.Required
$svcProp.Uninstallable = $service.Uninstallable
$svcProp."Source Package" = $service.ExtensionData.SourcePackage.SourcePackageName
$svcProp."Source Package Desc" = $service.ExtensionData.SourcePackage.Description
$svcTemp = New-Object –TypeName PSObject –Prop $svcProp
$svcInfo += $svcTemp
}
If ($svcInfo) {
$svcInfo | Sort Service | Export-Xlsx -Path $FullPath -WorksheetName "Services Info" -Title "Services Info" -AppendWorksheet -SheetPosition "end"
}
# Get SNMP Info
$snmpInfo = @()
$snmpDetails = Get-VMHostSnmp -Server $ESX
$snmpProp = [ordered]@{}
$snmpProp.Enabled = $snmpDetails.Enabled
$snmpProp.Port = $snmpDetails.Port
$snmpProp."Read Only Communities" = $snmpDetails.ReadOnlyCommunities | Out-String
$snmpProp."Trap Targets" = $snmpDetails.TrapTargets | Out-String
$snmpTemp = New-Object –TypeName PSObject –Prop $snmpProp
$snmpInfo += $snmpTemp
If ($snmpInfo) {
$snmpInfo | Export-Xlsx -Path $FullPath -WorksheetName "SNMP Info" -Title "SNMP Info" -AppendWorksheet -SheetPosition "end"
}
# Get Installed ESX(i) Patches
$patchInfo = @()
Try {
$patches = (Get-EsxCli).software.vib.list()
ForEach ($patch in $patches) {
$patchProp = [ordered]@{}
$patchProp.Name = $patch.Name
$patchProp.ID = $patch.ID
$patchProp.Vendor = $patch.Vendor
$patchProp.Version = $patch.Version
$patchProp."Acceptance Level" = $patch.AcceptanceLevel
$patchProp."Created Date" = $patch.CreationDate
$patchProp."Install Date" = $patch.InstallDate
$patchProp.Status = $patch.Status
$patchTemp = New-Object –TypeName PSObject –Prop $patchProp
$patchInfo += $patchTemp
}
} Catch {
$patches = $VMHost | Get-VMHostPatch
ForEach ($patch in $patches) {
$patchProp = [ordered]@{}
$patchProp.Name = $patch.Description
$patchProp.ID = $patch.ID
$patchProp."Install Date" = $patch.InstallDate
$patchTemp = New-Object –TypeName PSObject –Prop $patchProp
$patchInfo += $patchTemp
}
}
If ($patchInfo) {
$patchInfo | Sort "Install Date" -Descending | Export-Xlsx -Path $FullPath -WorksheetName "Patch Info" -Title "Patch Info" -AppendWorksheet -SheetPosition "end"
}
# Get Local Users
$accountInfo = @()
$accounts = Get-VMHostAccount -Server $ESX
ForEach ($account in $accounts) {
$accountProp = [ordered]@{}
$accountProp.Name = $account.Name
$accountProp.Description = $account.Description
$accountProp.ShellAccess = $account.ShellAccessEnabled
$accountProp.Groups = $account.Groups | Out-String
$accountTemp = New-Object –TypeName PSObject –Prop $accountProp
$accountInfo += $accountTemp
}
If ($accountInfo) {
$accountInfo | Sort IsSystem, Name | Export-Xlsx -Path $FullPath -WorksheetName "Local Users" -Title "Local Users" -AppendWorksheet -SheetPosition "end"
}
# Get Local Groups
$grpInfo = @()
Try {
$grps = Get-VMHostAccount -Server $ESX -Group -ErrorAction Stop
ForEach ($grp in $grps) {
$grpProp = [ordered]@{}
$grpProp.Name = $grp.Name
$grpProp.Description = $grp.Description
$grpProp.Users = $grp.Users | Out-String
$grpTemp = New-Object –TypeName PSObject –Prop $grpProp
$grpInfo += $grpTemp
}
} Catch {}
If ($grpInfo) {
$grpInfo | Sort Name | Export-Xlsx -Path $FullPath -WorksheetName "Local Groups" -Title "Local Groups" -AppendWorksheet -SheetPosition "end"
}
# Get VI Roles
$roleInfo = @()
$roles = Get-VIRole -Server $ESX
ForEach ($role in $roles) {
$roleProp = [ordered]@{}
$roleProp.Name = $role.Name
$roleProp.Description = $role.Description
$roleProp.IsSystem = $role.IsSystem
$roleProp.Privileges = $role.PrivilegeList | Out-String
$roleTemp = New-Object –TypeName PSObject –Prop $roleProp
$roleInfo += $roleTemp
}
If ($roleInfo) {
$roleInfo | Sort IsSystem, Name | Export-Xlsx -Path $FullPath -WorksheetName "VI Roles" -Title "VI Roles" -AppendWorksheet -SheetPosition "end"
}
# Get Permissions
$permInfo = @()
$perms = Get-VIPermission -Server $ESX
ForEach ($perm in $perms) {
$permProp = [ordered]@{}
$permProp.Entity = $perm.Entity
$permProp.Role = $perm.Role
$permProp.Principal = $perm.Principal
$permProp.IsGroup = $perm.IsGroup
$permProp.Propagate = $perm.Propagate
$permTemp = New-Object –TypeName PSObject –Prop $permProp
$permInfo += $permTemp
}
If ($permInfo) {
$permInfo | Sort Entity, Principal | Export-Xlsx -Path $FullPath -WorksheetName "Permissions" -Title "Permissions" -AppendWorksheet -SheetPosition "end"
}
# Get VM Info
$vmInfo = @()
$vms = $VMHost | Get-VM
ForEach ($vm in $vms) {
$vmProp = [ordered]@{}
$vmProp.Name = $vm.Name
$vmProp.State = $vm.PowerState
$vmProp.FullName = If (!$VM.Guest.hostname) {"Tools Not Running\Unknown"} Else {$VM.Guest.hostname}
$vmProp.GuestOS = If (!$VM.Guest.OSFullName) {"Tools Not Running\Unknown"} Else {$VM.Guest.OSFullName}
$vmProp.IP = If (!$VM.Guest.IPAddress[0]) {"Tools Not Running\Unknown"} Else {$VM.Guest.IPAddress[0]}
$vmProp.NumCPU = $vm.NumCPU
[int]$vmProp."Memory (GB)" = $vm.MemoryGB
$vmProp."Disk (GB)" = [Math]::Round((($vm.HardDisks | Measure-Object -Property CapacityKB -Sum).Sum * 1KB / 1GB),2)
$vmProp."DiskFree (GB)" = If (![Math]::Round((($vm.Guest.Disks | Measure-Object -Property FreeSpace -Sum).Sum / 1GB),2)) `
{"Tools Not Running\Unknown"} Else {[Math]::Round((($vm.Guest.Disks | Measure-Object -Property FreeSpace -Sum).Sum / 1GB),2)}
$vmProp."DiskUsed (GB)" = If ($vmProp."DiskFree (GB)" -eq "Tools Not Running\Unknown") `
{"Tools Not Running\Unknown"} Else {$vmProp."Disk (GB)" - $vmProp."DiskFree (GB)"}
$vmProp.Notes = $VM.Notes
$vmTemp = New-Object –TypeName PSObject –Prop $vmProp
$vmInfo += $vmTemp
}
If ($vmInfo) {
$vmInfo | Sort Created -Descending | Export-Xlsx -Path $FullPath -WorksheetName "VM Info" -Title "VM Info" -AppendWorksheet -SheetPosition "end"
}
# Get VM Snapshots
$snapInfo = @()
$snaps = $VMHost | Get-VM | Get-Snapshot
ForEach ($snap in $snaps) {
$snapProp = [ordered]@{}
$snapProp.VM = $snap.VM
$snapProp.Name = $snap.Name
$snapProp.Description = $snap.Description
$snapProp.Created = $snap.Created
$snapProp."Size (GB)" = [Math]::Round($snap.SizeGB,2)
$snapProp.IsCurrent = $snap.IsCurrent
$snapTemp = New-Object –TypeName PSObject –Prop $snapProp
$snapInfo += $snapTemp
}
If ($snapInfo) {
$snapInfo | Sort Created -Descending | Export-Xlsx -Path $FullPath -WorksheetName "Snapshot Info" -Title "Snapshot Info" -AppendWorksheet -SheetPosition "end"
}
Disconnect-VIServer $ESX -Confirm:$false
Write-Host "$ESX Report Complete - $FullPath"
} Else {
Write-Host "Unable to connect to $ESX" -ForegroundColor Red
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.