SHIFT

--- Sjoerd Hooft's InFormation Technology ---

User Tools

Site Tools


Sidebar

Recently Changed Pages:

View All Pages


View All Tags


LinkedIn




WIKI Disclaimer: As with most other things on the Internet, the content on this wiki is not supported. It was contributed by me and is published “as is”. It has worked for me, and might work for you.
Also note that any view or statement expressed anywhere on this site are strictly mine and not the opinions or views of my employer.


Pages with comments

View All Comments

powerclivmupgrade

Script: PowerCLI: Upgrade VMs to New Tools and Hardware Level Version

Note: If you need a simple version to just upgrade the hardware level to 9 (vSphere 5.1) look here.

This is a 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 <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 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 <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 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 <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 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
You could leave a comment if you were logged in.
powerclivmupgrade.txt · Last modified: 2021/09/24 00:25 (external edit)