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