Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added network_interfaces property to virtual machine data source #1274

Merged
merged 4 commits into from
May 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions vsphere/data_source_vsphere_virtual_machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import (
"log"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"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"
"github.com/vmware/govmomi/vim25/types"
)

func dataSourceVSphereVirtualMachine() *schema.Resource {
Expand Down Expand Up @@ -81,6 +83,55 @@ func dataSourceVSphereVirtualMachine() *schema.Resource {
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"network_interfaces": {
Type: schema.TypeList,
Description: "The types of network interfaces found on the virtual machine, sorted by unit number.",
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"adapter_type": {
Type: schema.TypeString,
Computed: true,
},
"bandwidth_limit": {
Type: schema.TypeInt,
Optional: true,
Default: -1,
Description: "The upper bandwidth limit of this network interface, in Mbits/sec.",
ValidateFunc: validation.IntAtLeast(-1),
},
"bandwidth_reservation": {
Type: schema.TypeInt,
Optional: true,
Default: 0,
Description: "The bandwidth reservation of this network interface, in Mbits/sec.",
ValidateFunc: validation.IntAtLeast(0),
},
"bandwidth_share_level": {
Type: schema.TypeString,
Optional: true,
Default: string(types.SharesLevelNormal),
Description: "The bandwidth share allocation level for this interface. Can be one of low, normal, high, or custom.",
ValidateFunc: validation.StringInSlice(sharesLevelAllowedValues, false),
},
"bandwidth_share_count": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "The share count for this network interface when the share level is custom.",
ValidateFunc: validation.IntAtLeast(0),
},
"mac_address": {
Type: schema.TypeString,
Computed: true,
},
"network_id": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"guest_ip_addresses": {
Type: schema.TypeList,
Description: "The current list of IP addresses on this virtual machine.",
Expand Down Expand Up @@ -151,12 +202,19 @@ func dataSourceVSphereVirtualMachineRead(d *schema.ResourceData, meta interface{
if err != nil {
return fmt.Errorf("error reading network interface types: %s", err)
}
networkInterfaces, err := virtualdevice.ReadNetworkInterfaces(object.VirtualDeviceList(props.Config.Hardware.Device))
if err != nil {
return fmt.Errorf("error reading network interfaces: %s", err)
}
if err := d.Set("disks", disks); err != nil {
return fmt.Errorf("error setting disk sizes: %s", err)
}
if err := d.Set("network_interface_types", nics); err != nil {
return fmt.Errorf("error setting network interface types: %s", err)
}
if err := d.Set("network_interfaces", networkInterfaces); err != nil {
return fmt.Errorf("error setting network interfaces: %s", err)
}
if props.Guest != nil {
if err := buildAndSelectGuestIPs(d, *props.Guest); err != nil {
return fmt.Errorf("error setting guest IP addresses: %s", err)
Expand Down
16 changes: 16 additions & 0 deletions vsphere/data_source_vsphere_virtual_machine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ func TestAccDataSourceVSphereVirtualMachine_basic(t *testing.T) {
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", "network_interfaces.#"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "network_interfaces.0.adapter_type"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "network_interfaces.0.bandwidth_limit"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "network_interfaces.0.bandwidth_reservation"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "network_interfaces.0.bandwidth_share_level"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "network_interfaces.0.bandwidth_share_count"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "network_interfaces.0.mac_address"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "network_interfaces.0.network_id"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "firmware"),
),
},
Expand Down Expand Up @@ -78,6 +86,14 @@ func TestAccDataSourceVSphereVirtualMachine_noDatacenterAndAbsolutePath(t *testi
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", "network_interfaces.#"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "network_interfaces.0.adapter_type"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "network_interfaces.0.bandwidth_limit"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "network_interfaces.0.bandwidth_reservation"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "network_interfaces.0.bandwidth_share_level"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "network_interfaces.0.bandwidth_share_count"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "network_interfaces.0.mac_address"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "network_interfaces.0.network_id"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.template", "firmware"),
),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,64 @@ func ReadNetworkInterfaceTypes(l object.VirtualDeviceList) ([]string, error) {
return out, nil
}

// ReadNetworkInterfaces returns a list of network interfaces. This is used
// in the VM data source to discover the properties of the network interfaces on the
// virtual machine. The list is sorted by the order that they would be added in
// if a clone were to be done.
func ReadNetworkInterfaces(l object.VirtualDeviceList) ([]map[string]interface{}, error) {
log.Printf("[DEBUG] ReadNetworkInterfaces: Fetching network interfaces")
devices := l.Select(func(device types.BaseVirtualDevice) bool {
if _, ok := device.(types.BaseVirtualEthernetCard); ok {
return true
}
return false
})
log.Printf("[DEBUG] ReadNetworkInterface: Network devices located: %s", DeviceListString(devices))
// Sort the device list, in case it's not sorted already.
devSort := virtualDeviceListSorter{
Sort: devices,
DeviceList: l,
}
sort.Sort(devSort)
devices = devSort.Sort
log.Printf("[DEBUG] ReadNetworkInterfaceTypes: Network devices order after sort: %s", DeviceListString(devices))
var out []map[string]interface{}
for _, device := range devices {
m := make(map[string]interface{})

ethernetCard := device.(types.BaseVirtualEthernetCard).GetVirtualEthernetCard()

// Determine the network from the backing object
var networkID string

switch backing := ethernetCard.Backing.(type) {
case *types.VirtualEthernetCardNetworkBackingInfo:
if backing.Network != nil {
networkID = backing.Network.Value
}
case *types.VirtualEthernetCardOpaqueNetworkBackingInfo:
networkID = backing.OpaqueNetworkId
case *types.VirtualEthernetCardDistributedVirtualPortBackingInfo:
networkID = backing.Port.PortgroupKey
default:
}

// Set properties

m["adapter_type"] = virtualEthernetCardString(device.(types.BaseVirtualEthernetCard))
m["bandwidth_limit"] = ethernetCard.ResourceAllocation.Limit
m["bandwidth_reservation"] = ethernetCard.ResourceAllocation.Reservation
m["bandwidth_share_level"] = ethernetCard.ResourceAllocation.Share.Level
m["bandwidth_share_count"] = ethernetCard.ResourceAllocation.Share.Shares
m["mac_address"] = ethernetCard.MacAddress
m["network_id"] = networkID

out = append(out, m)
}
log.Printf("[DEBUG] ReadNetworkInterfaces: Network interfaces returned: %+v", out)
return out, nil
}

// baseVirtualEthernetCardToBaseVirtualDevice converts a
// BaseVirtualEthernetCard value into a BaseVirtualDevice.
func baseVirtualEthernetCardToBaseVirtualDevice(v types.BaseVirtualEthernetCard) types.BaseVirtualDevice {
Expand Down
21 changes: 21 additions & 0 deletions website/docs/d/virtual_machine.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,27 @@ The following attributes are exported:
* `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`.
* `network_interfaces` - Information about each of the network interfaces on this
virtual machine or template. These are sorted by device bus order so that they
can be applied to a `vsphere_virtual_machine` resource in the order the resource
expects while cloning. This is useful for discovering certain network interface
settings while performing a linked clone, as all settings that are output by this
data source must be the same on the destination virtual machine as the source.
The sub-attributes are:
* `adapter_type` - The network interface types for each network interface found
on the virtual machine, in device bus order. Will be one of `e1000`, `e1000e` or
`vmxnet3`.
* `bandwidth_limit` - The upper bandwidth limit of this network interface,
in Mbits/sec.
* `bandwidth_reservation` - The bandwidth reservation of this network interface,
in Mbits/sec.
* `bandwidth_share_level` - The bandwidth share allocation level for this interface.
Can be one of `low`, `normal`, `high`, or `custom`.
* `bandwidth_share_count` - The share count for this network interface when the
share level is custom.
* `mac_address` - The MAC address of this network interface.
* `network_id` - The managed object reference ID of the network this interface is
connected to.
* `firmware` - The firmware type for this virtual machine. Can be `bios` or `efi`.
* `guest_ip_addresses` - A list of IP addresses as reported by VMWare tools.

Expand Down