From bc92afcd337b74909b34a03ebb74f197d20d5b25 Mon Sep 17 00:00:00 2001 From: mristok Date: Fri, 27 Oct 2023 16:01:17 -0500 Subject: [PATCH] fix(vgpu): convert name to name_regex, add doc --- .../data_source_vsphere_host_vgpu_profile.go | 320 +++++++++--------- .../docs/d/host_vgpu_profile.html.markdown | 79 +++++ 2 files changed, 243 insertions(+), 156 deletions(-) create mode 100644 website/docs/d/host_vgpu_profile.html.markdown diff --git a/vsphere/data_source_vsphere_host_vgpu_profile.go b/vsphere/data_source_vsphere_host_vgpu_profile.go index 35161749c..8cc20e80b 100644 --- a/vsphere/data_source_vsphere_host_vgpu_profile.go +++ b/vsphere/data_source_vsphere_host_vgpu_profile.go @@ -1,156 +1,164 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package vsphere - -import ( - "crypto/sha256" - "fmt" - "log" - - "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": { - Type: schema.TypeString, - Optional: true, - Description: "The name of the vGPU Profile to search for on host.", - }, - "vgpu_profiles": { - Type: schema.TypeList, - Description: "List of vGPU profiles available via 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") - 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] 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 { - vgpus := make([]interface{}, 1) - - // Loop over all vGPU profile and attempt to match by name - for _, v := range vgpusRaw { - if v.Vgpu == name { - // Identified matching vGPU profile - log.Printf("[DEBUG] 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] Host %s does not support vGPU profile %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 -} +// 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/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.