Commit d424ed1e authored by Rickard von Essen's avatar Rickard von Essen

builder/parallels: Use most recent DHCP lease when determening IP.

Fixes #1746. Problem establishing SSH connection with Fedora 21 and
Parallels
parent ef9cceca
...@@ -55,6 +55,7 @@ func NewDriver() (Driver, error) { ...@@ -55,6 +55,7 @@ func NewDriver() (Driver, error) {
var drivers map[string]Driver var drivers map[string]Driver
var prlctlPath string var prlctlPath string
var supportedVersions []string var supportedVersions []string
dhcp_lease_file := "/Library/Preferences/Parallels/parallels_dhcp_leases"
if runtime.GOOS != "darwin" { if runtime.GOOS != "darwin" {
return nil, fmt.Errorf( return nil, fmt.Errorf(
...@@ -75,10 +76,12 @@ func NewDriver() (Driver, error) { ...@@ -75,10 +76,12 @@ func NewDriver() (Driver, error) {
"10": &Parallels10Driver{ "10": &Parallels10Driver{
Parallels9Driver: Parallels9Driver{ Parallels9Driver: Parallels9Driver{
PrlctlPath: prlctlPath, PrlctlPath: prlctlPath,
dhcp_lease_file: dhcp_lease_file,
}, },
}, },
"9": &Parallels9Driver{ "9": &Parallels9Driver{
PrlctlPath: prlctlPath, PrlctlPath: prlctlPath,
dhcp_lease_file: dhcp_lease_file,
}, },
} }
......
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"regexp" "regexp"
"strconv"
"strings" "strings"
"time" "time"
...@@ -18,6 +19,8 @@ import ( ...@@ -18,6 +19,8 @@ import (
type Parallels9Driver struct { type Parallels9Driver struct {
// This is the path to the "prlctl" application. // This is the path to the "prlctl" application.
PrlctlPath string PrlctlPath string
// The path to the parallels_dhcp_leases file
dhcp_lease_file string
} }
func (d *Parallels9Driver) Import(name, srcPath, dstDir string, reassignMac bool) error { func (d *Parallels9Driver) Import(name, srcPath, dstDir string, reassignMac bool) error {
...@@ -276,31 +279,43 @@ func (d *Parallels9Driver) Mac(vmName string) (string, error) { ...@@ -276,31 +279,43 @@ func (d *Parallels9Driver) Mac(vmName string) (string, error) {
} }
// Finds the IP address of a VM connected that uses DHCP by its MAC address // Finds the IP address of a VM connected that uses DHCP by its MAC address
//
// Parses the file /Library/Preferences/Parallels/parallels_dhcp_leases
// file contain a list of DHCP leases given by Parallels Desktop
// Example line:
// 10.211.55.181="1418921112,1800,001c42f593fb,ff42f593fb000100011c25b9ff001c42f593fb"
// IP Address ="Lease expiry, Lease time, MAC, MAC or DUID"
func (d *Parallels9Driver) IpAddress(mac string) (string, error) { func (d *Parallels9Driver) IpAddress(mac string) (string, error) {
var stdout bytes.Buffer
dhcp_lease_file := "/Library/Preferences/Parallels/parallels_dhcp_leases"
if len(mac) != 12 { if len(mac) != 12 {
return "", fmt.Errorf("Not a valid MAC address: %s. It should be exactly 12 digits.", mac) return "", fmt.Errorf("Not a valid MAC address: %s. It should be exactly 12 digits.", mac)
} }
cmd := exec.Command("grep", "-i", mac, dhcp_lease_file) leases, err := ioutil.ReadFile(d.dhcp_lease_file)
cmd.Stdout = &stdout if err != nil {
if err := cmd.Run(); err != nil {
return "", err return "", err
} }
stdoutString := strings.TrimSpace(stdout.String()) re := regexp.MustCompile("(.*)=\"(.*),(.*)," + strings.ToLower(mac) + ",.*\"")
re := regexp.MustCompile("(.*)=.*") mostRecentIp := ""
ipMatch := re.FindAllStringSubmatch(stdoutString, 1) mostRecentLease := uint64(0)
for _, l := range re.FindAllStringSubmatch(string(leases), -1) {
ip := l[1]
expiry, _ := strconv.ParseUint(l[2], 10, 64)
leaseTime, _ := strconv.ParseUint(l[3], 10, 32)
log.Printf("Found lease: %s for MAC: %s, expiring at %d, leased for %d s.\n", ip, mac, expiry, leaseTime)
if mostRecentLease <= expiry-leaseTime {
mostRecentIp = ip
mostRecentLease = expiry - leaseTime
}
}
if len(ipMatch) != 1 { if len(mostRecentIp) == 0 {
return "", fmt.Errorf("IP lease not found for MAC address %s in: %s\n", mac, dhcp_lease_file) return "", fmt.Errorf("IP lease not found for MAC address %s in: %s\n", mac, d.dhcp_lease_file)
} }
ip := ipMatch[0][1] log.Printf("Found IP lease: %s for MAC address %s\n", mostRecentIp, mac)
log.Printf("Found IP lease: %s for MAC address %s\n", ip, mac) return mostRecentIp, nil
return ip, nil
} }
func (d *Parallels9Driver) ToolsIsoPath(k string) (string, error) { func (d *Parallels9Driver) ToolsIsoPath(k string) (string, error) {
......
package common package common
import ( import (
"io/ioutil"
"os"
"testing" "testing"
) )
func TestParallels9Driver_impl(t *testing.T) { func TestParallels9Driver_impl(t *testing.T) {
var _ Driver = new(Parallels9Driver) var _ Driver = new(Parallels9Driver)
} }
func TestIpAddress(t *testing.T) {
tf, err := ioutil.TempFile("", "packer")
if err != nil {
t.Fatalf("err: %s", err)
}
defer os.Remove(tf.Name())
d := Parallels9Driver{
dhcp_lease_file: tf.Name(),
}
// No lease should be found in an empty file
ip, err := d.IpAddress("123456789012")
if err == nil {
t.Fatalf("Found IP: \"%v\". No IP should be found!\n", ip)
}
// The most recent lease, 10.211.55.126 should be found
c := []byte(`
[vnic0]
10.211.55.125="1418288000,1800,001c4235240c,ff4235240c000100011c1c10e7001c4235240c"
10.211.55.126="1418288969,1800,001c4235240c,ff4235240c000100011c1c11ad001c4235240c"
10.211.55.254="1411712008,1800,001c42a51419,01001c42a51419"
`)
ioutil.WriteFile(tf.Name(), c, 0666)
ip, err = d.IpAddress("001C4235240c")
if err != nil {
t.Fatalf("Error: %v\n", err)
}
if ip != "10.211.55.126" {
t.Fatalf("Should have found 10.211.55.126, not %s!\n", ip)
}
// The most recent lease, 10.211.55.124 should be found
c = []byte(`[vnic0]
10.211.55.124="1418288969,1800,001c4235240c,ff4235240c000100011c1c11ad001c4235240c"
10.211.55.125="1418288000,1800,001c4235240c,ff4235240c000100011c1c10e7001c4235240c"
10.211.55.254="1411712008,1800,001c42a51419,01001c42a51419"
`)
ioutil.WriteFile(tf.Name(), c, 0666)
ip, err = d.IpAddress("001c4235240c")
if err != nil {
t.Fatalf("Error: %v\n", err)
}
if ip != "10.211.55.124" {
t.Fatalf("Should have found 10.211.55.124, not %s!\n", ip)
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment