Merge pull request #1154 from rasa/765-add-tools-upload-flavor-support-in-vmware-vmx

builder/vmware-vmx: Added tools_upload_flavor support
This commit is contained in:
Mitchell Hashimoto 2014-05-10 10:07:34 -07:00
commit 1b1d87128c
7 changed files with 154 additions and 96 deletions

View File

@ -0,0 +1,40 @@
package common
import (
"fmt"
"github.com/mitchellh/multistep"
"os"
)
type StepPrepareTools struct {
RemoteType string `mapstructure:"remote_type"`
ToolsUploadFlavor string `mapstructure:"tools_upload_flavor"`
ToolsUploadPath string `mapstructure:"tools_upload_path"`
}
func (c *StepPrepareTools) Run(state multistep.StateBag) multistep.StepAction {
driver := state.Get("driver").(Driver)
if c.RemoteType == "esx5" {
return multistep.ActionContinue
}
if c.ToolsUploadFlavor == "" {
return multistep.ActionContinue
}
path := driver.ToolsIsoPath(c.ToolsUploadFlavor)
if _, err := os.Stat(path); err != nil {
state.Put("error", fmt.Errorf(
"Couldn't find VMware tools for '%s'! VMware often downloads these\n"+
"tools on-demand. However, to do this, you need to create a fake VM\n"+
"of the proper type then click the 'install tools' option in the\n"+
"VMware GUI.", c.ToolsUploadFlavor))
return multistep.ActionHalt
}
state.Put("tools_upload_source", path)
return multistep.ActionContinue
}
func (c *StepPrepareTools) Cleanup(multistep.StateBag) {}

View File

