Tuesday, February 1, 2022

Powershell script to collect VM info from Vcenter

# Script: ListVMs.ps1 - Ravi - 1st Feb 2022 
# Usage  : .\listvms <vcenter or host ip>:[Manadatory] <user>:[Manadatory] <password>:[Manadatory] <sortBy>:[Optional]
# Example: .\listvms 192.168.0.1 root mypassword ramalloc
#
# Desc   : Retrieves a list of virtual machines from an ESXi host or vCenter Server, extracting a subset of 
#          vm properties values returned by Get-View. The list is converted to HTML and written to disk. 
#          The script automatically displays the report by invoking the default browser.

#Command line parameters
[CmdletBinding()]
Param(
 [Parameter(Mandatory=$true,Position=1)]
 [string]$hostIP,
 
 [Parameter(Mandatory=$false,Position=2)]
 [string]$user,
 
 [Parameter(Mandatory=$false,Position=3)]
 [string]$pass,
 
 [Parameter(Mandatory=$false,Position=4)]
 [string]$sortBy
)

#Populate PSObject with the required vm properties 
function vmProperties
{
 param([PSObject]$view)
 
 $list=foreach ($vm in $view){
 
 #Get net info
  $ips=$vm.guest.net.ipaddress
  $macs=$vm.guest.net.MacAddress
 
 #State info
  if ($vm.Runtime.PowerState -eq "poweredOn") {$state="ON"}
   elseif ($vm.Runtime.PowerState -eq "poweredOff") {$state="OFF"}
    else {$state="n/a"}
 
 #VMtools state
  if ($vm.summary.guest.ToolsRunningStatus -eq "guestToolsRunning") {$vmtools="Running"}
   elseif ($vm.summary.guest.ToolsRunningStatus -eq "guestToolsNotRunning") {$vmtools="Not running"}
    else {$vmtools="n/a"}
 
 #Check for multi-homed vms - max. 2 ips
  if ($ips.count -gt 1)
  {$ips=$vm.guest.net.ipaddress[0] + " " + $vm.guest.net.ipaddress[1]} 
 
  if ($macs.count -gt 1)
   {$macs=$vm.guest.net.macaddress[0] + " " + $vm.guest.net.macaddress[1]} 
 
 #Populate object
 [PSCustomObject]@{
  "Name" = $vm.Name
  "Cluster" = ($vms | Get-Cluster).Name
  "OS" = $vm.Guest.GuestFullName
  "Hostname" = $vm.summary.guest.hostname
  "vCPUs" = $vm.Config.hardware.NumCPU
  "Cores" = $vm.Config.Hardware.NumCoresPerSocket
  "RAM Alloc" = $vm.Config.Hardware.MemoryMB
  "RAM Host" = $vm.summary.QuickStats.HostMemoryUsage
  "RAM guest" = $vm.summary.QuickStats.GuestMemoryUsage
  "NICS" = $vm.Summary.config.NumEthernetCards
  "vmtoolversion" = $vm.Config.Tools.ToolsVersion
  "IPs" = $ips
  "MACs" = $macs
  "vmTools" = $vmtools
  "State" = $state
  "UUID" = $vm.Summary.config.Uuid
  "VM ID" = $vm.Summary.vm.value
  }
 }
 
 return $list
}

#Stylesheet - this is used by the ConvertTo-html cmdlet
function header{
 $style = @"
 <style>
 body{
 font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
 }
 
 table{
  border-collapse: collapse;
  border: none;
  font: 10pt Verdana, Geneva, Arial, Helvetica, sans-serif;
  color: black;
  margin-bottom: 10px;
 }
 
 table td{
  font-size: 10px;
  padding-left: 0px;
  padding-right: 20px;
  text-align: left;
 }
 
 table th{
  font-size: 10px;
  font-weight: bold;
  padding-left: 0px;
  padding-right: 20px;
  text-align: left;
 }
 
 h2{
  clear: both; font-size: 130%;color:#00134d;
 }
 
 p{
  margin-left: 10px; font-size: 12px;
 }
 
 table.list{
  float: left;
 }
 
 table tr:nth-child(even){background: #e6f2ff;} 
 table tr:nth-child(odd) {background: #FFFFFF;}

 div.column {width: 320px; float: left;}
 div.first {padding-right: 20px; border-right: 1px grey solid;}
 div.second {margin-left: 30px;}

 table{
  margin-left: 10px;
 }
 –>
 </style>
"@

 return [string] $style
 }

#############################
### Script entry point ###
#############################

#Path to html report
 $repPath=(gci env:userprofile).value+"\desktop\test.htm"

#Report Title
 $title = "<h2>VMs hosted on $hostIP</h2>"

#Sort by
 if ($sortBy -eq "") {$sortBy="Name"; $desc=$False} 
  elseif ($sortBy.Equals("ramalloc")) {$sortBy = "RAM Alloc"; $desc=$True} 
   elseif ($sortBy.Equals("ramhost")) {$sortBy = "RAM Host"; $desc=$True} 
    elseif ($sortBy.Equals("os")) {$sortBy = "OS"; $desc=$False}

Try{
 #Drop any previously established connections
  Disconnect-VIServer -Confirm:$False -ErrorAction SilentlyContinue
 
 #Connect to vCenter or ESXi
  if (($user -eq "") -or ($pass -eq "")) 
   {Connect-VIServer $hostIP -ErrorAction Stop}
  else 
    {Connect-VIServer $hostIP -User $user -Password $pass -ErrorAction Stop}

 #Get a VirtualMachine view of all vms
  $vmView = Get-View -viewtype VirtualMachine
  $vms = Get-VM
 
 #Iterate through the view object, write the set of vm properties to a PSObject and convert the whole lot to HTML
  (vmProperties -view $vmView) | Sort-Object -Property @{Expression=$sortBy;Descending=$desc} | ConvertTo-Html -Head $(header) -PreContent $title | Set-Content -Path $repPath -ErrorAction Stop
 
 #Disconnect from vCenter or ESXi
  Disconnect-VIServer -Confirm:$False -Server $hostIP -ErrorAction Stop
 
 #Load report in default browser
  Invoke-Expression "cmd.exe /C start $repPath"
 }
Catch
 {
  Write-Host $_.Exception.Message
 }