Managing VMware Tools advanced options: PowerCLI

The other day I was looking at my virtual machines’ VMware Tools status, and sadly, many of them are out of date. It seems like I spend a lot of my time on host patching, but the Tools update seems to fall by the wayside. Perhaps it’s the disruption to production that rebooting causes (and the related change records and change management meetings), or maybe it’s the sheer number of VMs that I have to manage. I was curious what other folks’ infrastructure looked like, so I posed the question on Twitter: “#VMware admins, how good are you at keeping the Tools up to date?”

I only got a handful of responses, but they varied from “fanatical”, to “so so”. Tim Oudin said that he keeps his virtual machines up to date by setting “Check and upgrade Tools during power cycling” under a VM’s Options > VMware Tools. That got me thinking, “How can I enable that setting on hundreds of VMs?”

The answer is (of course) PowerCLI. Since there’s no cmdlet that will do this, we have to utilize our good friend, the vSphere API. The data object that we’re interested in is VirtualMachineConfigSpec. While doing the necessary research for this article, I ran into a very interesting property, changeVersion. This property is useful because it guards against updates that have happened between when the VM’s configInfo is read and when it is applied. We don’t need to increment or change the value of the changeVersion property, we just need to supply the current changeVersion.

Enabling VMware Tools upgrade at power cycle:

$vm = Get-VM -Name "virtualmachine"
$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
$spec.changeVersion = $vm.ExtensionData.Config.ChangeVersion
$spec.tools = New-Object VMware.Vim.ToolsConfigInfo
$spec.tools.toolsUpgradePolicy = "upgradeAtPowerCycle"

$_this = Get-View -Id $vm.Id
$_this.ReconfigVM_Task($spec)

Enabling a VM to sync its time with the host:

$vm = Get-VM -Name "virtualmachine"
$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
$spec.changeVersion = $vm.ExtensionData.Config.ChangeVersion
$spec.tools = New-Object VMware.Vim.ToolsConfigInfo
$spec.tools.syncTimeWithHost = $true

$_this = Get-View -Id $vm.Id
$_this.ReconfigVM_Task($spec)

Here are the snippets you’ll need in case you want to undo these settings.

Disabling VMware Tools upgrade:

$spec.tools.toolsUpgradePolicy = "manual"

Disabling VM time sync:

$spec.tools.syncTimeWithHost = $false

