VMware Cloud Community
VMUnderstudy
Contributor
Contributor

Getting vmware tools version for over 1000 clients

Hi Everyone,

I have a little job that I would like your help with. I am quite new to powercli side of things etc (Apologies if I posted in wrong forum, but couldn't see a more relevent one)

I have an estate of approx 1,400 clients that I need to get the version for because I suspect a lot of them are severely out of date.

Now there is a useful script that reports this that I got from philthevirtualiser.com as below. On my own test rig with a few VMs it works fine . However I don't want to clobber the Vcenter server with a request for tools versions from over 1400 clients at once.  Therefore what would be useful if I could get a list of the servers and then just run the query, one machine at a time with a small pause. Where do I start modifying the below script ?

Any help appreciated.

01 # Add in the VI Toolkit goodness
02if ( (Get-PSSnapin -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue) -eq $null )
03{
04Add-PSsnapin VMware.VimAutomation.Core
05}
06
07# Connect to the vCenter server(s)
08$vcserver= @()
09
10$vcserver += connect-VIServer "<Your vCenter Server>"
11
12# get the vmware tools version for each VM
13
14get-vm |% { get-view $_.id } | select Name, @{ Name="ToolsVersion"; Expression={$_.config.tools.toolsVersion}}
15
16# Disconnect from the vCenter server(s)
17disconnect-viserver $vcserver -Confirm:$False
18
19# END
20###
Reply
0 Kudos
6 Replies
LucD
Leadership
Leadership

I think that doing the Get-VM for each individual guest will clobber your vCenter more than doing it for all the guests in one go.

But the following should put a little bit less strain on the vCenter

# Add in the VI Toolkit goodness 
if ( (Get-PSSnapin -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue) -eq $null )
{
   
Add-PSsnapin VMware.VimAutomation.Core
}

# Connect to the vCenter server(s)
$vcserver
= connect-VIServer "<Your vCenter Server>"

# get the vmware tools version for each VM
get-vm
|%{
    $_ |
Select Name, @{Name="ToolsVersion"; Expression={$_.Extensiondata.config.tools.toolsVersion}}
   
sleep 1
}

# Disconnect from the vCenter server(s)
disconnect-viserver
$vcserver -Confirm:$False

Instead of the Get-View cmdlet, the script uses the Extensiondata property.

This will still cause a call to the vCenter, but will require less data to be returned, so less traffic from the vCenter.

And after each Select the script pauses for 1 second.

If you don't think that is needed, just remove that line.

An even better method would be to use the New-VIProperty cmdlet.

Something like this

New-VIProperty -Name ToolsVersion -ObjectType VirtualMachine `
    -ValueFromExtensionProperty 'config.tools.ToolsVersion' `
    -Force

# Add in the VI Toolkit goodness
if ( (Get-PSSnapin -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue) -eq $null )
{
   
Add-PSsnapin VMware.VimAutomation.Core
}

# Connect to the vCenter server(s)
$vcserver
= connect-VIServer "<Your vCenter Server>"

#
get the vmware tools version for each VM
get-vm |%{
   
$_ | Select Name, ToolsVersion
   
sleep 1
}

# Disconnect from the vCenter server(s)
disconnect-viserver $vcserver -Confirm:$False


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
mattboren
Expert
Expert

Hello, LucD-

Looks like there needs to be one additional item in the Select portion of each of those methods.  Since the Select is inside of a Foreach-Object loop, it is not receiving any object from a pipeline, so we need to specify the InputObject like:

    Select -InputObject $_ Name, @{Name="ToolsVersion"; Expression={$_.Extensiondata.config.tools.toolsVersion}}

and

    Select -InputObject $_ Name, ToolsVersion

,respectively.  I noticed that as I was trying to think of another way to optimize this for lowest impact to vCenter (as requested) and for highest speed, and it was not working for me as written.

Then, as I tested, I wondered if the Sleep in the Foreach-Object loop is doing anything to lessen the impact on the vCenter server.  The query has already been executed at that point, and the object being reported about is already in the client's PowerShell session, is it not?  That is, after the initial Get-VM, there is no more communication with the vCenter server during the Select, right?  If so, the Sleep is not affecting the vCenter load.

As for another way to try to help lessen the impact on vCenter, I wrote the info-gathering portion of the script using Get-View instead of Get-VM and New-VIProperty, as such:

...
## get the VMware Tools version for each VM
Get-View -ViewType VirtualMachine -Property Name,Config.Tools.ToolsVersion,Config.Template -Filter @{"Config.Template" = "false"} | Select Name, @{n="ToolsVersion"; e={$_.Config.Tools.ToolsVersion}}
...

Basically, that is your first method, but using Get-View instead of Get-VM, and with no Sleep.  For about 2600 VMs that took about 11 seconds.  The shortened run time should help lower impact, shouldn't it?

Message was edited by: mattboren -- added summary after "new" code snippet

Reply
0 Kudos
RvdNieuwendijk
Leadership
Leadership

Hi Matt,

you don't need to retrieve the Config.Template value in the Get-View properties. This will make the script faster. And we go for maximum speed, don't we. Smiley Wink

Get-View -ViewType VirtualMachine -Property Name,Config.Tools.ToolsVersion -Filter @{
  "Config.Template" = "False"} | `
Select-Object Name,@{N="ToolsVersion"; E={$_.Config.Tools.ToolsVersion}}

This script runs in my environment with about 500 virtual machines in 1.7 seconds. So I would not wurry about that.

Regards, Robert

Message was edited by: RvdNieuwendijk

Blog: https://rvdnieuwendijk.com/ | Twitter: @rvdnieuwendijk | Author of: https://www.packtpub.com/virtualization-and-cloud/learning-powercli-second-edition
Reply
0 Kudos
allencrawford
Enthusiast
Enthusiast

I'm not on a computer with PowerShell at the moment, but if you don't gather the .Config.Template property in the Get-View statement, how can you filter on it?  Seems like it may always return $false ($null) to me and therefore gather templates as well.  Of course, I'd argue why we're excluding templates in the first place since they could have VMware Tools installed and out-of-date too.

Reply
0 Kudos
RvdNieuwendijk
Leadership
Leadership

Hi Allen,

the Get-View cmdlet does the filtering before the selection is made. You can easily test this with the following two commands, that both give the same result:

Get-View -ViewType VirtualMachine -Filter @{"Config.Template" = "False"} | Measure-Object
Get-View -ViewType VirtualMachine -Property Name -Filter @{"Config.Template" = "False"} | Measure-Object

This is why you dont have to specify Config.Template in the property list.

I must agree though that it makes sense to also retrieve the tools version for templates as templates need to be updated some times as well. In this case the script will be:

Get-View -ViewType VirtualMachine -Property Name,Config.Tools.ToolsVersion | `
Select-Object Name,@{N="ToolsVersion"; E={$_.Config.Tools.ToolsVersion}}

Regards, Robert

Blog: https://rvdnieuwendijk.com/ | Twitter: @rvdnieuwendijk | Author of: https://www.packtpub.com/virtualization-and-cloud/learning-powercli-second-edition
Reply
0 Kudos
mattboren
Expert
Expert

Hello, Robert-

Thanks for pointing out that we need not retrieve the property that we are filtering on (unless using that property later on).  I was surely slowing things down with retrieving the extra property unnecessarily.

Yes, max speed!

Reply
0 Kudos