Change VMware vGPU settings with PowerShell

Within larger organizations, centralized desktop with graphical performance is becoming a common use case. When building these of environments performance testing is crucial to get optimal user experience. During testing, it can occur you have to change the vGPU settings. Within this blog post, I will share a script that helps you change GPU profiles for multiple machines.

Which vGPU settings need to be changed?

When using a vGPU you need to specify a virtual GPU profile. Depending on the type of card you have multiple profiles to choose from depending on the use case. Please see the following overview of available profiles:

NVIDIA GRID Graphics Board

Virtual GPU Profile

Graphics Memory

Max Displays Per User

Max Resolution Per Display

Max Users Per Graphics Board

Recommended Use Case

GRID K2 K280Q 4 GB 4 2560×1600 2 Designer
K260Q 2 GB 4 2560×1600 4 Designer/Power User
K240Q 1 GB 2 2560×1600 8 Designer/Power User
K220Q 512 MB 2 2560×1600 16 Designer/Power User
GRID K1 K180Q 4 GB 4 2560×1600 4 Entry Designer
K160Q 2 GB 4 2560×1600 8 Power User
K140Q 1 GB 2 2560×1600 16 Power User
K120Q 512 MB 2 2560×1600 32 Power User

Source: http://blogs.vmware.com/euc/2015/03/nvidia-grid-vgpu-vmware-horizon.html

These profiles can be specified in VMware vCenter in the properties of the VMs.

vmware-vgpu-profiles

When you have to change this setting for 16 or 32 VM’s it can be time-consuming.

Changing vGPU settings with PowerShell

The following script can changes this profile based on the available on the server.

Please note: Changing profiles may cause problems so use the script at your own risk.

Param (
        [Parameter(Mandatory=$true)] $hostname,
		[Parameter(Mandatory=$true)] $username,
		[Parameter(Mandatory=$true)] $password,
		[Parameter(Mandatory=$true)] $vmname
    )
	
# Load VMware snapin
Add-PSSnapin VMware*

# Connect to the VMware Host
Connect-VIServer -Server $hostname -User $username -Password $password | Out-Null

# Collect host information
$vmHost = Get-VMHost $hostname

# Define vGPU Profiles
$vGpuProfiles = $vmhost.ExtensionData.Config.SharedPassthruGpuTypes

Write-Host "#############################"
Write-Host "# Available vGPU profiles   #"
Write-Host "# Select your vGPU profiles #"
Write-Host "#############################"

$i = 0
foreach ($vGpuProfile in $vGpuProfiles)
{
	Write-Host "[$i] - $vGpuProfile"
	$i++
}
Write-Host "#############################"

do 
{
	try 
	{	
		$validated = $true
		$max = $i -1 
		[int]$vGpuSelectionInt = Read-Host -Prompt "Please choose a vGPU profile (select between 0 - $max)"
	}
	catch {$validated = $false}
}
until (($vGpuSelectionInt -ge 0 -and $vGpuSelectionInt -le $max) -and $validated)
$vGpuSelection = $vGpuProfiles[$vGpuSelectionInt]
Write-Host "You have selected:" $vGpuSelection

# Collect the VM's that need to change the vGPU profile
$vms = Get-VM -Name $vmName
$vmsOn = $vms | Where-Object {$_.PowerState -eq "PoweredOn"}

Write-Host "VM's wihtin the selection:" $vms.Count
Write-Host "Couple VM's are still powered on, shutdown command will be executed for:" $vmsOn.Count

# Go into the shutdown loop when VM's are still on
if ($vmsOn.Count -gt 0)
{
	do
	{
		# Collect the VM's that need to change the vGPU profile
		$vmsOn = Get-VM -Name $vmName | Where-Object {$_.PowerState -eq "PoweredOn"}
		
		$activeShutdown = $false
		# Shutdown PoweredOn VM's 
		foreach ($vmOn in $vmsOn)
		{
				Write-Host "Shutdown VM:" $vmOn
				if ($vmOn.ExtensionData.Guest.GuestState -eq "running")
				{
					$vmOn | Stop-VMGuest -Confirm:$false | Out-Null
				}
				else
				{
					$vmOn | Stop-VM -Confirm:$false | Out-Null
				}
				
				$activeShutdown = $true
		}
		
		# Sleep when shutdown is active
		if ($activeShutdown)
		{
			Start-Sleep -Seconds 10
		}
	}
	until ($vmsOn.Count -le 0)
}

foreach ($vm in $vms)
{

    $vGPUDevices = $vm.ExtensionData.Config.hardware.Device | Where { $_.backing.vgpu}
    	if ($vGPUDevices.Count -gt 0)
	{
		Write-Host "Remove existing vGPU configuration from VM:" $vm.Name
		foreach ($vGPUDevice in $vGPUDevices)
		{
			$controllerKey = $vGPUDevice.controllerKey
			$key = $vGPUDevice.Key
			$unitNumber = $vGPUDevice.UnitNumber
			$device = $vGPUDevice.device
			$summary = $vGPUDevice.Summary
		  
			$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
			$spec.deviceChange = New-Object VMware.Vim.VirtualDeviceConfigSpec[] (1)
			$spec.deviceChange[0] = New-Object VMware.Vim.VirtualDeviceConfigSpec
			$spec.deviceChange[0].operation = 'remove'
			$spec.deviceChange[0].device = New-Object VMware.Vim.VirtualPCIPassthrough
			$spec.deviceChange[0].device.controllerKey = $controllerKey
			$spec.deviceChange[0].device.unitNumber = $unitNumber
			$spec.deviceChange[0].device.deviceInfo = New-Object VMware.Vim.Description
			$spec.deviceChange[0].device.deviceInfo.summary = $summary
			$spec.deviceChange[0].device.deviceInfo.label = $device
			$spec.deviceChange[0].device.key = $key
			$_this = $VM  | Get-View
			$nulloutput = $_this.ReconfigVM_Task($spec)
		}
	}

	Write-Host "Adding new vGPU configuration from VM:" $vm.Name
	$vmSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
    $vmSpec.deviceChange = New-Object VMware.Vim.VirtualDeviceConfigSpec[] (1)
    $vmSpec.deviceChange[0] = New-Object VMware.Vim.VirtualDeviceConfigSpec
    $vmSpec.deviceChange[0].operation = 'add'
    $vmSpec.deviceChange[0].device = New-Object VMware.Vim.VirtualPCIPassthrough
    $vmSpec.deviceChange[0].device.deviceInfo = New-Object VMware.Vim.Description
    $vmSpec.deviceChange[0].device.deviceInfo.summary = ''
    $vmSpec.deviceChange[0].device.deviceInfo.label = 'New PCI device'
    $vmSpec.deviceChange[0].device.backing = New-Object VMware.Vim.VirtualPCIPassthroughVmiopBackingInfo
    $vmSpec.deviceChange[0].device.backing.vgpu = "$vGpuSelection"
	
    $vmobj = $vm | Get-View
    
	$reconfig = $vmobj.ReconfigVM_Task($vmSpec)
    if ($reconfig) {
        $changedVm = Get-VM $vm
        $vGPUDevice = $changedVm.ExtensionData.Config.hardware.Device | Where { $_.backing.vgpu}
       }   
}
Write-Host "Done with configuration"
timeout /t 15

Conclusion

This script can help you with quickly change the vGPU profiles within VMware so you can continue with testing these settings. I hope this is valuable for you to use and feel free to leave a comment or question.