Adding a vGPU For a vSphere 6.0 VM via PowerCLI

I had a conversation with a VMware customer the other day and they were asking if there was a way to automate the addition and removal of a vGPU to a VM dynamically on a requested or scheduled basis, VMGuru has a great post here on what exactly a vGPU is, I highly recommend reading it.

They asked for a PowerCLI command or function to configure the VM graphics card, specifically to assign a vGPU resources to the VM, a desktop user’s VM is configured by default with vSGA (to not tie up  vGPU resources) then the user schedules the vGPU resource for a specific time frame using their end user portal, before the scheduled vGPU reservation time frame the user is logged out and the script would kick in. The script would reconfigure the VM settings and assigns a vGPU profile to it, the equivalent of what is being done in the UI as follows:

image

The desktop user then logs in and now the VM is configured with the vGPU resource, after a little scripting and testing on an environment with a NVIDIA GRID I was able to provide the below script.

As per the normal I though I would blog it as it may be useful in the future to someone.

Sample output of the script running

image

The Code

 

Function Get-GPUProfile {
    Param ($vmhost)
    $VMhost = Get-VMhost $VMhost
    $vmhost.ExtensionData.Config.SharedPassthruGpuTypes
}
 
Function Get-vGPUDevice {
    Param ($vm)
    $VM = Get-VM $VM
    $vGPUDevice = $VM.ExtensionData.Config.hardware.Device | Where { $_.backing.vgpu}
    $vGPUDevice | Select Key, ControllerKey, Unitnumber, @{Name="Device";Expression={$_.DeviceInfo.Label}}, @{Name="Summary";Expression={$_.DeviceInfo.Summary}}
}
 
Function Remove-vGPU {
    Param (
        [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true,Position=0)] $VM,
        [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true,Position=1)] $vGPUDevice
    )
 
    $ControllerKey = $vGPUDevice.controllerKey
    $key = $vGPUDevice.Key
    $UnitNumber = $vGPUDevice.UnitNumber
    $device = $vGPUDevice.device
    $Summary = $vGPUDevice.Summary
 
    $VM = Get-VM $VM
 
    $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)
}
 
Function New-vGPU {
    Param ($VM, $vGPUProfile)
    $VM = Get-VM $VM
    $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 = 'add'
    $spec.deviceChange[0].device = New-Object VMware.Vim.VirtualPCIPassthrough
    $spec.deviceChange[0].device.deviceInfo = New-Object VMware.Vim.Description
    $spec.deviceChange[0].device.deviceInfo.summary = ''
    $spec.deviceChange[0].device.deviceInfo.label = 'New PCI device'
    $spec.deviceChange[0].device.backing = New-Object VMware.Vim.VirtualPCIPassthroughVmiopBackingInfo
    $spec.deviceChange[0].device.backing.vgpu = "$vGPUProfile"
    $vmobj = $VM | Get-View
    $reconfig = $vmobj.ReconfigVM_Task($spec)
    if ($reconfig) {
        $ChangedVM = Get-VM $VM
        $vGPUDevice = $ChangedVM.ExtensionData.Config.hardware.Device | Where { $_.backing.vgpu}
        $vGPUDevice | Select Key, ControllerKey, Unitnumber, @{Name="Device";Expression={$_.DeviceInfo.Label}}, @{Name="Summary";Expression={$_.DeviceInfo.Summary}}
 
    }   
}
 
 
$VMHost = Get-VMHost 10.114.64.86
$vGPUProfile = Get-GPUProfile -vmhost $VMHost
 
Write-Host "The following vGPU Profiles are available to choose for this host"
$vGPUProfile
 
# Choose a profile to use from the list
$ChosenvGPUProfile = $vGPUProfile | Where {$_ -eq "grid_m60-4q" }
 
# Get a VM to add it to
$VM = Get-VM 3DVM_Win7_20GB_86
 
Write-Host "Adding the vGPU to $vm"
New-vGPU -VM $vm -vGPUProfile $ChosenvGPUProfile
 
# At a later date
Read-Host "The device has been added, press enter to remove again"
Write-Host "Removing the GPU Devices in $VM"
Remove-vGPU -VM $vm -vGPUDevice (Get-vGPUDevice -vm $VM)
 

4 thoughts on “Adding a vGPU For a vSphere 6.0 VM via PowerCLI”

  1. Thank for you writing this! Much appreciated! Any chance the “reserve all memory” command could be written into the New-vGPU function?

  2. Alan – thanks! this was super helpful and easy to use! I imported the functions into my profile, so it would follow me anywhere I used Powershell_ISE! Thanks.

  3. Alan,

    This is GREAT!!!! Got any extra spice to get passthrough K1 or K2 assigned via POSH?

    Cheers, Matt
    Autodesk CloudPC team

    1. Sorry I don’t have a configuration with that, perhaps try onyx for the web client to see if that brings back any help? We also have a cmdlet for pass through devices so try that too

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.