@ -1,9 +1,8 @@
package iso
package common
import (
"fmt"
"github.com/mitchellh/multistep"
vmwcommon "github.com/mitchellh/packer/builder/vmware/common"
"github.com/mitchellh/packer/packer"
"os"
)
@ -12,20 +11,24 @@ type toolsUploadPathTemplate struct {
Flavor string
}
type stepUploadTools struct{}
type StepUploadTools struct {
RemoteType string `mapstructure:"remote_type"`
ToolsUploadFlavor string `mapstructure:"tools_upload_flavor"`
ToolsUploadPath string `mapstructure:"tools_upload_path"`
Tpl *packer.ConfigTemplate
}
func (*stepUploadTools) Run(state multistep.StateBag) multistep.StepAction {
config := state.Get("config").(*config)
driver := state.Get("driver").(vmwcommon.Driver)
func (c *StepUploadTools) Run(state multistep.StateBag) multistep.StepAction {
driver := state.Get("driver").(Driver)
if config.RemoteType == "esx5" {
if c.RemoteType == "esx5" {
if err := driver.ToolsInstall(); err != nil {
state.Put("error", fmt.Errorf("Couldn't mount VMware tools ISO."))
}
return multistep.ActionContinue
}
if config.ToolsUploadFlavor == "" {
if c.ToolsUploadFlavor == "" {
return multistep.ActionContinue
}
@ -33,7 +36,7 @@ func (*stepUploadTools) Run(state multistep.StateBag) multistep.StepAction {
tools_source := state.Get("tools_upload_source").(string)
ui := state.Get("ui").(packer.Ui)
ui.Say(fmt.Sprintf("Uploading the '%s' VMware Tools", config.ToolsUploadFlavor))
ui.Say(fmt.Sprintf("Uploading the '%s' VMware Tools", c.ToolsUploadFlavor))
f, err := os.Open(tools_source)
if err != nil {
state.Put("error", fmt.Errorf("Error opening VMware Tools ISO: %s", err))
@ -41,8 +44,10 @@ func (*stepUploadTools) Run(state multistep.StateBag) multistep.StepAction {
}
defer f.Close()
tplData := &toolsUploadPathTemplate{Flavor: config.ToolsUploadFlavor}
config.ToolsUploadPath, err = config.tpl.Process(config.ToolsUploadPath, tplData)
tplData := &toolsUploadPathTemplate{
Flavor: c.ToolsUploadFlavor,
}
c.ToolsUploadPath, err = c.Tpl.Process(c.ToolsUploadPath, tplData)
if err != nil {
err := fmt.Errorf("Error preparing upload path: %s", err)
state.Put("error", err)
@ -50,7 +55,7 @@ func (*stepUploadTools) Run(state multistep.StateBag) multistep.StepAction {
return multistep.ActionHalt
}
if err := comm.Upload(config.ToolsUploadPath, f); err != nil {
if err := comm.Upload(c.ToolsUploadPath, f); err != nil {
err := fmt.Errorf("Error uploading VMware Tools: %s", err)
state.Put("error", err)
ui.Error(err.Error())
@ -60,4 +65,4 @@ func (*stepUploadTools) Run(state multistep.StateBag) multistep.StepAction {
return multistep.ActionContinue
}
func (*stepUploadTools) Cleanup(multistep.StateBag) {}
func (c *StepUploadTools) Cleanup(multistep.StateBag) {}

View File

@ -0,0 +1,38 @@
package common
import (
"fmt"
"text/template"
"github.com/mitchellh/packer/packer"
)
type ToolsConfig struct {
ToolsUploadFlavor string `mapstructure:"tools_upload_flavor"`
ToolsUploadPath string `mapstructure:"tools_upload_path"`
}
func (c *ToolsConfig) Prepare(t *packer.ConfigTemplate) []error {
if c.ToolsUploadPath == "" {
c.ToolsUploadPath = "{{ .Flavor }}.iso"
}
templates := map[string]*string{
"tools_upload_flavor": &c.ToolsUploadFlavor,
}
var err error
errs := make([]error, 0)
for n, ptr := range templates {
*ptr, err = t.Process(*ptr, nil)
if err != nil {
errs = append(errs, fmt.Errorf("Error processing %s: %s", n, err))
}
}
if _, err := template.New("path").Parse(c.ToolsUploadPath); err != nil {
errs = append(errs, fmt.Errorf("tools_upload_path invalid: %s", err))
}
return errs
}

View File

@ -12,7 +12,6 @@ import (
"math/rand"
"os"
"strings"
"text/template"
"time"
)
@ -30,27 +29,26 @@ type config struct {
vmwcommon.RunConfig `mapstructure:",squash"`
vmwcommon.ShutdownConfig `mapstructure:",squash"`
vmwcommon.SSHConfig `mapstructure:",squash"`
vmwcommon.ToolsConfig `mapstructure:",squash"`
vmwcommon.VMXConfig `mapstructure:",squash"`
DiskName string `mapstructure:"vmdk_name"`
DiskSize uint `mapstructure:"disk_size"`
DiskTypeId string `mapstructure:"disk_type_id"`
FloppyFiles []string `mapstructure:"floppy_files"`
GuestOSType string `mapstructure:"guest_os_type"`
ISOChecksum string `mapstructure:"iso_checksum"`
ISOChecksumType string `mapstructure:"iso_checksum_type"`
ISOUrls []string `mapstructure:"iso_urls"`
VMName string `mapstructure:"vm_name"`
HTTPDir string `mapstructure:"http_directory"`
HTTPPortMin uint `mapstructure:"http_port_min"`
HTTPPortMax uint `mapstructure:"http_port_max"`
BootCommand []string `mapstructure:"boot_command"`
SkipCompaction bool `mapstructure:"skip_compaction"`
ToolsUploadFlavor string `mapstructure:"tools_upload_flavor"`
ToolsUploadPath string `mapstructure:"tools_upload_path"`
VMXTemplatePath string `mapstructure:"vmx_template_path"`
VNCPortMin uint `mapstructure:"vnc_port_min"`
VNCPortMax uint `mapstructure:"vnc_port_max"`
DiskName string `mapstructure:"vmdk_name"`
DiskSize uint `mapstructure:"disk_size"`
DiskTypeId string `mapstructure:"disk_type_id"`
FloppyFiles []string `mapstructure:"floppy_files"`
GuestOSType string `mapstructure:"guest_os_type"`
ISOChecksum string `mapstructure:"iso_checksum"`
ISOChecksumType string `mapstructure:"iso_checksum_type"`
ISOUrls []string `mapstructure:"iso_urls"`
VMName string `mapstructure:"vm_name"`
HTTPDir string `mapstructure:"http_directory"`
HTTPPortMin uint `mapstructure:"http_port_min"`
HTTPPortMax uint `mapstructure:"http_port_max"`
BootCommand []string `mapstructure:"boot_command"`
SkipCompaction bool `mapstructure:"skip_compaction"`
VMXTemplatePath string `mapstructure:"vmx_template_path"`
VNCPortMin uint `mapstructure:"vnc_port_min"`
VNCPortMax uint `mapstructure:"vnc_port_max"`
RemoteType string `mapstructure:"remote_type"`
RemoteDatastore string `mapstructure:"remote_datastore"`
@ -84,6 +82,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(b.config.tpl)...)
errs = packer.MultiErrorAppend(errs, b.config.ShutdownConfig.Prepare(b.config.tpl)...)
errs = packer.MultiErrorAppend(errs, b.config.SSHConfig.Prepare(b.config.tpl)...)
errs = packer.MultiErrorAppend(errs, b.config.ToolsConfig.Prepare(b.config.tpl)...)
errs = packer.MultiErrorAppend(errs, b.config.VMXConfig.Prepare(b.config.tpl)...)
warnings := make([]string, 0)
@ -144,26 +143,21 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
b.config.RemotePort = 22
}
if b.config.ToolsUploadPath == "" {
b.config.ToolsUploadPath = "{{ .Flavor }}.iso"
}
// Errors
templates := map[string]*string{
"disk_name": &b.config.DiskName,
"guest_os_type": &b.config.GuestOSType,
"http_directory": &b.config.HTTPDir,
"iso_checksum": &b.config.ISOChecksum,
"iso_checksum_type": &b.config.ISOChecksumType,
"iso_url": &b.config.RawSingleISOUrl,
"tools_upload_flavor": &b.config.ToolsUploadFlavor,
"vm_name": &b.config.VMName,
"vmx_template_path": &b.config.VMXTemplatePath,
"remote_type": &b.config.RemoteType,
"remote_host": &b.config.RemoteHost,
"remote_datastore": &b.config.RemoteDatastore,
"remote_user": &b.config.RemoteUser,
"remote_password": &b.config.RemotePassword,
"disk_name": &b.config.DiskName,
"guest_os_type": &b.config.GuestOSType,
"http_directory": &b.config.HTTPDir,
"iso_checksum": &b.config.ISOChecksum,
"iso_checksum_type": &b.config.ISOChecksumType,
"iso_url": &b.config.RawSingleISOUrl,
"vm_name": &b.config.VMName,
"vmx_template_path": &b.config.VMXTemplatePath,
"remote_type": &b.config.RemoteType,
"remote_host": &b.config.RemoteHost,
"remote_datastore": &b.config.RemoteDatastore,
"remote_user": &b.config.RemoteUser,
"remote_password": &b.config.RemotePassword,
}
for n, ptr := range templates {
@ -245,11 +239,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
}
}
if _, err := template.New("path").Parse(b.config.ToolsUploadPath); err != nil {
errs = packer.MultiErrorAppend(
errs, fmt.Errorf("tools_upload_path invalid: %s", err))
}
if b.config.VMXTemplatePath != "" {
if err := b.validateVMXTemplatePath(); err != nil {
errs = packer.MultiErrorAppend(
@ -320,7 +309,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
rand.Seed(time.Now().UTC().UnixNano())
steps := []multistep.Step{
&stepPrepareTools{},
&vmwcommon.StepPrepareTools{
RemoteType: b.config.RemoteType,
ToolsUploadFlavor: b.config.ToolsUploadFlavor,
ToolsUploadPath: b.config.ToolsUploadPath,
},
&common.StepDownload{
Checksum: b.config.ISOChecksum,
ChecksumType: b.config.ISOChecksumType,
@ -363,7 +356,12 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
SSHWaitTimeout: b.config.SSHWaitTimeout,
NoPty: b.config.SSHSkipRequestPty,
},
&stepUploadTools{},
&vmwcommon.StepUploadTools{
RemoteType: b.config.RemoteType,
ToolsUploadFlavor: b.config.ToolsUploadFlavor,
ToolsUploadPath: b.config.ToolsUploadPath,
Tpl: b.config.tpl,
},
&common.StepProvision{},
&vmwcommon.StepShutdown{
Command: b.config.ShutdownCommand,

View File

@ -1,38 +0,0 @@
package iso
import (
"fmt"
"github.com/mitchellh/multistep"
vmwcommon "github.com/mitchellh/packer/builder/vmware/common"
"os"
)
type stepPrepareTools struct{}
func (*stepPrepareTools) Run(state multistep.StateBag) multistep.StepAction {
config := state.Get("config").(*config)
driver := state.Get("driver").(vmwcommon.Driver)
if config.RemoteType == "esx5" {
return multistep.ActionContinue
}
if config.ToolsUploadFlavor == "" {
return multistep.ActionContinue
}
path := driver.ToolsIsoPath(config.ToolsUploadFlavor)
if _, err := os.Stat(path); err != nil {
state.Put("error", fmt.Errorf(
"Couldn't find VMware tools for '%s'! VMware often downloads these\n"+
"tools on-demand. However, to do this, you need to create a fake VM\n"+
"of the proper type then click the 'install tools' option in the\n"+
"VMware GUI.", config.ToolsUploadFlavor))
return multistep.ActionHalt
}
state.Put("tools_upload_source", path)
return multistep.ActionContinue
}
func (*stepPrepareTools) Cleanup(multistep.StateBag) {}

View File

@ -52,6 +52,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
// Build the steps.
steps := []multistep.Step{
&vmwcommon.StepPrepareTools{
RemoteType: b.config.RemoteType,
ToolsUploadFlavor: b.config.ToolsUploadFlavor,
ToolsUploadPath: b.config.ToolsUploadPath,
},
&vmwcommon.StepOutputDir{
Force: b.config.PackerForce,
},
@ -78,6 +83,12 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
SSHWaitTimeout: b.config.SSHWaitTimeout,
NoPty: b.config.SSHSkipRequestPty,
},
&vmwcommon.StepUploadTools{
RemoteType: b.config.RemoteType,
ToolsUploadFlavor: b.config.ToolsUploadFlavor,
ToolsUploadPath: b.config.ToolsUploadPath,
Tpl: b.config.tpl,
},
&common.StepProvision{},
&vmwcommon.StepShutdown{
Command: b.config.ShutdownCommand,

View File

@ -17,9 +17,11 @@ type Config struct {
vmwcommon.RunConfig `mapstructure:",squash"`
vmwcommon.ShutdownConfig `mapstructure:",squash"`
vmwcommon.SSHConfig `mapstructure:",squash"`
vmwcommon.ToolsConfig `mapstructure:",squash"`
vmwcommon.VMXConfig `mapstructure:",squash"`
FloppyFiles []string `mapstructure:"floppy_files"`
RemoteType string `mapstructure:"remote_type"`
SkipCompaction bool `mapstructure:"skip_compaction"`
SourcePath string `mapstructure:"source_path"`
VMName string `mapstructure:"vm_name"`
@ -52,9 +54,11 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
errs = packer.MultiErrorAppend(errs, c.RunConfig.Prepare(c.tpl)...)
errs = packer.MultiErrorAppend(errs, c.ShutdownConfig.Prepare(c.tpl)...)
errs = packer.MultiErrorAppend(errs, c.SSHConfig.Prepare(c.tpl)...)
errs = packer.MultiErrorAppend(errs, c.ToolsConfig.Prepare(c.tpl)...)
errs = packer.MultiErrorAppend(errs, c.VMXConfig.Prepare(c.tpl)...)
templates := map[string]*string{
"remote_type": &c.RemoteType,
"source_path": &c.SourcePath,
"vm_name": &c.VMName,
}