PeetersOnline.nl
Check VMware Configuration with Powershell
I have promised you I would post this script, so here it is!
This Powershell script generates an overview of any items that are not available to every ESX server in a VMware cluster. These items might prevent your vm’s being vmotioned by DRS or restarted by HA. Pretty serious business, I’d say!
The items involved are:
1. datastores
2. LUNs (important when using Raw Device Mappings)
3. port groups
The output is a nicely formatted HTML page showing not only which items are misconfigured, but also where the are available and where they are absent.
And here’s the script:
Compare-Clusters (Rename to .ps1)
Enjoy!
Hugo
23 Responses to Check VMware Configuration with Powershell
Tags
Active Directory API bind order cleanup cluster CPU Custom Fields datastores description device management directory tree errors Event Log file name filter Fun function HA IT known issues License Server LUN multipath NIC objects Oneliner portgroups PowerCLI PowerShell profile recursive Registry Scripts security session share snapshots SQL Stat VI Toolkit VMware vSphere WMI WSUS ZenArchives
- July 2012
- July 2011
- February 2011
- January 2011
- December 2010
- May 2010
- October 2009
- September 2009
- August 2009
- July 2009
- June 2009
- May 2009
- April 2009
- March 2009
- February 2009
- January 2009
- December 2008
- November 2008
- October 2008
- September 2008
- August 2008
- July 2008
- June 2008
- May 2008
- April 2008
- March 2008






