AUTOMATE UPDATE VM TOOLS AND HARDWARE VERSION WHILE TAKING A SNAP SHOT

I have been given the task of updating our VM Guests to the Correct Tools and HW version.

I've gone through various forums etc and have found the attached script which seems to update etc just as expected and produces a nice excel file of the changes made and of the IP addresses before and after the changes (which is great as the update seems to knock out the IP settings due to the new nic install).  The one thing it dont do, which i would like is take a Snapshot of the VM before the Updating gets performed.

If anyone has any improvements to the script please feel free, as like i said i found it on the web.  I think its from around 2010 so someone may know of updated versions of this one. that does what i need or may know how to modify this to do what i need.

Cheers
# This script will upgrade the VMWare Tools level and the hardware level from VMs
#
# Original Author:
# AFokkema: http://ict-freak.nl/2009/07/15/powercli-upgrading-vhardware-to-vsphere-part-2-vms/
#
# Modifications done by:
# Sjoerd Hooft: http://www.warmetal.nl/powerclivmupgrade
# Modifications:
# Improved readability: Removed blank lines when not required; Used standard white spaces for readablilty; Added variables section
# Changed the before and after hardware list: Use variables for the listname depending on timestamp; Added information for VMs with multiple nics; Removed Excel functionality so using csv allways
# Added the possibility for input from more than just a folder: 1 VM (for testing purposes); Folder; ResourcePool; File with VMs; All VMs
# Changed the power-off and power-on VM functions to check both tools and running status
# Changed the check tools state function to include all possible statuses
# Added the possibillity to exit the script when things go wrong
# Made separate functions for upgrading the tools and hardware level, and skipping linux guests
Add-PSSnapin -Name "VMware.VimAutomation.Core"
# Variables
$vCenter = Read-Host "Enter your vCenter servername"
#$Folder = Read-Host "Enter the name of the folder where the VMs are stored"
$timestamp = Get-Date -format "yyyyMMdd-HH.mm"
# Note: enter the csv file without extension:
$csvfile = "C:\VMUGTEST\$timestamp-vminfo.csv"
 
Function VM-Selection{
   $sourcetype = Read-Host "Do you want to upgrade AllVMs, a VM, Folder, ResourcePool or from a VMfile?"
   if($sourcetype -eq "AllVMs"){
      $abort = Read-Host "You've chosen $sourcetype, this is your last chance to abort by pressing <CTRL>+C. Press <ENTER> to continue selecting old hardware VMs"
      #$vms = Get-VM | Get-View | Where-Object {-not $_.config.template -and $_.Config.Version -eq "vmx-04" } | Select Name
      $vms = Get-VM | Get-View | Where-Object {-not $_.config.template} | Select Name
   }
   else{
      $sourcename = Read-Host "Give the name of the object or inputfile (full path) you want to upgrade"
      if($sourcetype -eq "VM"){
         $abort = Read-Host "You've chosen $sourcetype, this is your last chance to abort by pressing <CTRL>+C. Press <ENTER> to continue selecting old hardware VMs"
         #$vms = Get-VM $sourcename | Get-View | Where-Object {-not $_.config.template -and $_.Config.Version -eq "vmx-04" } | Select Name
         $vms = Get-VM $sourcename | Get-View | Where-Object {-not $_.config.template} | Select Name
      }
      elseif($sourcetype -eq "Folder"){
         $abort = Read-Host "You've chosen $sourcetype, this is your last chance to abort by pressing <CTRL>+C. Press <ENTER> to continue selecting old hardware VMs"
         #$vms = Get-Folder $sourcename | Get-VM  | Get-View | Where-Object {-not $_.config.template -and $_.Config.Version -eq "vmx-04" } | Select Name
         $vms = Get-Folder $sourcename | Get-VM  | Get-View | Where-Object {-not $_.config.template} | Select Name
      }
      elseif($sourcetype -eq "ResourcePool"){
         $abort = Read-Host "You've chosen $sourcetype, this is your last chance to abort by pressing <CTRL>+C. Press <ENTER> to continue selecting old hardware VMs"
         #$vms = Get-ResourcePool $sourcename | Get-VM  | Get-View | Where-Object {-not $_.config.template -and $_.Config.Version -eq "vmx-04" } | Select Name
         $vms = Get-ResourcePool $sourcename | Get-VM  | Get-View | Where-Object {-not $_.config.template} | Select Name
      }
      elseif(($sourcetype -eq "VMfile") -and ((Test-Path -path $sourcename) -eq $True)){
         $abort = Read-Host "You've chosen $sourcetype with this file: $sourcename, this is your last chance to abort by pressing <CTRL>+C. Press <ENTER> to continue selecting old hardware VMs"
         #$list = Get-Content $sourcename | Foreach-Object {Get-VM $_ | Get-View | Where-Object {-not $_.config.template -and $_.Config.Version -eq "vmx-04" } | Select Name }
         $list = Get-Content $sourcename | Foreach-Object {Get-VM $_ | Get-View | Where-Object {-not $_.config.template} | Select Name }
         $vms = $list
      }
      else{
         Write-Host "$sourcetype is not an exact match of AllVMs, VM, Folder, ResourcePool or VMfile, or the VMfile does not exist. Exit the script by pressing <CTRL>+C and try again."
      }
   }
   return $vms
}
 
