diff --git a/builder/vmware/common/artifact.go b/builder/vmware/common/artifact.go index e0b3e875e..cb61cd2f4 100644 --- a/builder/vmware/common/artifact.go +++ b/builder/vmware/common/artifact.go @@ -3,22 +3,26 @@ package common import ( "fmt" "os" - "path/filepath" "github.com/hashicorp/packer/packer" ) // BuilderId for the local artifacts const BuilderId = "mitchellh.vmware" +const BuilderIdESX = "mitchellh.vmware-esx" // Artifact is the result of running the VMware builder, namely a set // of files associated with the resulting machine. -type localArtifact struct { - id string - dir string - f []string +type artifact struct { + builderId string + id string + dir string + f []string + config map[string]string } +// NewLocalArtifact returns a VMware artifact containing the files +// in the given directory. // NewLocalArtifact returns a VMware artifact containing the files // in the given directory. func NewLocalArtifact(id string, dir string) (packer.Artifact, error) { @@ -37,33 +41,46 @@ func NewLocalArtifact(id string, dir string) (packer.Artifact, error) { return nil, err } - return &localArtifact{ - id: id, - dir: dir, - f: files, + return &artifact{ + builderId: id, + dir: dir, + f: files, }, nil } -func (a *localArtifact) BuilderId() string { +func NewArtifact(dir OutputDir, files []string, esxi bool) (packer.Artifact, err) { + builderID := BuilderId + if esxi { + builderID = BuilderIdESX + } + + return &artifact{ + builderId: builderID, + dir: dir.String(), + f: files, + }, nil +} + +func (a *artifact) BuilderId() string { return BuilderId } -func (a *localArtifact) Files() []string { +func (a *artifact) Files() []string { return a.f } -func (a *localArtifact) Id() string { +func (*artifact) Id() string { return a.id } -func (a *localArtifact) String() string { +func (a *artifact) String() string { return fmt.Sprintf("VM files in directory: %s", a.dir) } -func (a *localArtifact) State(name string) interface{} { +func (a *artifact) State(name string) interface{} { return nil } -func (a *localArtifact) Destroy() error { +func (a *artifact) Destroy() error { return os.RemoveAll(a.dir) } diff --git a/builder/vmware/common/driver_esx5.go b/builder/vmware/common/driver_esx5.go index 6c6b02c13..876ea7001 100644 --- a/builder/vmware/common/driver_esx5.go +++ b/builder/vmware/common/driver_esx5.go @@ -68,7 +68,7 @@ func (d *ESX5Driver) Clone(dst, src string, linked bool) error { return fmt.Errorf("Failed to copy the vmx file %s: %s", srcVmx, err) } - filesToClone, err := d.run(nil, "find", srcDir, "! -name '*.vmdk' ! -name '*.vmx' -type f") + filesToClone, err := d.run(nil, "find", srcDir, "! -name '*.vmdk' ! -name '*.vmx' -type f ! -size 0") if err != nil { return fmt.Errorf("Failed to get the file list to copy: %s", err) } @@ -96,22 +96,6 @@ func (d *ESX5Driver) Clone(dst, src string, linked bool) error { return fmt.Errorf("Failing to clone disk %s: %s", srcDisk, err) } } - - // - // // FIXME: VMName should be taken from the config. - // vmxEdits := []string{ - // "s/\\(display[Nn]ame = \\).*/\\1\"" + vmName + "\"/", - // "/ethernet..generated[aA]ddress =/d", - // "/uuid.bios =/d", - // "/uuid.location =/d", - // "/vc.uuid =/d", - // } - // for _, edit := range vmxEdits { - // err := d.sh("sed -i -e", "'", edit, "'", dstVmx) - // if err != nil { - // return fmt.Errorf("Failed to edit the destination file %s: %s", dstVmx, err) - // } - // } log.Printf("Successfully cloned %s to %s\n", src, dst) return nil } @@ -460,7 +444,11 @@ func (ESX5Driver) UpdateVMX(_, password string, port uint, data map[string]strin } func (d *ESX5Driver) CommHost(state multistep.StateBag) (string, error) { - port := d.CommConfig.Port() + sshc := state.Get("sshConfig").(SSHConfig).Comm + port := sshc.SSHPort + if sshc.Type == "winrm" { + port = sshc.WinRMPort + } if address, ok := state.GetOk("vm_address"); ok { return address.(string), nil diff --git a/builder/vmware/iso/artifact.go b/builder/vmware/common/remote_artifact.go similarity index 65% rename from builder/vmware/iso/artifact.go rename to builder/vmware/common/remote_artifact.go index 026b4580f..37dbc1812 100644 --- a/builder/vmware/iso/artifact.go +++ b/builder/vmware/common/remote_artifact.go @@ -1,4 +1,4 @@ -package iso +package common import ( "fmt" @@ -12,7 +12,7 @@ const ( // Artifact is the result of running the VMware builder, namely a set // of files associated with the resulting machine. -type Artifact struct { +type RemoteArtifact struct { builderId string id string dir OutputDir @@ -20,26 +20,26 @@ type Artifact struct { config map[string]string } -func (a *Artifact) BuilderId() string { +func (a *RemoteArtifact) BuilderId() string { return a.builderId } -func (a *Artifact) Files() []string { +func (a *RemoteArtifact) Files() []string { return a.f } -func (a *Artifact) Id() string { +func (*RemoteArtifact) Id() string { return a.id } -func (a *Artifact) String() string { +func (a *RemoteArtifact) String() string { return fmt.Sprintf("VM files in directory: %s", a.dir) } -func (a *Artifact) State(name string) interface{} { +func (a *RemoteArtifact) State(name string) interface{} { return a.config[name] } -func (a *Artifact) Destroy() error { +func (a *RemoteArtifact) Destroy() error { return a.dir.RemoveAll() } diff --git a/builder/vmware/iso/artifact_test.go b/builder/vmware/common/remote_artifact_test.go similarity index 84% rename from builder/vmware/iso/artifact_test.go rename to builder/vmware/common/remote_artifact_test.go index ea4bab42b..292a87b54 100644 --- a/builder/vmware/iso/artifact_test.go +++ b/builder/vmware/common/remote_artifact_test.go @@ -1,4 +1,4 @@ -package iso +package common import ( "testing" @@ -8,7 +8,7 @@ import ( func TestArtifact_Impl(t *testing.T) { var raw interface{} - raw = &Artifact{} + raw = &RemoteArtifact{} if _, ok := raw.(packer.Artifact); !ok { t.Fatal("Artifact must be a proper artifact") } diff --git a/builder/vmware/iso/builder.go b/builder/vmware/iso/builder.go index 0573e6c9c..e81431fcf 100644 --- a/builder/vmware/iso/builder.go +++ b/builder/vmware/iso/builder.go @@ -19,8 +19,6 @@ import ( "github.com/hashicorp/packer/template/interpolate" ) -const BuilderIdESX = "mitchellh.vmware-esx" - type Builder struct { config Config runner multistep.Runner @@ -257,9 +255,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe } // Determine the output dir implementation - var dir OutputDir + var dir vmwcommon.OutputDir switch d := driver.(type) { - case OutputDir: + case vmwcommon.OutputDir: dir = d default: dir = new(vmwcommon.LocalOutputDir) @@ -281,6 +279,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe state.Put("driver", driver) state.Put("hook", hook) state.Put("ui", ui) + state.Put("sshConfig", &b.config.SSHConfig) steps := []multistep.Step{ &vmwcommon.StepPrepareTools{ @@ -413,30 +412,13 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe dir.SetOutputDir(exportOutputPath) files, err = dir.ListFiles() } else { - files, err = state.Get("dir").(OutputDir).ListFiles() + files, err = state.Get("dir").(vmwcommon.OutputDir).ListFiles() } if err != nil { return nil, err } - // Set the proper builder ID - builderId := vmwcommon.BuilderId - if b.config.RemoteType != "" { - builderId = BuilderIdESX - } - - config := make(map[string]string) - config[ArtifactConfKeepRegistered] = strconv.FormatBool(b.config.KeepRegistered) - config[ArtifactConfFormat] = b.config.Format - config[ArtifactConfSkipExport] = strconv.FormatBool(b.config.SkipExport) - - return &Artifact{ - builderId: builderId, - id: b.config.VMName, - dir: dir, - f: files, - config: config, - }, nil + return vmwcommon.NewArtifact(dir, files, b.config.RemoteType != ""), nil } func (b *Builder) Cancel() { diff --git a/builder/vmware/iso/output_dir.go b/builder/vmware/iso/output_dir.go deleted file mode 100644 index 30eab2e31..000000000 --- a/builder/vmware/iso/output_dir.go +++ /dev/null @@ -1,14 +0,0 @@ -package iso - -// OutputDir is an interface type that abstracts the creation and handling -// of the output directory for VMware-based products. The abstraction is made -// so that the output directory can be properly made on remote (ESXi) based -// VMware products as well as local. -type OutputDir interface { - DirExists() (bool, error) - ListFiles() ([]string, error) - MkdirAll() error - Remove(string) error - RemoveAll() error - SetOutputDir(string) -} diff --git a/builder/vmware/vmx/builder.go b/builder/vmware/vmx/builder.go index 2034e57d9..088868eda 100644 --- a/builder/vmware/vmx/builder.go +++ b/builder/vmware/vmx/builder.go @@ -39,8 +39,17 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe return nil, fmt.Errorf("Failed creating VMware driver: %s", err) } - // Setup the directory - dir := new(vmwcommon.LocalOutputDir) + // Determine the output dir implementation + var dir vmwcommon.OutputDir + switch d := driver.(type) { + case vmwcommon.OutputDir: + dir = d + default: + dir = new(vmwcommon.LocalOutputDir) + } + if b.config.RemoteType != "" { + b.config.OutputDir = b.config.VMName + } dir.SetOutputDir(b.config.OutputDir) // Set up the state. @@ -51,6 +60,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe state.Put("driver", driver) state.Put("hook", hook) state.Put("ui", ui) + state.Put("sshConfig", b.config.SSHConfig) // Build the steps. steps := []multistep.Step{ @@ -138,6 +148,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe RemoveEthernetInterfaces: b.config.VMXConfig.VMXRemoveEthernet, VNCEnabled: !b.config.DisableVNC, }, + &vmwcommon.StepUploadVMX{ + RemoteType: b.config.RemoteType, + }, } // Run the steps. @@ -157,8 +170,12 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe if _, ok := state.GetOk(multistep.StateHalted); ok { return nil, errors.New("Build was halted.") } + files, err := state.Get("dir").(vmwcommon.OutputDir).ListFiles() + if err != nil { + return nil, err + } - return vmwcommon.NewLocalArtifact(b.config.VMName, b.config.OutputDir) + return vmwcommon.NewArtifact(dir, files, b.config.RemoteType != ""), nil } // Cancel.