VMware Cloud Community
emcclure
Enthusiast
Enthusiast
Jump to solution

Trying to get a script to update VM Tools on selected VMs

I'm trying to get write a script that will allow someone to select a VM folder and then it will scan the VM's in that folder to see if they need an upgrade or not.  Then a window would come up with a list of the VM's that need to be upgraded.  The user could then select the ones to upgrade and tools would be upgraded (w/o reboot).  I've tried a few different things, even with a csv file, but it seems whenever I kind of get it to work it only takes one VM and upgrades it.  I'm looking at the csv file and I see multiple machines in there.  Oh I'm also trying to ignore powered off machines.  Here's what I have for my code:

$vms = Get-Folder $myfolder | Get-VM

foreach ($vm in $vms) {

if ($vm.ExtensionData.Guest.ToolsVersionStatus2 -eq "guestToolsSupportedOld") {

 

$selectedvms = Get-VM -Name $vm.Name

    $selectedvms | select Name | Export-CSV -Path .\toolsneedupgrade.csv -NoTypeInformation -UseCulture -Append

  Write-Host "VM-->",$vm.Name, "needs to have tools upgraded"

  }

}

Import-Csv -Path .\toolsneedupgrade.csv -UseCulture | Foreach-Object -Process { Get-VM -Name $_.Name

    #Get-VM -Name $vm | #Out-GridView -Title 'Select the VMs you wish to upgrade tools on' -OutPutMode Multiple

}

foreach ($vm in $selectedvms) {

if ($vm.Guest.State -eq "Running")

{

Write-Host "VM -->",$vm.Name, "is powered on so tools will be updated"

Get-VM -Name $vm.Name | Update-Tools -NoReboot

}

elseif ($vm.Powerstate -eq "PoweredOff")

{

Write-Host "VM-->",$vm.Name, "is powered off, so ignoring"

}

And when I run it everything seems ok until I select the folder.  It then outputs this:

VM--> VM1 needs to have tools upgraded
VM--> VM2 needs to have tools upgraded

Name                 PowerState Num CPUs MemoryGB
----                 ---------- -------- --------
VM1             PoweredOff 4        24.000
VM2           PoweredOn  2        8.000
VM3             PoweredOn  2        8.000
VM1             PoweredOff 4        24.000
VM2             PoweredOn  2        8.000
VM --> VM2 is powered on so tools will be updated
Update-Tools : 12/6/2018 3:40:27 PM     Update-Tools            Operation is not valid due to the current state of the object.
At C:\Users\emcclure\Desktop\GenScripts\GenUpgradeVMTools.ps1:67 char:25
+ Get-VM -Name $vm.Name | Update-Tools -NoReboot
+                         ~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Update-Tools], VimException
    + FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VimAutomation.ViCore.Cmdlets.Commands.UpdateVmTools

It does wind up updating the VM tools on the machine, but doesn't get to the part where it sees the VM is powered off and moves on in the script.  I'm sure it's something simple I'm missing, but I'm not sure what.

Reply
0 Kudos
26 Replies
emcclure
Enthusiast
Enthusiast
Jump to solution

Hmm.  So it goes away from what I had, which was a way for someone to choose a bunch of VM's and just have them update without having to press Y all the time.  The multiple folder selection is nice, but one thing I do at the end of the scripts I have is disconnect from vCenter or loop them back to the start.  I understand with someone selecting multiple folders they might not need to loop back to the beginning, unless there's something they forgot or the loop takes them back to connecting to vCenter. 

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

This looks  more and more like a moving target :smileygrin:

You had this very strange construct to select continue or exit, that is what the y/n is doing.
If you don't need it, just remove that part.

I normally leave out the connect and disconnect from a vSphere server in my code, since it is rather trivial.

If you want that, it's straightforward to add these at the start and end of the script.

If I understand you correctly (now), you want a script that allows the user to go back to the datacenter/folder/vm selection at any part of the script?

Where do you ask that question?

After every VM?

When all selected VMs are handled?


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

Reply
0 Kudos
emcclure
Enthusiast
Enthusiast
Jump to solution

So the main goal of the thread was trying to get a script to update VM tools on selected VM's which I think we have accomplished.  I'd have to dig around to find the page where I did the loop and question thing at the end.  My scripts have that loop in them, so the user can go back to the datacenter selection as some vCenters we have contain multiple datacenters.  This is typically after whatever main task the script does which is basically at the end.  The updating of the tools I want to be automatic and not require any user input other than getting to the VM's to select.  I have the disconnect in there since we also have multiple vCenters and I've seen it when I don't disconnect and run the script on another vCenter it can get the datacenters from the previous vCenter into the script, possibly causing confusion for whomever else is running it.  I had the continue/exit part as I had requests to have that in the script, so someone wouldn't have to restart the script, it would just be done for them.  I'm sure it's rather messy and I've only been dealing with PowerCLI/PowerShell for about 7 months, so I'm using this forum and whatever else I can find on google to figure things out and get the scripts created for the users.  I'm always open to a better way of doing things, as long as I can loop a script back to the top with prompting the user for that and keeping the automated stuff automated.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

What I often do when going to write a more complex script, with many possible paths, is to try and describe the flows in simple text.

This often allows you to have a better idea of what you actually want to do, and how to organise the flow in a script.

