Configuring a VMware Tools Repository leveraging PowerCLI (6.7U1 and newer)

Heads up: this script only functions with vSphere 6.7 Update 1 and newer

Ever since version 10.0 VMware has decoupled VMware Tools from vSphere releases. This gives you the opportunity to deploy images of ESXi without VMware Tools integrated, which saves you disk space and speeds up the deployment process.

Another benefit of this change is that you can now standardize your environment based on a single version by configuring a centralized repository, which gives you option to be in control of which version your environment is running with minimal effort.

In early 2019 VMware published a blog post on how to do this manually through the Managed Object Browser (MOB). However doing so is quite the task at it involves a lot of clicking for just one host, now try and do this for 20 ESXi hosts.

To make life easier I decided to create a PowerCLI script which loops all ESXi hosts for a given vCenter Server (you could add filters to only alter ESXi hosts with a specific property) and changes the directory for the “ProductLockerLocation” for said ESXi hosts.

Let’s take a look at the PowerCLI script step by step.

Table of Contents

Step 1

The first section is about connecting to vCenter using the information you’ll be prompted for upon running the script. You can safely alter this to provide the credentials in the script, use New-VICredentialStoreItem or save the credentials in an encrypted file.

    # Ask the user for the required information to connect to vCenter
    $vCenterServer = Read-Host "Enter the vCenter Server hostname"
    $AdminUsername = Read-Host ("Enter the username for the administrative account")
    $AdminPassword = Read-Host ("Password for " + $AdminUsername) -AsSecureString:$true
    $Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList $AdminUsername, $AdminPassword

    # Connect to the specified vCenter Server
    Connect-viserver -Server $vCenterServer -Credential $Credentials

Step 2

The second section is about getting the information required to actually start changing something. In my case I tend to use Get-VMHost to fetch all ESXi hosts and alter the configuration, but you’re free to add some sort of filter here.
The second action that takes place is that you’ll be prompted with an overview with the available datastores in the environment, of which you’re required to select the one on which you’ll upload the VMware Tools files.
Third and finally in this step is that you’ll be prompted to provide a name for the folder which will be created (if it’s not yet available). This is the folder in which you’ll have to place the VMware Tools files.

    # Specify different variables used in the script
    $ESXiHosts = Get-VMHost
    $DSName = (Get-Datastore | Out-GridView -PassThru).Name
    $DSFolder = Read-Host ("Enter the folder name for the VMware Tools Repository")
    $DSPath = "/vmfs/volumes/$DSName"
    $Location = "$DSPath/$DSFolder"

Step 3

After the second section the script will mount a PSDrive and check if the folder already exists. If it doesn’t exist, it will be created with the information specified in the previous part.
If it happens to already exist, the script will move to changing the actual configuration.

    # Start with testing if the directory exists, if not it will be created. Otherwise the VMware Tools location will be changed.
    Write-Output "Checking if the folder already exists on the datastore"
    $Datastore = Get-Datastore -Name "$DSName"
    New-PSDrive -Location $Datastore -Name DS -PSProvider VimDatastore -Root "\" | Out-Null
    $CheckPath = Test-Path "DS:\$DSFolder"

    If ($CheckPath -match "False") {
      Write-Output "The folder '$DSFolder' on datastore '$DSName' does not exist, creating it now."
      # Creating the folder on the datastore
      New-Item -Path "DS:\$DSFolder" -ItemType Directory | Out-Null
      #  Disconnects the earlier created PSDrive
      Remove-PSDrive -Name DS -Confirm:$false | Out-Null
    }

Step 4

Once everything is prepared we can now start changing the configuration itself.

    ForEach ($ESXiHost in $ESXiHosts) {
      $esx = Get-VMHost -Name $ESXiHost
      $OldLocation = $esx.ExtensionData.QueryProductLockerLocation()
      $esx.ExtensionData.UpdateProductLockerLocation($Location) | Out-Null
      Write-Output "Changed VMware Tools location on $ESXiHost from $OldLocation to $Location"
    }

After which the script will disconnect from vCenter and calls it a day.
The script is using a simple version of “try and catch”, which means it will stop at any error and calls it out in the console.

All you have to do now is upload the content of the VMware Tools package to the new location. The VM’s will automatically compare to this location now and show if they are up-to-date or not.

As with anything found on the internet, test it in a lab environment first!
The full code is available below to copy or to download as a .PS1 file.

 <#
.SYNOPSIS
    Change_VMware_Tools_Location.ps1 - PowerShell Script to change the VMware Tools location to a central one (like a datastore)
.DESCRIPTION
    This script is used to alter the default VMware Tools location to a central one (for all ESXi hosts).
    It will list a grid view of all datastores so you can select the one to use and prompts you for the name of the folder to create.
    The VMware Tools files itself will not be uploaded, this is a manual action.

    This script only works on vSphere 6.7 Update 1 and newer. Older versions require a different method for changing the VMware Tools location!
.OUTPUTS
    Results are printed to the console.
.NOTES
    Author        Jesper Alberts, Twitter: @jesperalberts, Blog: www.vjal.nl

    Change Log    V1.00, 12/03/2020 - Initial version
#>

$ErrorActionPreference = "Stop"

try {

    # Ask the user for the required information to connect to vCenter
    $vCenterServer = Read-Host "Enter the vCenter Server hostname"
    $AdminUsername = Read-Host ("Enter the username for the administrative account")
    $AdminPassword = Read-Host ("Password for " + $AdminUsername) -AsSecureString:$true
    $Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList $AdminUsername, $AdminPassword

    # Connect to the specified vCenter Server
    Connect-viserver -Server $vCenterServer -Credential $Credentials
    # Specify different variables used in the script
    $ESXiHosts = Get-VMHost
    $DSName = (Get-Datastore | Out-GridView -PassThru).Name
    $DSFolder = Read-Host ("Enter the folder name for the VMware Tools Repository")
    $DSPath = "/vmfs/volumes/$DSName"
    $Location = "$DSPath/$DSFolder"

    # Start with testing if the directory exists, if not it will be created. Otherwise the VMware Tools location will be changed.
    Write-Output "Checking if the folder already exists on the datastore"
    $Datastore = Get-Datastore -Name "$DSName"
    New-PSDrive -Location $Datastore -Name DS -PSProvider VimDatastore -Root "\" | Out-Null
    $CheckPath = Test-Path "DS:\$DSFolder"

    If ($CheckPath -match "False") {
      Write-Output "The folder '$DSFolder' on datastore '$DSName' does not exist, creating it now."
      # Creating the folder on the datastore
      New-Item -Path "DS:\$DSFolder" -ItemType Directory | Out-Null
      #  Disconnects the earlier created PSDrive
      Remove-PSDrive -Name DS -Confirm:$false | Out-Null
    }
    ForEach ($ESXiHost in $ESXiHosts) {
      $esx = Get-VMHost -Name $ESXiHost
      $OldLocation = $esx.ExtensionData.QueryProductLockerLocation()
      $esx.ExtensionData.UpdateProductLockerLocation($Location) | Out-Null
      Write-Output "Changed VMware Tools location on $ESXiHost from $OldLocation to $Location"
    }
    Disconnect-VIServer -Confirm:$False | Out-Null
  }
  catch {
    Write-Warning $Error[0]
  }

Please follow and like us:

Leave a Reply

Your email address will not be published. Required fields are marked *