Replaced a hacky type assertion in the VMware builder with a call to Driver.GetVmwareDriver() that returns the driver-specific structure for ip and addressing information. Also implemented the addressing functions for the ESXi driver interface.

This fixes an issue where a driver might not have defined a VmwareDriver by forcing a developer to implement it via the standard Driver interface.
This commit is contained in:
Ali Rizvi-Santiago 2017-04-13 17:39:55 -05:00
parent 898b27c16d
commit 75fbfa0763
9 changed files with 126 additions and 2 deletions

View File

@ -64,6 +64,7 @@ type Driver interface {
/// These methods are generally implemented by the VmwareDriver
/// structure within this file. A driver implementation can
/// reimplement these, though, if it wants.
GetVmwareDriver() VmwareDriver
// Get the guest hw address for the vm
GuestAddress(multistep.StateBag) (string, error)

View File

@ -173,3 +173,7 @@ const fusionSuppressPlist = `<?xml version="1.0" encoding="UTF-8"?>
<true/>
</dict>
</plist>`
func (d *Fusion5Driver) GetVmwareDriver() VmwareDriver {
return d.VmwareDriver
}

View File

@ -68,3 +68,7 @@ func (d *Fusion6Driver) Verify() error {
return compareVersions(matches[1], VMWARE_FUSION_VERSION, "Fusion Professional")
}
func (d *Fusion6Driver) GetVmwareDriver() VmwareDriver {
return d.Fusion5Driver.VmwareDriver
}

View File

@ -209,3 +209,7 @@ func (d *Player5Driver) ToolsIsoPath(flavor string) string {
func (d *Player5Driver) ToolsInstall() error {
return nil
}
func (d *Player5Driver) GetVmwareDriver() VmwareDriver {
return d.VmwareDriver
}

View File

@ -35,3 +35,7 @@ func (d *Player6Driver) Verify() error {
return playerVerifyVersion(VMWARE_PLAYER_VERSION)
}
func (d *Player6Driver) GetVmwareDriver() VmwareDriver {
return d.Player5Driver.VmwareDriver
}

View File

@ -33,3 +33,7 @@ func (d *Workstation10Driver) Verify() error {
return workstationVerifyVersion(VMWARE_WS_VERSION)
}
func (d *Workstation10Driver) GetVmwareDriver() VmwareDriver {
return d.Workstation9Driver.VmwareDriver
}

View File

@ -170,3 +170,7 @@ func (d *Workstation9Driver) ToolsIsoPath(flavor string) string {
func (d *Workstation9Driver) ToolsInstall() error {
return nil
}
func (d *Workstation9Driver) GetVmwareDriver() VmwareDriver {
return d.VmwareDriver
}

View File

@ -26,7 +26,7 @@ import (
// ESX5 driver talks to an ESXi5 hypervisor remotely over SSH to build
// virtual machines. This driver can only manage one machine at a time.
type ESX5Driver struct {
vmwcommon.VmwareDriver
base vmwcommon.VmwareDriver
Host string
Port uint
@ -173,6 +173,101 @@ func (d *ESX5Driver) HostIP(multistep.StateBag) (string, error) {
return host, err
}
func (d *ESX5Driver) GuestIP(multistep.StateBag) (string, error) {
// GuestIP is defined by the user as d.Host..but let's validate it just to be sure
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", d.Host, d.Port))
defer conn.Close()
if err != nil {
return "", err
}
host, _, err := net.SplitHostPort(conn.RemoteAddr().String())
return host, err
}
func (d *ESX5Driver) HostAddress(multistep.StateBag) (string, error) {
// make a connection
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", d.Host, d.Port))
defer conn.Close()
if err != nil {
return "", err
}
// get the local address (the host)
host, _, err := net.SplitHostPort(conn.LocalAddr().String())
if err != nil {
return "", fmt.Errorf("Unable to determine host address for ESXi: %v", err)
}
// iterate through all the interfaces..
interfaces, err := net.Interfaces()
if err != nil {
return "", fmt.Errorf("Unable to enumerate host interfaces : %v", err)
}
for _, intf := range interfaces {
addrs, err := intf.Addrs()
if err != nil {
continue
}
// ..checking to see if any if it's addrs match the host address
for _, addr := range addrs {
if addr.String() == host { // FIXME: Is this the proper way to compare two HardwareAddrs?
return intf.HardwareAddr.String(), nil
}
}
}
// ..unfortunately nothing was found
return "", fmt.Errorf("Unable to locate interface matching host address in ESXi: %v", host)
}
func (d *ESX5Driver) GuestAddress(multistep.StateBag) (string, error) {
// list all the interfaces on the esx host
r, err := d.esxcli("network", "ip", "interface", "list")
if err != nil {
return "", fmt.Errorf("Could not retrieve network interfaces for ESXi: %v", err)
}
// rip out the interface name and the MAC address from the csv output
addrs := make(map[string]string)
for record, err := r.read(); record != nil && err == nil; record, err = r.read() {
if strings.ToUpper(record["Enabled"]) != "TRUE" {
continue
}
addrs[record["Name"]] = record["MAC Address"]
}
// list all the addresses on the esx host
r, err = d.esxcli("network", "ip", "interface", "ipv4", "get")
if err != nil {
return "", fmt.Errorf("Could not retrieve network addresses for ESXi: %v", err)
}
// figure out the interface name that matches the specified d.Host address
var intf string
intf = ""
for record, err := r.read(); record != nil && err == nil; record, err = r.read() {
if record["IPv4 Address"] == d.Host && record["Name"] != "" {
intf = record["Name"]
break
}
}
if intf == "" {
return "", fmt.Errorf("Unable to find matching address for ESXi guest")
}
// find the MAC address according to the interface name
result, ok := addrs[intf]
if !ok {
return "", fmt.Errorf("Unable to find address for ESXi guest interface")
}
// ..and we're good
return result, nil
}
func (d *ESX5Driver) VNCAddress(_ string, portMin, portMax uint) (string, uint, error) {
var vncPort uint
@ -530,6 +625,10 @@ func (d *ESX5Driver) esxcli(args ...string) (*esxcliReader, error) {
return &esxcliReader{r, header}, nil
}
func (d *ESX5Driver) GetVmwareDriver() vmwcommon.VmwareDriver {
return d.base
}
type esxcliReader struct {
cr *csv.Reader
header []string

View File

@ -370,7 +370,7 @@ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multist
/// Check the network type that the user specified
network := config.Network
driver := state.Get("driver").(vmwcommon.VmwareDriver)
driver := state.Get("driver").(vmwcommon.Driver).GetVmwareDriver()
// read netmap config
pathNetmap := driver.NetmapConfPath()