Powershell: VMWare and physical Windows server inventory
We will describe in this post how to make an inventory of your physical and VMWare virtual machines running Windows Server. For each virtual machine, we will also retrieve on which physical host the server is running. If you have a VMWare virtualized environment this script can be useful to help you decide which type of Windows server edition you need to purchase in order to lower your costs. For more information on how to license MS Windows Server in a VMWare environment you can read this article.
For each machine (Physical server, Virtual Machine, ESX host) we retrieve:
- The machine name.
- The machine physical model, if this is a Virtual Machine “VM” is returned.
- The total number of CPUs of the machine.
- The total number of Cores of the machine.
- Total RAM of the machine.
- OS of the machine. For the Windows Server machines, we also return the Edition (Enterprise, Standard, Datacenter). For the ESX hosts, “ESX” is returned.
For each ESX host we return the Virtual Machines running on it. The Virtual Machines positions are a snapshot picture at the time the script is running. Your Virtual Machines might move later to another ESX host because of the DRS mechanism. Below is an example of result file retrieved with the script:
In order to achieve this inventory we will use PowerCli, WMI and the AD Cmdlets. Firstly we will retrieve all the servers which have been active during the last 90 days:
$d = [DateTime]::Today.AddDays(-90) $servers = Get-ADComputer -searchbase "DC=ldap389,DC=info" -Properties OperatingSystem, OperatingSystemServicePack -Filter 'PasswordLastSet -ge $d' | Where-Object {$_.OperatingSystem -like ‘*server*’} |
Then we retrieve the Windows OS edition of each computer account. For Windows 2008 servers, that information is stored in the OperatingSystem account attribute. For other versions, the edition is retrieved by querying the server with the Win32_OperatingSystem WMI class. In order to compute the total number of CPUs and Cores of each Windows server we will use the Win32_Processor WMI class. Under Windows 2003, the computing method os different depending on wether or not you patched your OS with KB932370.
For Windows 2008 and patched Windows 2003 Operating systems:
$Win32_cpu = Get-WmiObject -class win32_processor -computer $ServerName $NbCPUs = ($Win32_cpu | measure-object).count $Nbcores = ($Win32_cpu | measure-object NumberOfCores -sum).sum |
For non patched Windows 2003 OS (read this post for more details):
$physCount = new-object hashtable $Win32_cpu = Get-WmiObject -class win32_processor -computer $ServerName $Win32_cpu |%{$physCount[$_.SocketDesignation] = 1} $NbCPUs = $physCount.count $Nbcores = ($Win32_cpu | measure-object).count |
If the Manufacturer value returned by the Win32_ComputerSystem WMI class is equal to VMware, Inc. the server is a VMWare virtual machine: In that case we retrieve the ESX host on which the VM is running. The virtual machines are sorted by ESX host: Thanks to a hashtable with the ESX hosts names containing hashtables with the Virtual machines of each ESX host. Read this article on how to manipulate a hashtable that contains hashtables. The common value between the AD computer object and the Virtual Machine PowerCli object is the DNSHostname AD attribute and the Hostname value stored in the Guest object of the VM (thanks NiTRo for that tip). That way the script will run even if your Virtual Machine names are not equal to your server hostnames.
If the server is a physical machine, we write the result directly in the output file.
Once we have retrieved all the ESX hosts names and VMs information, we retrieve physical information (Model, total CPUs, total cores, RAM) for each ESX host by using PowerCli, as described in this post:
$hard = (get-vmhost $esx).Extensiondata.Summary.Hardware $mem = [int] ($hard.MemorySize/1mb) $NbCPUs = $hard.NumCpuPkgs $Nbcores = $hard.NumCpuCores $model = $hard.Model |
To download the full script just click on the link below:
Launch the script in a PowerCli session and do not forget to import the AD module (import-module ActiveDirectory): There we go, we used WMI, PowerCli and the AD Cmdlets in a single script 🙂
This post is also available in: French