Today, I am going to share a script, which personally used a lot, not only as a standalone script, but, in conjunction with other scripts in a workflow to generate multiple CSV files of our VMware environment globally. After that, pass CSV files to next script to ingest in my SQL Database inventory system. Once ingested, run SQL Stored Procedures and queries to provide different results in relation with other Database tables.
I will talk about that integration in a separate blog. I use this data with IT Service Management data and other data sources to come up with different IT Management reports.
Enough introduction, let’s move to the script now. This script will provide inventory of VMware Virtual Machines, ESXi Hosts, Clusters, Networks, Data stores, Events etc. However, you can add more inventory stuffs here based on your requirements.
You need to login with a credential with enough permissions to run the script, and, provide ESXi VCenter FQDN as parameter. You also need to install VMware PowerCLI on your working system as this script is using it to gather information. If you don’t have PowerCLI already installed, download it from VMware website.
Thanks for the download and let me know if you face any issue.
Param(
[Parameter(Mandatory=$true)]
[string]$vcenterFQDN
)
$vcname = $vcenterFQDN.Split(".")[0]
Connect-VIServer $vcenterFQDN -Credential (Get-Credentials)
$currentDir = $(Get-Location).Path
ForEach($module in "VMInfo","HOSTInfo","CluInfo","DSInfo","NetInfo","EventInfo")
{
switch($module)
{
"VMInfo"
{
$VMOPath = "$($currentDir)\"+$vcname+"_VM.csv"
if(Test-Path $VMOPath){remove-item $VMOPath -force}
$VMInfo = Get-View -ViewType VirtualMachine -Property Name, Guest.GuestFullName, Snapshot,Config.Hardware.MemoryMB, Config.Hardware.NumCPU,Config.Version,Config.Hardware.NumCoresPerSocket, Guest.Disk, Runtime.PowerState, Summary.Guest.ToolsVersionStatus,Config.Hardware.Device, Summary.Guest.ToolsRunningStatus, Config.Version, Config.Template,Guest,Datastore,Config.DatastoreUrl
foreach ($vm in $VmInfo)
{
$VMIP = ""
if(!([String]::IsNullOrEmpty($vm.Guest.HostName))){$VMName = ($vm.Guest.HostName).Split(",")[0]}
else{$VMName = $vm.Name.Split(",")[0]}
if($VMName -notlike "*.*"){
if((Resolve-DnsName $VMName | Select-Object Name).Name){$VMName = (Resolve-DnsName $VMName | Select-Object Name).Name}
else{$VMName = $vm.Name.Split(",")[0]}
}
$VMHostName = & {$vm.UpdateViewData("Runtime.Host.Name"); $vm.Runtime.LinkedView.Host.Name}
$VMClusterName = & {$vm.UpdateViewData("runtime.host.parent.name");$vm.Runtime.LinkedView.Host.LinkedView.Parent.Name}
$VMDataCenter = & {$vm.UpdateViewData("runtime.host.parent.parent.parent.name");$vm.Runtime.LinkedView.Host.LinkedView.Parent.LinkedView.Parent.LinkedView.parent.name}
$VMOS = ($vm.Guest.GuestFullName).Replace(","," ").Split([environment]::NewLine)[0]
if($null -ne $vm.snapshot){$VMWithSnapshot = "YES"}else{$VMWithSnapshot = "NO"}
$VMNumCPU = $vm.Config.Hardware.NumCPU
$VMCoresPerSocket = $vm.Config.Hardware.NumCoresPerSocket
$VMMemMB = $vm.Config.Hardware.MemoryMB
$VMDiskSizeGB = [Math]::Round(($vm.Guest.Disk.capacity | Measure-Object -Sum).Sum / 1GB,0)
$VMFreeDiskGB = [Math]::Round(($vm.Guest.Disk.Freespace | Measure-Object -Sum).Sum / 1GB,0)
$VMPowState = $vm.Runtime.PowerState
$VMToolUpdate = $vm.Summary.Guest.ToolsVersionStatus
$VMToolState = $vm.Summary.Guest.ToolsRunningStatus
$VMHardware = $vm.Config.Version
$VMIsTemplate = $vm.Config.Template
$VMVLAN = &{$vm.UpdateViewData("Network.Name");$vm.LinkedView.Network.name -Join ";"}
$VMNetAType = $vm.Config.Hardware.Device | Where-Object{$_ -is [VMware.Vim.VirtualEthernetCard]} | ForEach-Object{$_.gettype().Name -Join ";"}
$VMMACAddress = $vm.Config.Hardware.Device | Where-Object{$_ -is [VMware.Vim.VirtualEthernetCard]} | ForEach-Object{$_.MacAddress -Join ";"}
$VMIP = ($vm.Guest.Net.IpAddress | ?{$_ -notlike "*f*"}) -join ";"
$VMDataStore = $vm.Config.DatastoreUrl.Name -join ";"
"$vcenterFQDN,$VMName,$VMHostName,$VMClusterName,$VMDataCenter,$VMOS,$VMWithSnapshot,$VMNumCPU,$VMCoresPerSocket,$VMMemMB,$VMDiskSizeGB,$VMFreeDiskGB,$VMPowState,$VMToolState,$VMToolUpdate,$VMHardware,$VMIsTemplate,$VMVLAN,$VMNetAType,$VMMACAddress,$VMIP,$VMDataStore" | Out-File $VMOPath -Append -Encoding ASCII
}
}
"HostInfo"
{
$HOSTOPath = "$($currentDir)\"+$vcname+"_HOST.csv"
if(Test-Path $HOSTOPath){remove-item $HOSTOPath -force}
$HostInfo = Get-View -ViewType HostSystem
ForEach($vHost in $HostInfo)
{
$vHostName = $vHost.Name
$vHostClu = &{$vHost.UpdateViewData("Parent.Name");$vHost.LinkedView.Parent.Name}
if((&{$vHost.UpdateViewData("Parent.Parent.Parent.Name");$vHost.LinkedView.Parent.LinkedView.Parent.LinkedView.Parent.Name}) -eq 'host'){
$vHostDataCenter = &{$vHost.UpdateViewData("Parent.Parent.Parent.Parent.Name");$vHost.LinkedView.Parent.LinkedView.Parent.LinkedView.Parent.LinkedView.Parent.Name}
}
else{
$vHostDataCenter = &{$vHost.UpdateViewData("Parent.Parent.Parent.Name");$vHost.LinkedView.Parent.LinkedView.Parent.LinkedView.Parent.Name}
}
$vHostDatastores = &{$vHost.UpdateViewData("Datastore.Name");$vHost.LinkedView.Datastore.Name -join ";"}
$vHostVerion = $vHost.Config.Product.Version
$vHostBuild = $vHost.Config.Product.Build
$vHostConState = $vHost.Runtime.ConnectionState
$vHostPowState = $vHost.Runtime.PowerState
$vHostUptime = (Get-Date) - ($vHost.Runtime.BootTime) | Select-Object -ExpandProperty days
$vHostVMotionState = $vHost.Summary.Config.VmotionEnabled
$vHostVMotionIP = $vHost.Config.Vmotion.ipconfig.ipaddress -join ";"
$vHostVendor = $vHost.Summary.Hardware.Vendor
$vHostModel = $vHost.Summary.Hardware.Model
$vHostCPUModel = $vHost.Summary.Hardware.CpuModel
$vHostCPUSocket = $vHost.Summary.Hardware.NumCpuPkgs
$vHostCPUCore = $vHost.Summary.Hardware.NumCpuCores
$vHostCPUSpeed = $vHost.Summary.Hardware.CpuMhz
$vHostHyperthreading = $vHost.Config.HyperThread.Active
$vHostHBADevices = (get-vmhosthba -type FibreChannel -VMHost $vHost.Name).Device -join ";"
$vHostHBAModels = (get-vmhosthba -type FibreChannel -VMHost $vHost.Name).Model -join ";"
$vHostNICs = $vHost.Summary.Hardware.NumNics -Join ";"
$vHostMemory = [Math]::Round($vHost.Summary.Hardware.MemorySize / 1gb,0)
$vHostSerialNumber = ($vHost.Hardware.SystemInfo.OtherIdentifyingInfo | Where-Object {$_.IdentifierType.Key -eq "ServiceTag" }).identifiervalue
$vHostBIOS = $vHost.Hardware.BiosInfo.BiosVersion
$vHostBIOSRDate = $vHost.Hardware.BiosInfo.ReleaseDate
$vHostVLANs = &{$vHost.UpdateViewData("Network.Name");$vHost.LinkedView.Network.Name -Join ";"}
$vCenterVer = (Get-VMHost -Name $vHostName | Select-Object ApiVersion).ApiVersion
"$vcenterFQDN,$vHostName,$vHostClu,$vHostDataCenter,$vHostDatastores,$vHostVerion,$vHostBuild,$vHostConState,$vHostPowState,$vHostUptime,$vHostVMotionState,$vHostVMotionIP,$vHostVendor,$vHostModel,$vHostCPUModel,$vHostCPUSocket,$vHostCPUCore,$vHostCPUSpeed,$vHostHyperthreading,$vHostHBADevices,$vHostHBAModels,$vHostNICs,$vHostMemory,$vHostSerialNumber,$vHostBIOS,$vHostBIOSRDate,$vHostVLANs,$vCenterVer" | Out-File $HOSTOPath -Append -Encoding ASCII
}
}
"CluInfo"
{
$CLUOPath = "$($currentDir)\"+$vcname+"_CLUSTER.csv"
if(Test-Path $CLUOPath){remove-item $CLUOPath -force}
Get-View -ViewType ClusterComputeResource -Property Name,Configuration.DrsConfig,Summary.NumHosts,Host,Network,Datastore | Sort-Object -Property Name | Foreach-Object {
$clu = $_
if($clu.Host -ne $null){$CLUHostNames = &{$clu.UpdateViewData("Host.Name");$clu.LinkedView.Host.name -Join ";"}}else{$CLUHostNames = ""}
if($clu.Network -ne $null){$CLUVLANs = &{$clu.UpdateViewData("Network.Name");$clu.LinkedView.Network.Name -Join ";"}}else{$CLUVLANs = ""}
if($clu.Datastore -ne $null){$CLUDatastores = &{ $clu.UpdateViewData("Datastore.Name");$clu.LinkedView.Datastore.Name -Join ";"}}else{$CLUDatastores = ""}
$CLUName = $clu.Name
$CLUDatacenter = &{$clu.UpdateViewData("Parent.Parent.Name");$clu.LinkedView.Parent.LinkedView.Parent.Name}
$CLUDRSBehavior = $clu.Configuration.DrsConfig.DefaultVmBehavior
$CLUVMotionRate = $clu.Configuration.DrsConfig.VmotionRate
$CLUNumHost = $clu.Summary.NumHosts
"$vcenterFQDN,$CLUName,$CLUDatacenter,$CLUDRSBehavior,$CLUVMotionRate,$CLUNumHost,$CLUHostNames,$CLUVLANs,$CLUDatastores" | Out-file $CLUOPath -Append -Encoding ASCII
}
}
"DSInfo"
{
$DSOPath = "$($currentDir)\"+$vcname+"_DATASTORE.csv"
if(Test-Path $DSOPath){remove-item $DSOPath -force}
get-view -ViewType Datastore -Property Name,Summary.Capacity,Summary.FreeSpace,vm,info | Sort-Object -Property Name | Foreach-Object {
$ds = $_
$DSNAME = $ds.name
$DSCapacityGB = $ds.Summary.Capacity / 1gb
$DSFreeGB = $ds.Summary.FreeSpace / 1gb
$DSType = $ds.info.vmfs.Type
$DSBlockSizeMB = $ds.info.vmfs.BlockSizeMb
$DSVersion = $ds.info.vmfs.Version
$DSNAAID = $ds.Info.Vmfs.Extent.diskName
$DSClu = Get-DatastoreCluster -Datastore $DSNAME | Select-Object -ExpandProperty Name
"$vcenterFQDN,$DSNAME,$DSCapacityGB,$DSFreeGB,$DSType,$DSBlockSizeMB,$DSVersion,$DSNAAID,$DSClu" | Out-File $DSOPath -Append -Encoding ASCII
}
}
"NetInfo"
{
$NetOPath = "$($currentDir)\"+$vcname+"_NETWORK.csv"
if(Test-Path $NetOPath){remove-item $NetOPath -force}
get-view -ViewType Network -Property Name | Sort-Object -Property Name | Foreach-Object {
$VMNet = $_
$VMNetName = $VMNet.Name
"$vcenterFQDN,$VMNetName" | Out-File $NetOPath -Append -Encoding ASCII
}
}
"EventInfo"
{
$EventOPath = "$($currentDir)\"+$vcname+"_EVENT.csv"
if(Test-Path $EventOPath){remove-item $EventOPath -force}
$si=get-view ServiceInstance
$em= get-view $si.Content.EventManager
$EventFilterSpecByTime = New-Object VMware.Vim.EventFilterSpecByTime
$EventFilterSpecByTime.BeginTime = (get-date).AddMonths(-6)
$EventFilterSpec = New-Object VMware.Vim.EventFilterSpec
$EventFilterSpec.Time = $EventFilterSpecByTime
$EventFilterSpec.Type = "VmCreatedEvent","VmDeployedEvent","VmClonedEvent"
$createEvents = $em.QueryEvents($EventFilterSpec) | Select-Object CreatedTime,@{N="VM";E={$_.VM.Name}},UserName
ForEach($e in $createEvents){
$status = "Created"
$createDate = $e.CreatedTime.ToString("dd-MMM-yyyy")
$vmName = $e.VM
$userName = $e.UserName
"$vcenterFQDN,$status,$createDate,$vmName,$userName"| Out-File $EventOPath -Append -Encoding ASCII
}
$EventFilterSpec.Type = "VmRemovedEvent"
$createEvents = $em.QueryEvents($EventFilterSpec) | Select-Object CreatedTime,@{N="VM";E={$_.VM.Name}},UserName
ForEach($e in $createEvents){
$status = "Deleted"
$createDate = $e.CreatedTime.ToString("dd-MMM-yyyy")
$vmName = $e.VM
$userName = $e.UserName
"$vcenterFQDN,$status,$createDate,$vmName,$userName"| Out-File $EventOPath -Append -Encoding ASCII
}
}
}
}
Disconnect-VIServer $vcenterFQDN -confirm:$false
Exit
If you have not installed VMware PowerCLI. Login to VMware official site and download it from the Products search list as shown in below screenshot.