github.com/alouche/packer@v0.3.7/builder/virtualbox/driver.go (about) 1 package virtualbox 2 3 import ( 4 "bytes" 5 "fmt" 6 "log" 7 "os/exec" 8 "regexp" 9 "strings" 10 "time" 11 ) 12 13 // A driver is able to talk to VirtualBox and perform certain 14 // operations with it. 15 type Driver interface { 16 // Checks if the VM with the given name is running. 17 IsRunning(string) (bool, error) 18 19 // Stop stops a running machine, forcefully. 20 Stop(string) error 21 22 // SuppressMessages should do what needs to be done in order to 23 // suppress any annoying popups from VirtualBox. 24 SuppressMessages() error 25 26 // VBoxManage executes the given VBoxManage command 27 VBoxManage(...string) error 28 29 // Verify checks to make sure that this driver should function 30 // properly. If there is any indication the driver can't function, 31 // this will return an error. 32 Verify() error 33 34 // Version reads the version of VirtualBox that is installed. 35 Version() (string, error) 36 } 37 38 type VBox42Driver struct { 39 // This is the path to the "VBoxManage" application. 40 VBoxManagePath string 41 } 42 43 func (d *VBox42Driver) IsRunning(name string) (bool, error) { 44 var stdout bytes.Buffer 45 46 cmd := exec.Command(d.VBoxManagePath, "showvminfo", name, "--machinereadable") 47 cmd.Stdout = &stdout 48 if err := cmd.Run(); err != nil { 49 return false, err 50 } 51 52 for _, line := range strings.Split(stdout.String(), "\n") { 53 // Need to trim off CR character when running in windows 54 line = strings.TrimRight(line, "\r") 55 56 if line == `VMState="running"` { 57 return true, nil 58 } 59 60 // We consider "stopping" to still be running. We wait for it to 61 // be completely stopped or some other state. 62 if line == `VMState="stopping"` { 63 return true, nil 64 } 65 66 // We consider "paused" to still be running. We wait for it to 67 // be completely stopped or some other state. 68 if line == `VMState="paused"` { 69 return true, nil 70 } 71 } 72 73 return false, nil 74 } 75 76 func (d *VBox42Driver) Stop(name string) error { 77 if err := d.VBoxManage("controlvm", name, "poweroff"); err != nil { 78 return err 79 } 80 81 return nil 82 } 83 84 func (d *VBox42Driver) SuppressMessages() error { 85 extraData := map[string]string{ 86 "GUI/RegistrationData": "triesLeft=0", 87 "GUI/SuppressMessages": "confirmInputCapture,remindAboutAutoCapture,remindAboutMouseIntegrationOff,remindAboutMouseIntegrationOn,remindAboutWrongColorDepth", 88 "GUI/UpdateDate": fmt.Sprintf("1 d, %d-01-01, stable", time.Now().Year()+1), 89 "GUI/UpdateCheckCount": "60", 90 } 91 92 for k, v := range extraData { 93 if err := d.VBoxManage("setextradata", "global", k, v); err != nil { 94 return err 95 } 96 } 97 98 return nil 99 } 100 101 func (d *VBox42Driver) VBoxManage(args ...string) error { 102 var stdout, stderr bytes.Buffer 103 104 log.Printf("Executing VBoxManage: %#v", args) 105 cmd := exec.Command(d.VBoxManagePath, args...) 106 cmd.Stdout = &stdout 107 cmd.Stderr = &stderr 108 err := cmd.Run() 109 110 stdoutString := strings.TrimSpace(stdout.String()) 111 stderrString := strings.TrimSpace(stderr.String()) 112 113 if _, ok := err.(*exec.ExitError); ok { 114 err = fmt.Errorf("VBoxManage error: %s", stderrString) 115 } 116 117 log.Printf("stdout: %s", stdoutString) 118 log.Printf("stderr: %s", stderrString) 119 120 return err 121 } 122 123 func (d *VBox42Driver) Verify() error { 124 return nil 125 } 126 127 func (d *VBox42Driver) Version() (string, error) { 128 var stdout bytes.Buffer 129 130 cmd := exec.Command(d.VBoxManagePath, "--version") 131 cmd.Stdout = &stdout 132 if err := cmd.Run(); err != nil { 133 return "", err 134 } 135 136 versionOutput := strings.TrimSpace(stdout.String()) 137 log.Printf("VBoxManage --version output: %s", versionOutput) 138 versionRe := regexp.MustCompile("[^.0-9]") 139 matches := versionRe.Split(versionOutput, 2) 140 if len(matches) == 0 { 141 return "", fmt.Errorf("No version found: %s", versionOutput) 142 } 143 144 log.Printf("VirtualBox version: %s", matches[0]) 145 return matches[0], nil 146 }