diff --git a/builder/vmware/common/run_config.go b/builder/vmware/common/run_config.go index 89f48b9c6..9463d8753 100644 --- a/builder/vmware/common/run_config.go +++ b/builder/vmware/common/run_config.go @@ -8,8 +8,10 @@ import ( ) type RunConfig struct { - Headless bool `mapstructure:"headless"` - RawBootWait string `mapstructure:"boot_wait"` + Headless bool `mapstructure:"headless"` + RawBootWait string `mapstructure:"boot_wait"` + DisableVNC bool `mapstructure:"disable_vnc"` + BootCommand []string `mapstructure:"boot_command"` VNCBindAddress string `mapstructure:"vnc_bind_address"` VNCPortMin uint `mapstructure:"vnc_port_min"` @@ -38,6 +40,11 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error { var errs []error var err error + if len(c.BootCommand) > 0 && c.DisableVNC { + errs = append(errs, + fmt.Errorf("A boot command cannot be used when vnc is disabled.")) + } + if c.RawBootWait != "" { c.BootWait, err = time.ParseDuration(c.RawBootWait) if err != nil { diff --git a/builder/vmware/common/step_configure_vnc.go b/builder/vmware/common/step_configure_vnc.go index b591573a0..4e4798862 100644 --- a/builder/vmware/common/step_configure_vnc.go +++ b/builder/vmware/common/step_configure_vnc.go @@ -21,7 +21,7 @@ import ( // Produces: // vnc_port uint - The port that VNC is configured to listen on. type StepConfigureVNC struct { - Skip bool + Enabled bool VNCBindAddress string VNCPortMin uint VNCPortMax uint @@ -77,7 +77,7 @@ func VNCPassword(skipPassword bool) string { } func (s *StepConfigureVNC) Run(state multistep.StateBag) multistep.StepAction { - if s.Skip { + if !s.Enabled { log.Println("Skipping VNC configuration step...") return multistep.ActionContinue } diff --git a/builder/vmware/common/step_run.go b/builder/vmware/common/step_run.go index bd463799d..2ea61f899 100644 --- a/builder/vmware/common/step_run.go +++ b/builder/vmware/common/step_run.go @@ -2,9 +2,10 @@ package common import ( "fmt" + "time" + "github.com/hashicorp/packer/packer" "github.com/mitchellh/multistep" - "time" ) // This step runs the created virtual machine. diff --git a/builder/vmware/common/step_type_boot_command.go b/builder/vmware/common/step_type_boot_command.go index 7f2841fa8..28db3c72e 100644 --- a/builder/vmware/common/step_type_boot_command.go +++ b/builder/vmware/common/step_type_boot_command.go @@ -36,14 +36,14 @@ type bootCommandTemplateData struct { // Produces: // type StepTypeBootCommand struct { + VNCEnabled bool BootCommand []string VMName string Ctx interpolate.Context - Skip bool } func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction { - if s.Skip { + if !s.VNCEnabled { log.Println("Skipping boot command step...") return multistep.ActionContinue } diff --git a/builder/vmware/iso/builder.go b/builder/vmware/iso/builder.go index ffa763c50..c772d17a2 100644 --- a/builder/vmware/iso/builder.go +++ b/builder/vmware/iso/builder.go @@ -38,7 +38,6 @@ type Config struct { vmwcommon.VMXConfig `mapstructure:",squash"` AdditionalDiskSize []uint `mapstructure:"disk_additional_size"` - BootCommand []string `mapstructure:"boot_command"` DiskName string `mapstructure:"vmdk_name"` DiskSize uint `mapstructure:"disk_size"` DiskTypeId string `mapstructure:"disk_type_id"` @@ -149,6 +148,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { if b.config.RemotePort == 0 { b.config.RemotePort = 22 } + if b.config.VMXTemplatePath != "" { if err := b.validateVMXTemplatePath(); err != nil { errs = packer.MultiErrorAppend( @@ -179,6 +179,12 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { "will forcibly halt the virtual machine, which may result in data loss.") } + if b.config.Headless && b.config.DisableVNC { + warnings = append(warnings, + "Headless mode uses VNC to retrieve output. Since VNC has been disabled,\n"+ + "you won't be able to see any output.") + } + if errs != nil && len(errs.Errors) > 0 { return warnings, errs } @@ -259,7 +265,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe HTTPPortMax: b.config.HTTPPortMax, }, &vmwcommon.StepConfigureVNC{ - Skip: b.config.BootCommand == nil, + Enabled: !b.config.DisableVNC, VNCBindAddress: b.config.VNCBindAddress, VNCPortMin: b.config.VNCPortMin, VNCPortMax: b.config.VNCPortMax, @@ -274,7 +280,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe Headless: b.config.Headless, }, &vmwcommon.StepTypeBootCommand{ - Skip: b.config.BootCommand == nil, + VNCEnabled: !b.config.DisableVNC, BootCommand: b.config.BootCommand, VMName: b.config.VMName, Ctx: b.config.ctx, @@ -305,7 +311,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe }, &vmwcommon.StepCleanVMX{ RemoveEthernetInterfaces: b.config.VMXConfig.VMXRemoveEthernet, - SkipVNCDisable: b.config.BootCommand == nil, + SkipVNCDisable: b.config.DisableVNC, }, &StepUploadVMX{ RemoteType: b.config.RemoteType, diff --git a/builder/vmware/vmx/builder.go b/builder/vmware/vmx/builder.go index 894c3488a..ef2e4cc86 100644 --- a/builder/vmware/vmx/builder.go +++ b/builder/vmware/vmx/builder.go @@ -80,6 +80,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe HTTPPortMax: b.config.HTTPPortMax, }, &vmwcommon.StepConfigureVNC{ + Enabled: !b.config.DisableVNC, VNCBindAddress: b.config.VNCBindAddress, VNCPortMin: b.config.VNCPortMin, VNCPortMax: b.config.VNCPortMax, @@ -91,6 +92,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe Headless: b.config.Headless, }, &vmwcommon.StepTypeBootCommand{ + VNCEnabled: !b.config.DisableVNC, BootCommand: b.config.BootCommand, VMName: b.config.VMName, Ctx: b.config.ctx, @@ -121,6 +123,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe }, &vmwcommon.StepCleanVMX{ RemoveEthernetInterfaces: b.config.VMXConfig.VMXRemoveEthernet, + SkipVNCDisable: b.config.DisableVNC, }, } diff --git a/builder/vmware/vmx/config.go b/builder/vmware/vmx/config.go index 145705fd7..b4d1c009f 100644 --- a/builder/vmware/vmx/config.go +++ b/builder/vmware/vmx/config.go @@ -24,11 +24,10 @@ type Config struct { vmwcommon.ToolsConfig `mapstructure:",squash"` vmwcommon.VMXConfig `mapstructure:",squash"` - BootCommand []string `mapstructure:"boot_command"` - RemoteType string `mapstructure:"remote_type"` - SkipCompaction bool `mapstructure:"skip_compaction"` - SourcePath string `mapstructure:"source_path"` - VMName string `mapstructure:"vm_name"` + RemoteType string `mapstructure:"remote_type"` + SkipCompaction bool `mapstructure:"skip_compaction"` + SourcePath string `mapstructure:"source_path"` + VMName string `mapstructure:"vm_name"` ctx interpolate.Context } @@ -84,6 +83,12 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { "will forcibly halt the virtual machine, which may result in data loss.") } + if c.Headless && c.DisableVNC { + warnings = append(warnings, + "Headless mode uses VNC to retrieve output. Since VNC has been disabled,\n"+ + "you won't be able to see any output.") + } + // Check for any errors. if errs != nil && len(errs.Errors) > 0 { return nil, warnings, errs diff --git a/website/source/docs/builders/vmware-iso.html.md b/website/source/docs/builders/vmware-iso.html.md index 137c7a704..29a1a7cb3 100644 --- a/website/source/docs/builders/vmware-iso.html.md +++ b/website/source/docs/builders/vmware-iso.html.md @@ -114,6 +114,9 @@ builder. User's Guide](https://www.vmware.com/pdf/VirtualDiskManager.pdf) for desktop VMware clients. For ESXi, refer to the proper ESXi documentation. +* `disable_vnc` (bool) - Whether to create a VNC connection or not. + A `boot_command` cannot be used when this is `false`. Defaults to `false`. + - `floppy_files` (array of strings) - A list of files to place onto a floppy disk that is attached when the VM is booted. This is most useful for unattended Windows installs, which look for an `Autounattend.xml` file on @@ -446,10 +449,11 @@ various files locally, and uploads these to the remote machine. Packer currently uses SSH to communicate to the ESXi machine rather than the vSphere API. At some point, the vSphere API may be used. -Packer also requires VNC if issuing boot commands during a build, which may be +Packer also requires VNC to issue boot commands during a build, which may be disabled on some remote VMware Hypervisors. Please consult the appropriate documentation on how to update VMware Hypervisor's firewall to allow these -connections. +connections. VNC can be disabled by not setting a `boot_command` and setting +`disable_vnc` to `true`. To use a remote VMware vSphere Hypervisor to build your virtual machine, fill in the required `remote_*` configurations: @@ -481,8 +485,8 @@ modify as well: - `format` (string) - Either "ovf", "ova" or "vmx", this specifies the output format of the exported virtual machine. This defaults to "ovf". - Before using this option, you need to install `ovftool`. This option - works currently only with option remote_type set to "esx5". + Before using this option, you need to install `ovftool`. This option + works currently only with option remote_type set to "esx5". ### VNC port discovery diff --git a/website/source/docs/builders/vmware-vmx.html.md b/website/source/docs/builders/vmware-vmx.html.md index 1cd6feb64..8aac027b5 100644 --- a/website/source/docs/builders/vmware-vmx.html.md +++ b/website/source/docs/builders/vmware-vmx.html.md @@ -71,6 +71,9 @@ builder. five seconds and one minute 30 seconds, respectively. If this isn't specified, the default is 10 seconds. +* `disable_vnc` (bool) - Whether to create a VNC connection or not. + A `boot_command` cannot be used when this is `false`. Defaults to `false`. + - `floppy_files` (array of strings) - A list of files to place onto a floppy disk that is attached when the VM is booted. This is most useful for unattended Windows installs, which look for an `Autounattend.xml` file on