Skip to content

Commit

Permalink
Merged the virtual machine configuration schema between the both the …
Browse files Browse the repository at this point in the history
…resource and datasource (#1157)

* Merged the virtual machine configuration schema used by the vsphere_virtual_machine resource into its data source, and modified the suppression functions in the data structure to use the ovf_deploy attribute conditionally.

* Added some more attributes to check to the tests for the "vsphere_virtual_machine" data source.

* Updated the docs for the "vsphere_virtual_machine" data source to add some of the newly added attributes.

* Fixed the way the schema is defined for the "vsphere_virtual_machine" data source.

* Cherry-pick didn't seem to include the additions to the virtual machine disk subresource file.
  • Loading branch information
arizvisa authored Aug 14, 2020
1 parent d96db7d commit 5e5ed21
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 90 deletions.
175 changes: 88 additions & 87 deletions vsphere/data_source_vsphere_virtual_machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,103 +5,99 @@ import (
"log"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-provider-vsphere/vsphere/internal/helper/structure"
"github.com/hashicorp/terraform-provider-vsphere/vsphere/internal/helper/virtualmachine"
"github.com/hashicorp/terraform-provider-vsphere/vsphere/internal/virtualdevice"
"github.com/vmware/govmomi/object"
)

func dataSourceVSphereVirtualMachine() *schema.Resource {
return &schema.Resource{
Read: dataSourceVSphereVirtualMachineRead,

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Description: "The name or path of the virtual machine.",
Required: true,
},
"datacenter_id": {
Type: schema.TypeString,
Description: "The managed object ID of the datacenter the virtual machine is in. This is not required when using ESXi directly, or if there is only one datacenter in your infrastructure.",
Optional: true,
},
"scsi_controller_scan_count": {
Type: schema.TypeInt,
Description: "The number of SCSI controllers to scan for disk sizes and controller types on.",
Optional: true,
Default: 1,
},
"sata_controller_scan_count": {
Type: schema.TypeInt,
Description: "The number of SATA controllers to scan for disk sizes and controller types on.",
Optional: true,
Default: 0,
},
"ide_controller_scan_count": {
Type: schema.TypeInt,
Description: "The number of IDE controllers to scan for disk sizes and controller types on.",
Optional: true,
Default: 2,
},
"guest_id": {
Type: schema.TypeString,
Description: "The guest ID of the virtual machine.",
Computed: true,
},
"firmware": {
Type: schema.TypeString,
Description: "The firmware type for this virtual machine.",
Computed: true,
},
"alternate_guest_name": {
Type: schema.TypeString,
Description: "The alternate guest name of the virtual machine when guest_id is a non-specific operating system, like otherGuest.",
Computed: true,
},
"scsi_type": {
Type: schema.TypeString,
Computed: true,
Description: "The common SCSI bus type of all controllers on the virtual machine.",
},
"scsi_bus_sharing": {
Type: schema.TypeString,
Computed: true,
Description: "Mode for sharing the SCSI bus.",
},
"disks": {
Type: schema.TypeList,
Description: "Select configuration attributes from the disks on this virtual machine, sorted by bus and unit number.",
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"size": {
Type: schema.TypeInt,
Computed: true,
},
"eagerly_scrub": {
Type: schema.TypeBool,
Computed: true,
},
"thin_provisioned": {
Type: schema.TypeBool,
Computed: true,
},
s := map[string]*schema.Schema{
"datacenter_id": {
Type: schema.TypeString,
Description: "The managed object ID of the datacenter the virtual machine is in. This is not required when using ESXi directly, or if there is only one datacenter in your infrastructure.",
Optional: true,
},
"scsi_controller_scan_count": {
Type: schema.TypeInt,
Description: "The number of SCSI controllers to scan for disk sizes and controller types on.",
Optional: true,
Default: 1,
},
"sata_controller_scan_count": {
Type: schema.TypeInt,
Description: "The number of SATA controllers to scan for disk sizes and controller types on.",
Optional: true,
Default: 0,
},
"ide_controller_scan_count": {
Type: schema.TypeInt,
Description: "The number of IDE controllers to scan for disk sizes and controller types on.",
Optional: true,
Default: 2,
},
"scsi_type": {
Type: schema.TypeString,
Computed: true,
Description: "The common SCSI bus type of all controllers on the virtual machine.",
},
"scsi_bus_sharing": {
Type: schema.TypeString,
Computed: true,
Description: "Mode for sharing the SCSI bus.",
},
"disks": {
Type: schema.TypeList,
Description: "Select configuration attributes from the disks on this virtual machine, sorted by bus and unit number.",
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"size": {
Type: schema.TypeInt,
Computed: true,
},
"eagerly_scrub": {
Type: schema.TypeBool,
Computed: true,
},
"thin_provisioned": {
Type: schema.TypeBool,
Computed: true,
},
"label": {
Type: schema.TypeString,
Computed: true,
},
"unit_number": {
Type: schema.TypeInt,
Computed: true,
},
},
},
"network_interface_types": {
Type: schema.TypeList,
Description: "The types of network interfaces found on the virtual machine, sorted by unit number.",
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"guest_ip_addresses": {
Type: schema.TypeList,
Description: "The current list of IP addresses on this virtual machine.",
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
"network_interface_types": {
Type: schema.TypeList,
Description: "The types of network interfaces found on the virtual machine, sorted by unit number.",
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"guest_ip_addresses": {
Type: schema.TypeList,
Description: "The current list of IP addresses on this virtual machine.",
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
}

// Merge the VirtualMachineConfig structure so that we can include the number of
// include the number of cpus, memory, firmware, disks, etc.
structure.MergeSchema(s, schemaVirtualMachineConfigSpec())

// Now that the schema has been composed and merged, we can attach our reader and
// return the resource back to our host process.
return &schema.Resource{
Read: dataSourceVSphereVirtualMachineRead,
Schema: s,
}
}

Expand Down Expand Up @@ -136,6 +132,11 @@ func dataSourceVSphereVirtualMachineRead(d *schema.ResourceData, meta interface{
return fmt.Errorf("virtual machine %q does not have a UUID", vm.InventoryPath)
}

// Read general VM config info
if err := flattenVirtualMachineConfigInfo(d, props.Config); err != nil {
return fmt.Errorf("error reading virtual machine configuration: %s", err)
}

d.SetId(props.Config.Uuid)
d.Set("guest_id", props.Config.GuestId)
d.Set("alternate_guest_name", props.Config.AlternateGuestName)
Expand Down
14 changes: 14 additions & 0 deletions vsphere/data_source_vsphere_virtual_machine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,17 @@ func TestAccDataSourceVSphereVirtualMachine_basic(t *testing.T) {
regexp.MustCompile("^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$")),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "guest_id"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "scsi_type"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "memory"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "num_cpus"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "num_cores_per_socket"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "firmware"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "hardware_version"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "disks.#"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "disks.0.size"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "disks.0.eagerly_scrub"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "disks.0.thin_provisioned"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "disks.0.unit_number"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "disks.0.label"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "network_interface_types.#"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "firmware"),
),
Expand All @@ -55,10 +62,17 @@ func TestAccDataSourceVSphereVirtualMachine_noDatacenterAndAbsolutePath(t *testi
regexp.MustCompile("^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$")),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "guest_id"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "scsi_type"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "memory"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "num_cpus"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "num_cores_per_socket"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "firmware"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "hardware_version"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "disks.#"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "disks.0.size"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "disks.0.eagerly_scrub"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "disks.0.thin_provisioned"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "disks.0.unit_number"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "disks.0.label"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "network_interface_types.#"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "firmware"),
),
Expand Down
16 changes: 16 additions & 0 deletions vsphere/internal/virtualdevice/virtual_machine_disk_subresource.go
Original file line number Diff line number Diff line change
Expand Up @@ -1186,9 +1186,17 @@ func ReadDiskAttrsForDataSource(l object.VirtualDeviceList, d *schema.ResourceDa
if backing.ThinProvisioned != nil {
thin = *backing.ThinProvisioned
}
if di, ok := disk.DeviceInfo.(*types.Description); ok {
m["label"] = di.Label
} else {
m["label"] = fmt.Sprintf("Disk %d", i)
}

m["size"] = diskCapacityInGiB(disk)
m["eagerly_scrub"] = eager
m["thin_provisioned"] = thin
m["unit_number"] = disk.UnitNumber

out = append(out, m)
}
log.Printf("[DEBUG] ReadDiskAttrsForDataSource: Attributes returned: %+v", out)
Expand Down Expand Up @@ -1486,6 +1494,12 @@ func (r *DiskSubresource) DiffExisting() error {

// Ensure that there is no change in either eagerly_scrub or thin_provisioned
// - these values cannot be changed once set.
if _, err = r.GetWithVeto("label"); err != nil {
return fmt.Errorf("virtual disk %q: %s", name, err)
}
if _, err = r.GetWithVeto("unit_number"); err != nil {
return fmt.Errorf("virtual disk %q: %s", name, err)
}
if _, err = r.GetWithVeto("eagerly_scrub"); err != nil {
return fmt.Errorf("virtual disk %q: %s", name, err)
}
Expand Down Expand Up @@ -1548,6 +1562,8 @@ func (r *DiskSubresource) DiffGeneral() error {
switch {
case r.Get("datastore_id").(string) == "":
return fmt.Errorf("datastore_id for disk %q is required when attach is set", name)
case r.Get("label").(int) > 0:
return fmt.Errorf("label for disk %q cannot be defined when attach is set", name)
case r.Get("size").(int) > 0:
return fmt.Errorf("size for disk %q cannot be defined when attach is set", name)
case r.Get("eagerly_scrub").(bool):
Expand Down
24 changes: 21 additions & 3 deletions vsphere/virtual_machine_config_structure.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,15 @@ func schemaVirtualMachineConfigSpec() map[string]*schema.Schema {
Default: 1024,
Description: "The size of the virtual machine's memory, in MB.",
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
if len(d.Get("ovf_deploy").([]interface{})) > 0 {
ovf, ok := d.GetOk("ovf_deploy")
if !ok {
return false
}

if items, ok := ovf.([]interface{}); ok && len(items) > 0 {
return true
}

return false
},
},
Expand All @@ -243,9 +249,15 @@ func schemaVirtualMachineConfigSpec() map[string]*schema.Schema {
Optional: true,
Description: "User-provided description of the virtual machine.",
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
if len(d.Get("ovf_deploy").([]interface{})) > 0 && new == "" {
ovf, ok := d.GetOk("ovf_deploy")
if !ok {
return false
}

if items, ok := ovf.([]interface{}); ok && len(items) > 0 && new == "" {
return true
}

return false
},
},
Expand All @@ -255,9 +267,15 @@ func schemaVirtualMachineConfigSpec() map[string]*schema.Schema {
Computed: true,
Description: "The guest ID for the operating system.",
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
if len(d.Get("ovf_deploy").([]interface{})) > 0 {
ovf, ok := d.GetOk("ovf_deploy")
if !ok {
return false
}

if items, ok := ovf.([]interface{}); ok && len(items) > 0 && new == "" {
return true
}

return false
},
},
Expand Down
10 changes: 10 additions & 0 deletions website/docs/d/virtual_machine.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,14 @@ The following attributes are exported:
* `guest_id` - The guest ID of the virtual machine or template.
* `alternate_guest_name` - The alternate guest name of the virtual machine when
guest_id is a non-specific operating system, like `otherGuest`.
* `annotation` - The user-provided description of this virtual machine.
* `memory` - The size of the virtual machine's memory, in MB.
* `num_cpus` - The total number of virtual processor cores assigned to this
virtual machine.
* `num_cores_per_socket` - The number of cores per socket for this virtual machine.
* `firmware` - The firmware interface that is used by this virtual machine. Can be
either `bios` or `EFI`.
* `hardware_version` - The hardware version number on this virtual machine.
* `scsi_type` - The common type of all SCSI controllers on this virtual machine.
Will be one of `lsilogic` (LSI Logic Parallel), `lsilogic-sas` (LSI Logic
SAS), `pvscsi` (VMware Paravirtual), `buslogic` (BusLogic), or `mixed` when
Expand All @@ -79,9 +87,11 @@ The following attributes are exported:
source must be the same on the destination virtual machine as the source.
Only the first number of controllers defined by `scsi_controller_scan_count`
are scanned for disks. The sub-attributes are:
* `label` - The label for the disk.
* `size` - The size of the disk, in GIB.
* `eagerly_scrub` - Set to `true` if the disk has been eager zeroed.
* `thin_provisioned` - Set to `true` if the disk has been thin provisioned.
* `unit_number` - The disk number on the storage bus.
* `network_interface_types` - The network interface types for each network
interface found on the virtual machine, in device bus order. Will be one of
`e1000`, `e1000e`, `pcnet32`, `sriov`, `vmxnet2`, or `vmxnet3`.
Expand Down

0 comments on commit 5e5ed21

Please sign in to comment.