Inventory ESXi hosts in VMware vCenter

In an earlier post, I have shared with you a PowerShell script I use to create a report of all VM’s running in our vCenters. In this post you can find a similar script to create a report of all ESXi hosts in our vCenters.

This script will create a report containing the following information on the ESXi host:

  • Serial number
  • Hostname
  • vCenter name
  • Datacenter name
  • Cluster name
  • Manufacturer
  • Model
  • BIOS version
  • Number of physical CPU’s
  • CPU type
  • Number of cores per CPU
  • ESXi version
  • ESXi license number
  • Amount of memory
  • The IP address of the primary DNS server
  • The IP address of the secondary DNS server
  • The name of the management adapter
  • The IP address of the management adapter
  • The MTU size of the management adapter
  • The name of the vMotion adapter
  • The IP address of the vMotion adapter
  • The MTU size of the vMotion adapter
  • The name of the vSAN adapter
  • The IP address of the vSAN adapter
  • The MTU size of the vSAN management adapter
    (in case you do not use vSAN, you can remove the last three objects from the script)

    To use the script, you will need to update variable $ListOfvCenters.
    If you want to connect to the vCenter(s) using your current credentials, just remove everything related to $Credentials.

[UPDATE] Earlier today, I ran this script for the very first time in PowerShell 7 (yes, a bit late, I know 🙂 ) and I noticed that command Get-VMHostHardware is not available in PowerShell 7. While trouble shooting this, I encountered this site: https://community.broadcom.com/vmware-cloud-foundation/discussion/get-vmhosthardware. It looks like someone is using my script and already found out about this issue. I updated this script and fixed the issue where the serial number was empty in most cases. Any other bugs…please let me know.

# Import VMware PowerCLI module
If (-not (Get-Module -Name 'VMware.PowerCLI')) {
    Import-Module VMware.PowerCLI
}

# Variable declaration
$Report = New-Object System.Collections.ArrayList
$DateTime = $((Get-Date).ToString('yyyy-MM-dd_hh-mm-ss'))

# Set report output path
$OutputPath = "$env:USERPROFILE\Documents\Reports"
If ( -Not (Test-Path -Path $OutputPath)) {
    New-Item -ItemType directory -Path $OutputPath
}
$Outputfile = "All-ESXi-hosts-$DateTime"

Function MyLogger {
    Param(
        [Parameter(Mandatory = $True)] [String] $Message,
        [Parameter(Mandatory = $False)] [Boolean] $Log = $False
    )
    $TimeStamp = Get-Date -Format "dd-MMM-yyyy HH:mm:ss"

    Write-Host -NoNewline -ForegroundColor White "[$timestamp]"
    Write-Host -ForegroundColor Green " $message"

    $logMessage = "[$timeStamp] $message"
    If ($Log -eq $True) {
        $logMessage | Out-File -Append -LiteralPath $LogFile
    }
} #Function MyLogger

Function MyLoggerError {
    Param(
        [Parameter(Mandatory = $True)] [String] $Message,
        [Parameter(Mandatory = $False)] [Boolean] $Log = $False
    )

    $TimeStamp = Get-Date -Format "dd-MMM-yyyy HH:mm:ss"

    Write-Host -NoNewline -ForegroundColor White "[$timestamp]"
    Write-Host -ForegroundColor Red -BackgroundColor Yellow " $message"

    $logMessage = "[$timeStamp] $message"
    If ($Log -eq $True) {
        $logMessage | Out-File -Append -LiteralPath $LogFile
    }
} #Function MyLoggerError

# Get credentials to use to connect to the vCenter(s)
Clear-Host
$Credentials = Get-Credential -Message "Please enter the username and password to use to connect to the vCenter(s)"

# Connect to vCenter(s)
$ListOfvCenters = (
    "<FQDN/IP address of vCenter #1",
    "vcenter01.yourdomain.local",
    "10.10.10.50"
)
Connect-VIServer $ListOfvCenters -Credential $Credentials -ErrorAction Continue

# Get a list of all ESXi hosts running in the vCenter(s)
$ListOfVMHosts = Get-VMHost | Sort-Object Name

# Get required information for each host
$Count = $ListOfVMHosts.Count
$Counter = 1

