github.com/mmcquillan/packer@v1.1.1-0.20171009221028-c85cf0483a5d/builder/virtualbox/common/driver_4_2.go (about) 1 package common 2 3 import ( 4 "bytes" 5 "fmt" 6 "log" 7 "os/exec" 8 "regexp" 9 "strconv" 10 "strings" 11 "time" 12 ) 13 14 type VBox42Driver struct { 15 // This is the path to the "VBoxManage" application. 16 VBoxManagePath string 17 } 18 19 func (d *VBox42Driver) CreateSATAController(vmName string, name string, portcount int) error { 20 version, err := d.Version() 21 if err != nil { 22 return err 23 } 24 25 portCountArg := "--sataportcount" 26 if strings.HasPrefix(version, "4.3") || strings.HasPrefix(version, "5.") { 27 portCountArg = "--portcount" 28 } 29 30 command := []string{ 31 "storagectl", vmName, 32 "--name", name, 33 "--add", "sata", 34 portCountArg, strconv.Itoa(portcount), 35 } 36 37 return d.VBoxManage(command...) 38 } 39 40 func (d *VBox42Driver) CreateSCSIController(vmName string, name string) error { 41 42 command := []string{ 43 "storagectl", vmName, 44 "--name", name, 45 "--add", "scsi", 46 "--controller", "LSILogic", 47 } 48 49 return d.VBoxManage(command...) 50 } 51 52 func (d *VBox42Driver) Delete(name string) error { 53 return d.VBoxManage("unregistervm", name, "--delete") 54 } 55 56 func (d *VBox42Driver) Iso() (string, error) { 57 var stdout bytes.Buffer 58 59 cmd := exec.Command(d.VBoxManagePath, "list", "systemproperties") 60 cmd.Stdout = &stdout 61 if err := cmd.Run(); err != nil { 62 return "", err 63 } 64 65 DefaultGuestAdditionsRe := regexp.MustCompile("Default Guest Additions ISO:(.+)") 66 67 for _, line := range strings.Split(stdout.String(), "\n") { 68 // Need to trim off CR character when running in windows 69 // Trimming whitespaces at this point helps to filter out empty value 70 line = strings.TrimRight(line, " \r") 71 72 matches := DefaultGuestAdditionsRe.FindStringSubmatch(line) 73 if matches == nil { 74 continue 75 } 76 77 isoname := strings.Trim(matches[1], " \r\n") 78 log.Printf("Found Default Guest Additions ISO: %s", isoname) 79 80 return isoname, nil 81 } 82 83 return "", fmt.Errorf("Cannot find \"Default Guest Additions ISO\" in vboxmanage output (or it is empty)") 84 } 85 86 func (d *VBox42Driver) Import(name string, path string, flags []string) error { 87 args := []string{ 88 "import", path, 89 "--vsys", "0", 90 "--vmname", name, 91 } 92 args = append(args, flags...) 93 94 return d.VBoxManage(args...) 95 } 96 97 func (d *VBox42Driver) IsRunning(name string) (bool, error) { 98 var stdout bytes.Buffer 99 100 cmd := exec.Command(d.VBoxManagePath, "showvminfo", name, "--machinereadable") 101 cmd.Stdout = &stdout 102 if err := cmd.Run(); err != nil { 103 return false, err 104 } 105 106 for _, line := range strings.Split(stdout.String(), "\n") { 107 // Need to trim off CR character when running in windows 108 line = strings.TrimRight(line, "\r") 109 110 if line == `VMState="running"` { 111 return true, nil 112 } 113 114 // We consider "stopping" to still be running. We wait for it to 115 // be completely stopped or some other state. 116 if line == `VMState="stopping"` { 117 return true, nil 118 } 119 120 // We consider "paused" to still be running. We wait for it to 121 // be completely stopped or some other state. 122 if line == `VMState="paused"` { 123 return true, nil 124 } 125 } 126 127 return false, nil 128 } 129 130 func (d *VBox42Driver) Stop(name string) error { 131 if err := d.VBoxManage("controlvm", name, "poweroff"); err != nil { 132 return err 133 } 134 135 // We sleep here for a little bit to let the session "unlock" 136 time.Sleep(2 * time.Second) 137 138 return nil 139 } 140 141 func (d *VBox42Driver) SuppressMessages() error { 142 extraData := map[string]string{ 143 "GUI/RegistrationData": "triesLeft=0", 144 "GUI/SuppressMessages": "confirmInputCapture,remindAboutAutoCapture,remindAboutMouseIntegrationOff,remindAboutMouseIntegrationOn,remindAboutWrongColorDepth", 145 "GUI/UpdateDate": fmt.Sprintf("1 d, %d-01-01, stable", time.Now().Year()+1), 146 "GUI/UpdateCheckCount": "60", 147 } 148 149 for k, v := range extraData { 150 if err := d.VBoxManage("setextradata", "global", k, v); err != nil { 151 return err 152 } 153 } 154 155 return nil 156 } 157 158 func (d *VBox42Driver) VBoxManage(args ...string) error { 159 var stdout, stderr bytes.Buffer 160 161 log.Printf("Executing VBoxManage: %#v", args) 162 cmd := exec.Command(d.VBoxManagePath, args...) 163 cmd.Stdout = &stdout 164 cmd.Stderr = &stderr 165 err := cmd.Run() 166 167 stdoutString := strings.TrimSpace(stdout.String()) 168 stderrString := strings.TrimSpace(stderr.String()) 169 170 if _, ok := err.(*exec.ExitError); ok { 171 err = fmt.Errorf("VBoxManage error: %s", stderrString) 172 } 173 174 if err == nil { 175 // Sometimes VBoxManage gives us an error with a zero exit code, 176 // so we also regexp match an error string. 177 m, _ := regexp.MatchString("VBoxManage([.a-z]+?): error:", stderrString) 178 if m { 179 err = fmt.Errorf("VBoxManage error: %s", stderrString) 180 } 181 } 182 183 log.Printf("stdout: %s", stdoutString) 184 log.Printf("stderr: %s", stderrString) 185 186 return err 187 } 188 189 func (d *VBox42Driver) Verify() error { 190 return nil 191 } 192 193 func (d *VBox42Driver) Version() (string, error) { 194 var stdout bytes.Buffer 195 196 cmd := exec.Command(d.VBoxManagePath, "--version") 197 cmd.Stdout = &stdout 198 if err := cmd.Run(); err != nil { 199 return "", err 200 } 201 202 versionOutput := strings.TrimSpace(stdout.String()) 203 log.Printf("VBoxManage --version output: %s", versionOutput) 204 205 // If the "--version" output contains vboxdrv, then this is indicative 206 // of problems with the VirtualBox setup and we shouldn't really continue, 207 // whether or not we can read the version. 208 if strings.Contains(versionOutput, "vboxdrv") { 209 return "", fmt.Errorf("VirtualBox is not properly setup: %s", versionOutput) 210 } 211 212 versionRe := regexp.MustCompile("^([.0-9]+)(?:_(?:RC|OSEr)[0-9]+)?") 213 matches := versionRe.FindAllStringSubmatch(versionOutput, 1) 214 if matches == nil || len(matches[0]) != 2 { 215 return "", fmt.Errorf("No version found: %s", versionOutput) 216 } 217 218 log.Printf("VirtualBox version: %s", matches[0][1]) 219 return matches[0][1], nil 220 }