90 lines
2.1 KiB
Go
90 lines
2.1 KiB
Go
package common
|
|
|
|
import (
|
|
"errors"
|
|
"io/ioutil"
|
|
"log"
|
|
"os"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// Interface to help find the IP address of a running virtual machine.
|
|
type GuestIPFinder interface {
|
|
GuestIP() (string, error)
|
|
}
|
|
|
|
// DHCPLeaseGuestLookup looks up the IP address of a guest using DHCP
|
|
// lease information from the VMware network devices.
|
|
type DHCPLeaseGuestLookup struct {
|
|
// Driver that is being used (to find leases path)
|
|
Driver Driver
|
|
|
|
// Device that the guest is connected to.
|
|
Device string
|
|
|
|
// MAC address of the guest.
|
|
MACAddress string
|
|
}
|
|
|
|
func (f *DHCPLeaseGuestLookup) GuestIP() (string, error) {
|
|
dhcpLeasesPath := f.Driver.DhcpLeasesPath(f.Device)
|
|
log.Printf("DHCP leases path: %s", dhcpLeasesPath)
|
|
if dhcpLeasesPath == "" {
|
|
return "", errors.New("no DHCP leases path found.")
|
|
}
|
|
|
|
fh, err := os.Open(dhcpLeasesPath)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer fh.Close()
|
|
|
|
dhcpBytes, err := ioutil.ReadAll(fh)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
var lastIp string
|
|
var lastLeaseEnd time.Time
|
|
|
|
var curIp string
|
|
var curLeaseEnd time.Time
|
|
|
|
ipLineRe := regexp.MustCompile(`^lease (.+?) {$`)
|
|
endTimeLineRe := regexp.MustCompile(`^\s*ends \d (.+?);$`)
|
|
macLineRe := regexp.MustCompile(`^\s*hardware ethernet (.+?);$`)
|
|
|
|
for _, line := range strings.Split(string(dhcpBytes), "\n") {
|
|
// Need to trim off CR character when running in windows
|
|
line = strings.TrimRight(line, "\r")
|
|
|
|
matches := ipLineRe.FindStringSubmatch(line)
|
|
if matches != nil {
|
|
lastIp = matches[1]
|
|
continue
|
|
}
|
|
|
|
matches = endTimeLineRe.FindStringSubmatch(line)
|
|
if matches != nil {
|
|
lastLeaseEnd, _ = time.Parse("2006/01/02 15:04:05", matches[1])
|
|
continue
|
|
}
|
|
|
|
// If the mac address matches and this lease ends farther in the
|
|
// future than the last match we might have, then choose it.
|
|
matches = macLineRe.FindStringSubmatch(line)
|
|
if matches != nil && matches[1] == f.MACAddress && curLeaseEnd.Before(lastLeaseEnd) {
|
|
curIp = lastIp
|
|
curLeaseEnd = lastLeaseEnd
|
|
}
|
|
}
|
|
|
|
if curIp == "" {
|
|
return "", errors.New("IP not found for MAC in DHCP leases")
|
|
}
|
|
|
|
return curIp, nil
|
|
}
|