From d4c45b412e81035c193dbf7e995927b74198bb96 Mon Sep 17 00:00:00 2001 From: Ross Smith II Date: Thu, 1 Aug 2013 23:55:56 -0700 Subject: [PATCH] Add support for VMWare Workstation on Windows XP, fixes #237 --- builder/vmware/driver_workstation9.go | 4 + builder/vmware/driver_workstation9_unix.go | 4 + builder/vmware/driver_workstation9_windows.go | 148 +++++++++++++----- builder/vmware/host_ip_vmnetnatconf.go | 18 ++- 4 files changed, 130 insertions(+), 44 deletions(-) diff --git a/builder/vmware/driver_workstation9.go b/builder/vmware/driver_workstation9.go index a9bdfb857..ef236cbca 100644 --- a/builder/vmware/driver_workstation9.go +++ b/builder/vmware/driver_workstation9.go @@ -135,3 +135,7 @@ func (d *Workstation9Driver) ToolsIsoPath(flavor string) string { func (d *Workstation9Driver) DhcpLeasesPath(device string) string { return workstationDhcpLeasesPath(device) } + +func (d *Workstation9Driver) VmnetnatConfPath() string { + return workstationVmnetnatConfPath() +} diff --git a/builder/vmware/driver_workstation9_unix.go b/builder/vmware/driver_workstation9_unix.go index 8c96e7219..31d0f33dc 100644 --- a/builder/vmware/driver_workstation9_unix.go +++ b/builder/vmware/driver_workstation9_unix.go @@ -41,3 +41,7 @@ func workstationDhcpLeasesPath(device string) string { func workstationToolsIsoPath(flavor string) string { return "/usr/lib/vmware/isoimages/" + flavor + ".iso" } + +func workstationVmnetnatConfPath() string { + return "" +} diff --git a/builder/vmware/driver_workstation9_windows.go b/builder/vmware/driver_workstation9_windows.go index 69c0ad483..5cd53c1d2 100644 --- a/builder/vmware/driver_workstation9_windows.go +++ b/builder/vmware/driver_workstation9_windows.go @@ -18,63 +18,44 @@ func workstationCheckLicense() error { } func workstationFindVdiskManager() (string, error) { - path, err := exec.LookPath("vmware-vdiskmanager.exe") - if err == nil { + path, _ := exec.LookPath("vmware-vdiskmanager.exe") + if fileExists(path) { return path, nil } - path, err = workstationVMwareRoot() - if err != nil { - return "", err - } - - return filepath.Join(path, "vmware-vdiskmanager.exe"), nil + return findProgramFile("vmware-vdiskmanager.exe"), nil } func workstationFindVMware() (string, error) { - path, err := exec.LookPath("vmware.exe") - if err == nil { + path, _ := exec.LookPath("vmware.exe") + if fileExists(path) { return path, nil } - path, err = workstationVMwareRoot() - if err != nil { - return "", err - } - - return filepath.Join(path, "vmware.exe"), nil + return findProgramFile("vmware.exe"), nil } func workstationFindVmrun() (string, error) { - path, err := exec.LookPath("vmrun.exe") - if err == nil { + path, _ := exec.LookPath("vmrun.exe") + if fileExists(path) { return path, nil } - path, err = workstationVMwareRoot() - if err != nil { - return "", err - } - - return filepath.Join(path, "vmrun.exe"), nil + return findProgramFile("vmrun.exe"), nil } func workstationToolsIsoPath(flavor string) string { - path, err := workstationVMwareRoot() - if err != nil { - return "" - } - - return filepath.Join(path, flavor+".iso") + return findProgramFile(flavor + ".iso") } func workstationDhcpLeasesPath(device string) string { - programData := os.Getenv("ProgramData") - if programData == "" { - return "" + path, _ := workstationVmnetDhcpLeasesPathFromRegistry() + + if fileExists(path) { + return path } - return filepath.Join(programData, "/VMware/vmnetdhcp.leases") + return findDataFile("vmnetdhcp.leases") } // See http://blog.natefinch.com/2012/11/go-win-stuff.html @@ -126,6 +107,101 @@ func workstationVMwareRoot() (s string, err error) { return } - s = strings.Replace(s, "\\", "/", -1) - return + return normalizePath(s), nil +} + +// This reads the VMware DHCP leases path from the Windows registry. +func workstationVmnetDhcpLeasesPathFromRegistry() (s string, err error) { + key := "SYSTEM\\CurrentControlSet\\services\\VMnetDHCP\\Parameters" + subkey := "LeaseFile" + s, err = readRegString(syscall.HKEY_LOCAL_MACHINE, key, subkey) + if err != nil { + log.Printf(`Unable to read registry key %s\%s`, key, subkey) + return + } + + return normalizePath(s), nil +} + +func fileExists(file string) bool { + if file == "" { + return false + } + + if _, err := os.Stat(file); err != nil { + if os.IsNotExist(err) { + return false + } + log.Println(err.Error()) + } + + return true +} + +func normalizePath(path string) string { + path = strings.Replace(path, "\\", "/", -1) + path = strings.Replace(path, "//", "/", -1) + path = strings.TrimRight(path, "/") + return path +} + +type Paths [][]string + +func findFile(file string, paths Paths) string { + for _, a := range paths { + if a[0] == "" { + continue + } + + path := filepath.Join(a[0], a[1], file) + + path = normalizePath(path) + + log.Printf("Searching for file '%s'", path) + + if fileExists(path) { + log.Printf("Found file '%s'", path) + return path + } + } + + log.Printf("File not found: '%s'", file) + + return "" +} + +func findProgramFile(file string) string { + path, _ := workstationVMwareRoot() + + paths := Paths{ + []string{os.Getenv("VMWARE_HOME"), ""}, + []string{path, ""}, + []string{os.Getenv("ProgramFiles(x86)"), "/VMware/VMware Workstation"}, + []string{os.Getenv("ProgramFiles"), "/VMware/VMware Workstation"}, + } + + return findFile(file, paths) +} + +func findDataFile(file string) string { + path, _ := workstationVmnetDhcpLeasesPathFromRegistry() + + if path != "" { + path = filepath.Dir(path) + } + + paths := Paths{ + []string{os.Getenv("VMWARE_DATA"), ""}, + []string{path, ""}, + []string{os.Getenv("ProgramData"), "/VMWare"}, + []string{os.Getenv("ALLUSERSPROFILE"), "/VMWare"}, + } + + return findFile(file, paths) +} + +func workstationVmnetnatConfPath() string { + const VMNETNAT_CONF = "vmnetnat.conf" + + return findDataFile(VMNETNAT_CONF) } diff --git a/builder/vmware/host_ip_vmnetnatconf.go b/builder/vmware/host_ip_vmnetnatconf.go index bc1289e3d..2cc5f878b 100644 --- a/builder/vmware/host_ip_vmnetnatconf.go +++ b/builder/vmware/host_ip_vmnetnatconf.go @@ -6,7 +6,6 @@ import ( "fmt" "io" "os" - "path/filepath" "regexp" "strings" ) @@ -17,15 +16,18 @@ import ( type VMnetNatConfIPFinder struct{} func (*VMnetNatConfIPFinder) HostIP() (string, error) { - programData := os.Getenv("ProgramData") - if programData == "" { - return "", errors.New("ProgramData directory not found.") + const VMNETNAT_CONF = "vmnetnat.conf" + + driver := &Workstation9Driver{} + + vmnetnat := driver.VmnetnatConfPath() + + if vmnetnat == "" { + return "", fmt.Errorf("Could not find %s", VMNETNAT_CONF) } - programData = strings.Replace(programData, "\\", "/", -1) - vmnetnat := filepath.Join(programData, "/VMware/vmnetnat.conf") if _, err := os.Stat(vmnetnat); err != nil { - return "", fmt.Errorf("Error with vmnetnat.conf: %s", err) + return "", fmt.Errorf("Error with %s: %s", VMNETNAT_CONF, err) } f, err := os.Open(vmnetnat) @@ -62,5 +64,5 @@ func (*VMnetNatConfIPFinder) HostIP() (string, error) { } } - return "", errors.New("host IP not found in NAT config") + return "", errors.New("host IP not found in " + vmnetnat) }