Function PowerOn-VM($vm){
   Start-VM -VM $vm -Confirm:$false -RunAsync | Out-Null
   Write-Host "$vm is starting!" -ForegroundColor Green
   sleep 5
 
   do {
      $vmview = get-VM $vm | Get-View
      $getvm = Get-VM $vm
      $powerstate = $getvm.PowerState
      $toolsstatus = $vmview.Guest.ToolsStatus
 
      Write-Host "$vm is starting, powerstate is $powerstate and toolsstatus is $toolsstatus!" -ForegroundColor Green
      sleep 10
      #NOTE that if the tools in the VM get the state toolsNotRunning this loop will never end. There needs to be a timekeeper variable to make sure the loop ends
 
    }until(($powerstate -match "PoweredOn") -and (($toolsstatus -match "toolsOld") -or ($toolsstatus -match "toolsOk") -or ($toolsstatus -match "toolsNotInstalled")))
 
    if (($toolsstatus -match "toolsOk") -or ($toolsstatus -match "toolsOld")){
       $Startup = "OK"
       Write-Host "$vm is started and has ToolsStatus $toolsstatus"
    }
    else{
       $Startup = "ERROR"
       [console]::ForegroundColor = "Red"
       Read-Host "The ToolsStatus of $vm is $toolsstatus. This is unusual. Press <CTRL>+C to quit the script or press <ENTER> to continue"
       [console]::ResetColor()
    }
    return $Startup
}
 
Function PowerOff-VM($vm){
   Shutdown-VMGuest -VM $vm -Confirm:$false | Out-Null
   Write-Host "$vm is stopping!" -ForegroundColor Blue
   sleep 5
 
   do {
      $vmview = Get-VM $vm | Get-View
      $getvm = Get-VM $vm
      $powerstate = $getvm.PowerState
      $toolsstatus = $vmview.Guest.ToolsStatus
 
      Write-Host "$vm is stopping with powerstate $powerstate and toolsStatus $toolsstatus!" -ForegroundColor Green
      sleep 10
 
   }until($powerstate -match "PoweredOff")
 
   if (($powerstate -match "PoweredOff") -and (($toolsstatus -match "toolsNotRunning") -or ($toolsstatus -match "toolsNotInstalled"))){
      $Shutdown = "OK"
      Write-Host "$vm is powered-off"
   }
   else{
      $Shutdown = "ERROR"
      [console]::ForegroundColor = "Red"
      Read-Host "The ToolsStatus of $vm is $toolsstatus. This is unusual. Press <CTRL>+C to quit the script or press <ENTER> to continue"
      [console]::ResetColor()
   }
   return $Shutdown
}
 
Function Check-ToolsStatus($vm){
   $vmview = get-VM $vm | Get-View
   $status = $vmview.Guest.ToolsStatus
 
   if ($status -match "toolsOld"){
      $vmTools = "Old"}
   elseif($status -match "toolsNotRunning"){
      $vmTools = "NotRunning"}
   elseif($status -match "toolsNotInstalled"){
      $vmTools = "NotInstalled"}
   elseif($status -match "toolsOK"){
      $vmTools = "OK"}
   else{
      $vmTools = "ERROR"
      Read-Host "The ToolsStatus of $vm is $vmTools. Press <CTRL>+C to quit the script or press <ENTER> to continue"
      }
   return $vmTools
}
 
