Finding vms with vmware tools that need to be upgraded. vmware tools status and version

Right, this is not some rocket science here but still i thought some people may be looking for that.

get-cluster your_cluster |Get-VM|?{$_.Extensiondata.Summary.Guest.ToolsVersionStatus -like 'guestToolsNeedUpgrade'} | select name,@{N='tools vers';E={$_.ExtensionData.Config.Tools.ToolsVersion}},@{N='Tools Status';E={$_.Extensiondata.Summary.Guest.ToolsVersionStatus}}

So i wanted to take cluster ‘your_cluster’ and get all vms in this cluster that have tools status of ‘guestToolsNeedUpgrade’. Well basically that’s pretty much it but i noticed that on large inventory it takes quite time to receive this list. So what might be interesting for people who have bigger vInfrastructure 😉
This query takes
Seconds : 41
So i spend few more minutes to get the same list but using get-view. It took:
Seconds : 1
Milliseconds : 174

And the line:

get-view -ViewType virtualmachine -SearchRoot (get-cluster your_cluster).id -Filter @{'Summary.Guest.ToolsVersionStatus'='guestToolsNeedUpgrade'} | Select Name,@{N='tools ver';E={$_.Config.Tools.ToolsVersion}},@{N='Tools Status';E={$_.Summary.Guest.ToolsVersionStatus}}

So difference is 40 seconds 😉 Output is formatted like this
Name tools ver Tools Status
—- ———- ————
myvm1 8300 guestToolsNeedUpgrade
myvm2 8300 guestToolsNeedUpgrade
…… ….. ……………..

Check host advanced settings using powercli

I wanted to check settings for NFS that i have in place for all hosts in specific cluster.
Here is what i came up with:

get-cluster 'myCluster' | get-vmhost | %{ $hostn=$_.Name; Get-VMHostAdvancedConfiguration -VMHost $_ | % { $_.getEnumerator()| ? {$_.Key -like "NFS*"}|select Name,Value,@{N='host';E={$hostn}} }  } | export-csv c:\nfssettings.csv
----Output before sending to export-csv
Name                            Value host
----                            ----- ----
NFS.WorldletAffinity            x     host1
NFS.VolumeRemountFrequency      y     host1
NFS.LockUpdateTimeout           z     host1
NFS.LogNfsStat3                 y     host2

In nfssettings.csv you will have nice table with nfs_setting_name , value, and host name from which it was taken.
What’s with the $_.GetEnumerator() ?, right, so when you will run

Get-VMHostAdvancedConfiguration -vmhost "your_host" | gm

You will notice that we are receiving hashtable. Since this is hashtable we can not fitler it with just simple where,select as this comes as a 1 BIG table. It looks like it consists of rows etc etc… so you would think that those are several objects, but at the end it is just like 1 big hashtable 😉 So we want to have ability to go through each element in this hashtable to search only for those with key similar to NFS*. Obviously if you want to search for other things like NFS, then put the proper name instead of NFS.

Get-VMHostAdvancedConfiguration -vmhost "your_host"
(Get-VMHostAdvancedConfiguration -vmhost "your_host").GetEnumerator()

Although they output is the same, when you are using GetEnumerator it is possible for you to do select with where-object.
Instead of receiving object type of hashtable, we are receiving now multiple System.Collections.DictionaryEntry which have Key and Value property. That’s why now we can use Where-Object to seek for your NFS settings.Since we are querying all host systems within cluster i want to have also a column with host name so that’s why i had to do $hostn=$_.Name; in the loop. To store the host name because this information would be lost in next pipeline.

Quicky#1 Get csv report on virtual machine partitions in cluster/multiple clusters

I was asked today how to do that kind of report. It’s really handy to have one of those, and i was surprised that i haven’t wrote about that so far on my blog. So here it is 😉

$(foreach ( $cluster in 'xyz1','yxx2' ) { get-view -SearchRoot (get-cluster $cluster).id -viewtype VirtualMachine -Filter @{"Summary.Runtime.PowerState"="poweredOn";"Config.Template"="False"}  | % {$esxhost=(get-view ($_.Summary.Runtime.Host)).name;$vmname=$_.Name;$_.Guest.Disk | select @{N="VMName";E={$vmname}},DiskPath,@{N="CapacityGB"; E={[Math]::Round($_.Capacity/1GB,2)} },@{N="FeeSpaceGB";E={[Math]::Round($_.FreeSpace/1GB,2)}},@{N="Cluster";E={$cluster} },@{N="Host";E={$esxhost} } }  })  | Export-Csv "c:\ReportVMsDiskUsage.csv" -NoTypeInformation

Yes, i know 😉
So what it does. It will output a csv file in my example to c:\ReportVMsDiskUsage.csv”. Contents are : Name of VM, disk letter/path, Capacity in Gb, FreeSpace in GB, Cluster name on which vm resides, Host name on which vm resides.
This one liner looks bit complicated but once disassembled it’s very easy to understand what i am doing.
I am using the sub-expression $ ( ) | Export-csv … . I did that because i want the whole output in my csv file. Without first getting the whole output it’s very hard i suppose to use the export-csv to put it to 1 file. If you want this to run against 1 cluster or more clusters, just adjust the strings in the foreach($cluster in ….) .
It can be very easy to adjust this one liner to ignore cluster, do the report on the highest level. I am using switch -SearchRoot from get-view and giving him the location of get-cluster X. If you do not want to narrow down the results, just don’t use the -SearchRoot, and it will give you output for all vms that are:
-Filter @{“Summary.Runtime.PowerState”=”poweredOn”;”Config.Template”=”False”}
Powered On, and are not tempaltes.
Before sending the output ” $_.Guest.Disk | ….” further , i also grab all other needed properites, like vmname,esxhost.
It also useful to check the output first before sending it to export-csv. So let’s take a look by running :

foreach ( $cluster in 'xyz1','yxx2' ) { get-view -SearchRoot (get-cluster $cluster).id -viewtype VirtualMachine -Filter @{"Summary.Runtime.PowerState"="poweredOn";"Config.Template"="False"}  | % {$esxhost=(get-view ($_.Summary.Runtime.Host)).name;$vmname=$_.Name;$_.Guest.Disk | select @{N="VMName";E={$vmname}},DiskPath,@{N="CapacityGB"; E={[Math]::Round($_.Capacity/1GB,2)} },@{N="FeeSpaceGB";E={[Math]::Round($_.FreeSpace/1GB,2)}},@{N="Cluster";E={$cluster} },@{N="Host";E={$esxhost} } }  }

You will see report on each vm . from each cluster. Then we need to get the WHOLE output as one and send it to export-csv, and this is why i used
sub-expression $() | export-csv… to grab first the whole output. I got loops for each cluster so , i cant export the loop to export-csv, as the file will be overwritten as the end by the last loop output. You could ommit the export-csv and the sub-expression here by sending the output straight to file using ” >> file.csv ” , but in this case you would have to prepare some [string]$line, which will have commas in it so it would look like a csv file.
If you find any bug in my scripts or you know more efficient way to do things describes in my posts, please do comment and share your experience.