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