github.com/sneal/packer@v0.5.2/builder/vmware/common/driver.go (about) 1 package common 2 3 import ( 4 "bytes" 5 "fmt" 6 "log" 7 "os/exec" 8 "runtime" 9 "strings" 10 11 "github.com/mitchellh/multistep" 12 ) 13 14 // A driver is able to talk to VMware, control virtual machines, etc. 15 type Driver interface { 16 // Clone clones the VMX and the disk to the destination path. The 17 // destination is a path to the VMX file. The disk will be copied 18 // to that same directory. 19 Clone(dst string, src string) error 20 21 // CompactDisk compacts a virtual disk. 22 CompactDisk(string) error 23 24 // CreateDisk creates a virtual disk with the given size. 25 CreateDisk(string, string, string) error 26 27 // Checks if the VMX file at the given path is running. 28 IsRunning(string) (bool, error) 29 30 // SSHAddress returns the SSH address for the VM that is being 31 // managed by this driver. 32 SSHAddress(multistep.StateBag) (string, error) 33 34 // Start starts a VM specified by the path to the VMX given. 35 Start(string, bool) error 36 37 // Stop stops a VM specified by the path to the VMX given. 38 Stop(string) error 39 40 // SuppressMessages modifies the VMX or surrounding directory so that 41 // VMware doesn't show any annoying messages. 42 SuppressMessages(string) error 43 44 // Get the path to the VMware ISO for the given flavor. 45 ToolsIsoPath(string) string 46 47 // Get the path to the DHCP leases file for the given device. 48 DhcpLeasesPath(string) string 49 50 // Verify checks to make sure that this driver should function 51 // properly. This should check that all the files it will use 52 // appear to exist and so on. If everything is okay, this doesn't 53 // return an error. Otherwise, this returns an error. 54 Verify() error 55 } 56 57 // NewDriver returns a new driver implementation for this operating 58 // system, or an error if the driver couldn't be initialized. 59 func NewDriver(dconfig *DriverConfig, config *SSHConfig) (Driver, error) { 60 drivers := []Driver{} 61 62 switch runtime.GOOS { 63 case "darwin": 64 drivers = []Driver{ 65 &Fusion6Driver{ 66 Fusion5Driver: Fusion5Driver{ 67 AppPath: dconfig.FusionAppPath, 68 SSHConfig: config, 69 }, 70 }, 71 &Fusion5Driver{ 72 AppPath: dconfig.FusionAppPath, 73 SSHConfig: config, 74 }, 75 } 76 case "linux": 77 drivers = []Driver{ 78 &Workstation9Driver{ 79 SSHConfig: config, 80 }, 81 &Player5LinuxDriver{ 82 SSHConfig: config, 83 }, 84 } 85 case "windows": 86 drivers = []Driver{ 87 &Workstation9Driver{ 88 SSHConfig: config, 89 }, 90 } 91 default: 92 return nil, fmt.Errorf("can't find driver for OS: %s", runtime.GOOS) 93 } 94 95 errs := "" 96 for _, driver := range drivers { 97 err := driver.Verify() 98 if err == nil { 99 return driver, nil 100 } 101 errs += "* " + err.Error() + "\n" 102 } 103 104 return nil, fmt.Errorf( 105 "Unable to initialize any driver for this platform. The errors\n"+ 106 "from each driver are shown below. Please fix at least one driver\n"+ 107 "to continue:\n%s", errs) 108 } 109 110 func runAndLog(cmd *exec.Cmd) (string, string, error) { 111 var stdout, stderr bytes.Buffer 112 113 log.Printf("Executing: %s %v", cmd.Path, cmd.Args[1:]) 114 cmd.Stdout = &stdout 115 cmd.Stderr = &stderr 116 err := cmd.Run() 117 118 stdoutString := strings.TrimSpace(stdout.String()) 119 stderrString := strings.TrimSpace(stderr.String()) 120 121 if _, ok := err.(*exec.ExitError); ok { 122 err = fmt.Errorf("VMware error: %s", stderrString) 123 } 124 125 log.Printf("stdout: %s", stdoutString) 126 log.Printf("stderr: %s", stderrString) 127 128 // Replace these for Windows, we only want to deal with Unix 129 // style line endings. 130 returnStdout := strings.Replace(stdout.String(), "\r\n", "\n", -1) 131 returnStderr := strings.Replace(stderr.String(), "\r\n", "\n", -1) 132 133 return returnStdout, returnStderr, err 134 }