From 81ad800fb6ea336236d572d855b16f1de60f1191 Mon Sep 17 00:00:00 2001 From: Rickard von Essen Date: Tue, 17 Jan 2017 10:33:43 +0100 Subject: [PATCH] builder/vmware: Try to use `ip address` to find host IP Closes #4406 --- builder/vmware/common/host_ip_ifconfig.go | 51 ++++++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/builder/vmware/common/host_ip_ifconfig.go b/builder/vmware/common/host_ip_ifconfig.go index 10f527c99..19aea66a7 100644 --- a/builder/vmware/common/host_ip_ifconfig.go +++ b/builder/vmware/common/host_ip_ifconfig.go @@ -8,12 +8,59 @@ import ( "regexp" ) -// IfconfigIPFinder finds the host IP based on the output of `ifconfig`. +// IfconfigIPFinder finds the host IP based on the output of `ip address` or `ifconfig`. type IfconfigIPFinder struct { Device string } func (f *IfconfigIPFinder) HostIP() (string, error) { + ip, err := ipaddress(f.Device) + if err != nil || ip == "" { + return ifconfig(f.Device) + } + return ip, err +} + +func ipaddress(device string) (string, error) { + var ipPath string + + // On some systems, ip is in /sbin which is generally not + // on the PATH for a standard user, so we just check that first. + if _, err := os.Stat("/sbin/ip"); err == nil { + ipPath = "/sbin/ip" + } + + if ipPath == "" { + var err error + ipPath, err = exec.LookPath("ip") + if err != nil { + return "", err + } + } + + stdout := new(bytes.Buffer) + cmd := exec.Command(ipPath, "address", "show", "dev", device) + // Force LANG=C so that the output is what we expect it to be + // despite the locale. + cmd.Env = append(cmd.Env, "LANG=C") + cmd.Env = append(cmd.Env, os.Environ()...) + + cmd.Stdout = stdout + cmd.Stderr = new(bytes.Buffer) + if err := cmd.Run(); err != nil { + return "", err + } + + re := regexp.MustCompile(`inet[^\d]+([\d\.]+)/`) + matches := re.FindStringSubmatch(stdout.String()) + if matches == nil { + return "", errors.New("IP not found in ip a output...") + } + + return matches[1], nil +} + +func ifconfig(device string) (string, error) { var ifconfigPath string // On some systems, ifconfig is in /sbin which is generally not @@ -32,7 +79,7 @@ func (f *IfconfigIPFinder) HostIP() (string, error) { stdout := new(bytes.Buffer) - cmd := exec.Command(ifconfigPath, f.Device) + cmd := exec.Command(ifconfigPath, device) // Force LANG=C so that the output is what we expect it to be // despite the locale. cmd.Env = append(cmd.Env, "LANG=C")