From 2a40f471b724077d382d459fc18051a26a08f56a Mon Sep 17 00:00:00 2001 From: "Thor K. H" Date: Tue, 24 Mar 2020 15:28:04 +0100 Subject: [PATCH] Add vgpu_profile support for using GRID vGPUs It hooks directly into Configure, common for both vsphere-clone and vsphere-iso. Note that acceptance tests are still missing. --- builder/vsphere/clone/config.hcl2spec.go | 2 + builder/vsphere/common/step_hardware.go | 4 ++ .../vsphere/common/step_hardware.hcl2spec.go | 24 ++++++----- builder/vsphere/driver/vm.go | 40 +++++++++++++++++++ builder/vsphere/iso/config.hcl2spec.go | 2 + .../common/HardwareConfig-not-required.mdx | 3 ++ 6 files changed, 64 insertions(+), 11 deletions(-) diff --git a/builder/vsphere/clone/config.hcl2spec.go b/builder/vsphere/clone/config.hcl2spec.go index 96bbac00f..380d9604f 100644 --- a/builder/vsphere/clone/config.hcl2spec.go +++ b/builder/vsphere/clone/config.hcl2spec.go @@ -43,6 +43,7 @@ type FlatConfig struct { RAMReserveAll *bool `mapstructure:"RAM_reserve_all" cty:"RAM_reserve_all"` MemoryHotAddEnabled *bool `mapstructure:"RAM_hot_plug" cty:"RAM_hot_plug"` VideoRAM *int64 `mapstructure:"video_ram" cty:"video_ram"` + VGPUProfile *string `mapstructure:"vgpu_profile" cty:"vgpu_profile"` NestedHV *bool `mapstructure:"NestedHV" cty:"NestedHV"` ConfigParams map[string]string `mapstructure:"configuration_parameters" cty:"configuration_parameters"` BootOrder *string `mapstructure:"boot_order" cty:"boot_order"` @@ -141,6 +142,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "RAM_reserve_all": &hcldec.AttrSpec{Name: "RAM_reserve_all", Type: cty.Bool, Required: false}, "RAM_hot_plug": &hcldec.AttrSpec{Name: "RAM_hot_plug", Type: cty.Bool, Required: false}, "video_ram": &hcldec.AttrSpec{Name: "video_ram", Type: cty.Number, Required: false}, + "vgpu_profile": &hcldec.AttrSpec{Name: "vgpu_profile", Type: cty.String, Required: false}, "NestedHV": &hcldec.AttrSpec{Name: "NestedHV", Type: cty.Bool, Required: false}, "configuration_parameters": &hcldec.BlockAttrsSpec{TypeName: "configuration_parameters", ElementType: cty.String, Required: false}, "boot_order": &hcldec.AttrSpec{Name: "boot_order", Type: cty.String, Required: false}, diff --git a/builder/vsphere/common/step_hardware.go b/builder/vsphere/common/step_hardware.go index e7025208a..453cc2d3e 100644 --- a/builder/vsphere/common/step_hardware.go +++ b/builder/vsphere/common/step_hardware.go @@ -34,6 +34,9 @@ type HardwareConfig struct { MemoryHotAddEnabled bool `mapstructure:"RAM_hot_plug"` // Amount of video memory in MB. VideoRAM int64 `mapstructure:"video_ram"` + // vGPU profile for accelerated graphics. See [NVIDIA GRID vGPU documentation](https://docs.nvidia.com/grid/latest/grid-vgpu-user-guide/index.html#configure-vmware-vsphere-vm-with-vgpu) + // for examples of profile names. Defaults to none. + VGPUProfile string `mapstructure:"vgpu_profile"` // Enable nested hardware virtualization for VM. Defaults to `false`. NestedHV bool `mapstructure:"NestedHV"` } @@ -71,6 +74,7 @@ func (s *StepConfigureHardware) Run(_ context.Context, state multistep.StateBag) CpuHotAddEnabled: s.Config.CpuHotAddEnabled, MemoryHotAddEnabled: s.Config.MemoryHotAddEnabled, VideoRAM: s.Config.VideoRAM, + VGPUProfile: s.Config.VGPUProfile, }) if err != nil { state.Put("error", err) diff --git a/builder/vsphere/common/step_hardware.hcl2spec.go b/builder/vsphere/common/step_hardware.hcl2spec.go index 9640dccc8..de683d220 100644 --- a/builder/vsphere/common/step_hardware.hcl2spec.go +++ b/builder/vsphere/common/step_hardware.hcl2spec.go @@ -9,17 +9,18 @@ import ( // FlatHardwareConfig is an auto-generated flat version of HardwareConfig. // Where the contents of a field with a `mapstructure:,squash` tag are bubbled up. type FlatHardwareConfig struct { - CPUs *int32 `mapstructure:"CPUs" cty:"CPUs"` - CpuCores *int32 `mapstructure:"cpu_cores" cty:"cpu_cores"` - CPUReservation *int64 `mapstructure:"CPU_reservation" cty:"CPU_reservation"` - CPULimit *int64 `mapstructure:"CPU_limit" cty:"CPU_limit"` - CpuHotAddEnabled *bool `mapstructure:"CPU_hot_plug" cty:"CPU_hot_plug"` - RAM *int64 `mapstructure:"RAM" cty:"RAM"` - RAMReservation *int64 `mapstructure:"RAM_reservation" cty:"RAM_reservation"` - RAMReserveAll *bool `mapstructure:"RAM_reserve_all" cty:"RAM_reserve_all"` - MemoryHotAddEnabled *bool `mapstructure:"RAM_hot_plug" cty:"RAM_hot_plug"` - VideoRAM *int64 `mapstructure:"video_ram" cty:"video_ram"` - NestedHV *bool `mapstructure:"NestedHV" cty:"NestedHV"` + CPUs *int32 `mapstructure:"CPUs" cty:"CPUs"` + CpuCores *int32 `mapstructure:"cpu_cores" cty:"cpu_cores"` + CPUReservation *int64 `mapstructure:"CPU_reservation" cty:"CPU_reservation"` + CPULimit *int64 `mapstructure:"CPU_limit" cty:"CPU_limit"` + CpuHotAddEnabled *bool `mapstructure:"CPU_hot_plug" cty:"CPU_hot_plug"` + RAM *int64 `mapstructure:"RAM" cty:"RAM"` + RAMReservation *int64 `mapstructure:"RAM_reservation" cty:"RAM_reservation"` + RAMReserveAll *bool `mapstructure:"RAM_reserve_all" cty:"RAM_reserve_all"` + MemoryHotAddEnabled *bool `mapstructure:"RAM_hot_plug" cty:"RAM_hot_plug"` + VideoRAM *int64 `mapstructure:"video_ram" cty:"video_ram"` + VGPUProfile *string `mapstructure:"vgpu_profile" cty:"vgpu_profile"` + NestedHV *bool `mapstructure:"NestedHV" cty:"NestedHV"` } // FlatMapstructure returns a new FlatHardwareConfig. @@ -44,6 +45,7 @@ func (*FlatHardwareConfig) HCL2Spec() map[string]hcldec.Spec { "RAM_reserve_all": &hcldec.AttrSpec{Name: "RAM_reserve_all", Type: cty.Bool, Required: false}, "RAM_hot_plug": &hcldec.AttrSpec{Name: "RAM_hot_plug", Type: cty.Bool, Required: false}, "video_ram": &hcldec.AttrSpec{Name: "video_ram", Type: cty.Number, Required: false}, + "vgpu_profile": &hcldec.AttrSpec{Name: "vgpu_profile", Type: cty.String, Required: false}, "NestedHV": &hcldec.AttrSpec{Name: "NestedHV", Type: cty.Bool, Required: false}, } return s diff --git a/builder/vsphere/driver/vm.go b/builder/vsphere/driver/vm.go index 2c1543932..e987bea0b 100644 --- a/builder/vsphere/driver/vm.go +++ b/builder/vsphere/driver/vm.go @@ -47,6 +47,7 @@ type HardwareConfig struct { CpuHotAddEnabled bool MemoryHotAddEnabled bool VideoRAM int64 + VGPUProfile string } type NIC struct { @@ -349,6 +350,31 @@ func (vm *VirtualMachine) Configure(config *HardwareConfig) error { } confSpec.DeviceChange = append(confSpec.DeviceChange, spec) } + if config.VGPUProfile != "" { + devices, err := vm.vm.Device(vm.driver.ctx) + if err != nil { + return err + } + + pciDevices := devices.SelectByType((*types.VirtualPCIPassthrough)(nil)) + vGPUDevices := pciDevices.SelectByBackingInfo((*types.VirtualPCIPassthroughVmiopBackingInfo)(nil)) + var operation types.VirtualDeviceConfigSpecOperation + if len(vGPUDevices) > 1 { + return err + } else if len(pciDevices) == 1 { + operation = types.VirtualDeviceConfigSpecOperationEdit + } else if len(pciDevices) == 0 { + operation = types.VirtualDeviceConfigSpecOperationAdd + } + + vGPUProfile := newVGPUProfile(config.VGPUProfile) + spec := &types.VirtualDeviceConfigSpec{ + Device: &vGPUProfile, + Operation: operation, + } + log.Printf("Adding vGPU device with profile '%s'", config.VGPUProfile) + confSpec.DeviceChange = append(confSpec.DeviceChange, spec) + } task, err := vm.vm.Reconfigure(vm.driver.ctx, confSpec) if err != nil { @@ -584,6 +610,20 @@ func addNetwork(d *Driver, devices object.VirtualDeviceList, config *CreateConfi return devices, nil } +func newVGPUProfile(vGPUProfile string) types.VirtualPCIPassthrough { + return types.VirtualPCIPassthrough{ + VirtualDevice: types.VirtualDevice{ + DeviceInfo: &types.Description{ + Summary: "", + Label: fmt.Sprintf("New vGPU %v PCI device", vGPUProfile), + }, + Backing: &types.VirtualPCIPassthroughVmiopBackingInfo{ + Vgpu: vGPUProfile, + }, + }, + } +} + func (vm *VirtualMachine) AddCdrom(controllerType string, isoPath string) error { devices, err := vm.vm.Device(vm.driver.ctx) if err != nil { diff --git a/builder/vsphere/iso/config.hcl2spec.go b/builder/vsphere/iso/config.hcl2spec.go index 4cf98deef..1c82af1cf 100644 --- a/builder/vsphere/iso/config.hcl2spec.go +++ b/builder/vsphere/iso/config.hcl2spec.go @@ -54,6 +54,7 @@ type FlatConfig struct { RAMReserveAll *bool `mapstructure:"RAM_reserve_all" cty:"RAM_reserve_all"` MemoryHotAddEnabled *bool `mapstructure:"RAM_hot_plug" cty:"RAM_hot_plug"` VideoRAM *int64 `mapstructure:"video_ram" cty:"video_ram"` + VGPUProfile *string `mapstructure:"vgpu_profile" cty:"vgpu_profile"` NestedHV *bool `mapstructure:"NestedHV" cty:"NestedHV"` ConfigParams map[string]string `mapstructure:"configuration_parameters" cty:"configuration_parameters"` ISOChecksum *string `mapstructure:"iso_checksum" required:"true" cty:"iso_checksum"` @@ -179,6 +180,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "RAM_reserve_all": &hcldec.AttrSpec{Name: "RAM_reserve_all", Type: cty.Bool, Required: false}, "RAM_hot_plug": &hcldec.AttrSpec{Name: "RAM_hot_plug", Type: cty.Bool, Required: false}, "video_ram": &hcldec.AttrSpec{Name: "video_ram", Type: cty.Number, Required: false}, + "vgpu_profile": &hcldec.AttrSpec{Name: "vgpu_profile", Type: cty.String, Required: false}, "NestedHV": &hcldec.AttrSpec{Name: "NestedHV", Type: cty.Bool, Required: false}, "configuration_parameters": &hcldec.BlockAttrsSpec{TypeName: "configuration_parameters", ElementType: cty.String, Required: false}, "iso_checksum": &hcldec.AttrSpec{Name: "iso_checksum", Type: cty.String, Required: false}, diff --git a/website/pages/partials/builder/vsphere/common/HardwareConfig-not-required.mdx b/website/pages/partials/builder/vsphere/common/HardwareConfig-not-required.mdx index 7990d5b06..3000d0c8d 100644 --- a/website/pages/partials/builder/vsphere/common/HardwareConfig-not-required.mdx +++ b/website/pages/partials/builder/vsphere/common/HardwareConfig-not-required.mdx @@ -21,5 +21,8 @@ - `video_ram` (int64) - Amount of video memory in MB. +- `vgpu_profile` (string) - vGPU profile for accelerated graphics. See [NVIDIA GRID vGPU documentation](https://docs.nvidia.com/grid/latest/grid-vgpu-user-guide/index.html#configure-vmware-vsphere-vm-with-vgpu) + for examples of profile names. Defaults to none. + - `NestedHV` (bool) - Enable nested hardware virtualization for VM. Defaults to `false`. \ No newline at end of file