/drivers/virtualbox/vbm.go

https://gitlab.com/Red54/machine · Go · 94 lines · 82 code · 8 blank · 4 comment · 22 complexity · 3f76af27e363c4e20edd702e0127d7d3 MD5 · raw file

  1. package virtualbox
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "os"
  7. "os/exec"
  8. "path/filepath"
  9. "regexp"
  10. "runtime"
  11. "strings"
  12. "github.com/docker/machine/libmachine/log"
  13. )
  14. var (
  15. reVMNameUUID = regexp.MustCompile(`"(.+)" {([0-9a-f-]+)}`)
  16. reVMInfoLine = regexp.MustCompile(`(?:"(.+)"|(.+))=(?:"(.*)"|(.*))`)
  17. reColonLine = regexp.MustCompile(`(.+):\s+(.*)`)
  18. reEqualLine = regexp.MustCompile(`(.+)=(.*)`)
  19. reEqualQuoteLine = regexp.MustCompile(`"(.+)"="(.*)"`)
  20. reMachineNotFound = regexp.MustCompile(`Could not find a registered machine named '(.+)'`)
  21. )
  22. var (
  23. ErrMachineExist = errors.New("machine already exists")
  24. ErrMachineNotExist = errors.New("machine does not exist")
  25. ErrVBMNotFound = errors.New("VBoxManage not found")
  26. vboxManageCmd = setVBoxManageCmd()
  27. )
  28. // detect the VBoxManage cmd's path if needed
  29. func setVBoxManageCmd() string {
  30. cmd := "VBoxManage"
  31. if path, err := exec.LookPath(cmd); err == nil {
  32. return path
  33. }
  34. if runtime.GOOS == "windows" {
  35. if p := os.Getenv("VBOX_INSTALL_PATH"); p != "" {
  36. if path, err := exec.LookPath(filepath.Join(p, cmd)); err == nil {
  37. return path
  38. }
  39. }
  40. if p := os.Getenv("VBOX_MSI_INSTALL_PATH"); p != "" {
  41. if path, err := exec.LookPath(filepath.Join(p, cmd)); err == nil {
  42. return path
  43. }
  44. }
  45. // look at HKEY_LOCAL_MACHINE\SOFTWARE\Oracle\VirtualBox\InstallDir
  46. p := "C:\\Program Files\\Oracle\\VirtualBox"
  47. if path, err := exec.LookPath(filepath.Join(p, cmd)); err == nil {
  48. return path
  49. }
  50. }
  51. return cmd
  52. }
  53. func vbm(args ...string) error {
  54. _, _, err := vbmOutErr(args...)
  55. return err
  56. }
  57. func vbmOut(args ...string) (string, error) {
  58. stdout, _, err := vbmOutErr(args...)
  59. return stdout, err
  60. }
  61. func vbmOutErr(args ...string) (string, string, error) {
  62. cmd := exec.Command(vboxManageCmd, args...)
  63. log.Debugf("COMMAND: %v %v", vboxManageCmd, strings.Join(args, " "))
  64. var stdout bytes.Buffer
  65. var stderr bytes.Buffer
  66. cmd.Stdout = &stdout
  67. cmd.Stderr = &stderr
  68. err := cmd.Run()
  69. stderrStr := stderr.String()
  70. if len(args) > 0 {
  71. log.Debugf("STDOUT:\n{\n%v}", stdout.String())
  72. log.Debugf("STDERR:\n{\n%v}", stderrStr)
  73. }
  74. if err != nil {
  75. if ee, ok := err.(*exec.Error); ok && ee.Err == exec.ErrNotFound {
  76. err = ErrVBMNotFound
  77. }
  78. } else {
  79. // VBoxManage will sometimes not set the return code, but has a fatal error
  80. // such as VBoxManage.exe: error: VT-x is not available. (VERR_VMX_NO_VMX)
  81. if strings.Contains(stderrStr, "error:") {
  82. err = fmt.Errorf("%v %v failed: %v", vboxManageCmd, strings.Join(args, " "), stderrStr)
  83. }
  84. }
  85. return stdout.String(), stderrStr, err
  86. }