Function Check-VMHardwareVersion($vm){
   $vmView = get-VM $vm | Get-View
   $vmVersion = $vmView.Config.Version
   $v4 = "vmx-04"
   $v7 = "vmx-07"
 
   if ($vmVersion -eq $v4){
      $vmHardware = "Old"}
   elseif($vmVersion -eq $v7){
      $vmHardware = "OK"}
   else{
      $vmHardware = "ERROR"
      [console]::ForegroundColor = "Red"
      Read-Host "The Hardware version of $vm is not set to $v4 or $v7. This is unusual. Press <CTRL>+C to quit the script or press <ENTER> to continue"
      [console]::ResetColor()
   }
   return $vmHardware
}
 
Function Upgrade-VMHardware($vm){
   $vmview = Get-VM $vm | Get-View
   $vmVersion = $vmView.Config.Version
   $v4 = "vmx-04"
   $v7 = "vmx-07"
 
   if ($vmVersion -eq $v4){
      Write-Host "Version 4 detected" -ForegroundColor Red
 
# Update Hardware
      Write-Host "Upgrading Hardware on" $vm -ForegroundColor Green
      Get-View ($vmView.UpgradeVM_Task($v7)) | Out-Null
   }
}
 
Function CreateHWList($vms, $csvfile){
# The setup for this hwlist comes from http://www.warmetal.nl/powerclicsvvminfo
   Write-Host "Creating a CSV File with VM info" -ForegroundColor Green
 
   $MyCol = @()
      ForEach ($item in $vms){
         $vm = $item.Name
         # Variable getvm is required, for some reason the $vm cannot be used to query the host and the IP-address
         $getvm = Get-VM $VM
         $vmview = Get-VM $VM | Get-View
 
         # VM has to be turned on to make sure all information can be recorded
         $powerstate = $getvm.PowerState
         if ($powerstate -ne "PoweredOn"){
            PowerOn-VM $vm}
 
         $vmnic = Get-NetworkAdapter -VM $VM
         $nicmac = Get-NetworkAdapter -VM $VM | ForEach-Object {$_.MacAddress}
         $nictype = Get-NetworkAdapter -VM $VM | ForEach-Object {$_.Type}
         $nicname = Get-NetworkAdapter -VM $VM | ForEach-Object {$_.NetworkName}
 
         $VMInfo = "" | Select VMName,NICCount,IPAddress,MacAddress,NICType,NetworkName,GuestRunningOS,PowerState,ToolsVersion,ToolsStatus,ToolsRunningStatus,HWLevel,VMHost
         $VMInfo.VMName = $vmview.Name
         $VMInfo.NICCount = $vmview.Guest.Net.Count
         $VMInfo.IPAddress = [String]$getvm.Guest.IPAddress
         $VMInfo.MacAddress = [String]$nicmac
         $VMInfo.NICType = [String]$nictype
         $VMInfo.NetworkName = [String]$nicname
         $VMInfo.GuestRunningOS = $vmview.Guest.GuestFullname
         $VMInfo.PowerState = $getvm.PowerState
         $VMInfo.ToolsVersion = $vmview.Guest.ToolsVersion
         $VMInfo.ToolsStatus = $vmview.Guest.ToolsStatus
         $VMInfo.ToolsRunningStatus = $vmview.Guest.ToolsRunningStatus
         $VMInfo.HWLevel = $vmview.Config.Version
         $VMInfo.VMHost = $getvm.VMHost
 
         $myCol += $VMInfo
      }
 
   if ((Test-Path -path $csvfile) -ne $True){
      $myCol |Export-csv -NoTypeInformation $csvfile
   }
   else{
      $myCol |Export-csv -NoTypeInformation $csvfile-after.csv
   }
}
 
