= 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