diff --git a/builder/vmware/common/driver.go b/builder/vmware/common/driver.go index f825334ec..992d0939c 100644 --- a/builder/vmware/common/driver.go +++ b/builder/vmware/common/driver.go @@ -13,6 +13,11 @@ import ( // A driver is able to talk to VMware, control virtual machines, etc. type Driver interface { + // Clone clones the VMX and the disk to the destination path. The + // destination is a path to the VMX file. The disk will be copied + // to that same directory. + Clone(dst string, src string) error + // CompactDisk compacts a virtual disk. CompactDisk(string) error diff --git a/builder/vmware/common/driver_fusion5.go b/builder/vmware/common/driver_fusion5.go index 7d75dc0c7..40b62ad5c 100644 --- a/builder/vmware/common/driver_fusion5.go +++ b/builder/vmware/common/driver_fusion5.go @@ -1,6 +1,7 @@ package common import ( + "errors" "fmt" "io/ioutil" "os" @@ -20,6 +21,10 @@ type Fusion5Driver struct { SSHConfig *SSHConfig } +func (d *Fusion5Driver) Clone(dst, src string) error { + return errors.New("Cloning is not supported with Fusion 5. Please use Fusion 6+.") +} + func (d *Fusion5Driver) CompactDisk(diskPath string) error { defragCmd := exec.Command(d.vdiskManagerPath(), "-d", diskPath) if _, _, err := runAndLog(defragCmd); err != nil { @@ -111,7 +116,8 @@ func (d *Fusion5Driver) Verify() error { if _, err := os.Stat(d.vmrunPath()); err != nil { if os.IsNotExist(err) { - return fmt.Errorf("Critical application 'vmrun' not found at path: %s", d.vmrunPath()) + return fmt.Errorf( + "Critical application 'vmrun' not found at path: %s", d.vmrunPath()) } return err @@ -119,7 +125,9 @@ func (d *Fusion5Driver) Verify() error { if _, err := os.Stat(d.vdiskManagerPath()); err != nil { if os.IsNotExist(err) { - return fmt.Errorf("Critical application vdisk manager not found at path: %s", d.vdiskManagerPath()) + return fmt.Errorf( + "Critical application vdisk manager not found at path: %s", + d.vdiskManagerPath()) } return err diff --git a/builder/vmware/common/driver_mock.go b/builder/vmware/common/driver_mock.go index edae482c5..2f5486bac 100644 --- a/builder/vmware/common/driver_mock.go +++ b/builder/vmware/common/driver_mock.go @@ -9,6 +9,11 @@ import ( type DriverMock struct { sync.Mutex + CloneCalled bool + CloneDst string + CloneSrc string + CloneErr error + CompactDiskCalled bool CompactDiskPath string CompactDiskErr error @@ -54,6 +59,13 @@ type DriverMock struct { VerifyErr error } +func (d *DriverMock) Clone(dst string, src string) error { + d.CloneCalled = true + d.CloneDst = dst + d.CloneSrc = src + return d.CloneErr +} + func (d *DriverMock) CompactDisk(path string) error { d.CompactDiskCalled = true d.CompactDiskPath = path diff --git a/builder/vmware/common/driver_player5.go b/builder/vmware/common/driver_player5.go index 6434c201f..1bec4ea25 100644 --- a/builder/vmware/common/driver_player5.go +++ b/builder/vmware/common/driver_player5.go @@ -1,6 +1,7 @@ package common import ( + "errors" "fmt" "os" "os/exec" @@ -21,6 +22,10 @@ type Player5LinuxDriver struct { SSHConfig *SSHConfig } +func (d *Player5LinuxDriver) Clone(dst, src string) error { + return errors.New("Cloning is not supported with Player 5. Please use Player 6+.") +} + func (d *Player5LinuxDriver) CompactDisk(diskPath string) error { if d.QemuImgPath != "" { return d.qemuCompactDisk(diskPath) diff --git a/builder/vmware/common/driver_workstation9.go b/builder/vmware/common/driver_workstation9.go index bfa5f5389..8643d8b1f 100644 --- a/builder/vmware/common/driver_workstation9.go +++ b/builder/vmware/common/driver_workstation9.go @@ -1,6 +1,7 @@ package common import ( + "errors" "fmt" "log" "os" @@ -22,6 +23,10 @@ type Workstation9Driver struct { SSHConfig *SSHConfig } +func (d *Workstation9Driver) Clone(dst, src string) error { + return errors.New("Cloning is not supported with WS 9. Please use WS 10+.") +} + func (d *Workstation9Driver) CompactDisk(diskPath string) error { defragCmd := exec.Command(d.VdiskManagerPath, "-d", diskPath) if _, _, err := runAndLog(defragCmd); err != nil { diff --git a/builder/vmware/vmx/step_clone_vmx.go b/builder/vmware/vmx/step_clone_vmx.go index 431406ab1..075df0d63 100644 --- a/builder/vmware/vmx/step_clone_vmx.go +++ b/builder/vmware/vmx/step_clone_vmx.go @@ -1,12 +1,11 @@ package vmx import ( - "io" "log" - "os" "path/filepath" "github.com/mitchellh/multistep" + vmwcommon "github.com/mitchellh/packer/builder/vmware/common" "github.com/mitchellh/packer/packer" ) @@ -18,29 +17,16 @@ type StepCloneVMX struct { } func (s *StepCloneVMX) Run(state multistep.StateBag) multistep.StepAction { + driver := state.Get("driver").(vmwcommon.Driver) ui := state.Get("ui").(packer.Ui) vmxPath := filepath.Join(s.OutputDir, s.VMName+".vmx") - ui.Say("Cloning VMX...") + ui.Say("Cloning source VM...") log.Printf("Cloning from: %s", s.Path) log.Printf("Cloning to: %s", vmxPath) - from, err := os.Open(s.Path) - if err != nil { - state.Put("error", err) - return multistep.ActionHalt - } - defer from.Close() - - to, err := os.Create(vmxPath) - if err != nil { - state.Put("error", err) - return multistep.ActionHalt - } - defer to.Close() - - if _, err := io.Copy(to, from); err != nil { + if err := driver.Clone(vmxPath, s.Path); err != nil { state.Put("error", err) return multistep.ActionHalt } diff --git a/builder/vmware/vmx/step_clone_vmx_test.go b/builder/vmware/vmx/step_clone_vmx_test.go index 2a4f00124..4d6532724 100644 --- a/builder/vmware/vmx/step_clone_vmx_test.go +++ b/builder/vmware/vmx/step_clone_vmx_test.go @@ -1,12 +1,10 @@ package vmx import ( - "io/ioutil" - "os" - "path/filepath" "testing" "github.com/mitchellh/multistep" + vmwcommon "github.com/mitchellh/packer/builder/vmware/common" ) func TestStepCloneVMX_impl(t *testing.T) { @@ -14,25 +12,14 @@ func TestStepCloneVMX_impl(t *testing.T) { } func TestStepCloneVMX(t *testing.T) { - // Setup some state - td, err := ioutil.TempDir("", "packer") - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.RemoveAll(td) - - // Create the source - sourcePath := filepath.Join(td, "source.vmx") - if err := ioutil.WriteFile(sourcePath, []byte("foo"), 0644); err != nil { - t.Fatalf("err: %s", err) - } - state := testState(t) step := new(StepCloneVMX) - step.OutputDir = td - step.Path = sourcePath + step.OutputDir = "/foo" + step.Path = "/bar/bar.vmx" step.VMName = "foo" + driver := state.Get("driver").(*vmwcommon.DriverMock) + // Test the run if action := step.Run(state); action != multistep.ActionContinue { t.Fatalf("bad action: %#v", action) @@ -41,16 +28,7 @@ func TestStepCloneVMX(t *testing.T) { t.Fatal("should NOT have error") } - // Test we have our VMX - if _, err := os.Stat(filepath.Join(td, "foo.vmx")); err != nil { - t.Fatalf("err: %s", err) - } - - data, err := ioutil.ReadFile(filepath.Join(td, "foo.vmx")) - if err != nil { - t.Fatalf("err: %s", err) - } - if string(data) != "foo" { - t.Fatalf("bad: %#v", string(data)) + if !driver.CloneCalled { + t.Fatal("clone should be called") } }