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