diff --git a/vsphere/data_source_vsphere_host_vgpu_profile.go b/vsphere/data_source_vsphere_host_vgpu_profile.go new file mode 100644 index 000000000..8cc20e80b --- /dev/null +++ b/vsphere/data_source_vsphere_host_vgpu_profile.go @@ -0,0 +1,164 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package vsphere + +import ( + "crypto/sha256" + "fmt" + "log" + "regexp" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-vsphere/vsphere/internal/helper/hostsystem" + "github.com/vmware/govmomi/vim25/types" +) + +func dataSourceVSphereHostVGpuProfile() *schema.Resource { + return &schema.Resource{ + Read: dataSourceVSphereHostVGpuProfileRead, + Schema: map[string]*schema.Schema{ + "host_id": { + Type: schema.TypeString, + Required: true, + Description: "The Managed Object ID of the host system.", + }, + "name_regex": { + Type: schema.TypeString, + Optional: true, + Description: "A regular expression used to match the vGPU Profile on the host.", + }, + "vgpu_profiles": { + Type: schema.TypeList, + Description: "List of vGPU profiles available via the host.", + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "vgpu": { + Type: schema.TypeString, + Computed: true, + Description: "Name of a particular VGPU available as a shared GPU device (vGPU profile).", + }, + "disk_snapshot_supported": { + Type: schema.TypeBool, + Computed: true, + Description: "Indicates whether the GPU plugin on this host is capable of disk-only snapshots when VM is not powered off.", + }, + "memory_snapshot_supported": { + Type: schema.TypeBool, + Computed: true, + Description: "Indicates whether the GPU plugin on this host is capable of memory snapshots.", + }, + "suspend_supported": { + Type: schema.TypeBool, + Computed: true, + Description: "Indicates whether the GPU plugin on this host is capable of suspend-resume.", + }, + "migrate_supported": { + Type: schema.TypeBool, + Computed: true, + Description: "Indicates whether the GPU plugin on this host is capable of migration.", + }, + }, + }, + }, + }, + } +} + +func dataSourceVSphereHostVGpuProfileRead(d *schema.ResourceData, meta interface{}) error { + log.Printf("[DEBUG] DataHostVGpuProfile: Beginning vGPU Profile lookup on %s", d.Get("host_id").(string)) + + client := meta.(*Client).vimClient + + host, err := hostsystem.FromID(client, d.Get("host_id").(string)) + if err != nil { + return err + } + + hprops, err := hostsystem.Properties(host) + if err != nil { + return err + } + + // Create unique ID based on the host_id + idsum := sha256.New() + if _, err := idsum.Write([]byte(fmt.Sprintf("%#v", d.Get("host_id").(string)))); err != nil { + return err + } + + d.SetId(fmt.Sprintf("%x", idsum.Sum(nil))) + + log.Printf("[DEBUG] DataHostVGpuProfile: Looking for available vGPU profiles") + + // Retrieve the SharedGpuCapabilities from host properties + vgpusRaw := hprops.Config.SharedGpuCapabilities + + // If searching for a specific vGPU profile (by name) + name, ok := d.GetOk("name_regex") + if (ok) && (name.(string) != "") { + return searchVGpuProfileByName(d, vgpusRaw, name.(string)) + } + + // Loop over all vGPU profiles on host + vgpus := make([]interface{}, len(vgpusRaw)) + for i, v := range vgpusRaw { + log.Printf("[DEBUG] DataHostVGpuProfile: Host %s has vGPU profile %s", d.Get("host_id").(string), v.Vgpu) + vgpu := map[string]interface{}{ + "vgpu": v.Vgpu, + "disk_snapshot_supported": v.DiskSnapshotSupported, + "memory_snapshot_supported": v.MemorySnapshotSupported, + "suspend_supported": v.SuspendSupported, + "migrate_supported": v.MigrateSupported, + } + vgpus[i] = vgpu + } + + // Set the `vgpu_profile` output to all vGPU profiles + if err := d.Set("vgpu_profiles", vgpus); err != nil { + return err + } + + log.Printf("[DEBUG] DataHostVGpuProfile: Identified %d vGPU profiles available on %s", len(vgpus), d.Get("host_id").(string)) + + return nil +} + +func searchVGpuProfileByName(d *schema.ResourceData, vgpusRaw []types.HostSharedGpuCapabilities, name string) error { + log.Printf("[DEBUG] DataHostVGpuProfile: Selecting devices which match name regex") + + vgpus := make([]interface{}, 0, len(vgpusRaw)) + + re, err := regexp.Compile(name) + if err != nil { + return err + } + + // Loop over all vGPU profile and attempt to match by name + for _, v := range vgpusRaw { + if re.Match([]byte(v.Vgpu)) { + // Identified matching vGPU profile + log.Printf("[DEBUG] DataHostVGpuProfile: Host %s has vGPU profile %s", d.Get("host_id").(string), v.Vgpu) + vgpu := map[string]interface{}{ + "vgpu": v.Vgpu, + "disk_snapshot_supported": v.DiskSnapshotSupported, + "memory_snapshot_supported": v.MemorySnapshotSupported, + "suspend_supported": v.SuspendSupported, + "migrate_supported": v.MigrateSupported, + } + vgpus = append(vgpus, vgpu) + } + } + + if len(vgpus) == 0 { + log.Printf("[DEBUG] DataHostVGpuProfile: Host %s does not support vGPU profile name regex [%s]", d.Get("host_id").(string), name) + } + + // Set the `vgpu_profile` output to located vGPU. + // If a matching vGPU profile is not found, return null + if err := d.Set("vgpu_profiles", vgpus); err != nil { + return err + } + + return nil +} diff --git a/vsphere/provider.go b/vsphere/provider.go index 06a47d610..246051b6f 100644 --- a/vsphere/provider.go +++ b/vsphere/provider.go @@ -159,6 +159,7 @@ func Provider() *schema.Provider { "vsphere_host": dataSourceVSphereHost(), "vsphere_host_pci_device": dataSourceVSphereHostPciDevice(), "vsphere_host_thumbprint": dataSourceVSphereHostThumbprint(), + "vsphere_host_vgpu_profile": dataSourceVSphereHostVGpuProfile(), "vsphere_license": dataSourceVSphereLicense(), "vsphere_network": dataSourceVSphereNetwork(), "vsphere_ovf_vm_template": dataSourceVSphereOvfVMTemplate(), diff --git a/website/docs/d/host_vgpu_profile.html.markdown b/website/docs/d/host_vgpu_profile.html.markdown new file mode 100644 index 000000000..c0502a82a --- /dev/null +++ b/website/docs/d/host_vgpu_profile.html.markdown @@ -0,0 +1,79 @@ +--- +subcategory: "Host and Cluster Management" +layout: "vsphere" +page_title: "VMware vSphere: vsphere_host_vgpu_profile" +sidebar_current: "docs-vsphere-data-source-host_vgpu_profile" +description: |- + A data source that can be used to get information for + one or all vGPU profiles available on an ESXi host. +--- + +# vsphere_host_vgpu_profile + +The `vsphere_host_vgpu_profile` data source can be used to discover the +available vGPU profiles of a vSphere host. + +## Example Usage to return all vGPU profiles + +```hcl +data "vsphere_datacenter" "datacenter" { + name = "dc-01" +} + +data "vsphere_host" "host" { + name = "esxi-01.example.com" + datacenter_id = data.vsphere_datacenter.datacenter.id +} + +data "vsphere_host_vgpu_profile" "vgpu_profile" { + host_id = data.vsphere_host.host.id +} +``` + +## Example Usage with vGPU profile name_regex + +```hcl +data "vsphere_datacenter" "datacenter" { + name = "dc-01" +} + +data "vsphere_host" "host" { + name = "esxi-01.example.com" + datacenter_id = data.vsphere_datacenter.datacenter.id +} + +data "vsphere_host_vgpu_profile" "vgpu_profile" { + host_id = data.vsphere_host.host.id + name_regex = "a100" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `host_id` - (Required) The [managed object reference ID][docs-about-morefs] of a host. +* `name_regex` - (Optional) A regular expression that will be used to match the + host vGPU profile name. + +[docs-about-morefs]: /docs/providers/vsphere/index.html#use-of-managed-object-references-by-the-vsphere-provider + +## Attribute Reference + +The following attributes are exported: + +* `host_id` - The [managed objectID][docs-about-morefs] of the ESXi host. +* `id` - Unique (SHA256) id based on the host_id if the ESXi host. +* `name_regex` - (Optional) A regular expression that will be used to match the + host vGPU profile name. +* `vgpu_profiles` - The list of available vGPU profiles on the ESXi host. + This may be and empty array if no vGPU profile are identified. + * `vgpu` - Name of a particular vGPU available as a shared GPU device (vGPU profile). + * `disk_snapshot_supported` - Indicates whether the GPU plugin on this host is + capable of disk-only snapshots when VM is not powered off. + * `memory_snapshot_supported` - Indicates whether the GPU plugin on this host is + capable of memory snapshots. + * `migrate_supported` - Indicates whether the GPU plugin on this host is capable + of migration. + * `suspend_supported` - Indicates whether the GPU plugin on this host is capable + of suspend-resume.