github.com/sneal/packer@v0.5.2/builder/vmware/common/guest_ip.go (about)

     1  package common
     2  
     3  import (
     4  	"errors"
     5  	"io/ioutil"
     6  	"log"
     7  	"os"
     8  	"regexp"
     9  	"strings"
    10  	"time"
    11  )
    12  
    13  // Interface to help find the IP address of a running virtual machine.
    14  type GuestIPFinder interface {
    15  	GuestIP() (string, error)
    16  }
    17  
    18  // DHCPLeaseGuestLookup looks up the IP address of a guest using DHCP
    19  // lease information from the VMware network devices.
    20  type DHCPLeaseGuestLookup struct {
    21  	// Driver that is being used (to find leases path)
    22  	Driver Driver
    23  
    24  	// Device that the guest is connected to.
    25  	Device string
    26  
    27  	// MAC address of the guest.
    28  	MACAddress string
    29  }
    30  
    31  func (f *DHCPLeaseGuestLookup) GuestIP() (string, error) {
    32  	dhcpLeasesPath := f.Driver.DhcpLeasesPath(f.Device)
    33  	log.Printf("DHCP leases path: %s", dhcpLeasesPath)
    34  	if dhcpLeasesPath == "" {
    35  		return "", errors.New("no DHCP leases path found.")
    36  	}
    37  
    38  	fh, err := os.Open(dhcpLeasesPath)
    39  	if err != nil {
    40  		return "", err
    41  	}
    42  	defer fh.Close()
    43  
    44  	dhcpBytes, err := ioutil.ReadAll(fh)
    45  	if err != nil {
    46  		return "", err
    47  	}
    48  
    49  	var lastIp string
    50  	var lastLeaseEnd time.Time
    51  
    52  	var curIp string
    53  	var curLeaseEnd time.Time
    54  
    55  	ipLineRe := regexp.MustCompile(`^lease (.+?) {$`)
    56  	endTimeLineRe := regexp.MustCompile(`^\s*ends \d (.+?);$`)
    57  	macLineRe := regexp.MustCompile(`^\s*hardware ethernet (.+?);$`)
    58  
    59  	for _, line := range strings.Split(string(dhcpBytes), "\n") {
    60  		// Need to trim off CR character when running in windows
    61  		line = strings.TrimRight(line, "\r")
    62  
    63  		matches := ipLineRe.FindStringSubmatch(line)
    64  		if matches != nil {
    65  			lastIp = matches[1]
    66  			continue
    67  		}
    68  
    69  		matches = endTimeLineRe.FindStringSubmatch(line)
    70  		if matches != nil {
    71  			lastLeaseEnd, _ = time.Parse("2006/01/02 15:04:05", matches[1])
    72  			continue
    73  		}
    74  
    75  		// If the mac address matches and this lease ends farther in the
    76  		// future than the last match we might have, then choose it.
    77  		matches = macLineRe.FindStringSubmatch(line)
    78  		if matches != nil && matches[1] == f.MACAddress && curLeaseEnd.Before(lastLeaseEnd) {
    79  			curIp = lastIp
    80  			curLeaseEnd = lastLeaseEnd
    81  		}
    82  	}
    83  
    84  	if curIp == "" {
    85  		return "", errors.New("IP not found for MAC in DHCP leases")
    86  	}
    87  
    88  	return curIp, nil
    89  }