diff --git a/builder/vmware/common/driver.go b/builder/vmware/common/driver.go index 55de3ff14..f825334ec 100644 --- a/builder/vmware/common/driver.go +++ b/builder/vmware/common/driver.go @@ -1,6 +1,13 @@ package common import ( + "bytes" + "fmt" + "log" + "os/exec" + "runtime" + "strings" + "github.com/mitchellh/multistep" ) @@ -41,3 +48,76 @@ type Driver interface { // return an error. Otherwise, this returns an error. Verify() error } + +// NewDriver returns a new driver implementation for this operating +// system, or an error if the driver couldn't be initialized. +func NewDriver(config *SSHConfig) (Driver, error) { + drivers := []Driver{} + + switch runtime.GOOS { + case "darwin": + drivers = []Driver{ + &Fusion5Driver{ + AppPath: "/Applications/VMware Fusion.app", + SSHConfig: config, + }, + } + case "linux": + drivers = []Driver{ + &Workstation9Driver{ + SSHConfig: config, + }, + &Player5LinuxDriver{ + SSHConfig: config, + }, + } + case "windows": + drivers = []Driver{ + &Workstation9Driver{ + SSHConfig: config, + }, + } + default: + return nil, fmt.Errorf("can't find driver for OS: %s", runtime.GOOS) + } + + errs := "" + for _, driver := range drivers { + err := driver.Verify() + if err == nil { + return driver, nil + } + errs += "* " + err.Error() + "\n" + } + + return nil, fmt.Errorf( + "Unable to initialize any driver for this platform. The errors\n"+ + "from each driver are shown below. Please fix at least one driver\n"+ + "to continue:\n%s", errs) +} + +func runAndLog(cmd *exec.Cmd) (string, string, error) { + var stdout, stderr bytes.Buffer + + log.Printf("Executing: %s %v", cmd.Path, cmd.Args[1:]) + cmd.Stdout = &stdout + cmd.Stderr = &stderr + err := cmd.Run() + + stdoutString := strings.TrimSpace(stdout.String()) + stderrString := strings.TrimSpace(stderr.String()) + + if _, ok := err.(*exec.ExitError); ok { + err = fmt.Errorf("VMware error: %s", stderrString) + } + + log.Printf("stdout: %s", stdoutString) + log.Printf("stderr: %s", stderrString) + + // Replace these for Windows, we only want to deal with Unix + // style line endings. + returnStdout := strings.Replace(stdout.String(), "\r\n", "\n", -1) + returnStderr := strings.Replace(stderr.String(), "\r\n", "\n", -1) + + return returnStdout, returnStderr, err +} diff --git a/builder/vmware/iso/driver_fusion5.go b/builder/vmware/common/driver_fusion5.go similarity index 95% rename from builder/vmware/iso/driver_fusion5.go rename to builder/vmware/common/driver_fusion5.go index 9366c1755..7d75dc0c7 100644 --- a/builder/vmware/iso/driver_fusion5.go +++ b/builder/vmware/common/driver_fusion5.go @@ -1,4 +1,4 @@ -package iso +package common import ( "fmt" @@ -9,7 +9,6 @@ import ( "strings" "github.com/mitchellh/multistep" - vmwcommon "github.com/mitchellh/packer/builder/vmware/common" ) // Fusion5Driver is a driver that can run VMWare Fusion 5. @@ -18,7 +17,7 @@ type Fusion5Driver struct { AppPath string // SSHConfig are the SSH settings for the Fusion VM - SSHConfig *vmwcommon.SSHConfig + SSHConfig *SSHConfig } func (d *Fusion5Driver) CompactDisk(diskPath string) error { @@ -66,7 +65,7 @@ func (d *Fusion5Driver) IsRunning(vmxPath string) (bool, error) { } func (d *Fusion5Driver) SSHAddress(state multistep.StateBag) (string, error) { - return vmwcommon.SSHAddressFunc(d.SSHConfig)(state) + return SSHAddressFunc(d.SSHConfig)(state) } func (d *Fusion5Driver) Start(vmxPath string, headless bool) error { diff --git a/builder/vmware/iso/driver_player5.go b/builder/vmware/common/driver_player5.go similarity index 96% rename from builder/vmware/iso/driver_player5.go rename to builder/vmware/common/driver_player5.go index a317d0c59..6434c201f 100644 --- a/builder/vmware/iso/driver_player5.go +++ b/builder/vmware/common/driver_player5.go @@ -1,4 +1,4 @@ -package iso +package common import ( "fmt" @@ -8,7 +8,6 @@ import ( "strings" "github.com/mitchellh/multistep" - vmwcommon "github.com/mitchellh/packer/builder/vmware/common" ) // Player5LinuxDriver is a driver that can run VMware Player 5 on Linux. @@ -19,7 +18,7 @@ type Player5LinuxDriver struct { VmrunPath string // SSHConfig are the SSH settings for the Fusion VM - SSHConfig *vmwcommon.SSHConfig + SSHConfig *SSHConfig } func (d *Player5LinuxDriver) CompactDisk(diskPath string) error { @@ -93,7 +92,7 @@ func (d *Player5LinuxDriver) IsRunning(vmxPath string) (bool, error) { } func (d *Player5LinuxDriver) SSHAddress(state multistep.StateBag) (string, error) { - return vmwcommon.SSHAddressFunc(d.SSHConfig)(state) + return SSHAddressFunc(d.SSHConfig)(state) } func (d *Player5LinuxDriver) Start(vmxPath string, headless bool) error { diff --git a/builder/vmware/iso/driver_workstation9.go b/builder/vmware/common/driver_workstation9.go similarity index 95% rename from builder/vmware/iso/driver_workstation9.go rename to builder/vmware/common/driver_workstation9.go index e87c3b2e2..bfa5f5389 100644 --- a/builder/vmware/iso/driver_workstation9.go +++ b/builder/vmware/common/driver_workstation9.go @@ -1,4 +1,4 @@ -package iso +package common import ( "fmt" @@ -9,7 +9,6 @@ import ( "strings" "github.com/mitchellh/multistep" - vmwcommon "github.com/mitchellh/packer/builder/vmware/common" ) // Workstation9Driver is a driver that can run VMware Workstation 9 @@ -20,7 +19,7 @@ type Workstation9Driver struct { VmrunPath string // SSHConfig are the SSH settings for the Fusion VM - SSHConfig *vmwcommon.SSHConfig + SSHConfig *SSHConfig } func (d *Workstation9Driver) CompactDisk(diskPath string) error { @@ -68,7 +67,7 @@ func (d *Workstation9Driver) IsRunning(vmxPath string) (bool, error) { } func (d *Workstation9Driver) SSHAddress(state multistep.StateBag) (string, error) { - return vmwcommon.SSHAddressFunc(d.SSHConfig)(state) + return SSHAddressFunc(d.SSHConfig)(state) } func (d *Workstation9Driver) Start(vmxPath string, headless bool) error { diff --git a/builder/vmware/iso/driver_workstation9_unix.go b/builder/vmware/common/driver_workstation9_unix.go similarity index 98% rename from builder/vmware/iso/driver_workstation9_unix.go rename to builder/vmware/common/driver_workstation9_unix.go index c3c6288cd..f90c326f4 100644 --- a/builder/vmware/iso/driver_workstation9_unix.go +++ b/builder/vmware/common/driver_workstation9_unix.go @@ -1,6 +1,6 @@ // +build !windows -package iso +package common import ( "errors" diff --git a/builder/vmware/iso/driver_workstation9_windows.go b/builder/vmware/common/driver_workstation9_windows.go similarity index 99% rename from builder/vmware/iso/driver_workstation9_windows.go rename to builder/vmware/common/driver_workstation9_windows.go index 3c4d91105..17095badc 100644 --- a/builder/vmware/iso/driver_workstation9_windows.go +++ b/builder/vmware/common/driver_workstation9_windows.go @@ -1,6 +1,6 @@ // +build windows -package iso +package common import ( "log" diff --git a/builder/vmware/iso/driver.go b/builder/vmware/iso/driver.go index 402b1b363..22c6b6902 100644 --- a/builder/vmware/iso/driver.go +++ b/builder/vmware/iso/driver.go @@ -1,12 +1,7 @@ package iso import ( - "bytes" "fmt" - "log" - "os/exec" - "runtime" - "strings" vmwcommon "github.com/mitchellh/packer/builder/vmware/common" ) @@ -16,43 +11,18 @@ import ( func NewDriver(config *config) (vmwcommon.Driver, error) { drivers := []vmwcommon.Driver{} - if config.RemoteType != "" { - drivers = []vmwcommon.Driver{ - &ESX5Driver{ - Host: config.RemoteHost, - Port: config.RemotePort, - Username: config.RemoteUser, - Password: config.RemotePassword, - Datastore: config.RemoteDatastore, - }, - } - } else { - switch runtime.GOOS { - case "darwin": - drivers = []vmwcommon.Driver{ - &Fusion5Driver{ - AppPath: "/Applications/VMware Fusion.app", - SSHConfig: &config.SSHConfig, - }, - } - case "linux": - drivers = []vmwcommon.Driver{ - &Workstation9Driver{ - SSHConfig: &config.SSHConfig, - }, - &Player5LinuxDriver{ - SSHConfig: &config.SSHConfig, - }, - } - case "windows": - drivers = []vmwcommon.Driver{ - &Workstation9Driver{ - SSHConfig: &config.SSHConfig, - }, - } - default: - return nil, fmt.Errorf("can't find driver for OS: %s", runtime.GOOS) - } + if config.RemoteType == "" { + return vmwcommon.NewDriver(&config.SSHConfig) + } + + drivers = []vmwcommon.Driver{ + &ESX5Driver{ + Host: config.RemoteHost, + Port: config.RemotePort, + Username: config.RemoteUser, + Password: config.RemotePassword, + Datastore: config.RemoteDatastore, + }, } errs := "" @@ -69,29 +39,3 @@ func NewDriver(config *config) (vmwcommon.Driver, error) { "from each driver are shown below. Please fix at least one driver\n"+ "to continue:\n%s", errs) } - -func runAndLog(cmd *exec.Cmd) (string, string, error) { - var stdout, stderr bytes.Buffer - - log.Printf("Executing: %s %v", cmd.Path, cmd.Args[1:]) - cmd.Stdout = &stdout - cmd.Stderr = &stderr - err := cmd.Run() - - stdoutString := strings.TrimSpace(stdout.String()) - stderrString := strings.TrimSpace(stderr.String()) - - if _, ok := err.(*exec.ExitError); ok { - err = fmt.Errorf("VMware error: %s", stderrString) - } - - log.Printf("stdout: %s", stdoutString) - log.Printf("stderr: %s", stderrString) - - // Replace these for Windows, we only want to deal with Unix - // style line endings. - returnStdout := strings.Replace(stdout.String(), "\r\n", "\n", -1) - returnStderr := strings.Replace(stderr.String(), "\r\n", "\n", -1) - - return returnStdout, returnStderr, err -} diff --git a/builder/vmware/iso/host_ip_vmnetnatconf.go b/builder/vmware/iso/host_ip_vmnetnatconf.go index 658a0abd4..0ba0a3727 100644 --- a/builder/vmware/iso/host_ip_vmnetnatconf.go +++ b/builder/vmware/iso/host_ip_vmnetnatconf.go @@ -8,6 +8,8 @@ import ( "os" "regexp" "strings" + + vmwcommon "github.com/mitchellh/packer/builder/vmware/common" ) // VMnetNatConfIPFinder finds the IP address of the host machine by @@ -16,7 +18,7 @@ import ( type VMnetNatConfIPFinder struct{} func (*VMnetNatConfIPFinder) HostIP() (string, error) { - driver := &Workstation9Driver{} + driver := &vmwcommon.Workstation9Driver{} vmnetnat := driver.VmnetnatConfPath() if vmnetnat == "" {