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_clean_vmx.go b/builder/vmware/common/step_clean_vmx.go index d016f35a3..853233e89 100644 --- a/builder/vmware/common/step_clean_vmx.go +++ b/builder/vmware/common/step_clean_vmx.go @@ -21,6 +21,7 @@ import ( // type StepCleanVMX struct { RemoveEthernetInterfaces bool + VNCEnabled bool } func (s StepCleanVMX) Run(state multistep.StateBag) multistep.StepAction { @@ -59,8 +60,10 @@ func (s StepCleanVMX) Run(state multistep.StateBag) multistep.StepAction { vmxData[ide+"clientdevice"] = "TRUE" } - ui.Message("Disabling VNC server...") - vmxData["remotedisplay.vnc.enabled"] = "FALSE" + if s.VNCEnabled { + ui.Message("Disabling VNC server...") + vmxData["remotedisplay.vnc.enabled"] = "FALSE" + } if s.RemoveEthernetInterfaces { ui.Message("Removing Ethernet Interfaces...") diff --git a/builder/vmware/common/step_configure_vnc.go b/builder/vmware/common/step_configure_vnc.go index 4b6a6cdae..4e4798862 100644 --- a/builder/vmware/common/step_configure_vnc.go +++ b/builder/vmware/common/step_configure_vnc.go @@ -21,6 +21,7 @@ import ( // Produces: // vnc_port uint - The port that VNC is configured to listen on. type StepConfigureVNC struct { + Enabled bool VNCBindAddress string VNCPortMin uint VNCPortMax uint @@ -76,6 +77,11 @@ func VNCPassword(skipPassword bool) string { } func (s *StepConfigureVNC) Run(state multistep.StateBag) multistep.StepAction { + if !s.Enabled { + log.Println("Skipping VNC configuration step...") + return multistep.ActionContinue + } + driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) vmxPath := state.Get("vmx_path").(string) 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 e82a07031..28db3c72e 100644 --- a/builder/vmware/common/step_type_boot_command.go +++ b/builder/vmware/common/step_type_boot_command.go @@ -36,12 +36,18 @@ type bootCommandTemplateData struct { // Produces: // type StepTypeBootCommand struct { + VNCEnabled bool BootCommand []string VMName string Ctx interpolate.Context } func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction { + if !s.VNCEnabled { + log.Println("Skipping boot command step...") + return multistep.ActionContinue + } + debug := state.Get("debug").(bool) driver := state.Get("driver").(Driver) httpPort := state.Get("http_port").(uint) diff --git a/builder/vmware/iso/builder.go b/builder/vmware/iso/builder.go index 688f52d72..44db307a7 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,6 +265,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, @@ -273,6 +280,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, @@ -303,6 +311,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe }, &vmwcommon.StepCleanVMX{ RemoveEthernetInterfaces: b.config.VMXConfig.VMXRemoveEthernet, + VNCEnabled: !b.config.DisableVNC, }, &StepUploadVMX{ RemoteType: b.config.RemoteType, diff --git a/builder/vmware/vmx/builder.go b/builder/vmware/vmx/builder.go index 894c3488a..b7c70d548 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, + VNCEnabled: !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 4c8c79b8b..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 @@ -449,7 +452,8 @@ point, the vSphere API may be used. 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