Foreach ($VMHost in $ListOfVMHosts) {

    $TestVMHostConnection = $null
    $TestVMHostConnection = Get-VMHost -Name $VMHost

    If ($TestVMHostConnection) {

        MyLogger -Message "Processing host $VMHost [$Counter/$Count]"
        #Write-Host "Processing host $VMHost.Name [$Counter/$Count]"

        $HostNetwork = $VMHost |  Get-VMHostNetwork

        $HostNetworkvMotionAdapter = $VMHost |  Get-VMHostNetworkAdapter -VMKernel |  Where-Object { $_.VMotionEnabled -eq $true }
        $HostNetworkManagementTrafficAdapter = $VMHost |  Get-VMHostNetworkAdapter -VMKernel |  Where-Object { $_.ManagementTrafficEnabled -eq $true }
        $HostNetworkvSANTrafficAdapter = $VMHost |  Get-VMHostNetworkAdapter -VMKernel |  Where-Object { $_.VsanTrafficEnabled -eq $true }

        $MemoryTotalGB = [math]::Round($VMHost.MemoryTotalGB)

        $Object = [PSCustomObject]@{
            SerialNumber     = ($VMHost.ExtensionData.Hardware.SystemInfo.OtherIdentifyingInfo | Where-Object { $_.IdentifierType.Key -eq "ServiceTag" }).IdentifierValue # Serialnumber needs to be first for VLOOKUP to work in Excel
            vCenter          = $VMHost.Uid.Substring($VMHost.Uid.IndexOf('@') + 1).Split(":")[0]
            DataCenter       = ($VMHost | Get-Datacenter)
            Cluster          = $VMHost.Parent
            HostName         = $VMHost.Name
            Manufacturer     = $VMHost.Manufacturer
            Model            = $VMHost.Model
            Bios             = $VMHost.ExtensionData.Hardware.BiosInfo.BiosVersion
            Processor        = $VMHost.ProcessorType
            CPU              = $VMHost.ExtensionData.Hardware.CpuInfo.NumCpuPackages
            CPUCores         = $VMHost.ExtensionData.Hardware.CpuInfo.NumCpuCores
            MemoryGB         = $MemoryTotalGB
            ESXVersion       = $VMHost.ExtensionData.Summary.Config.Product.FullName
            ESXLicenseKey    = $VMHost.LicenseKey
            DNS1             = $HostNetwork.DnsAddress[0]
            DNS2             = $HostNetwork.DnsAddress[1]
            Gateway          = $HostNetwork.VMKernelGateway
            ManagementDevice = $HostNetworkManagementTrafficAdapter.name
            ManagementIP     = $HostNetworkManagementTrafficAdapter.ip
            ManagementMTU    = $HostNetworkManagementTrafficAdapter.mtu
            vMotionDevice    = $HostNetworkvMotionAdapter.name
            vMotionIP        = $HostNetworkvMotionAdapter.ip
            vMotionMTU       = $HostNetworkvMotionAdapter.mtu
            vSANDevice       = $HostNetworkvSANTrafficAdapter.name
            vSANIP           = $HostNetworkvSANTrafficAdapter.ip
            vSANMTU          = $HostNetworkvSANTrafficAdapter.mtu
        }

        $Report.add($Object) | Out-Null
    } Else {
        MyLoggerError -Message  "There was an error processing host $VMHost.Name [$Counter/$Count]"
    }
    $Counter++
}

$Report | Export-Csv "$Outputfile.csv" -NoTypeInformation -UseCulture

$DefaultVIServers | Disconnect-VIServer -Confirm:$false

As always, please keep in mind this script is tailored to my environment, but can be used as a template for your environment. I do not pretend to be a PowerShell guru and as such my script may not be perfect. I am open to suggestions  🙂 . If you found this script useful, I’d appreciate it if you leave a comment.

2 thoughts on “Inventory ESXi hosts in VMware vCenter”

  1. Nice Script Dennis, or should I address you as “Mr. Kool”? 🙂

    What was your intention with the “My Logger” routine?

    1. Hi Roger, Dennis will do just fine 🙂

      I just noted I forgot to add the MyLogger function to the code. I use that function to show output while running the script. In this case, it shows the number of hosts to be processed. In other scripts I use this function to log the output to a text file.
      Thanks for bringing this to my attention, much appreciated, code is now updated. !!

Leave a Reply

Your email address will not be published. Required fields are marked *