Does the following reflect what you want to achieve?

  • Ask which vCenter
    • will the list be hard-coded in the script?
    • can we obtain the available centers from an outside source (file)?
  • Connect to a vCenter
  • A - Ask which datacenter
    • Are multiple selections allowed?
  • B - Ask which folders
    • Are multiple selections allowed?
  • C - Ask which VMs
    • Are multiple selections allowed?
  • Ask if the script should prompt after each VM or if all selected VMs shall be done automatically
  • Test if the VM is powered on and needs its Tools to be updated
    • Y: update the Tools
      • Should this be logged?
    • N: should this be logged?
  • Ask what user wants to do: new datacenter selectio/new folder selection/new VM selection/quit
    • datacenter: go back to A
    • folder: go back to B
    • VM: go back to C
  • Disconnect from the vCenter


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

Reply
0 Kudos
emcclure
Enthusiast
Enthusiast
Jump to solution

Hi LucD,

So I try to make all of my scripts as generic as possible.  I eliminate any hard coding of vCenters, folders, etc unless the script is just meant for me.  I do this so anybody can run the script on any vCenter and it will just work as designed without having to make any changes to it.  As to what you said here's my answers:

  • Ask which vCenter
    • will the list be hard-coded in the script? no
    • can we obtain the available centers from an outside source (file)? I just have the user enter the vCenter in
  • Connect to a vCenter
  • A - Ask which datacenter
    • Are multiple selections allowed? Typically they select one at a time.  Teams have their own DC's so folder names/VM names could be duplicated.
  • B - Ask which folders
    • Are multiple selections allowed? For this script sure.  For most others I have them select one at a time.
  • C - Ask which VMs
    • Are multiple selections allowed? Yes, much easier to do in an automated fashion
  • Ask if the script should prompt after each VM or if all selected VMs shall be done automatically Script should do them all automatically since the VM's were already selected by the user
  • Test if the VM is powered on and needs its Tools to be updated
    • Y: update the Tools
      • Should this be logged? Just the output of a write-host should suffice.
    • N: should this be logged?
  • Ask what user wants to do: new datacenter selectio/new folder selection/new VM selection/quit - This seems nice.  It could allow a user to go to a specific spot instead of just the beginning.  Not something I've been asked to do by anybody yet, but would be a nice functionality.
    • datacenter: go back to A
    • folder: go back to B
    • VM: go back to C
  • Disconnect from the vCenter Yep.  Always disconnect at the end when done.  This could even be another option for the datacenter, folder, vm option.
Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Ok, let's see how this version fulfills your requirements.

$vcName = Read-Host -Prompt 'Enter the vCenter name'

Connect-VIServer -Server $vcName

while($true){

    $endAnswer = 'D'

    while($endAnswer -ne 'Q'){

        if($endAnswer -eq 'D'){

            $dc = Get-Datacenter | Select -ExpandProperty Name

            if($dc.count -gt 1){

                $dc = $dc | Out-GridView -OutputMode Single -Title 'Select one datacenter'

            }

            $endAnswer = 'F'

        }

        if($endAnswer -eq 'F'){

            $folder = Get-Folder -Location $dc -Type VM | Select -ExpandProperty Name

            if($folder.count -gt 1){

                $folder = $folder | Out-GridView -OutputMode Multiple -Title 'Select one or more folders'

            }

            $endAnswer = 'V'

        }

        if($endAnswer -eq 'V'){

            $vms = Get-VM -Location $folder |

                where {$_.ExtensionData.Guest.ToolsVersionStatus2 -eq "guestToolsSupportedOld"} |

                Select -ExpandProperty Name

            if($vms.Count -eq 0){

                Write-Host "No VMs found that require a VMware Tools update"

                break

            }

            if($vms.count -gt 1){

                $vms = $vms | Out-GridView -OutputMode Multiple -Title 'Select one or more folders'

            }

        }

        if($vms.count -gt 0){

            foreach($vm in Get-VM -Name $vms){

                if($vm.PowerState -eq 'PoweredOn'){

                    if($vm.Guest.State -eq 'Running'){

                        Write-Host "VMware Tools on VM $($vm.Name) will be updated"

                        Get-VM -Name $vm.Name | Update-Tools -NoReboot

                    }

                    else{

                        Write-Host "VMware Tools are not running on VM $($vm.Name)"

                    }

                }

                else{

                    Write-Host "VM $($vm.Name) is not powered on"

                }

            }

        }

        else{

            Write-Host "No VMs selected"

        }

        write-host "Please select an option"

        Write-Host "D - Go back to the datacenter selection"

        Write-Host "F - Go back to the folder selection"

        Write-Host "V - Go back to the VM selection"

        Write-Host "Q - Exit the script"

        $endAnswer = ''

        while('D','F','V','Q' -notcontains $endAnswer){

            $endAnswer = (Read-Host -Prompt 'Your answer').ToUpper()

        }

    }

    Disconnect-VIServer -Server $vcName -Confirm:$false

    break

}


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

Reply
0 Kudos
emcclure
Enthusiast
Enthusiast
Jump to solution

Hi LucD,

That works great.  I think I'm going to use this new way to setup the scripts for looping as it seems to be easier and better for the users.  Thanks so much.

Reply
0 Kudos