From 2467f470cd3035d23b75e0c8246f6afdfe8bbc77 Mon Sep 17 00:00:00 2001 From: Anthony ARNAUD Date: Tue, 30 Mar 2021 23:19:39 -0400 Subject: [PATCH] fix #1265 support vGPU Original implementation of PciPassthrough can't be use for vGPU because it's link to host systemId --- .../virtual_machine_device_subresource.go | 60 +++++++++++++++++++ vsphere/resource_vsphere_virtual_machine.go | 28 ++++++++- website/docs/r/virtual_machine.html.markdown | 2 + 3 files changed, 88 insertions(+), 2 deletions(-) diff --git a/vsphere/internal/virtualdevice/virtual_machine_device_subresource.go b/vsphere/internal/virtualdevice/virtual_machine_device_subresource.go index de685da51..b02bba480 100644 --- a/vsphere/internal/virtualdevice/virtual_machine_device_subresource.go +++ b/vsphere/internal/virtualdevice/virtual_machine_device_subresource.go @@ -1060,3 +1060,63 @@ func PciPassthroughApplyOperation(d *schema.ResourceData, c *govmomi.Client, l o } return applyConfig.VirtualDevice, applyConfig.Spec, nil } + +// SharedPciPassthroughApplyOperation checks for changes in a virtual machine's +// Shared PCI passthrough device and creates config specs to apply apply to the +// virtual machine. +func SharedPciPassthroughApplyOperation(d *schema.ResourceData, c *govmomi.Client, l object.VirtualDeviceList) (object.VirtualDeviceList, []types.BaseVirtualDeviceConfigSpec, error) { + old, new := d.GetChange("shared_pci_device_id") + oldDevId := old.(string) + newDevId := new.(string) + + var specs []types.BaseVirtualDeviceConfigSpec + if oldDevId == newDevId { + return l, specs, nil + } + + if oldDevId != "" { + vm, err := virtualmachine.FromUUID(c, d.Id()) + if err != nil { + return nil, nil, err + } + vprops, err := virtualmachine.Properties(vm) + if err != nil { + return nil, nil, err + } + // This will only find a device for delete operations. + for _, vmDevP := range vprops.Config.Hardware.Device { + if vmDev, ok := vmDevP.(*types.VirtualPCIPassthrough); ok { + if vmDev.Backing.(*types.VirtualPCIPassthroughVmiopBackingInfo).Vgpu == oldDevId { + dspec, err := object.VirtualDeviceList{vmDev}.ConfigSpec(types.VirtualDeviceConfigSpecOperationRemove) + if err != nil { + return nil, nil, err + } + specs = append(specs, dspec...) + + l = applyDeviceChange(l, dspec) + d.Set("reboot_required", true) + } + } + } + } + + if newDevId != "" { + dev := &types.VirtualPCIPassthrough{ + VirtualDevice: types.VirtualDevice{ + DynamicData: types.DynamicData{}, + Backing: &types.VirtualPCIPassthroughVmiopBackingInfo{ + Vgpu: newDevId, + }, + }, + } + dspec, err := object.VirtualDeviceList{dev}.ConfigSpec(types.VirtualDeviceConfigSpecOperationAdd) + if err != nil { + return nil, nil, err + } + specs = append(specs, dspec...) + l = applyDeviceChange(l, dspec) + d.Set("reboot_required", true) + } + + return l, specs, nil +} diff --git a/vsphere/resource_vsphere_virtual_machine.go b/vsphere/resource_vsphere_virtual_machine.go index 0692a79ea..85e6782fe 100644 --- a/vsphere/resource_vsphere_virtual_machine.go +++ b/vsphere/resource_vsphere_virtual_machine.go @@ -239,6 +239,12 @@ func resourceVSphereVirtualMachine() *schema.Resource { Description: "A list of PCI passthrough devices", Elem: &schema.Schema{Type: schema.TypeString}, }, + "shared_pci_device_id": { + Type: schema.TypeString, + Optional: true, + Description: "Id of Shared PCI passthrough device, 'grid_rtx8000-8q'", + Elem: &schema.Schema{Type: schema.TypeString}, + }, "clone": { Type: schema.TypeList, Optional: true, @@ -504,8 +510,20 @@ func resourceVSphereVirtualMachineRead(d *schema.ResourceData, meta interface{}) var pciDevs []string for _, dev := range vprops.Config.Hardware.Device { if pci, ok := dev.(*types.VirtualPCIPassthrough); ok { - devId := pci.Backing.(*types.VirtualPCIPassthroughDeviceBackingInfo).Id - pciDevs = append(pciDevs, devId) + if pciBacking, ok := pci.Backing.(*types.VirtualPCIPassthroughDeviceBackingInfo); ok { + devId := pciBacking.Id + pciDevs = append(pciDevs, devId) + } else { + if pciBacking, ok := pci.Backing.(*types.VirtualPCIPassthroughVmiopBackingInfo); ok { + err = d.Set("shared_pci_device_id", pciBacking.Vgpu) + if err != nil { + return err + } + } else { + log.Printf("[WARN] Ignoring VM %q VirtualPCIPassthrough device with backing type of %T", + vm.InventoryPath, pci.Backing) + } + } } } err = d.Set("pci_device_id", pciDevs) @@ -1838,6 +1856,12 @@ func applyVirtualDevices(d *schema.ResourceData, c *govmomi.Client, l object.Vir return nil, err } spec = virtualdevice.AppendDeviceChangeSpec(spec, delta...) + // Shared PCI passthrough device + l, delta, err = virtualdevice.SharedPciPassthroughApplyOperation(d, c, l) + if err != nil { + return nil, err + } + spec = virtualdevice.AppendDeviceChangeSpec(spec, delta...) log.Printf("[DEBUG] %s: Final device list: %s", resourceVSphereVirtualMachineIDString(d), virtualdevice.DeviceListString(l)) log.Printf("[DEBUG] %s: Final device change spec: %s", resourceVSphereVirtualMachineIDString(d), virtualdevice.DeviceChangeString(spec)) return spec, nil diff --git a/website/docs/r/virtual_machine.html.markdown b/website/docs/r/virtual_machine.html.markdown index 2519f5556..3ce87affe 100644 --- a/website/docs/r/virtual_machine.html.markdown +++ b/website/docs/r/virtual_machine.html.markdown @@ -614,6 +614,8 @@ external disks on virtual machines that are assigned to datastore clusters. more details. * `pci_device_id` - (Optional) List of host PCI device IDs to create PCI passthroughs for. + * `shared_pci_device_id` - (Optional) Shared PCI device ID to create PCI + passthroughs for. [virtual-machine-hardware-compatibility]: https://kb.vmware.com/s/article/2007240