diff --git a/builder/virtualbox/common/driver.go b/builder/virtualbox/common/driver.go new file mode 100644 index 000000000..75b259ac3 --- /dev/null +++ b/builder/virtualbox/common/driver.go @@ -0,0 +1,77 @@ +package common + +import ( + "log" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" +) + +// A driver is able to talk to VirtualBox and perform certain +// operations with it. Some of the operations on here may seem overly +// specific, but they were built specifically in mind to handle features +// of the VirtualBox builder for Packer, and to abstract differences in +// versions out of the builder steps, so sometimes the methods are +// extremely specific. +type Driver interface { + // Create a SATA controller. + CreateSATAController(vm string, controller string) error + + // 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) +} + +func NewDriver() (Driver, error) { + var vboxmanagePath string + + // On Windows, we check VBOX_INSTALL_PATH env var for the path + if runtime.GOOS == "windows" { + if installPath := os.Getenv("VBOX_INSTALL_PATH"); installPath != "" { + log.Printf("[DEBUG] builder/virtualbox: VBOX_INSTALL_PATH: %s", + installPath) + for _, path := range strings.Split(installPath, ";") { + path = filepath.Join(path, "VBoxManage.exe") + if _, err := os.Stat(path); err == nil { + vboxmanagePath = path + break + } + } + } + } + + if vboxmanagePath == "" { + var err error + vboxmanagePath, err = exec.LookPath("VBoxManage") + if err != nil { + return nil, err + } + } + + log.Printf("VBoxManage path: %s", vboxmanagePath) + driver := &VBox42Driver{vboxmanagePath} + if err := driver.Verify(); err != nil { + return nil, err + } + + return driver, nil +} diff --git a/builder/virtualbox/iso/driver.go b/builder/virtualbox/common/driver_4_2.go similarity index 76% rename from builder/virtualbox/iso/driver.go rename to builder/virtualbox/common/driver_4_2.go index 6e1b79c8d..9b937faf9 100644 --- a/builder/virtualbox/iso/driver.go +++ b/builder/virtualbox/common/driver_4_2.go @@ -1,4 +1,4 @@ -package iso +package common import ( "bytes" @@ -10,38 +10,6 @@ import ( "time" ) -// A driver is able to talk to VirtualBox and perform certain -// operations with it. Some of the operations on here may seem overly -// specific, but they were built specifically in mind to handle features -// of the VirtualBox builder for Packer, and to abstract differences in -// versions out of the builder steps, so sometimes the methods are -// extremely specific. -type Driver interface { - // Create a SATA controller. - CreateSATAController(vm string, controller string) error - - // 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 diff --git a/builder/virtualbox/common/driver_4_2_test.go b/builder/virtualbox/common/driver_4_2_test.go new file mode 100644 index 000000000..dc92ddd7c --- /dev/null +++ b/builder/virtualbox/common/driver_4_2_test.go @@ -0,0 +1,9 @@ +package common + +import ( + "testing" +) + +func TestVBox42Driver_impl(t *testing.T) { + var _ Driver = new(VBox42Driver) +} diff --git a/builder/virtualbox/iso/builder.go b/builder/virtualbox/iso/builder.go index 9cbc9dd92..d2c9ff4b2 100644 --- a/builder/virtualbox/iso/builder.go +++ b/builder/virtualbox/iso/builder.go @@ -9,9 +9,6 @@ import ( "github.com/mitchellh/packer/packer" "log" "os" - "os/exec" - "path/filepath" - "runtime" "strings" "time" ) @@ -382,7 +379,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) { // Create the driver that we'll use to communicate with VirtualBox - driver, err := b.newDriver() + driver, err := vboxcommon.NewDriver() if err != nil { return nil, fmt.Errorf("Failed creating VirtualBox driver: %s", err) } @@ -467,38 +464,3 @@ func (b *Builder) Cancel() { b.runner.Cancel() } } - -func (b *Builder) newDriver() (Driver, error) { - var vboxmanagePath string - - if runtime.GOOS == "windows" { - // On Windows, we check VBOX_INSTALL_PATH env var for the path - if installPath := os.Getenv("VBOX_INSTALL_PATH"); installPath != "" { - log.Printf("[DEBUG] builder/virtualbox: VBOX_INSTALL_PATH: %s", - installPath) - for _, path := range strings.Split(installPath, ";") { - path = filepath.Join(path, "VBoxManage.exe") - if _, err := os.Stat(path); err == nil { - vboxmanagePath = path - break - } - } - } - } - - if vboxmanagePath == "" { - var err error - vboxmanagePath, err = exec.LookPath("VBoxManage") - if err != nil { - return nil, err - } - } - - log.Printf("VBoxManage path: %s", vboxmanagePath) - driver := &VBox42Driver{vboxmanagePath} - if err := driver.Verify(); err != nil { - return nil, err - } - - return driver, nil -} diff --git a/builder/virtualbox/iso/step_attach_floppy.go b/builder/virtualbox/iso/step_attach_floppy.go index 86a0b7c48..e784a0fc0 100644 --- a/builder/virtualbox/iso/step_attach_floppy.go +++ b/builder/virtualbox/iso/step_attach_floppy.go @@ -3,6 +3,7 @@ package iso import ( "fmt" "github.com/mitchellh/multistep" + vboxcommon "github.com/mitchellh/packer/builder/virtualbox/common" "github.com/mitchellh/packer/packer" "io" "io/ioutil" @@ -39,7 +40,7 @@ func (s *stepAttachFloppy) Run(state multistep.StateBag) multistep.StepAction { return multistep.ActionHalt } - driver := state.Get("driver").(Driver) + driver := state.Get("driver").(vboxcommon.Driver) ui := state.Get("ui").(packer.Ui) vmName := state.Get("vmName").(string) @@ -84,7 +85,7 @@ func (s *stepAttachFloppy) Cleanup(state multistep.StateBag) { // Delete the floppy disk defer os.Remove(s.floppyPath) - driver := state.Get("driver").(Driver) + driver := state.Get("driver").(vboxcommon.Driver) vmName := state.Get("vmName").(string) command := []string{ diff --git a/builder/virtualbox/iso/step_attach_guest_additions.go b/builder/virtualbox/iso/step_attach_guest_additions.go index a7832a768..f35710259 100644 --- a/builder/virtualbox/iso/step_attach_guest_additions.go +++ b/builder/virtualbox/iso/step_attach_guest_additions.go @@ -3,6 +3,7 @@ package iso import ( "fmt" "github.com/mitchellh/multistep" + vboxcommon "github.com/mitchellh/packer/builder/virtualbox/common" "github.com/mitchellh/packer/packer" "log" ) @@ -24,7 +25,7 @@ type stepAttachGuestAdditions struct { func (s *stepAttachGuestAdditions) Run(state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*config) - driver := state.Get("driver").(Driver) + driver := state.Get("driver").(vboxcommon.Driver) ui := state.Get("ui").(packer.Ui) vmName := state.Get("vmName").(string) @@ -65,7 +66,7 @@ func (s *stepAttachGuestAdditions) Cleanup(state multistep.StateBag) { return } - driver := state.Get("driver").(Driver) + driver := state.Get("driver").(vboxcommon.Driver) ui := state.Get("ui").(packer.Ui) vmName := state.Get("vmName").(string) diff --git a/builder/virtualbox/iso/step_attach_iso.go b/builder/virtualbox/iso/step_attach_iso.go index 3eeeeec6a..5d4ec42ef 100644 --- a/builder/virtualbox/iso/step_attach_iso.go +++ b/builder/virtualbox/iso/step_attach_iso.go @@ -3,6 +3,7 @@ package iso import ( "fmt" "github.com/mitchellh/multistep" + vboxcommon "github.com/mitchellh/packer/builder/virtualbox/common" "github.com/mitchellh/packer/packer" ) @@ -16,7 +17,7 @@ type stepAttachISO struct { } func (s *stepAttachISO) Run(state multistep.StateBag) multistep.StepAction { - driver := state.Get("driver").(Driver) + driver := state.Get("driver").(vboxcommon.Driver) isoPath := state.Get("iso_path").(string) ui := state.Get("ui").(packer.Ui) vmName := state.Get("vmName").(string) @@ -48,7 +49,7 @@ func (s *stepAttachISO) Cleanup(state multistep.StateBag) { return } - driver := state.Get("driver").(Driver) + driver := state.Get("driver").(vboxcommon.Driver) vmName := state.Get("vmName").(string) command := []string{ diff --git a/builder/virtualbox/iso/step_create_disk.go b/builder/virtualbox/iso/step_create_disk.go index 64dce39b3..6875d7b33 100644 --- a/builder/virtualbox/iso/step_create_disk.go +++ b/builder/virtualbox/iso/step_create_disk.go @@ -3,6 +3,7 @@ package iso import ( "fmt" "github.com/mitchellh/multistep" + vboxcommon "github.com/mitchellh/packer/builder/virtualbox/common" "github.com/mitchellh/packer/packer" "path/filepath" "strconv" @@ -15,7 +16,7 @@ type stepCreateDisk struct{} func (s *stepCreateDisk) Run(state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*config) - driver := state.Get("driver").(Driver) + driver := state.Get("driver").(vboxcommon.Driver) ui := state.Get("ui").(packer.Ui) vmName := state.Get("vmName").(string) diff --git a/builder/virtualbox/iso/step_create_vm.go b/builder/virtualbox/iso/step_create_vm.go index 4b88ac8ce..942d33363 100644 --- a/builder/virtualbox/iso/step_create_vm.go +++ b/builder/virtualbox/iso/step_create_vm.go @@ -3,6 +3,7 @@ package iso import ( "fmt" "github.com/mitchellh/multistep" + vboxcommon "github.com/mitchellh/packer/builder/virtualbox/common" "github.com/mitchellh/packer/packer" ) @@ -16,7 +17,7 @@ type stepCreateVM struct { func (s *stepCreateVM) Run(state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*config) - driver := state.Get("driver").(Driver) + driver := state.Get("driver").(vboxcommon.Driver) ui := state.Get("ui").(packer.Ui) name := config.VMName @@ -60,7 +61,7 @@ func (s *stepCreateVM) Cleanup(state multistep.StateBag) { return } - driver := state.Get("driver").(Driver) + driver := state.Get("driver").(vboxcommon.Driver) ui := state.Get("ui").(packer.Ui) ui.Say("Unregistering and deleting virtual machine...") diff --git a/builder/virtualbox/iso/step_download_guest_additions.go b/builder/virtualbox/iso/step_download_guest_additions.go index 5905dfed7..dbb8b9d3c 100644 --- a/builder/virtualbox/iso/step_download_guest_additions.go +++ b/builder/virtualbox/iso/step_download_guest_additions.go @@ -4,6 +4,7 @@ import ( "bytes" "fmt" "github.com/mitchellh/multistep" + vboxcommon "github.com/mitchellh/packer/builder/virtualbox/common" "github.com/mitchellh/packer/common" "github.com/mitchellh/packer/packer" "io" @@ -31,7 +32,7 @@ type stepDownloadGuestAdditions struct{} func (s *stepDownloadGuestAdditions) Run(state multistep.StateBag) multistep.StepAction { var action multistep.StepAction - driver := state.Get("driver").(Driver) + driver := state.Get("driver").(vboxcommon.Driver) ui := state.Get("ui").(packer.Ui) config := state.Get("config").(*config) diff --git a/builder/virtualbox/iso/step_export.go b/builder/virtualbox/iso/step_export.go index 37d113410..5e5f5e8f6 100644 --- a/builder/virtualbox/iso/step_export.go +++ b/builder/virtualbox/iso/step_export.go @@ -3,6 +3,7 @@ package iso import ( "fmt" "github.com/mitchellh/multistep" + vboxcommon "github.com/mitchellh/packer/builder/virtualbox/common" "github.com/mitchellh/packer/packer" "log" "path/filepath" @@ -19,7 +20,7 @@ type stepExport struct{} func (s *stepExport) Run(state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*config) - driver := state.Get("driver").(Driver) + driver := state.Get("driver").(vboxcommon.Driver) ui := state.Get("ui").(packer.Ui) vmName := state.Get("vmName").(string) diff --git a/builder/virtualbox/iso/step_forward_ssh.go b/builder/virtualbox/iso/step_forward_ssh.go index 351513a11..38fd28a35 100644 --- a/builder/virtualbox/iso/step_forward_ssh.go +++ b/builder/virtualbox/iso/step_forward_ssh.go @@ -3,6 +3,7 @@ package iso import ( "fmt" "github.com/mitchellh/multistep" + vboxcommon "github.com/mitchellh/packer/builder/virtualbox/common" "github.com/mitchellh/packer/packer" "log" "math/rand" @@ -19,7 +20,7 @@ type stepForwardSSH struct{} func (s *stepForwardSSH) Run(state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*config) - driver := state.Get("driver").(Driver) + driver := state.Get("driver").(vboxcommon.Driver) ui := state.Get("ui").(packer.Ui) vmName := state.Get("vmName").(string) diff --git a/builder/virtualbox/iso/step_remove_devices.go b/builder/virtualbox/iso/step_remove_devices.go index 4fcaeb6e4..763e22670 100644 --- a/builder/virtualbox/iso/step_remove_devices.go +++ b/builder/virtualbox/iso/step_remove_devices.go @@ -3,6 +3,7 @@ package iso import ( "fmt" "github.com/mitchellh/multistep" + vboxcommon "github.com/mitchellh/packer/builder/virtualbox/common" "github.com/mitchellh/packer/packer" ) @@ -15,7 +16,7 @@ import ( type stepRemoveDevices struct{} func (s *stepRemoveDevices) Run(state multistep.StateBag) multistep.StepAction { - driver := state.Get("driver").(Driver) + driver := state.Get("driver").(vboxcommon.Driver) ui := state.Get("ui").(packer.Ui) vmName := state.Get("vmName").(string) diff --git a/builder/virtualbox/iso/step_run.go b/builder/virtualbox/iso/step_run.go index de4936dd9..1d5cc63be 100644 --- a/builder/virtualbox/iso/step_run.go +++ b/builder/virtualbox/iso/step_run.go @@ -3,6 +3,7 @@ package iso import ( "fmt" "github.com/mitchellh/multistep" + vboxcommon "github.com/mitchellh/packer/builder/virtualbox/common" "github.com/mitchellh/packer/packer" "time" ) @@ -18,7 +19,7 @@ type stepRun struct { func (s *stepRun) Run(state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*config) - driver := state.Get("driver").(Driver) + driver := state.Get("driver").(vboxcommon.Driver) ui := state.Get("ui").(packer.Ui) vmName := state.Get("vmName").(string) @@ -64,7 +65,7 @@ func (s *stepRun) Cleanup(state multistep.StateBag) { return } - driver := state.Get("driver").(Driver) + driver := state.Get("driver").(vboxcommon.Driver) ui := state.Get("ui").(packer.Ui) if running, _ := driver.IsRunning(s.vmName); running { diff --git a/builder/virtualbox/iso/step_shutdown.go b/builder/virtualbox/iso/step_shutdown.go index 7c36a2534..e1f9d5028 100644 --- a/builder/virtualbox/iso/step_shutdown.go +++ b/builder/virtualbox/iso/step_shutdown.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "github.com/mitchellh/multistep" + vboxcommon "github.com/mitchellh/packer/builder/virtualbox/common" "github.com/mitchellh/packer/packer" "log" "time" @@ -26,7 +27,7 @@ type stepShutdown struct{} func (s *stepShutdown) Run(state multistep.StateBag) multistep.StepAction { comm := state.Get("communicator").(packer.Communicator) config := state.Get("config").(*config) - driver := state.Get("driver").(Driver) + driver := state.Get("driver").(vboxcommon.Driver) ui := state.Get("ui").(packer.Ui) vmName := state.Get("vmName").(string) diff --git a/builder/virtualbox/iso/step_suppress_messages.go b/builder/virtualbox/iso/step_suppress_messages.go index 595d97004..e93397ea7 100644 --- a/builder/virtualbox/iso/step_suppress_messages.go +++ b/builder/virtualbox/iso/step_suppress_messages.go @@ -3,6 +3,7 @@ package iso import ( "fmt" "github.com/mitchellh/multistep" + vboxcommon "github.com/mitchellh/packer/builder/virtualbox/common" "github.com/mitchellh/packer/packer" "log" ) @@ -12,7 +13,7 @@ import ( type stepSuppressMessages struct{} func (stepSuppressMessages) Run(state multistep.StateBag) multistep.StepAction { - driver := state.Get("driver").(Driver) + driver := state.Get("driver").(vboxcommon.Driver) ui := state.Get("ui").(packer.Ui) log.Println("Suppressing annoying messages in VirtualBox") diff --git a/builder/virtualbox/iso/step_type_boot_command.go b/builder/virtualbox/iso/step_type_boot_command.go index f0680efe9..d479b84e0 100644 --- a/builder/virtualbox/iso/step_type_boot_command.go +++ b/builder/virtualbox/iso/step_type_boot_command.go @@ -3,6 +3,7 @@ package iso import ( "fmt" "github.com/mitchellh/multistep" + vboxcommon "github.com/mitchellh/packer/builder/virtualbox/common" "github.com/mitchellh/packer/packer" "log" "strings" @@ -34,7 +35,7 @@ type stepTypeBootCommand struct{} func (s *stepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*config) - driver := state.Get("driver").(Driver) + driver := state.Get("driver").(vboxcommon.Driver) httpPort := state.Get("http_port").(uint) ui := state.Get("ui").(packer.Ui) vmName := state.Get("vmName").(string) diff --git a/builder/virtualbox/iso/step_upload_guest_additions.go b/builder/virtualbox/iso/step_upload_guest_additions.go index 839943125..0ae72c000 100644 --- a/builder/virtualbox/iso/step_upload_guest_additions.go +++ b/builder/virtualbox/iso/step_upload_guest_additions.go @@ -3,6 +3,7 @@ package iso import ( "fmt" "github.com/mitchellh/multistep" + vboxcommon "github.com/mitchellh/packer/builder/virtualbox/common" "github.com/mitchellh/packer/packer" "log" "os" @@ -18,7 +19,7 @@ type stepUploadGuestAdditions struct{} func (s *stepUploadGuestAdditions) Run(state multistep.StateBag) multistep.StepAction { comm := state.Get("communicator").(packer.Communicator) config := state.Get("config").(*config) - driver := state.Get("driver").(Driver) + driver := state.Get("driver").(vboxcommon.Driver) ui := state.Get("ui").(packer.Ui) // If we're attaching then don't do this, since we attached. diff --git a/builder/virtualbox/iso/step_upload_version.go b/builder/virtualbox/iso/step_upload_version.go index b84b5d948..3517d4f82 100644 --- a/builder/virtualbox/iso/step_upload_version.go +++ b/builder/virtualbox/iso/step_upload_version.go @@ -4,6 +4,7 @@ import ( "bytes" "fmt" "github.com/mitchellh/multistep" + vboxcommon "github.com/mitchellh/packer/builder/virtualbox/common" "github.com/mitchellh/packer/packer" "log" ) @@ -15,7 +16,7 @@ type stepUploadVersion struct{} func (s *stepUploadVersion) Run(state multistep.StateBag) multistep.StepAction { comm := state.Get("communicator").(packer.Communicator) config := state.Get("config").(*config) - driver := state.Get("driver").(Driver) + driver := state.Get("driver").(vboxcommon.Driver) ui := state.Get("ui").(packer.Ui) if config.VBoxVersionFile == "" { diff --git a/builder/virtualbox/iso/step_vboxmanage.go b/builder/virtualbox/iso/step_vboxmanage.go index e5c80f4b5..62b8c0340 100644 --- a/builder/virtualbox/iso/step_vboxmanage.go +++ b/builder/virtualbox/iso/step_vboxmanage.go @@ -3,6 +3,7 @@ package iso import ( "fmt" "github.com/mitchellh/multistep" + vboxcommon "github.com/mitchellh/packer/builder/virtualbox/common" "github.com/mitchellh/packer/packer" "strings" ) @@ -21,7 +22,7 @@ type stepVBoxManage struct{} func (s *stepVBoxManage) Run(state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*config) - driver := state.Get("driver").(Driver) + driver := state.Get("driver").(vboxcommon.Driver) ui := state.Get("ui").(packer.Ui) vmName := state.Get("vmName").(string)