Skip to content

Commit

Permalink
Merge pull request hashicorp#129 from mjrider/networkInterfaces
Browse files Browse the repository at this point in the history
Discovery network interfaces from pci devices instead from Guest information
  • Loading branch information
vancluever authored Aug 17, 2017
2 parents fe30565 + 6d23f58 commit a284473
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 20 deletions.
86 changes: 67 additions & 19 deletions vsphere/resource_vsphere_virtual_machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,11 @@ func resourceVSphereVirtualMachine() *schema.Resource {
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"key": &schema.Schema{
Type: schema.TypeInt,
Computed: true,
},

"label": &schema.Schema{
Type: schema.TypeString,
Required: true,
Expand Down Expand Up @@ -979,7 +984,7 @@ func resourceVSphereVirtualMachineRead(d *schema.ResourceData, meta interface{})

log.Printf("[DEBUG] Datacenter - %#v", dc)
log.Printf("[DEBUG] mvm.Summary.Config - %#v", mvm.Summary.Config)
log.Printf("[DEBUG] mvm.Summary.Config - %#v", mvm.Config)
log.Printf("[DEBUG] mvm.Config - %#v", mvm.Config)
log.Printf("[DEBUG] mvm.Guest.Net - %#v", mvm.Guest.Net)

err = d.Set("moid", mvm.Reference().Value)
Expand Down Expand Up @@ -1058,31 +1063,49 @@ func resourceVSphereVirtualMachineRead(d *schema.ResourceData, meta interface{})
}

networkInterfaces := make([]map[string]interface{}, 0)

deviceList := object.VirtualDeviceList(mvm.Config.Hardware.Device)
deviceList = deviceList.SelectByType((*types.VirtualEthernetCard)(nil))
log.Printf("[DEBUG] Device list %+v", deviceList)
for _, device := range deviceList {
networkInterface := make(map[string]interface{})
virtualDevice := device.GetVirtualDevice()
nic := device.(types.BaseVirtualEthernetCard)
DeviceName, _ := getNetworkName(client, vm, nic)
log.Printf("[DEBUG] device name %s", DeviceName)
networkInterface["label"] = DeviceName
networkInterface["mac_address"] = nic.GetVirtualEthernetCard().MacAddress
networkInterface["key"] = virtualDevice.Key
log.Printf("[DEBUG] networkInterface %#v", networkInterface)
networkInterfaces = append(networkInterfaces, networkInterface)
}
log.Printf("[DEBUG] networks: %#v", networkInterfaces)

for _, v := range mvm.Guest.Net {
if v.DeviceConfigId >= 0 {
log.Printf("[DEBUG] v.Network - %#v", v.Network)
networkInterface := make(map[string]interface{})
networkInterface["label"] = v.Network
networkInterface["mac_address"] = v.MacAddress
for _, ip := range v.IpConfig.IpAddress {
p := net.ParseIP(ip.IpAddress)
if p.To4() != nil {
log.Printf("[DEBUG] p.String - %#v", p.String())
log.Printf("[DEBUG] ip.PrefixLength - %#v", ip.PrefixLength)
networkInterface["ipv4_address"] = p.String()
networkInterface["ipv4_prefix_length"] = ip.PrefixLength
} else if p.To16() != nil {
log.Printf("[DEBUG] p.String - %#v", p.String())
log.Printf("[DEBUG] ip.PrefixLength - %#v", ip.PrefixLength)
networkInterface["ipv6_address"] = p.String()
networkInterface["ipv6_prefix_length"] = ip.PrefixLength
for _, networkInterface := range networkInterfaces {
if networkInterface["key"] == v.DeviceConfigId {
for _, ip := range v.IpConfig.IpAddress {
p := net.ParseIP(ip.IpAddress)
if p.To4() != nil {
log.Printf("[DEBUG] p.String - %#v", p.String())
log.Printf("[DEBUG] ip.PrefixLength - %#v", ip.PrefixLength)
networkInterface["ipv4_address"] = p.String()
networkInterface["ipv4_prefix_length"] = ip.PrefixLength
} else if p.To16() != nil {
log.Printf("[DEBUG] p.String - %#v", p.String())
log.Printf("[DEBUG] ip.PrefixLength - %#v", ip.PrefixLength)
networkInterface["ipv6_address"] = p.String()
networkInterface["ipv6_prefix_length"] = ip.PrefixLength
}
}
log.Printf("[DEBUG] networkInterface: %#v", networkInterface)
}
log.Printf("[DEBUG] networkInterface: %#v", networkInterface)
}
log.Printf("[DEBUG] networkInterface: %#v", networkInterface)
networkInterfaces = append(networkInterfaces, networkInterface)
}
}
log.Printf("[DEBUG] networks: %#v", networkInterfaces)
if mvm.Guest.IpStack != nil {
for _, v := range mvm.Guest.IpStack {
if v.IpRouteConfig != nil && v.IpRouteConfig.IpRoute != nil {
Expand Down Expand Up @@ -2164,3 +2187,28 @@ func (vm *virtualMachine) setupVirtualMachine(c *govmomi.Client) error {
}
return nil
}
func getNetworkName(c *govmomi.Client, vm *object.VirtualMachine, nic types.BaseVirtualEthernetCard) (string, error) {
backingInfo := nic.GetVirtualEthernetCard().Backing
var deviceName string
switch backingInfo.(type) {
case *types.VirtualEthernetCardNetworkBackingInfo:
deviceName = backingInfo.(*types.VirtualEthernetCardNetworkBackingInfo).DeviceName
break
case *types.VirtualEthernetCardDistributedVirtualPortBackingInfo:
portInfo := backingInfo.(*types.VirtualEthernetCardDistributedVirtualPortBackingInfo).Port
log.Printf("network Port %#v", portInfo)
o := object.NewDistributedVirtualPortgroup(c.Client, types.ManagedObjectReference{
Type: "DistributedVirtualPortgroup",
Value: portInfo.PortgroupKey,
})
var dvp mo.DistributedVirtualPortgroup
err := o.Properties(context.TODO(), o.Reference(), []string{"name", "config.distributedVirtualSwitch"}, &dvp)
if err != nil {
log.Printf("[ERROR]: Error retrieving portgroup %v", err)
return "", err
}
deviceName = dvp.Name
}
log.Printf("network Port DeviceName %#v", deviceName)
return deviceName, nil
}
77 changes: 76 additions & 1 deletion vsphere/resource_vsphere_virtual_machine_test.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
package vsphere

import (
"errors"
"fmt"
"log"
"os"
"regexp"
"testing"
"time"

"path/filepath"

"context"

"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/vmware/govmomi"
Expand All @@ -17,7 +21,6 @@ import (
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context"
)

///////
Expand Down Expand Up @@ -294,6 +297,39 @@ func TestAccVSphereVirtualMachine_basic(t *testing.T) {
})
}

func TestAccVSphereVirtualMachine_noPanicShutdown(t *testing.T) {
var vm virtualMachine
basic_vars := setupTemplateBasicBodyVars()
config := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_really_basic)

log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_really_basic)
log.Printf("[DEBUG] template config= %s", config)

resource.Test(t, resource.TestCase{
PreCheck: func() { testBasicPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckVSphereVirtualMachineDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: config,
Check: resource.ComposeTestCheckFunc(
TestFuncData{vm: vm, label: basic_vars.label}.testCheckFuncBasic(),
),
},
resource.TestStep{
PreConfig: func() {
if err := testPowerOffVM("terraform-test"); err != nil {
panic(err)
}
},
PlanOnly: true,
Config: config,
ExpectNonEmptyPlan: true,
},
},
})
}

const testAccCheckVSphereVirtualMachineConfig_debug = `
provider "vsphere" {
client_debug = true
Expand Down Expand Up @@ -1153,6 +1189,45 @@ func TestAccVSphereVirtualMachine_mac_address(t *testing.T) {
})
}

// testPowerOffVM does an immediate power-off of the virtual machine and is
// used to help set up a refresh scenario where a VM is powered off, which has
// been a source of panics.
func testPowerOffVM(name string) error {
client := testAccProvider.Meta().(*govmomi.Client)
finder := find.NewFinder(client.Client, true)

dc, err := getDatacenter(client, os.Getenv("VSPHERE_DATACENTER"))
if err != nil {
return fmt.Errorf("error fetching datacenter: %s", err)
}

finder.SetDatacenter(dc)
if err != nil {
return fmt.Errorf("error finding datacenter: %s", err)
}

vm, err := finder.VirtualMachine(context.TODO(), name)
if err != nil {
return err
}
if vm == nil {
return fmt.Errorf("VM not found: %s", name)
}
task, err := vm.PowerOff(context.TODO())
if err != nil {
return fmt.Errorf("error powering off VM: %s", err)
}
ctx, cancel := context.WithTimeout(context.Background(), time.Minute*5)
defer cancel()
if err := task.Wait(ctx); err != nil {
return fmt.Errorf("error waiting for poweroff: %s", err)
}
if ctx.Err() == context.Canceled {
return errors.New("timeout waiting for VM to shutdown")
}
return nil
}

func testAccCheckVSphereVirtualMachineDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*govmomi.Client)
finder := find.NewFinder(client.Client, true)
Expand Down

0 comments on commit a284473

Please sign in to comment.