From fcdcb26ba95b0fae299b9654861c36cfe54fb3dd Mon Sep 17 00:00:00 2001 From: "Dax T. Games" Date: Thu, 16 May 2019 13:15:55 -0400 Subject: [PATCH 1/2] packer 1.4+ compatibility --- main.go | 3 +- .../post-processor.go | 29 ++++++++++--------- 2 files changed, 17 insertions(+), 15 deletions(-) rename post-processor.go => vsphereova/post-processor.go (91%) diff --git a/main.go b/main.go index 8f5435b..caa1e8f 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "github.com/banno/packer-post-processor-vsphere-ova/vsphereova" "github.com/hashicorp/packer/packer/plugin" ) @@ -9,6 +10,6 @@ func main() { if err != nil { panic(err) } - server.RegisterPostProcessor(new(PostProcessor)) + server.RegisterPostProcessor(new(vsphereova.PostProcessor)) server.Serve() } diff --git a/post-processor.go b/vsphereova/post-processor.go similarity index 91% rename from post-processor.go rename to vsphereova/post-processor.go index ba68bf4..a7f46d0 100644 --- a/post-processor.go +++ b/vsphereova/post-processor.go @@ -1,6 +1,7 @@ -package main +package vsphereova import ( + "context" "bytes" "crypto/tls" "fmt" @@ -13,7 +14,6 @@ import ( "github.com/vmware/govmomi" "github.com/vmware/govmomi/find" "github.com/vmware/govmomi/vim25/types" - "golang.org/x/net/context" "io/ioutil" "net/http" "net/url" @@ -189,9 +189,10 @@ func (p *PostProcessor) RemoveOpticalDrive(vmx string, ui packer.Ui) error { return nil } -func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) { +// func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) { +func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, bool, error) { if _, ok := builtins[artifact.BuilderId()]; !ok { - return nil, false, fmt.Errorf("Unknown artifact type, can't build box: %s", artifact.BuilderId()) + return nil, false, false, fmt.Errorf("Unknown artifact type, can't build box: %s", artifact.BuilderId()) } ova := "" @@ -209,7 +210,7 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac } if ova == "" && (vmx == "" || vmdk == "") { - return nil, false, fmt.Errorf("ERROR: Neither OVA or VMX/VMDK were found!") + return nil, false, false, fmt.Errorf("ERROR: Neither OVA or VMX/VMDK were found!") } if ova != "" { @@ -231,7 +232,7 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac var ovftoolOut bytes.Buffer command.Stdout = &ovftoolOut if err := command.Run(); err != nil { - return nil, false, fmt.Errorf("Failed: %s\nStdout: %s", err, ovftoolOut.String()) + return nil, false, false, fmt.Errorf("Failed: %s\nStdout: %s", err, ovftoolOut.String()) } ui.Message(fmt.Sprintf("%s", ovftoolOut.String())) @@ -242,25 +243,25 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac if p.config.RemoveEthernet == "true" { if err := p.RemoveEthernet(vmx, ui); err != nil { - return nil, false, fmt.Errorf("Removing ethernet0 interface from VMX failed!") + return nil, false, false, fmt.Errorf("Removing ethernet0 interface from VMX failed!") } } if p.config.RemoveFloppy == "true" { if err := p.RemoveFloppy(vmx, ui); err != nil { - return nil, false, fmt.Errorf("Removing floppy drive from VMX failed!") + return nil, false, false, fmt.Errorf("Removing floppy drive from VMX failed!") } } if p.config.RemoveOpticalDrive == "true" { if err := p.RemoveOpticalDrive(vmx, ui); err != nil { - return nil, false, fmt.Errorf("Removing CD/DVD Drive from VMX failed!") + return nil, false, false, fmt.Errorf("Removing CD/DVD Drive from VMX failed!") } } if p.config.VirtualHardwareVer != "" { if err := p.SetVHardwareVersion(vmx, ui, p.config.VirtualHardwareVer); err != nil { - return nil, false, fmt.Errorf("Setting the Virtual Hardware Version in VMX failed!") + return nil, false, false, fmt.Errorf("Setting the Virtual Hardware Version in VMX failed!") } } @@ -289,7 +290,7 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac vmdk) if err != nil { - return nil, false, fmt.Errorf("Failed: %s", err) + return nil, false, false, fmt.Errorf("Failed: %s", err) } ui.Message(fmt.Sprintf("Uploaded %s", vmdk)) @@ -306,7 +307,7 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac vmx) if err != nil { - return nil, false, fmt.Errorf("Failed: %s", err) + return nil, false, false, fmt.Errorf("Failed: %s", err) } ui.Message(fmt.Sprintf("Uploaded %s", vmx)) @@ -314,11 +315,11 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac err = doRegistration(ui, p.config, vmx, clonerequired) if err != nil { - return nil, false, fmt.Errorf("Failed: %s", err) + return nil, false, false, fmt.Errorf("Failed: %s", err) } ui.Message("Uploaded and registered to VMware") - return artifact, false, nil + return artifact, false, false, nil } func doUpload(ui packer.Ui, url string, file string) error { From 4dbbef7f008ea25b06939d514666305409018560 Mon Sep 17 00:00:00 2001 From: "Dax T. Games" Date: Fri, 17 May 2019 10:00:09 -0400 Subject: [PATCH 2/2] . --- vsphereova/post-processor.go | 958 +++++++++++++++++------------------ 1 file changed, 479 insertions(+), 479 deletions(-) diff --git a/vsphereova/post-processor.go b/vsphereova/post-processor.go index a7f46d0..a4dfc13 100644 --- a/vsphereova/post-processor.go +++ b/vsphereova/post-processor.go @@ -2,537 +2,537 @@ package vsphereova import ( "context" - "bytes" - "crypto/tls" - "fmt" - "github.com/cheggaaa/pb" - vmwarecommon "github.com/hashicorp/packer/builder/vmware/common" - "github.com/hashicorp/packer/common" - "github.com/hashicorp/packer/helper/config" - "github.com/hashicorp/packer/packer" - "github.com/hashicorp/packer/template/interpolate" - "github.com/vmware/govmomi" - "github.com/vmware/govmomi/find" - "github.com/vmware/govmomi/vim25/types" - "io/ioutil" - "net/http" - "net/url" - "os" - "os/exec" - "strings" - "time" + "bytes" + "crypto/tls" + "fmt" + "github.com/cheggaaa/pb" + vmwarecommon "github.com/hashicorp/packer/builder/vmware/common" + "github.com/hashicorp/packer/common" + "github.com/hashicorp/packer/helper/config" + "github.com/hashicorp/packer/packer" + "github.com/hashicorp/packer/template/interpolate" + "github.com/vmware/govmomi" + "github.com/vmware/govmomi/find" + "github.com/vmware/govmomi/vim25/types" + "io/ioutil" + "net/http" + "net/url" + "os" + "os/exec" + "strings" + "time" ) var builtins = map[string]string{ - "mitchellh.virtualbox": "virtualbox", - "mitchellh.vmware": "vmware", + "mitchellh.virtualbox": "virtualbox", + "mitchellh.vmware": "vmware", } type Config struct { - common.PackerConfig `mapstructure:",squash"` - - Datacenter string `mapstructure:"datacenter"` - Datastore string `mapstructure:"datastore"` - Host string `mapstructure:"host"` - Password string `mapstructure:"password"` - Username string `mapstructure:"username"` - VMFolder string `mapstructure:"vm_folder"` - VMNetwork string `mapstructure:"vm_network"` - RemoveEthernet string `mapstructure:"remove_ethernet"` - RemoveFloppy string `mapstructure:"remove_floppy"` - RemoveOpticalDrive string `mapstructure:"remove_optical_drive"` - VirtualHardwareVer string `mapstructure:"virtual_hardware_version"` - ctx interpolate.Context + common.PackerConfig `mapstructure:",squash"` + + Datacenter string `mapstructure:"datacenter"` + Datastore string `mapstructure:"datastore"` + Host string `mapstructure:"host"` + Password string `mapstructure:"password"` + Username string `mapstructure:"username"` + VMFolder string `mapstructure:"vm_folder"` + VMNetwork string `mapstructure:"vm_network"` + RemoveEthernet string `mapstructure:"remove_ethernet"` + RemoveFloppy string `mapstructure:"remove_floppy"` + RemoveOpticalDrive string `mapstructure:"remove_optical_drive"` + VirtualHardwareVer string `mapstructure:"virtual_hardware_version"` + ctx interpolate.Context } type PostProcessor struct { - config Config + config Config } func (p *PostProcessor) Configure(raws ...interface{}) error { - err := config.Decode(&p.config, &config.DecodeOpts{ - Interpolate: true, - InterpolateFilter: &interpolate.RenderFilter{ - Exclude: []string{}, - }, - }, raws...) - - if err != nil { - return err - } - - // Defaults - if p.config.RemoveEthernet == "" { - p.config.RemoveEthernet = "false" - } - - if p.config.RemoveFloppy == "" { - p.config.RemoveFloppy = "false" - } - - if p.config.RemoveOpticalDrive == "" { - p.config.RemoveOpticalDrive = "false" - } - - if p.config.VirtualHardwareVer == "" { - p.config.VirtualHardwareVer = "10" - } - - // Accumulate any errors - errs := new(packer.MultiError) - - if _, err := exec.LookPath("ovftool"); err != nil { - errs = packer.MultiErrorAppend( - errs, fmt.Errorf("ovftool not found: %s", err)) - } - - // First define all our templatable parameters that are _required_ - templates := map[string]*string{ - "datacenter": &p.config.Datacenter, - "host": &p.config.Host, - "password": &p.config.Password, - "username": &p.config.Username, - "datastore": &p.config.Datastore, - "vm_folder": &p.config.VMFolder, - } - - for key, ptr := range templates { - if *ptr == "" { - errs = packer.MultiErrorAppend( - errs, fmt.Errorf("%s must be set", key)) - } - } - - if len(errs.Errors) > 0 { - return errs - } - - return nil + err := config.Decode(&p.config, &config.DecodeOpts{ + Interpolate: true, + InterpolateFilter: &interpolate.RenderFilter{ + Exclude: []string{}, + }, + }, raws...) + + if err != nil { + return err + } + + // Defaults + if p.config.RemoveEthernet == "" { + p.config.RemoveEthernet = "false" + } + + if p.config.RemoveFloppy == "" { + p.config.RemoveFloppy = "false" + } + + if p.config.RemoveOpticalDrive == "" { + p.config.RemoveOpticalDrive = "false" + } + + if p.config.VirtualHardwareVer == "" { + p.config.VirtualHardwareVer = "10" + } + + // Accumulate any errors + errs := new(packer.MultiError) + + if _, err := exec.LookPath("ovftool"); err != nil { + errs = packer.MultiErrorAppend( + errs, fmt.Errorf("ovftool not found: %s", err)) + } + + // First define all our templatable parameters that are _required_ + templates := map[string]*string{ + "datacenter": &p.config.Datacenter, + "host": &p.config.Host, + "password": &p.config.Password, + "username": &p.config.Username, + "datastore": &p.config.Datastore, + "vm_folder": &p.config.VMFolder, + } + + for key, ptr := range templates { + if *ptr == "" { + errs = packer.MultiErrorAppend( + errs, fmt.Errorf("%s must be set", key)) + } + } + + if len(errs.Errors) > 0 { + return errs + } + + return nil } func (p *PostProcessor) RemoveFloppy(vmx string, ui packer.Ui) error { - ui.Message(fmt.Sprintf("Removing floppy from %s", vmx)) - vmxData, err := vmwarecommon.ReadVMX(vmx) - if err != nil { - return err - } - for k, _ := range vmxData { - if strings.HasPrefix(k, "floppy0.") { - delete(vmxData, k) - } - } - vmxData["floppy0.present"] = "FALSE" - if err := vmwarecommon.WriteVMX(vmx, vmxData); err != nil { - return err - } - return nil + ui.Message(fmt.Sprintf("Removing floppy from %s", vmx)) + vmxData, err := vmwarecommon.ReadVMX(vmx) + if err != nil { + return err + } + for k, _ := range vmxData { + if strings.HasPrefix(k, "floppy0.") { + delete(vmxData, k) + } + } + vmxData["floppy0.present"] = "FALSE" + if err := vmwarecommon.WriteVMX(vmx, vmxData); err != nil { + return err + } + return nil } func (p *PostProcessor) RemoveEthernet(vmx string, ui packer.Ui) error { - ui.Message(fmt.Sprintf("Removing ethernet0 intercace from %s", vmx)) - vmxData, err := vmwarecommon.ReadVMX(vmx) - if err != nil { - return err - } - - for k, _ := range vmxData { - if strings.HasPrefix(k, "ethernet0.") { - delete(vmxData, k) - } - } - - vmxData["ethernet0.present"] = "FALSE" - if err := vmwarecommon.WriteVMX(vmx, vmxData); err != nil { - return err - } - - return nil + ui.Message(fmt.Sprintf("Removing ethernet0 intercace from %s", vmx)) + vmxData, err := vmwarecommon.ReadVMX(vmx) + if err != nil { + return err + } + + for k, _ := range vmxData { + if strings.HasPrefix(k, "ethernet0.") { + delete(vmxData, k) + } + } + + vmxData["ethernet0.present"] = "FALSE" + if err := vmwarecommon.WriteVMX(vmx, vmxData); err != nil { + return err + } + + return nil } func (p *PostProcessor) SetVHardwareVersion(vmx string, ui packer.Ui, hwversion string) error { - ui.Message(fmt.Sprintf("Setting the hardware version in the vmx to version '%s'", hwversion)) - - vmxContent, err := ioutil.ReadFile(vmx) - lines := strings.Split(string(vmxContent), "\n") - for i, line := range lines { - if strings.Contains(line, "virtualhw.version") { - lines[i] = fmt.Sprintf("virtualhw.version = \"%s\"", hwversion) - } - } - output := strings.Join(lines, "\n") - err = ioutil.WriteFile(vmx, []byte(output), 0644) - if err != nil { - return err - } - - return nil + ui.Message(fmt.Sprintf("Setting the hardware version in the vmx to version '%s'", hwversion)) + + vmxContent, err := ioutil.ReadFile(vmx) + lines := strings.Split(string(vmxContent), "\n") + for i, line := range lines { + if strings.Contains(line, "virtualhw.version") { + lines[i] = fmt.Sprintf("virtualhw.version = \"%s\"", hwversion) + } + } + output := strings.Join(lines, "\n") + err = ioutil.WriteFile(vmx, []byte(output), 0644) + if err != nil { + return err + } + + return nil } func (p *PostProcessor) RemoveOpticalDrive(vmx string, ui packer.Ui) error { - ui.Message(fmt.Sprintf("Removing optical drive from %s", vmx)) - vmxData, err := vmwarecommon.ReadVMX(vmx) - if err != nil { - return err - } - - for k, _ := range vmxData { - if strings.HasPrefix(k, "ide1:0.file") { - delete(vmxData, k) - } - } - - vmxData["ide1:0.present"] = "FALSE" - - if err := vmwarecommon.WriteVMX(vmx, vmxData); err != nil { - return err - } - return nil + ui.Message(fmt.Sprintf("Removing optical drive from %s", vmx)) + vmxData, err := vmwarecommon.ReadVMX(vmx) + if err != nil { + return err + } + + for k, _ := range vmxData { + if strings.HasPrefix(k, "ide1:0.file") { + delete(vmxData, k) + } + } + + vmxData["ide1:0.present"] = "FALSE" + + if err := vmwarecommon.WriteVMX(vmx, vmxData); err != nil { + return err + } + return nil } // func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) { func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, bool, error) { - if _, ok := builtins[artifact.BuilderId()]; !ok { - return nil, false, false, fmt.Errorf("Unknown artifact type, can't build box: %s", artifact.BuilderId()) - } - - ova := "" - vmx := "" - vmdk := "" - for _, path := range artifact.Files() { - if strings.HasSuffix(path, ".ova") { - ova = path - break - } else if strings.HasSuffix(path, ".vmx") { - vmx = path - } else if strings.HasSuffix(path, ".vmdk") { - vmdk = path - } - } - - if ova == "" && (vmx == "" || vmdk == "") { - return nil, false, false, fmt.Errorf("ERROR: Neither OVA or VMX/VMDK were found!") - } - - if ova != "" { - // Sweet, we've got an OVA, Now it's time to make that baby something we can work with. - var args []string - if p.config.RemoveEthernet != "true" { - args = append(args, - "--allowExtraConfig", - fmt.Sprintf("--extraConfig:ethernet0.networkName=%s", p.config.VMNetwork), - ) - } - args = append(args, - "--lax", - ova, - fmt.Sprintf("%s.vmx", strings.TrimSuffix(ova, ".ova")), - ) - - command := exec.Command("ovftool", args...) - var ovftoolOut bytes.Buffer - command.Stdout = &ovftoolOut - if err := command.Run(); err != nil { - return nil, false, false, fmt.Errorf("Failed: %s\nStdout: %s", err, ovftoolOut.String()) - } - - ui.Message(fmt.Sprintf("%s", ovftoolOut.String())) - - vmdk = fmt.Sprintf("%s-disk1.vmdk", strings.TrimSuffix(ova, ".ova")) - vmx = fmt.Sprintf("%s.vmx", strings.TrimSuffix(ova, ".ova")) - } - - if p.config.RemoveEthernet == "true" { - if err := p.RemoveEthernet(vmx, ui); err != nil { - return nil, false, false, fmt.Errorf("Removing ethernet0 interface from VMX failed!") - } - } - - if p.config.RemoveFloppy == "true" { - if err := p.RemoveFloppy(vmx, ui); err != nil { - return nil, false, false, fmt.Errorf("Removing floppy drive from VMX failed!") - } - } - - if p.config.RemoveOpticalDrive == "true" { - if err := p.RemoveOpticalDrive(vmx, ui); err != nil { - return nil, false, false, fmt.Errorf("Removing CD/DVD Drive from VMX failed!") - } - } - - if p.config.VirtualHardwareVer != "" { - if err := p.SetVHardwareVersion(vmx, ui, p.config.VirtualHardwareVer); err != nil { - return nil, false, false, fmt.Errorf("Setting the Virtual Hardware Version in VMX failed!") - } - } - - ui.Message(fmt.Sprintf("Uploading %s and %s to Datastore %s on host %s", vmdk, vmx, p.config.Datastore, p.config.Host)) - - clonerequired := false - if p.config.RemoveEthernet == "false" || p.config.RemoveFloppy == "false" || p.config.RemoveOpticalDrive == "false" { - clonerequired = true - } - - splitString := strings.Split(vmdk, "/") - vmdkDestPath := fmt.Sprintf("folder/%s/%s", p.config.VMFolder, splitString[len(splitString)-1]) - - splitString = strings.Split(vmx, "/") - vmxDestPath := fmt.Sprintf("folder/%s/%s", p.config.VMFolder, splitString[len(splitString)-1]) - - err := doUpload( - ui, - fmt.Sprintf("https://%s:%s@%s/%s?dcPath=%s&dsName=%s", - url.QueryEscape(p.config.Username), - url.QueryEscape(p.config.Password), - p.config.Host, - vmdkDestPath, - p.config.Datacenter, - p.config.Datastore), - vmdk) - - if err != nil { - return nil, false, false, fmt.Errorf("Failed: %s", err) - } - - ui.Message(fmt.Sprintf("Uploaded %s", vmdk)) - - err = doUpload( - ui, - fmt.Sprintf("https://%s:%s@%s/%s?dcPath=%s&dsName=%s", - url.QueryEscape(p.config.Username), - url.QueryEscape(p.config.Password), - p.config.Host, - vmxDestPath, - p.config.Datacenter, - p.config.Datastore), - vmx) - - if err != nil { - return nil, false, false, fmt.Errorf("Failed: %s", err) - } - - ui.Message(fmt.Sprintf("Uploaded %s", vmx)) - - err = doRegistration(ui, p.config, vmx, clonerequired) - - if err != nil { - return nil, false, false, fmt.Errorf("Failed: %s", err) - } - ui.Message("Uploaded and registered to VMware") - - return artifact, false, false, nil + if _, ok := builtins[artifact.BuilderId()]; !ok { + return nil, false, false, fmt.Errorf("Unknown artifact type, can't build box: %s", artifact.BuilderId()) + } + + ova := "" + vmx := "" + vmdk := "" + for _, path := range artifact.Files() { + if strings.HasSuffix(path, ".ova") { + ova = path + break + } else if strings.HasSuffix(path, ".vmx") { + vmx = path + } else if strings.HasSuffix(path, ".vmdk") { + vmdk = path + } + } + + if ova == "" && (vmx == "" || vmdk == "") { + return nil, false, false, fmt.Errorf("ERROR: Neither OVA or VMX/VMDK were found!") + } + + if ova != "" { + // Sweet, we've got an OVA, Now it's time to make that baby something we can work with. + var args []string + if p.config.RemoveEthernet != "true" { + args = append(args, + "--allowExtraConfig", + fmt.Sprintf("--extraConfig:ethernet0.networkName=%s", p.config.VMNetwork), + ) + } + args = append(args, + "--lax", + ova, + fmt.Sprintf("%s.vmx", strings.TrimSuffix(ova, ".ova")), + ) + + command := exec.Command("ovftool", args...) + var ovftoolOut bytes.Buffer + command.Stdout = &ovftoolOut + if err := command.Run(); err != nil { + return nil, false, false, fmt.Errorf("Failed: %s\nStdout: %s", err, ovftoolOut.String()) + } + + ui.Message(fmt.Sprintf("%s", ovftoolOut.String())) + + vmdk = fmt.Sprintf("%s-disk1.vmdk", strings.TrimSuffix(ova, ".ova")) + vmx = fmt.Sprintf("%s.vmx", strings.TrimSuffix(ova, ".ova")) + } + + if p.config.RemoveEthernet == "true" { + if err := p.RemoveEthernet(vmx, ui); err != nil { + return nil, false, false, fmt.Errorf("Removing ethernet0 interface from VMX failed!") + } + } + + if p.config.RemoveFloppy == "true" { + if err := p.RemoveFloppy(vmx, ui); err != nil { + return nil, false, false, fmt.Errorf("Removing floppy drive from VMX failed!") + } + } + + if p.config.RemoveOpticalDrive == "true" { + if err := p.RemoveOpticalDrive(vmx, ui); err != nil { + return nil, false, false, fmt.Errorf("Removing CD/DVD Drive from VMX failed!") + } + } + + if p.config.VirtualHardwareVer != "" { + if err := p.SetVHardwareVersion(vmx, ui, p.config.VirtualHardwareVer); err != nil { + return nil, false, false, fmt.Errorf("Setting the Virtual Hardware Version in VMX failed!") + } + } + + ui.Message(fmt.Sprintf("Uploading %s and %s to Datastore %s on host %s", vmdk, vmx, p.config.Datastore, p.config.Host)) + + clonerequired := false + if p.config.RemoveEthernet == "false" || p.config.RemoveFloppy == "false" || p.config.RemoveOpticalDrive == "false" { + clonerequired = true + } + + splitString := strings.Split(vmdk, "/") + vmdkDestPath := fmt.Sprintf("folder/%s/%s", p.config.VMFolder, splitString[len(splitString)-1]) + + splitString = strings.Split(vmx, "/") + vmxDestPath := fmt.Sprintf("folder/%s/%s", p.config.VMFolder, splitString[len(splitString)-1]) + + err := doUpload( + ui, + fmt.Sprintf("https://%s:%s@%s/%s?dcPath=%s&dsName=%s", + url.QueryEscape(p.config.Username), + url.QueryEscape(p.config.Password), + p.config.Host, + vmdkDestPath, + p.config.Datacenter, + p.config.Datastore), + vmdk) + + if err != nil { + return nil, false, false, fmt.Errorf("Failed: %s", err) + } + + ui.Message(fmt.Sprintf("Uploaded %s", vmdk)) + + err = doUpload( + ui, + fmt.Sprintf("https://%s:%s@%s/%s?dcPath=%s&dsName=%s", + url.QueryEscape(p.config.Username), + url.QueryEscape(p.config.Password), + p.config.Host, + vmxDestPath, + p.config.Datacenter, + p.config.Datastore), + vmx) + + if err != nil { + return nil, false, false, fmt.Errorf("Failed: %s", err) + } + + ui.Message(fmt.Sprintf("Uploaded %s", vmx)) + + err = doRegistration(ui, p.config, vmx, clonerequired) + + if err != nil { + return nil, false, false, fmt.Errorf("Failed: %s", err) + } + ui.Message("Uploaded and registered to VMware") + + return artifact, false, false, nil } func doUpload(ui packer.Ui, url string, file string) error { - data, err := os.Open(file) - if err != nil { - return err - } - defer data.Close() + data, err := os.Open(file) + if err != nil { + return err + } + defer data.Close() - fileInfo, err := data.Stat() - if err != nil { - return err - } + fileInfo, err := data.Stat() + if err != nil { + return err + } - bar := pb.New64(fileInfo.Size()).SetUnits(pb.U_BYTES) - bar.ShowSpeed = true - bar.Callback = ui.Message - bar.RefreshRate = time.Second * 5 - bar.SetWidth(40) - reader := bar.NewProxyReader(data) + bar := pb.New64(fileInfo.Size()).SetUnits(pb.U_BYTES) + bar.ShowSpeed = true + bar.Callback = ui.Message + bar.RefreshRate = time.Second * 5 + bar.SetWidth(40) + reader := bar.NewProxyReader(data) - req, err := http.NewRequest("PUT", url, reader) - if err != nil { - return err - } + req, err := http.NewRequest("PUT", url, reader) + if err != nil { + return err + } - req.Header.Add("Content-Type", "application/x-www-form-urlencoded") - req.ContentLength = fileInfo.Size() + req.Header.Add("Content-Type", "application/x-www-form-urlencoded") + req.ContentLength = fileInfo.Size() - tr := &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, - } + tr := &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } - client := &http.Client{Transport: tr} + client := &http.Client{Transport: tr} - bar.Start() - res, err := client.Do(req) - bar.Finish() + bar.Start() + res, err := client.Do(req) + bar.Finish() - if err != nil { - return err - } + if err != nil { + return err + } - defer res.Body.Close() + defer res.Body.Close() - return nil + return nil } func doRegistration(ui packer.Ui, config Config, vmx string, clonerequired bool) error { - sdkURL, err := url.Parse(fmt.Sprintf("https://%s:%s@%s/sdk", - url.QueryEscape(config.Username), - url.QueryEscape(config.Password), - config.Host)) - if err != nil { - return err - } + sdkURL, err := url.Parse(fmt.Sprintf("https://%s:%s@%s/sdk", + url.QueryEscape(config.Username), + url.QueryEscape(config.Password), + config.Host)) + if err != nil { + return err + } - client, err := govmomi.NewClient(context.TODO(), sdkURL, true) + client, err := govmomi.NewClient(context.TODO(), sdkURL, true) - if err != nil { - return err - } + if err != nil { + return err + } - finder := find.NewFinder(client.Client, false) + finder := find.NewFinder(client.Client, false) datacenter, err := finder.DatacenterOrDefault(context.TODO(), config.Datacenter) - if err != nil { - return err - } + if err != nil { + return err + } finder.SetDatacenter(datacenter) - folders, err := datacenter.Folders(context.TODO()) - if err != nil { - return err - } - - resourcePool, err := finder.DefaultResourcePool(context.TODO()) - - if err != nil { - return err - } - - splitString := strings.Split(vmx, "/") - last := splitString[len(splitString)-1] - vmName := strings.TrimSuffix(last, ".vmx") - - datastoreString := fmt.Sprintf("[%s] %s/%s.vmx", config.Datastore, config.VMFolder, vmName) - - ui.Message(fmt.Sprintf("Registering %s from %s", vmName, datastoreString)) - task, err := folders.VmFolder.RegisterVM(context.TODO(), datastoreString, vmName, false, resourcePool, nil) - if err != nil { - return err - } - _, err = task.WaitForResult(context.TODO(), nil) - if err != nil { - return err - } - ui.Message(fmt.Sprintf("Registererd VM %s", vmName)) + folders, err := datacenter.Folders(context.TODO()) + if err != nil { + return err + } + + resourcePool, err := finder.DefaultResourcePool(context.TODO()) + + if err != nil { + return err + } + + splitString := strings.Split(vmx, "/") + last := splitString[len(splitString)-1] + vmName := strings.TrimSuffix(last, ".vmx") + + datastoreString := fmt.Sprintf("[%s] %s/%s.vmx", config.Datastore, config.VMFolder, vmName) + + ui.Message(fmt.Sprintf("Registering %s from %s", vmName, datastoreString)) + task, err := folders.VmFolder.RegisterVM(context.TODO(), datastoreString, vmName, false, resourcePool, nil) + if err != nil { + return err + } + _, err = task.WaitForResult(context.TODO(), nil) + if err != nil { + return err + } + ui.Message(fmt.Sprintf("Registererd VM %s", vmName)) - vm, err := finder.VirtualMachine(context.TODO(), vmName) - - rpRef := resourcePool.Reference() - - if clonerequired { - cloneSpec := types.VirtualMachineCloneSpec{ - Location: types.VirtualMachineRelocateSpec{ - Pool: &rpRef, - }, - } - - cloneVmName := fmt.Sprintf("%s-vm", vmName) - - ui.Message(fmt.Sprintf("Cloning VM %s", cloneVmName)) - task, err = vm.Clone(context.TODO(), folders.VmFolder, cloneVmName, cloneSpec) - - if err != nil { - return err - } - - _, err = task.WaitForResult(context.TODO(), nil) - - if err != nil { - return err - } - - clonedVM, err := finder.VirtualMachine(context.TODO(), cloneVmName) - - if err != nil { - return err - } - - ui.Message(fmt.Sprintf("Powering on %s", cloneVmName)) - task, err = clonedVM.PowerOn(context.TODO()) - - if err != nil { - return err - } - - _, err = task.WaitForResult(context.TODO(), nil) - if err != nil { - return err - } - - ui.Message(fmt.Sprintf("Powered on %s", cloneVmName)) - - timeout := time.After(5 * time.Minute) - tick := time.Tick(500 * time.Millisecond) - - LoopWaitForVMToolsRunning: - for { - select { - case <-timeout: - task, err = clonedVM.PowerOff(context.TODO()) - if err != nil { - return err - } - _, err = task.WaitForResult(context.TODO(), nil) - if err != nil { - return err - } - return fmt.Errorf("Timed out while waiting for VM Tools to be recogonized") - case <-tick: - running, err := clonedVM.IsToolsRunning(context.TODO()) - if err != nil { - return err - } - if running { - break LoopWaitForVMToolsRunning - } - } - } - - ui.Message(fmt.Sprintf("Powering off %s", cloneVmName)) - task, err = clonedVM.PowerOff(context.TODO()) - - if err != nil { - return err - } - - _, err = task.WaitForResult(context.TODO(), nil) - - if err != nil { - return err - } - ui.Message(fmt.Sprintf("Powered off %s", cloneVmName)) - - ui.Message(fmt.Sprintf("Marking as template %s", cloneVmName)) - err = clonedVM.MarkAsTemplate(context.TODO()) - - if err != nil { - return err - } - - ui.Message(fmt.Sprintf("Destroying %s", cloneVmName)) - task, err = vm.Destroy(context.TODO()) - - _, err = task.WaitForResult(context.TODO(), nil) - - if err != nil { - return err - } - ui.Message(fmt.Sprintf("Destroyed %s", cloneVmName)) - } else { - ui.Message(fmt.Sprintf("Marking as template %s", vmName)) - err = vm.MarkAsTemplate(context.TODO()) - - if err != nil { - return err - } - ui.Message(fmt.Sprintf("%s is now a template", vmName)) - } - - return nil + vm, err := finder.VirtualMachine(context.TODO(), vmName) + + rpRef := resourcePool.Reference() + + if clonerequired { + cloneSpec := types.VirtualMachineCloneSpec{ + Location: types.VirtualMachineRelocateSpec{ + Pool: &rpRef, + }, + } + + cloneVmName := fmt.Sprintf("%s-vm", vmName) + + ui.Message(fmt.Sprintf("Cloning VM %s", cloneVmName)) + task, err = vm.Clone(context.TODO(), folders.VmFolder, cloneVmName, cloneSpec) + + if err != nil { + return err + } + + _, err = task.WaitForResult(context.TODO(), nil) + + if err != nil { + return err + } + + clonedVM, err := finder.VirtualMachine(context.TODO(), cloneVmName) + + if err != nil { + return err + } + + ui.Message(fmt.Sprintf("Powering on %s", cloneVmName)) + task, err = clonedVM.PowerOn(context.TODO()) + + if err != nil { + return err + } + + _, err = task.WaitForResult(context.TODO(), nil) + if err != nil { + return err + } + + ui.Message(fmt.Sprintf("Powered on %s", cloneVmName)) + + timeout := time.After(5 * time.Minute) + tick := time.Tick(500 * time.Millisecond) + + LoopWaitForVMToolsRunning: + for { + select { + case <-timeout: + task, err = clonedVM.PowerOff(context.TODO()) + if err != nil { + return err + } + _, err = task.WaitForResult(context.TODO(), nil) + if err != nil { + return err + } + return fmt.Errorf("Timed out while waiting for VM Tools to be recogonized") + case <-tick: + running, err := clonedVM.IsToolsRunning(context.TODO()) + if err != nil { + return err + } + if running { + break LoopWaitForVMToolsRunning + } + } + } + + ui.Message(fmt.Sprintf("Powering off %s", cloneVmName)) + task, err = clonedVM.PowerOff(context.TODO()) + + if err != nil { + return err + } + + _, err = task.WaitForResult(context.TODO(), nil) + + if err != nil { + return err + } + ui.Message(fmt.Sprintf("Powered off %s", cloneVmName)) + + ui.Message(fmt.Sprintf("Marking as template %s", cloneVmName)) + err = clonedVM.MarkAsTemplate(context.TODO()) + + if err != nil { + return err + } + + ui.Message(fmt.Sprintf("Destroying %s", cloneVmName)) + task, err = vm.Destroy(context.TODO()) + + _, err = task.WaitForResult(context.TODO(), nil) + + if err != nil { + return err + } + ui.Message(fmt.Sprintf("Destroyed %s", cloneVmName)) + } else { + ui.Message(fmt.Sprintf("Marking as template %s", vmName)) + err = vm.MarkAsTemplate(context.TODO()) + + if err != nil { + return err + } + ui.Message(fmt.Sprintf("%s is now a template", vmName)) + } + + return nil }