= Script: PowerCLI: Upgrade VMs to New Tools and Hardware Level Version =
**Summary**: Upgrade the VMWare Tools level and the hardware level from VMs \\
**Date**: Around 2013 \\
**Refactor**: 22 March 2025: Checked links and formatting. \\
{{tag>powershell vmware}}
> Note: If you need a simple version to just upgrade the hardware level to 9 (vSphere 5.1) look [[powercliupgradehwlevel9|here]].
This is a [[vspherepowercli|powershell/powercli]] script which upgrades VMs to the latest level of VMware Tools and to hardware level 7.
\\
The script works in phases:
* phase 1
* It makes a selection of the VMs to upgrade, depending on your input. That can be a single VM, a Folder, a ResourcePool, all VMs or a file with listed VMs.
* phase 2
* In phase 2 it makes a csv file with info from the VMs that might be important while upgrading.
* phase 3
* In phase 3 it checks whether the tools should be upgraded and does so if required
* It also checks whether the hardware level should be upgraded and again, does so if required
* phase 4
* The script ends by creating a csv file again to make sure you have an overview of the made changes
# This scripy 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
# 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:\Users\sjoerd\Desktop\powercli scripts\$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 +C. Press 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 +C. Press 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 +C. Press 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 +C. Press 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 +C. Press 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 +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 Yellow
sleep 10
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 Yellow
sleep 5
#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 +C to quit the script or press to continue"
[console]::ResetColor()
}
return $Startup
}
Function PowerOff-VM($vm){
Shutdown-VMGuest -VM $vm -Confirm:$false | Out-Null
Write-Host "$vm is stopping!" -ForegroundColor Yellow
sleep 10
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 Yellow
sleep 5
}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 +C to quit the script or press 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 +C to quit the script or press 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 +C to quit the script or press 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 Yellow
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 Yellow
$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 10
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 5
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
//This wiki has been made possible by://