Function CheckAndUpgradeTools($vm){
 
   $vmview = Get-VM $VM | Get-View
   $family = $vmview.Guest.GuestFamily
   $vmToolsStatus = Check-ToolsStatus $vm
 
   if($vmToolsStatus -eq "OK"){
      Write-Host "The VM tools are $vmToolsStatus on $vm"}
   elseif(($family -eq "windowsGuest") -and ($vmToolsStatus -ne "NotInstalled")){
      Write-Host "The VM tools are $vmToolsStatus on $vm. Starting update/install now! This will take at few minutes." -ForegroundColor Red
      Get-Date
      Get-VMGuest $vm | Update-Tools -NoReboot
      do{
      sleep 200
      Write-Host "Checking ToolsStatus $vm now"
      $vmToolsStatus = Check-ToolsStatus $vm
      }until($vmToolsStatus -eq "OK")
      PowerOff-VM $vm
      PowerOn-VM $vm
   }
   else{
      # ToDo: If the guest is running windows but tools notrunning/notinstalled it might be an option to invoke the installation through powershell.
      # Options are then Invoke-VMScript cmdlet or through windows installer: msiexec-i "D: \ VMware Tools64.msi" ADDLOCAL = ALL REMOVE = Audio, Hgfs, VMXNet, WYSE, GuestSDK, VICFSDK, VAssertSDK / qn
      # We're skipping all non-windows guest since automated installs are not supported
      Write-Host "$vm is a $family with tools status $vmToolsStatus. Therefore we're skipping this VM" -ForegroundColor Red
   }
}
 
Function CheckAndUpgrade($vm){
 
   $vmHardware = Check-VMHardwareVersion $vm
   $vmToolsStatus = Check-ToolsStatus $vm
 
   if($vmHardware -eq "OK"){
      Write-Host "The hardware level is $vmHardware on $vm"}
   elseif($vmToolsStatus -eq "OK"){
      Write-Host "The hardware level is $vmHardware on $vm." -ForegroundColor Red
      $PowerOffVM = PowerOff-VM $vm
      if($PowerOffVM -eq "OK"){
         Write-Host "Starting upgrade hardware level on $vm."
         Upgrade-VMHardware $vm
         sleep 90
         PowerOn-VM $vm
         Write-Host $vm "is up to date" -ForegroundColor Green
      }
      else{
      Write-Host "There is something wrong with the hardware level or the tools of $vm. Skipping $vm."
      }
   }
}
 
 Connect-VIServer $vCenter
 
$vms = VM-Selection
CreateHWList $vms $csvfile
foreach($item in $vms){
   $vm = $item.Name
   Write-Host "Test $vm"
   CheckAndUpgradeTools $vm
   CheckAndUpgrade $vm
}
CreateHWList $vms $csvfile
 
Disconnect-VIServer -Confirm:$false

Open in new window

LVL 1
Colchester_InstituteAsked:
Who is Participating?
 
Colchester_InstituteAuthor Commented:
already come across them but its working out how to incorporate taking the snapshot into the script i already have

PowerCli is VMs powershell so thats what i'm using especially with use of the attached script
0
 
Andrew Hancock (VMware vExpert / EE MVE^2)VMware and Virtualization ConsultantCommented:
Alot of the scripts jumpled across the Internet, have been merged and maintained into the VMware Community Pack

To run the VMware Community Pack
http://www.virtu-al.net/featured-scripts/vmware-powerpack/

you'll need PowerCLI and PowerGUI.

I would recommend using the following, also VMware recommends the use of PowerCLI, which is PowerShell interface with vSphere-specific additions.

http://communities.vmware.com/community/vmtn/server/vsphere/automationtools/powercli

One of the simplest PowerCLI examples, and something which is actually extremely useful on its own, is the Get-VM cmdlet. Which lists VMs.

PowerCLI can be a bit overwhelming to use,  But it can be enhanced with a nice toolset and a library of preconfigured scripts to jump-start your mass changes, which is possible with PowerGUI

http://powergui.org/index.jspa

There is a script in the VMware Community Pack, that you can select ALL VMs, or the VM you require to create Snapshots, with a name and description. There is also a script to run, which checks which VMs need VMware Tools need updating, but I could not find a script in the pack, to update the tools, but my version is out of date. But you could import this working script you have.

0
 
Colchester_InstituteAuthor Commented:
Already have all that haha

The reason i need the script is to Automate it. So the process would be.....
* Read a File of VMs,or select a Cluster/folder etc,
* Produce an excel sheet of the select VM(s) displaying HWV, State of Tools and the Machines IP,
* Check to see if Tools and/or HWV need updating if yes the take a snapshot and proceed with update
* Once the list is completed produce another Spreadsheet with the info machine of he HWV, State of tools and machine IP

At the moment the script i posted does most of that other than the snapshot part
0
 
Colchester_InstituteAuthor Commented:
There is a problem with updating the hardware version that can cause the server to lose its IP (its due to installing a new NIC) however i think this has been resolved in the Latest VM Update, so the script i first posted plus tips from the other comments will help
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.