diff --git a/vsphere/internal/virtualdevice/virtual_machine_device_subresource.go b/vsphere/internal/virtualdevice/virtual_machine_device_subresource.go index de685da51..558a11166 100644 --- a/vsphere/internal/virtualdevice/virtual_machine_device_subresource.go +++ b/vsphere/internal/virtualdevice/virtual_machine_device_subresource.go @@ -1060,3 +1060,61 @@ 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 + } + + 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