Inventory VMware virtual machines

For reporting purposes, I maintain an Excel sheet containing information on my server base. I update this sheet on a weekly basis. Part of the information displayed in this sheet comes from a PowerShell script I have created to extract the required data from our vCenters.

This script pulls the following information for every VM running in the vCenter environment:

  • VM Name
  • hardware version
  • power status
  • vCenter it runs on (in case you have more than 1)
  • ESXi host the VM runs on
  • cluster the VM is assigned to
  • VMware tools status
  • guest OS
  • number of vCPU’s
  • is CPU HotAdd enabled?
  • is there a CPU reservation?
  • amount of assigned RAM
  • is memory HotAdd enabled?
  • is VM memory reserved?
  • number of disks assigned to the VM
  • disk sizes
  • number of NICs
  • NIC types (E1000, VMNIC3)
  • NIC IP addresses
  • NIC MAC addressess
  • the folder it lives in
  • bootdelay

Maybe this script is sufficient for your needs. If not, it should be straight forward enough for you to adjust. A requirement for this script to work is the VMware PowerCLI PowerShell module, which can be installed with this PowerShell command:

Install-Module -Name VMware.PowerCLI -Scope CurrentUser

See https://blogs.vmware.com/PowerCLI for more information about VMware PowerCLI.

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.

# 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-VMs-$DateTime"

# 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)
$ListOfVMs = Get-VM | Sort-Object -Property Name                                             # Sort the VM list on alphabetical order
#$ListOfVMs = Get-VM | Where-Object {$_.Name -like "*text*"} | Sort-Object -Property Name   # User this line to get info on specified VM's

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

ForEach ($VM in $ListOfVMs) {
    try {
        Write-Host "Processing VM - [$Counter/$Count] -" $VM.name

        $VMView = $VM | Get-View -ErrorAction Ignore
        $VMNICs = Get-NetworkAdapter -VM $VM -ErrorAction Ignore
        $VMDisks = Get-HardDisk -VM $VM -ErrorAction Ignore

        $Object = [PSCustomObject]@{
            Name                = $VM.Name
            PowerState          = $VM.PowerState
            HardwareVersion     = $VM.HardwareVersion
            vCenter             = $VM.Uid.Substring($VM.Uid.IndexOf('@') + 1).Split(":")[0]
            Host                = $VM.VMHost.Name
            Cluster             = $VM.VMHost.Parent.name
            ToolsStatus         = $VMView.Guest.ToolsStatus
            GuestOS             = (Get-VMGuest -VM $VM).OSFullName
            NumCPU              = $VM.NumCpu
            CpuHotAddEnabled    = $VM.ExtensionData.config.CpuHotAddEnabled
            CPUReservation      = $VM.ExtensionData.Config.CPUAllocation.Reservation
            MemGB               = $VM.MemoryGB
            MemoryHotAddEnabled = $VM.ExtensionData.config.MemoryHotAddEnabled
            MemoryAllReserved   = $VM.ExtensionData.Config.MemoryReservationLockedToMax
            MemoryReservation   = $VM.ExtensionData.Config.MemoryAllocation.Reservation
            NumDisks            = $VMDisks.Count
            Disk1SizeGb         = $VMDisks.CapacityGb[0]
            Disk2SizeGb         = $VMDisks.CapacityGb[1]
            Disk3SizeGb         = $VMDisks.CapacityGb[2]
            Disk4SizeGb         = $VMDisks.CapacityGb[3]
            NumNICs             = $VMNICs.Count
            Nic0_Type           = $VMNICs.Type[0]
            NIC0_IP             = $VM.Guest.IPAddress[0]
            NIC0_Mac            = $VMNICs.MacAddress[0]
            Nic1_Type           = $VMNICs.Type[1]
            NIC1_IP             = $VM.Guest.IPAddress[1]
            NIC1_Mac            = $VMNICs.MacAddress[1]
            Nic2_Type           = $VMNICs.Type[2]
            NIC2_IP             = $VM.Guest.IPAddress[2]
            NIC2_Mac            = $VMNICs.MacAddress[2]
            Folder              = $VM.Folder.Name
            BootDelay           = $VM.ExtensionData.Config.BootOptions.BootDelay
            # LoggingEnabled  = $VM.ExtensionData.Config.Flags.EnableLogging
        }

        $Report.add($Object) | Out-Null
    } Catch {} Finally {
        $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.

9 thoughts on “Inventory VMware virtual machines”

  1. I could be wrong but isn’t line 30 incorrect? I think it should read
    $ListOfVMs = Get-VM | Sort-Object -Property Name

    1. Not necessarily, although in this case it will work. $DefaultVIServers is a variable that lists all vCenter servers you are connected to. Which in this case is the same as the list of servers in $ListOfvCenters.
      In case you want to disconnect from some but not all vCenters, you can use a variable listing just those servers.

      Makes sense ?

Leave a Reply

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