builder/virtualbox/ovf: StepImport to import an OVF

This commit is contained in:
Mitchell Hashimoto 2013-12-22 15:19:19 -08:00
parent 0de7bb33cd
commit dd767c9d54
8 changed files with 168 additions and 3 deletions

View File

@ -19,6 +19,12 @@ type Driver interface {
// Create a SATA controller.
CreateSATAController(vm string, controller string) error
// Delete a VM by name
Delete(string) error
// Import a VM
Import(string, string) error
// Checks if the VM with the given name is running.
IsRunning(string) (bool, error)

View File

@ -36,6 +36,20 @@ func (d *VBox42Driver) CreateSATAController(vmName string, name string) error {
return d.VBoxManage(command...)
}
func (d *VBox42Driver) Delete(name string) error {
return d.VBoxManage("unregistervm", name, "--delete")
}
func (d *VBox42Driver) Import(name, path string) error {
args := []string{
"import", path,
"--vsys", "0",
"--vmname", name,
}
return d.VBoxManage(args...)
}
func (d *VBox42Driver) IsRunning(name string) (bool, error) {
var stdout bytes.Buffer

View File

@ -9,6 +9,15 @@ type DriverMock struct {
CreateSATAControllerController string
CreateSATAControllerErr error
DeleteCalled bool
DeleteName string
DeleteErr error
ImportCalled bool
ImportName string
ImportPath string
ImportErr error
IsRunningName string
IsRunningReturn bool
IsRunningErr error
@ -36,6 +45,19 @@ func (d *DriverMock) CreateSATAController(vm string, controller string) error {
return d.CreateSATAControllerErr
}
func (d *DriverMock) Delete(name string) error {
d.DeleteCalled = true
d.DeleteName = name
return d.DeleteErr
}
func (d *DriverMock) Import(name, path string) error {
d.ImportCalled = true
d.ImportName = name
d.ImportPath = path
return d.ImportErr
}
func (d *DriverMock) IsRunning(name string) (bool, error) {
d.Lock()
defer d.Unlock()

View File

@ -39,9 +39,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
// Build the steps.
steps := []multistep.Step{
/*
new(stepDownloadGuestAdditions),
*/
&StepImport{
SourcePath: b.config.SourcePath,
},
&vboxcommon.StepOutputDir{
Force: b.config.PackerForce,
Path: b.config.OutputDir,

View File

@ -18,6 +18,8 @@ type Config struct {
vboxcommon.VBoxManageConfig `mapstructure:",squash"`
vboxcommon.VBoxVersionConfig `mapstructure:",squash"`
SourcePath string `mapstructure:"source_path"`
tpl *packer.ConfigTemplate
}

View File

@ -0,0 +1,47 @@
package ovf
import (
"fmt"
"github.com/mitchellh/multistep"
vboxcommon "github.com/mitchellh/packer/builder/virtualbox/common"
"github.com/mitchellh/packer/packer"
)
// This step imports an OVF VM into VirtualBox.
type StepImport struct {
Name string
SourcePath string
vmName string
}
func (s *StepImport) Run(state multistep.StateBag) multistep.StepAction {
driver := state.Get("driver").(vboxcommon.Driver)
ui := state.Get("ui").(packer.Ui)
ui.Say(fmt.Sprintf("Importing VM: %s", s.SourcePath))
if err := driver.Import(s.Name, s.SourcePath); err != nil {
err := fmt.Errorf("Error importing VM: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
s.vmName = s.Name
state.Put("vmName", s.Name)
return multistep.ActionContinue
}
func (s *StepImport) Cleanup(state multistep.StateBag) {
if s.vmName == "" {
return
}
driver := state.Get("driver").(vboxcommon.Driver)
ui := state.Get("ui").(packer.Ui)
ui.Say("Unregistering and deleting imported VM...")
if err := driver.Delete(s.vmName); err != nil {
ui.Error(fmt.Sprintf("Error deleting VM: %s", err))
}
}

View File

@ -0,0 +1,55 @@
package ovf
import (
"github.com/mitchellh/multistep"
vboxcommon "github.com/mitchellh/packer/builder/virtualbox/common"
"testing"
)
func TestStepImport_impl(t *testing.T) {
var _ multistep.Step = new(StepImport)
}
func TestStepImport(t *testing.T) {
state := testState(t)
step := new(StepImport)
step.Name = "bar"
step.SourcePath = "foo"
driver := state.Get("driver").(*vboxcommon.DriverMock)
// Test the run
if action := step.Run(state); action != multistep.ActionContinue {
t.Fatalf("bad action: %#v", action)
}
if _, ok := state.GetOk("error"); ok {
t.Fatal("should NOT have error")
}
// Test driver
if !driver.ImportCalled {
t.Fatal("import should be called")
}
if driver.ImportName != step.Name {
t.Fatalf("bad: %#v", driver.ImportName)
}
if driver.ImportPath != step.SourcePath {
t.Fatalf("bad: %#v", driver.ImportPath)
}
// Test output state
if name, ok := state.GetOk("vmName"); !ok {
t.Fatal("vmName should be set")
} else if name != "bar" {
t.Fatalf("bad: %#v", name)
}
// Test cleanup
step.Cleanup(state)
if !driver.DeleteCalled {
t.Fatal("delete should be called")
}
if driver.DeleteName != "bar" {
t.Fatalf("bad: %#v", driver.DeleteName)
}
}

View File

@ -0,0 +1,19 @@
package ovf
import (
"bytes"
"github.com/mitchellh/multistep"
vboxcommon "github.com/mitchellh/packer/builder/virtualbox/common"
"github.com/mitchellh/packer/packer"
"testing"
)
func testState(t *testing.T) multistep.StateBag {
state := new(multistep.BasicStateBag)
state.Put("driver", new(vboxcommon.DriverMock))
state.Put("ui", &packer.BasicUi{
Reader: new(bytes.Buffer),
Writer: new(bytes.Buffer),
})
return state
}