diff --git a/builder/vmware/common/driver.go b/builder/vmware/common/driver.go index 1a945d19b..ec34e70b5 100644 --- a/builder/vmware/common/driver.go +++ b/builder/vmware/common/driver.go @@ -23,7 +23,7 @@ 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 + Clone(dst string, src string, cloneType bool) 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 63211f99a..2599604b9 100644 --- a/builder/vmware/common/driver_fusion5.go +++ b/builder/vmware/common/driver_fusion5.go @@ -24,7 +24,7 @@ type Fusion5Driver struct { SSHConfig *SSHConfig } -func (d *Fusion5Driver) Clone(dst, src string) error { +func (d *Fusion5Driver) Clone(dst, src string, linked bool) error { return errors.New("Cloning is not supported with Fusion 5. Please use Fusion 6+.") } diff --git a/builder/vmware/common/driver_fusion6.go b/builder/vmware/common/driver_fusion6.go index 002d4227a..ff5e9d73e 100644 --- a/builder/vmware/common/driver_fusion6.go +++ b/builder/vmware/common/driver_fusion6.go @@ -18,11 +18,19 @@ type Fusion6Driver struct { Fusion5Driver } -func (d *Fusion6Driver) Clone(dst, src string) error { +func (d *Fusion6Driver) Clone(dst, src string, linked bool) error { + + var cloneType string + if linked { + cloneType = "linked" + } else { + cloneType = "full" + } + cmd := exec.Command(d.vmrunPath(), "-T", "fusion", "clone", src, dst, - "full") + cloneType) if _, _, err := runAndLog(cmd); err != nil { if strings.Contains(err.Error(), "parameters was invalid") { return fmt.Errorf( diff --git a/builder/vmware/common/driver_mock.go b/builder/vmware/common/driver_mock.go index 8c540913e..019b688fc 100644 --- a/builder/vmware/common/driver_mock.go +++ b/builder/vmware/common/driver_mock.go @@ -13,6 +13,7 @@ type DriverMock struct { CloneCalled bool CloneDst string CloneSrc string + Linked bool CloneErr error CompactDiskCalled bool @@ -107,10 +108,11 @@ func (m NetworkMapperMock) DeviceIntoName(device string) (string, error) { return "", nil } -func (d *DriverMock) Clone(dst string, src string) error { +func (d *DriverMock) Clone(dst string, src string, linked bool) error { d.CloneCalled = true d.CloneDst = dst d.CloneSrc = src + d.Linked = linked return d.CloneErr } diff --git a/builder/vmware/common/driver_player5.go b/builder/vmware/common/driver_player5.go index 5f492e6be..ccb1de2c2 100644 --- a/builder/vmware/common/driver_player5.go +++ b/builder/vmware/common/driver_player5.go @@ -25,7 +25,7 @@ type Player5Driver struct { SSHConfig *SSHConfig } -func (d *Player5Driver) Clone(dst, src string) error { +func (d *Player5Driver) Clone(dst, src string, linked bool) error { return errors.New("Cloning is not supported with VMWare Player version 5. Please use VMWare Player version 6, or greater.") } diff --git a/builder/vmware/common/driver_player6.go b/builder/vmware/common/driver_player6.go index 1ccb84b85..d121f02bc 100644 --- a/builder/vmware/common/driver_player6.go +++ b/builder/vmware/common/driver_player6.go @@ -13,13 +13,20 @@ type Player6Driver struct { Player5Driver } -func (d *Player6Driver) Clone(dst, src string) error { +func (d *Player6Driver) Clone(dst, src string, linked bool) error { // TODO(rasa) check if running player+, not just player + var cloneType string + if linked { + cloneType = "linked" + } else { + cloneType = "full" + } + cmd := exec.Command(d.Player5Driver.VmrunPath, "-T", "ws", "clone", src, dst, - "full") + cloneType) if _, _, err := runAndLog(cmd); err != nil { return err diff --git a/builder/vmware/common/driver_workstation10.go b/builder/vmware/common/driver_workstation10.go index 471fce37d..070df50c2 100644 --- a/builder/vmware/common/driver_workstation10.go +++ b/builder/vmware/common/driver_workstation10.go @@ -13,11 +13,19 @@ type Workstation10Driver struct { Workstation9Driver } -func (d *Workstation10Driver) Clone(dst, src string) error { +func (d *Workstation10Driver) Clone(dst, src string, linked bool) error { + + var cloneType string + if linked { + cloneType = "linked" + } else { + cloneType = "full" + } + cmd := exec.Command(d.Workstation9Driver.VmrunPath, "-T", "ws", "clone", src, dst, - "full") + cloneType) if _, _, err := runAndLog(cmd); err != nil { return err diff --git a/builder/vmware/common/driver_workstation9.go b/builder/vmware/common/driver_workstation9.go index 8186ac83f..50bf77f34 100644 --- a/builder/vmware/common/driver_workstation9.go +++ b/builder/vmware/common/driver_workstation9.go @@ -24,7 +24,7 @@ type Workstation9Driver struct { SSHConfig *SSHConfig } -func (d *Workstation9Driver) Clone(dst, src string) error { +func (d *Workstation9Driver) Clone(dst, src string, linked bool) error { return errors.New("Cloning is not supported with VMware WS version 9. Please use VMware WS version 10, or greater.") } diff --git a/builder/vmware/iso/driver_esx5.go b/builder/vmware/iso/driver_esx5.go index c31d8da95..b3eb8c078 100644 --- a/builder/vmware/iso/driver_esx5.go +++ b/builder/vmware/iso/driver_esx5.go @@ -41,7 +41,7 @@ type ESX5Driver struct { vmId string } -func (d *ESX5Driver) Clone(dst, src string) error { +func (d *ESX5Driver) Clone(dst, src string, linked bool) error { return errors.New("Cloning is not supported with the ESX driver.") } diff --git a/builder/vmware/vmx/builder.go b/builder/vmware/vmx/builder.go index 130c533d7..dbb74b7a1 100644 --- a/builder/vmware/vmx/builder.go +++ b/builder/vmware/vmx/builder.go @@ -69,6 +69,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe OutputDir: b.config.OutputDir, Path: b.config.SourcePath, VMName: b.config.VMName, + Linked: b.config.Linked, }, &vmwcommon.StepConfigureVMX{ CustomData: b.config.VMXData, diff --git a/builder/vmware/vmx/config.go b/builder/vmware/vmx/config.go index 0fb9993aa..1e32ac7b7 100644 --- a/builder/vmware/vmx/config.go +++ b/builder/vmware/vmx/config.go @@ -26,6 +26,7 @@ type Config struct { vmwcommon.ToolsConfig `mapstructure:",squash"` vmwcommon.VMXConfig `mapstructure:",squash"` + Linked bool `mapstructure:"linked"` RemoteType string `mapstructure:"remote_type"` SkipCompaction bool `mapstructure:"skip_compaction"` SourcePath string `mapstructure:"source_path"` diff --git a/builder/vmware/vmx/step_clone_vmx.go b/builder/vmware/vmx/step_clone_vmx.go index 9eebc0096..55c24d2a7 100644 --- a/builder/vmware/vmx/step_clone_vmx.go +++ b/builder/vmware/vmx/step_clone_vmx.go @@ -17,6 +17,7 @@ type StepCloneVMX struct { OutputDir string Path string VMName string + Linked bool } type vmxAdapter struct { @@ -64,7 +65,7 @@ func (s *StepCloneVMX) Run(_ context.Context, state multistep.StateBag) multiste ui.Say("Cloning source VM...") log.Printf("Cloning from: %s", s.Path) log.Printf("Cloning to: %s", vmxPath) - if err := driver.Clone(vmxPath, s.Path); err != nil { + if err := driver.Clone(vmxPath, s.Path, s.Linked); err != nil { state.Put("error", err) return multistep.ActionHalt } diff --git a/website/source/docs/builders/vmware-vmx.html.md.erb b/website/source/docs/builders/vmware-vmx.html.md.erb index 90880cb54..03c144de9 100644 --- a/website/source/docs/builders/vmware-vmx.html.md.erb +++ b/website/source/docs/builders/vmware-vmx.html.md.erb @@ -137,6 +137,9 @@ builder. doesn't shut down in this time, it is an error. By default, the timeout is `5m` or five minutes. +- `linked` (boolean) - Virtual machine is created a linked clone. + Defaults to `false`. + - `skip_compaction` (boolean) - VMware-created disks are defragmented and compacted at the end of the build process using `vmware-vdiskmanager`. In certain rare cases, this might actually end up making the resulting disks