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  }