Comments

  1. Andrew Fidel says:

    Just thought I’d add my extension here in case other people come looking, this does machines in a specific cluster and only sets the flag if it’s a Windows box (according to the documentation it only works for Windows guests anyways but I figure better safe than sorry)

    $machines = get-cluster “” | get-vm
    foreach ($vm in $machines){
    if ( $vm.guest.OSFullName -like “*Windows*)
    {
    $spec = New-Object VMware.Vim.VirtualMachineConfigSpec
    $spec.changeVersion = $vm.ExtensionData.Config.ChangeVersion
    $spec.tools = New-Object VMware.Vim.ToolsConfigInfo
    $spec.tools.toolsUpgradePolicy = “upgradeAtPowerCycle”

    $_this = Get-View -Id $vm.Id
    $_this.ReconfigVM_Task($spec)
    }
    }

    • Chris B says:

      Does anyone have any suggestions on outputting this to a text file? We’d like to be able to review and if any fail, then be able to identify those machines.

      • Chris B says:

        Forgot to include, I tried enabling transcription, but it only echos the task number.
        Optimally, we’d like to see each machine by name with a complete or fail.

  2. Does this require a reboot of the VM to disable vmware time sync?

  3. Another twist to this. I had a long text file of VM names that I needed to disable the VMware tools upgrade, so I did this:

    $a = Get-Content "c:\Temp\vm_list.txt"
    foreach ($i in $a){
    $vm = Get-VM -Name $i | % {Get-View $_.ID}
    $vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
    $vmConfigSpec.Tools = New-Object VMware.Vim.ToolsConfigInfo
    $vmConfigSpec.Tools.ToolsUpgradePolicy = "manual"
    $vm.ReconfigVM($vmConfigSpec)
    }

  4. Looks like a great script! But I get the following error run I run it in vSphere PowerCLI. Any idea what I’m doing wrong? I’ve tried it both with and without Forbes’ extra line.

    Get-View : Cannot validate argument on parameter ‘Id’. The argument is null or
    empty. Supply an argument that is not null or empty and then try the command ag
    ain.
    At C:\scripts\Enable VMTools Upgrade at Power Cycle.ps1:8 char:22
    + $_this = Get-View -Id <<<< $vm.Id
    + CategoryInfo : InvalidData: (:) [Get-View], ParameterBindingVal
    idationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutom
    ation.Commands.DotNetInterop.GetVIView

    You cannot call a method on a null-valued expression.
    At C:\scripts\Enable VMTools Upgrade at Power Cycle.ps1:9 char:23
    + $_this.ReconfigVM_Task <<<< ($spec)
    + CategoryInfo : InvalidOperation: (ReconfigVM_Task:String) [], R
    untimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    • Ignore me. On Line 1 I used $v instead of $vm. I did this because I was trying to work out how to accomodate Forbes’ extra line. Do I just stick it in on Line 2? It’s the $v that confuses me, it’s not defined anywhere!

    • Argh! Now the script looks like it will work, but I’m getting the message “Cannot complete operation due to concurrent modification by another operation” listed in vSphere Client. Any ideas?

  5. Damian, forgive my ignorance. I have no experience with using the PowerCLI. Is there a simple way to create and run the scripts above for us “non-programmer” types? ๐Ÿ™‚

    • Thanks for commenting, Ted. Yes, there are more accessible, or more user-friendly tools out there. You might want to check out PowerGui and the VMware Community PowerPack (available from the same site). The Community PowerPack uses PowerCLI to easily accomplish common administrative processes in VMware. Of course, you’ll still need to download and install VMware PowerCLI on the same computer that you’re going to install PowerGui & and the PowerPack.

      PowerGui is a great place to start learning PowerShell’s syntax, and getting familiarized with PowerCLI. That’s probably the best resource that I can think of. I hope I’ve answered your question, if not please let me know. ๐Ÿ™‚

      • This may be helpful… I used the above…and added a check to see if the flag was set on .config.tools.toolsUpgradePolicy… Worked for me!

        Get-VM | Get-View | ForEach-Object{
        Write-Output $_.name
        if ($_.config.tools.toolsUpgradePolicy -ne “upgradeAtPowerCycle”){
        $vm = Get-VM -Name $_.name
        $spec = New-Object VMware.Vim.VirtualMachineConfigSpec
        $spec.changeVersion = $vm.ExtensionData.Config.ChangeVersion
        $spec.tools = New-Object VMware.Vim.ToolsConfigInfo
        $spec.tools.toolsUpgradePolicy = “upgradeAtPowerCycle”
        $_this = Get-View -Id $vm.Id
        $_this.ReconfigVM_Task($spec)
        Write-Output “Completed”
        }
        }

      • Mark: Only trouble is, what racial crime will they claim Britain is redeeming itself from? With Atlanta it was Jim Crow and slavery. With Australia it was the treatment of aborigines. With Britain what do they mention – colonialism? The Crusades?Fidel to the rescue:Castro defends athlete who kicked judge in face…Castro wrote… that Cubans need to begin preparing now for London in 2012. “There will be European chauvinism, judge corruption, buying of brawn and brains … and a strong dose of racism,” he predicted.

      • I really think so, but I hate to jinx it !!GO PACK !!!PS- “Singletrack” is a dork. If Favre can’t “pick apart a piece of chicken”, how come he holds most of the QB records, has 2 Superbowl visits, and a ring ? Not to mention, what, 4 NFL MVP’s ? And don’t say it’s just because he’s played so long. He’s tough & durable, that’s a positive, not a negative.

  6. I ran something similar to your first script a couple of weeks ago across an vSphere instance. I also added in the following line:
    $vm = $v | Get-View | Where-Object {$_.Guest.GuestFamily -eq ‘windowsGuest’}
    to make sure the Linux/Solaris VMs were not changed.

    • Great idea, Forbes! Thanks for commenting. ๐Ÿ™‚

    • Doug Crist says:

      Another Powershell newbie here. Forbes, any chance I could see your entire script, or at least the first few lines? With the ‘Where’ clause, do I then still need the ForEach after it?

      Thanks,
      Doug

      • Hi Doug,
        This is what I did:

        Foreach ($v in (get-vm)) {
        $vm = $v | Get-View | Where-Object {$_.Guest.GuestFamily -eq 'windowsGuest'}
        $vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
        $vmConfigSpec.Tools = New-Object VMware.Vim.ToolsConfigInfo
        $vmConfigSpec.Tools.ToolsUpgradePolicy = "UpgradeAtPowerCycle"
        $vm.ReconfigVM($vmConfigSpec)
        }

        • Hi all, I’m trying to implement this however first specifying a list of machines that need to be changed,

          Using the following

          $a = Get-Content “c:\vmlist.csv”
          foreach ($i in $a){
          $vm = Get-VM -Name $i | % {Get-View $_.ID}
          $vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
          $vmConfigSpec.Tools = New-Object VMware.Vim.ToolsConfigInfo
          $vmConfigSpec.Tools.ToolsUpgradePolicy = “upgradeAtPowerCycle”
          $vm.ReconfigVM($vmConfigSpec)
          Write-Output โ€œCompletedโ€
          }

          This is fine and changes the majority of the machines however im getting 25% of the machines that cant be found and then get the following error, any ideas?

          Get-VM : 18/02/2013 16:16:11 Get-VM VM with name ‘Name’ was not found, using the specified filter(s).
          At line:3 char:13
          + $vm = Get-VM <<<< -Name $i | % {Get-View $_.ID}
          + CategoryInfo : ObjectNotFound: (:) [Get-VM], VimException
          + FullyQualifiedErrorId : Core_OutputHelper_WriteNotFoundError,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetVM

          You cannot call a method on a null-valued expression.
          At line:7 char:15
          + $vm.ReconfigVM <<<< ($vmConfigSpec)
          + CategoryInfo : InvalidOperation: (ReconfigVM:String) [], RuntimeException
          + FullyQualifiedErrorId : InvokeMethodOnNull

          Get-VM : 18/02/2013 16:16:28 Get-VM VM with name 'VMNAME**(Changed) ' was not found, using the specified filter(s).
          At line:3 char:13
          + $vm = Get-VM <<<< -Name $i | % {Get-View $_.ID}
          + CategoryInfo : ObjectNotFound: (:) [Get-VM], VimException
          + FullyQualifiedErrorId : Core_OutputHelper_WriteNotFoundError,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetVM

          You cannot call a method on a null-valued expression.
          At line:7 char:15
          + $vm.ReconfigVM <<<< ($vmConfigSpec)
          + CategoryInfo : InvalidOperation: (ReconfigVM:String) [], RuntimeException
          + FullyQualifiedErrorId : InvokeMethodOnNull

          Get-VM : 18/02/2013 16:16:28 Get-VM VM with name 'VMNAME**(Changed) ' was not found, using the specified filter(s).
          At line:3 char:13
          + $vm = Get-VM <<<< -Name $i | % {Get-View $_.ID}
          + CategoryInfo : ObjectNotFound: (:) [Get-VM], VimException
          + FullyQualifiedErrorId : Core_OutputHelper_WriteNotFoundError,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetVM

          You cannot call a method on a null-valued expression.
          At line:7 char:15
          + $vm.ReconfigVM <<<< ($vmConfigSpec)
          + CategoryInfo : InvalidOperation: (ReconfigVM:String) [], RuntimeException
          + FullyQualifiedErrorId : InvokeMethodOnNull

          Get-VM : 18/02/2013 16:16:28 Get-VM VM with name 'VMNAME**(Changed) ' was not found, using the specified filter(s).
          At line:3 char:13
          + $vm = Get-VM <<<< -Name $i | % {Get-View $_.ID}
          + CategoryInfo : ObjectNotFound: (:) [Get-VM], VimException
          + FullyQualifiedErrorId : Core_OutputHelper_WriteNotFoundError,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetVM

          You cannot call a method on a null-valued expression.
          At line:7 char:15
          + $vm.ReconfigVM <<<< ($vmConfigSpec)
          + CategoryInfo : InvalidOperation: (ReconfigVM:String) [], RuntimeException
          + FullyQualifiedErrorId : InvokeMethodOnNull

          Get-VM : 18/02/2013 16:16:29 Get-VM VM with name 'VMNAME**(Changed) ' was not found, using the specified filter(s).
          At line:3 char:13
          + $vm = Get-VM <<<< -Name $i | % {Get-View $_.ID}
          + CategoryInfo : ObjectNotFound: (:) [Get-VM], VimException
          + FullyQualifiedErrorId : Core_OutputHelper_WriteNotFoundError,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetVM

          You cannot call a method on a null-valued expression.
          At line:7 char:15
          + $vm.ReconfigVM <<<< ($vmConfigSpec)
          + CategoryInfo : InvalidOperation: (ReconfigVM:String) [], RuntimeException
          + FullyQualifiedErrorId : InvokeMethodOnNull

          Get-VM : 18/02/2013 16:16:52 Get-VM VM with name 'VMNAME**(Changedforsecurityreasons) ' was not found, using the specified filter(s).
          At line:3 char:13
          + $vm = Get-VM <<<< -Name $i | % {Get-View $_.ID}
          + CategoryInfo : ObjectNotFound: (:) [Get-VM], VimException
          + FullyQualifiedErrorId : Core_OutputHelper_WriteNotFoundError,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetVM

          You cannot call a method on a null-valued expression.
          At line:7 char:15
          + $vm.ReconfigVM <<<< ($vmConfigSpec)
          + CategoryInfo : InvalidOperation: (ReconfigVM:String) [], RuntimeException
          + FullyQualifiedErrorId : InvokeMethodOnNull

          Thanks in advance
          Alex

Trackbacks

  1. […] to disable auto update for all the VMs and re-enable it once it came across to the other side. All credit goes to Damian Karlson for this one. Just reposting so I have my own copy. # Get all the VMs $VMs = […]

  2. […] course, I started out with our friend Google. I found a pretty darn good post by Damian Karlson where I got most of my script and a few other links from that page for some more […]

  3. […] above script was inspired, and made possible by a post I came across on Damian Karlson’s blog, take a look for yourself.ย  I’ve just added some text output and progress display, the meat […]

  4. […] Managing VMware Tools advanced options: PowerCLI If you aren’t familiar with PowerCLI and are managing a vSphere installation you should make yourself familiar. Scripts like these are invaluable for making installation-wide changes. […]

Speak Your Mind

*