[...] it’s no surprise probably that Hugo Peeters created a script that does exactly that: This Powershell script generates an overview of any items that are not [...]
[...] Het script kun je hier vinden: http://www.peetersonline.nl/index.php/vmware/check-vmware-configuration-with-powershell/ [...]
That is one usefull script, nice one.
Very nice! Bookmarked, downloaded and printed! Thanks.
[...] it’s no surprise probably that Hugo Peeters created a script that does exactly that: This Powershell script generates an overview of any items that are not [...]
I had problems running your script:
PS C:\iso\powershell> ./compare-clusters.ps1
There were one or more problems with the server certificate:
* A certification chain processed correctly, but terminated in a root certificate which isn’t trust
d by the trust provider.
* A required certificate is not within its validity period.
* The certificate’s CN name does not match the passed value.
Get-View : The argument cannot be null or empty.
At C:\iso\powershell\compare-clusters.ps1:23 char:36
+ $VMHostViews = $VMHosts | Get-View <<<< | Sort Name
Get-Datastore : The argument cannot be null or empty.
At C:\iso\powershell\compare-clusters.ps1:26 char:37
+ $Datastores = Get-Datastore -VMHost <<<< $VMHosts
Get-Datastore : The argument cannot be null or empty.
At C:\iso\powershell\compare-clusters.ps1:27 char:82
+ $DSdiffs = $VMHosts | ForEach {Compare-Object $Datastores (Get-Datastore -VMHost <<<< $_) -S
yncWindow 1000} | ForEach {$_.InputObject} | Sort Name | Select Name -Unique
Compare-Object : Cannot bind argument to parameter ‘ReferenceObject’ because it is null.
At C:\iso\powershell\compare-clusters.ps1:48 char:30
+ $LUNdiffs += Compare-Object <<<< $LUNs $HostLUNs -SyncWindow 1000 | ForEach {$_.InputObj
ect}
Get-VirtualPortGroup : The argument cannot be null or empty.
At C:\iso\powershell\compare-clusters.ps1:73 char:44
+ $PortGroups = Get-VirtualPortGroup -VMHost <<<< $VMHosts | ForEach {$_.Name} | Select -Uniqu
e
Get-VirtualPortGroup : The argument cannot be null or empty.
At C:\iso\powershell\compare-clusters.ps1:77 char:42
+ $HostPGs = Get-VirtualPortGroup -VMHost <<<< $VMHost | ForEach {$_.Name} | Select -Uniqu
e
Compare-Object : Cannot bind argument to parameter ‘ReferenceObject’ because it is null.
At C:\iso\powershell\compare-clusters.ps1:78 char:29
+ $PGdiffs += Compare-Object <<<< $PortGroups $HostPGs -SyncWindow 1000 | ForEach {$_.Inpu
tObject}
The first error says that Get-View did not get any arguments. So there are two possible causes:
1) Get-View does not support input from pipeline. This is only the case for the beta release of the VI Toolkit. Make suer you use the v1.0.
2) The $VMHosts variable is empty, which would mean filling it somehow went wrong. Try dot-sourcing the script (start powershell interactively and run “. c:\iso\compare-clusters.ps1″ (without the quotes). Then take a look ate the variable $VMHosts if it contains anything.
Good luck,
Hugo
Hey thanks for the great script. I also get a bunch errors similar to the one posted above. For the most part the script seems to run and produce a report its been very helpful in identifying invalid configurations.
As for possible debugging information that may help with the errors.
VC is 2.5 Update 3 on Win2k3 Server
Host are mostly 3.01
Toolkit Version is 1.0 build 113525
Am not sure if your open to feed back to continue to improve the script or if you released it to the community and for them to have at it.
If so here is my feedback.
Since its a cluster audit it would be nice not to see the local disk. Since I’ve seen most environments local label vary from host to host usually something along the lines with the hostname this usually helps to ensure that nobody puts a VM on the Local host.
Also I glance thru the script and I’m not sure are you checking for VLAN tags. Are you ? I’ve seen many issues because somebody fat fingered a VLAN tag. So a VM will move but not respond to any pings. Or even the VMotion port group wont move the VM because of the VLAN tag.
Thanks again
Hi Daniel, thank you for taking the time to post your comment. I read every comment on my site and try to improve my scripts or help out in other ways. Keep watching my site and you might see an improved version of the script some time soon. Thanks again for your comments!
Hugo
How do I get rid of this annoying output when I run the powershell scripts?
There were one or more problems with the server certificate:
* A certification chain processed correctly, but terminated in a root certificat
e which isn’t trusted by the trust provider.
You can import the certificate to get rid of the first message, but the second one will remain as your server will most likely not be called ‘vmware’. Might work to create a dns alias for it, but that’s not very nice. Maybe you can find out a way to generate a new certificate with the proper server name in it. If anybody finds a way before I do, let me know.
Hugo
Thanks for lots of great scripts. Looking for VCB ones but liked what I found anyway. My script works some time but other times the snapshot times out. Wanted your clear connection script to see if that was my issue, wasn’t. Your list disks script will help also.
This is probably an open door, but how do I import a certificate?
Hi Hugo,
I was trying to do exactly as Daniel requested and managed to fudge something together. Would appreciate it if you would take the time to have a look and see how it could be improved as i think the method I came up with to compare VLANS works but is a little convoluted.
let me know if you have the time or inclination to take a look and i’ll post the script.
@Paul
Hi Paul,
Sure I’d like to check what you did. Drop me an email at: contact at peetersonline nl
Hugo
Just ran this script and it works fine but:
- you might want to filter the local luns (vmhba0:0:0) cause they usually have a different name on every single host in a cluster
- the script throws an error when a cluster doesn’t contain hosts
I was wondering if Paul had a workable solution or addition for auditing the port group VLANs. I love the script above but really need to audit the por group VLANs as well.
agree with Duncan, GREAT script but is there an easy way to filter out local luns?
Hi Guys,
Got the same issue, its reporting my local drives as datastores and reporting a mismatch on the clusters.
Any chance of looking into this? Great work otherwise… love it!
Hi Hugo,
Great script, I was a little confused on one of my outputs because there were several vmhba devices denoted across the ESXhosts. It is simple to figure out the ones that have 1 vmhba denoted and the rest saying true or false but having more than one has confused me. Can you help to decipher this?
LunUuid ESX001.xxx ESX002.xxx ESX003.xxx ESX005.xxx ESX011.xxx ESX020.xxx
0200010000600508b400106b3400009000020c0000485356323130 vmhba0:4:1 vmhba0:2:1 vmhba0:4:1 vmhba0:1:1 False vmhba0:2:1
0200020000600508b400106b3400009000020c0000485356323130 False False False False vmhba0:4:2 False
0200020000600508b400106b340000900002110000485356323130 vmhba0:4:2 vmhba0:2:2 vmhba0:4:2 vmhba0:1:2 False vmhba0:2:2
0200030000600508b400106b340000900002110000485356323130 False False False False vmhba0:4:3 False
Thanks!
Also, it would take longer but could you include a host rescan before the script starts executing so that all of the data can be current?
Would it be possible to exclude local disks ? Apart from
that great script!
[...] – I took the really cool looking cluster config check from the following site: http://www.peetersonline.nl/index.php/vmware/check-vmware-configuration-with-powershell/ and changed the output so it would appear in vCheck. This is a really cool looking report with [...]
Thanks for the script. I took a couple of snips from the vCheck script to add send-email capability. Also made some formatting and colorization additions.
# When displaying to the screen an output file is created. Set the format of the filename below:
$dateFormat = “yyyy-MM-dd__HH-mm”
# path and file name of output report
$date = Get-Date -format $dateFormat
$outputFile = ‘C:\vCheck_Reports\ESX-comparison_’ + $date + ‘.html’
# Virtual Center servername
$VCServer = “vcenter”
# Set the SMTP Server address
$SMTPSRV = “mail.domain.local”
# Set the Email address to recieve from
$EmailFrom = “user@domain.com”
# Set the Email address to send the email to – seperate multiple with comma
$EmailTo = “user@domain.com”
# When displaying to the screen an output file is created. Set the format of the filename below:
$dateFormat = “yyyyMMdd_HHmm” # use “d-M-yyyy” for legacy v5.0 format
# Use the following item to define if an email report should be sent once completed
$SendEmail = $true
# Use the following item to define if the output should be displayed in the local browser once completed
$DisplaytoScreen = $false
function Send-SMTPmail($to, $from, $subject, $smtpserver, $body) {
$mailer = new-object Net.Mail.SMTPclient($smtpserver)
$msg = new-object Net.Mail.MailMessage($from,$to,$subject,$body)
$msg.IsBodyHTML = $true
$mailer.send($msg)
}
Function Create-HTMLTable
{
param([array]$Array)
$arrHTML = $Array | ConvertTo-Html
$arrHTML[-1] = $arrHTML[-1].ToString().Replace(”,”")
Return $arrHTML[5..1000]
}
$output = @()
$output += ”
$output += ‘.sectionTitle{color:blue;font-weight:bold;}.section{margin-top:10px;margin-bottom:30px;}.errorDiv{color:red;font-weight:bold;}table{border-style:solid;border-width:1px;font-size:8pt;background-color:#ccc;width:100%;}th{text-align:left;}td{background-color:#fff;width:20%;border-style:solid;border-width:1px;}body{font-family:verdana;font-size:8pt;}h1{font-size:12pt;}h2{font-size:10pt;}’
$output += ‘ESXi Host Inconsistency Report’
# $output += ‘The following items are not available to all ESX servers in the cluster:’
$VC = Connect-VIServer $VCServer
ForEach ($Cluster in (Get-Cluster | Sort Name))
{
$VMHosts = $Cluster | Get-VMHost | Sort Name
$VMHostViews = $VMHosts | Get-View | Sort Name
$myDSCol = @()
$Datastores = Get-Datastore -VMHost $VMHosts
$DSdiffs = $VMHosts | ForEach {Compare-Object $Datastores (Get-Datastore -VMHost $_) -SyncWindow 1000} | ForEach {$_.InputObject} | Sort Name | Select Name -Unique
ForEach ($DSdiff in $DSdiffs)
{
If ($DSdiff.Name -ne $null)
{
$myDSObj = “” | Select Datastore
$myDSObj.Datastore = $DSdiff.Name
ForEach ($VMHost in $VMHosts)
{
$myDSObj | Add-Member -MemberType NoteProperty -Name $VMHost.Name -Value (!!(Get-Datastore -Name $myDSObj.Datastore -VMHost $VMHost -ErrorAction SilentlyContinue))
}
$myDSCol += $myDSObj
}
}
$myLUNCol = @()
$LUNs = $VMHostViews | ForEach {$_.Config.StorageDevice.ScsiLun | ForEach {$_.Uuid}} | Select -Unique
$LUNdiffs = @()
ForEach ($VMHostView in $VMHostViews)
{
$HostLUNs = $VMHostView.Config.StorageDevice.ScsiLun | ForEach {$_.Uuid} | Select -Unique
$LUNdiffs += Compare-Object $LUNs $HostLUNs -SyncWindow 1000 | ForEach {$_.InputObject}
Clear-Variable HostLUNs -ErrorAction SilentlyContinue
}
ForEach ($LUNdiff in ($LUNdiffs | Select -Unique | Sort))
{
If ($LUNdiff -ne $null)
{
$myLUNObj = “” | Select LunUuid
$myLUNObj.LunUuid = $LUNdiff
ForEach ($VMHostView in $VMHostViews)
{
If (($VMHostView.Config.StorageDevice.ScsiLun | Where {$_.Uuid -eq $myLUNObj.LunUuid}) -ne $null)
{
$myLUNObj | Add-Member -MemberType NoteProperty -Name $VMHostView.Name -Value (($VMHostView.Config.StorageDevice.ScsiLun | Where {$_.Uuid -eq $myLUNObj.LunUuid}).CanonicalName)
}
Else
{
$myLUNObj | Add-Member -MemberType NoteProperty -Name $VMHostView.Name -Value $False
}
}
$myLUNCol += $myLUNObj
}
}
$myPGCol = @()
$PortGroups = Get-VirtualPortGroup -VMHost $VMHosts | ForEach {$_.Name} | Select -Unique
$PGdiffs = @()
ForEach ($VMHost in $VMHosts)
{
$HostPGs = Get-VirtualPortGroup -VMHost $VMHost | ForEach {$_.Name} | Select -Unique
$PGdiffs += Compare-Object $PortGroups $HostPGs -SyncWindow 1000 | ForEach {$_.InputObject}
Clear-Variable HostPGs -ErrorAction SilentlyContinue
}
ForEach ($PGdiff in ($PGdiffs | Select -Unique | Sort))
{
If ($PGdiff -ne $null)
{
$myPGObj = “” | Select PortGroup
$myPGObj.PortGroup = $PGdiff
ForEach ($VMHost in $VMHosts)
{
$myPGObj | Add-Member -MemberType NoteProperty -Name $VMHost.Name -Value (!!(Get-VirtualPortGroup -Name $myPGObj.PortGroup -VMHost $VMHost -ErrorAction SilentlyContinue))
}
$myPGCol += $myPGObj
}
}
$output+= ”
$output += $Cluster.Name
$output+= ”
$output += ‘Datastore check: ‘
If ($myDSCol.Count -eq 0)
{
$output += “All datastores OK.”
$output += ”
}
Else
{
$output += ‘ERROR: Datastore config has incontistencies! Please investigate.’
$output += Create-HTMLTable $myDSCol
$output += ”
}
$output += ‘LUN check: ‘
If ($myLUNCol.Count -eq 0)
{
$output += ‘All LUNs OK.’
$output += ”
}
Else
{
$output += ‘ERROR: LUN config has incontistencies! Please investigate.’
$output += Create-HTMLTable $myLUNCol
$output += ”
}
$output += ‘Portgroup check: ‘
If ($myPGCol.Count -eq 0)
{
$output += “All portgroups OK.”
$output += ”
}
Else
{
$output += ‘ERROR: Portgroup config has incontistencies! Please investigate.’
$output += Create-HTMLTable $myPGCol
$output += ”
}
Clear-Variable VMHosts -ErrorAction SilentlyContinue
Clear-Variable Datastores -ErrorAction SilentlyContinue
Clear-Variable DSdiffs -ErrorAction SilentlyContinue
Clear-Variable PortGroups -ErrorAction SilentlyContinue
Clear-Variable PGdiffs -ErrorAction SilentlyContinue
Clear-Variable LUNs -ErrorAction SilentlyContinue
Clear-Variable LUNdiffs -ErrorAction SilentlyContinue
}
$output += ”
$output | Out-File $outputFile -Force
if ($DisplayToScreen) {
Write-Host “..Displaying HTML results”
Invoke-Item $Filename
}
Disconnect-VIServer -Confirm:$False
if ($SendEmail) {
Write-Host “..Emailing HTML results”
send-SMTPmail $EmailTo $EmailFrom “$VCServer ESXi host comparison check” $SMTPSRV $output
}