Commit 72924f0d authored by Ross Smith II's avatar Ross Smith II

builder/vmware-vmx: add cloning support on Windows [GH-824]

parent dc21bf01
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"log" "log"
"os/exec" "os/exec"
"runtime" "runtime"
"strconv"
"strings" "strings"
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
...@@ -89,6 +90,11 @@ func NewDriver(dconfig *DriverConfig, config *SSHConfig) (Driver, error) { ...@@ -89,6 +90,11 @@ func NewDriver(dconfig *DriverConfig, config *SSHConfig) (Driver, error) {
} }
case "windows": case "windows":
drivers = []Driver{ drivers = []Driver{
&Workstation10Driver{
Workstation9Driver: Workstation9Driver{
SSHConfig: config,
},
},
&Workstation9Driver{ &Workstation9Driver{
SSHConfig: config, SSHConfig: config,
}, },
...@@ -137,3 +143,32 @@ func runAndLog(cmd *exec.Cmd) (string, string, error) { ...@@ -137,3 +143,32 @@ func runAndLog(cmd *exec.Cmd) (string, string, error) {
return returnStdout, returnStderr, err return returnStdout, returnStderr, err
} }
func normalizeVersion(version string) (string, error) {
i, err := strconv.Atoi(version)
if err != nil {
return "", fmt.Errorf(
"VMWare WS version '%s' is not numeric", version)
}
return fmt.Sprintf("%02d", i), nil
}
func compareVersions(versionFound string, versionWanted string) error {
found, err := normalizeVersion(versionFound)
if err != nil {
return err
}
wanted, err := normalizeVersion(versionWanted)
if err != nil {
return err
}
if found < wanted {
return fmt.Errorf(
"VMWare WS %s, or greater, is required. Found version: %s", versionWanted, versionFound)
}
return nil
}
package common package common
import ( import (
"bytes"
"fmt"
"log"
"os/exec" "os/exec"
"regexp"
"runtime"
"strings"
) )
const VMWARE_WS_VERSION = "10"
// Workstation10Driver is a driver that can run VMware Workstation 10 // Workstation10Driver is a driver that can run VMware Workstation 10
// installations. Current only tested for UNIX // installations.
type Workstation10Driver struct { type Workstation10Driver struct {
Workstation9Driver Workstation9Driver
...@@ -31,37 +27,9 @@ func (d *Workstation10Driver) Clone(dst, src string) error { ...@@ -31,37 +27,9 @@ func (d *Workstation10Driver) Clone(dst, src string) error {
} }
func (d *Workstation10Driver) Verify() error { func (d *Workstation10Driver) Verify() error {
if runtime.GOOS != "linux" {
return fmt.Errorf("WS10 driver is only supported on Linux at the moment. Your OS: %s", runtime.GOOS)
}
if err := d.Workstation9Driver.Verify(); err != nil { if err := d.Workstation9Driver.Verify(); err != nil {
return err return err
} }
//TODO(pmyjavec) there is a better way to find this, how? return workstationVerifyVersion(VMWARE_WS_VERSION)
//the default will suffice for now.
vmxpath := "/usr/lib/vmware/bin/vmware-vmx"
var stderr bytes.Buffer
cmd := exec.Command(vmxpath, "-v")
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return err
}
versionRe := regexp.MustCompile(`(?i)VMware Workstation (\d+\.\d+\.\d+)\s`)
matches := versionRe.FindStringSubmatch(stderr.String())
if matches == nil {
return fmt.Errorf(
"Couldn't find VMware WS version in output: %s", stderr.String())
}
log.Printf("Detected VMware WS version: %s", matches[1])
if !strings.HasPrefix(matches[1], "10.") {
return fmt.Errorf(
"WS 10 not detected. Got version: %s", matches[1])
}
return nil
} }
// +build windows
package common
import (
"fmt"
"log"
"regexp"
"syscall"
)
func workstationVerifyVersion(version string) error {
key := `SOFTWARE\Wow6432Node\VMware, Inc.\VMware Workstation`
subkey := "ProductVersion"
productVersion, err := readRegString(syscall.HKEY_LOCAL_MACHINE, key, subkey)
if err != nil {
log.Printf(`Unable to read registry key %s\%s`, key, subkey)
key = `SOFTWARE\VMware, Inc.\VMware Workstation`
productVersion, err = readRegString(syscall.HKEY_LOCAL_MACHINE, key, subkey)
if err != nil {
log.Printf(`Unable to read registry key %s\%s`, key, subkey)
return err
}
}
versionRe := regexp.MustCompile(`^(\d+)\.`)
matches := versionRe.FindStringSubmatch(productVersion)
if matches == nil {
return fmt.Errorf(
"Could not find VMware WS version in registry key %s/subkey: %s", key, subkey, productVersion)
}
log.Printf("Detected VMware WS version: %s", matches[1])
return compareVersions(matches[1], version)
}
...@@ -13,7 +13,6 @@ import ( ...@@ -13,7 +13,6 @@ import (
) )
// Workstation9Driver is a driver that can run VMware Workstation 9 // Workstation9Driver is a driver that can run VMware Workstation 9
// on non-Windows platforms.
type Workstation9Driver struct { type Workstation9Driver struct {
AppPath string AppPath string
VdiskManagerPath string VdiskManagerPath string
...@@ -24,7 +23,7 @@ type Workstation9Driver struct { ...@@ -24,7 +23,7 @@ type Workstation9Driver struct {
} }
func (d *Workstation9Driver) Clone(dst, src string) error { func (d *Workstation9Driver) Clone(dst, src string) error {
return errors.New("Cloning is not supported with WS 9. Please use WS 10+.") return errors.New("Cloning is not supported with VMWare WS 9. Please use VMWare WS 10, or greater.")
} }
func (d *Workstation9Driver) CompactDisk(diskPath string) error { func (d *Workstation9Driver) CompactDisk(diskPath string) error {
......
...@@ -4,10 +4,14 @@ ...@@ -4,10 +4,14 @@
package common package common
import ( import (
"bytes"
"errors" "errors"
"fmt" "fmt"
"log"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"regexp"
"runtime"
) )
func workstationCheckLicense() error { func workstationCheckLicense() error {
...@@ -46,3 +50,30 @@ func workstationToolsIsoPath(flavor string) string { ...@@ -46,3 +50,30 @@ func workstationToolsIsoPath(flavor string) string {
func workstationVmnetnatConfPath() string { func workstationVmnetnatConfPath() string {
return "" return ""
} }
func workstationVerifyVersion(version string) error {
if runtime.GOOS != "linux" {
return fmt.Errorf("The VMWare WS %s driver is only supported on Linux, and Windows, at the moment. Your OS: %s", version, runtime.GOOS)
}
//TODO(pmyjavec) there is a better way to find this, how?
//the default will suffice for now.
vmxpath := "/usr/lib/vmware/bin/vmware-vmx"
var stderr bytes.Buffer
cmd := exec.Command(vmxpath, "-v")
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return err
}
versionRe := regexp.MustCompile(`(?i)VMware Workstation (\d+)\.`)
matches := versionRe.FindStringSubmatch(stderr.String())
if matches == nil {
return fmt.Errorf(
"Could not find VMWare WS version in output: %s", stderr.String())
}
log.Printf("Detected VMWare WS version: %s", matches[1])
return compareVersions(matches[1], version)
}
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