From 918db58604ae1729874daeba8a006d366f73a800 Mon Sep 17 00:00:00 2001 From: Megan Marsh Date: Wed, 22 Aug 2018 11:25:43 -0700 Subject: [PATCH 1/2] added new template variables to replace PACKER_KEY_INTERVAL with tunable key and keygroup intervals depending on driver used --- .../hyperv/common/step_type_boot_command.go | 11 +++++----- builder/hyperv/iso/builder.go | 9 +++++---- builder/hyperv/vmcx/builder.go | 9 +++++---- .../common/step_type_boot_command.go | 3 ++- builder/parallels/iso/builder.go | 1 + builder/parallels/pvm/builder.go | 1 + builder/qemu/step_type_boot_command.go | 2 +- .../common/step_type_boot_command.go | 11 +++++----- builder/virtualbox/iso/builder.go | 14 +++++++++---- builder/virtualbox/ovf/builder.go | 9 +++++---- .../vmware/common/step_type_boot_command.go | 3 ++- builder/vmware/iso/builder.go | 1 + builder/vmware/vmx/builder.go | 1 + common/bootcommand/config.go | 10 ++++++++++ common/bootcommand/pc_xt_driver.go | 6 +++++- common/bootcommand/pc_xt_driver_test.go | 6 +++--- common/bootcommand/vnc_driver.go | 6 +++++- common/bootcommand/vnc_driver_test.go | 2 +- website/source/docs/builders/qemu.html.md.erb | 20 ++++++++++++++++--- .../docs/builders/virtualbox-iso.html.md.erb | 18 +++++++++++++++-- .../docs/builders/virtualbox-ovf.html.md.erb | 19 ++++++++++++++++-- .../docs/builders/vmware-iso.html.md.erb | 20 ++++++++++++++++--- .../docs/builders/vmware-vmx.html.md.erb | 18 +++++++++++++++-- 23 files changed, 153 insertions(+), 47 deletions(-) diff --git a/builder/hyperv/common/step_type_boot_command.go b/builder/hyperv/common/step_type_boot_command.go index de96d4293..19574243a 100644 --- a/builder/hyperv/common/step_type_boot_command.go +++ b/builder/hyperv/common/step_type_boot_command.go @@ -21,10 +21,11 @@ type bootCommandTemplateData struct { // This step "types" the boot command into the VM via the Hyper-V virtual keyboard type StepTypeBootCommand struct { - BootCommand string - BootWait time.Duration - SwitchName string - Ctx interpolate.Context + BootCommand string + BootWait time.Duration + SwitchName string + Ctx interpolate.Context + GroupInterval int } func (s *StepTypeBootCommand) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { @@ -66,7 +67,7 @@ func (s *StepTypeBootCommand) Run(ctx context.Context, state multistep.StateBag) scanCodesToSendString := strings.Join(codes, " ") return driver.TypeScanCodes(vmName, scanCodesToSendString) } - d := bootcommand.NewPCXTDriver(sendCodes, -1) + d := bootcommand.NewPCXTDriver(sendCodes, -1, s.GroupInterval) ui.Say("Typing the boot command...") command, err := interpolate.Render(s.BootCommand, &s.Ctx) diff --git a/builder/hyperv/iso/builder.go b/builder/hyperv/iso/builder.go index d50e5e26a..15887eeeb 100644 --- a/builder/hyperv/iso/builder.go +++ b/builder/hyperv/iso/builder.go @@ -434,10 +434,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe }, &hypervcommon.StepTypeBootCommand{ - BootCommand: b.config.FlatBootCommand(), - BootWait: b.config.BootWait, - SwitchName: b.config.SwitchName, - Ctx: b.config.ctx, + BootCommand: b.config.FlatBootCommand(), + BootWait: b.config.BootWait, + SwitchName: b.config.SwitchName, + Ctx: b.config.ctx, + GroupInterval: b.config.BootConfig.BootGroupInterval, }, // configure the communicator ssh, winrm diff --git a/builder/hyperv/vmcx/builder.go b/builder/hyperv/vmcx/builder.go index 987c41a12..1f53df9e6 100644 --- a/builder/hyperv/vmcx/builder.go +++ b/builder/hyperv/vmcx/builder.go @@ -443,10 +443,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe }, &hypervcommon.StepTypeBootCommand{ - BootCommand: b.config.FlatBootCommand(), - BootWait: b.config.BootWait, - SwitchName: b.config.SwitchName, - Ctx: b.config.ctx, + BootCommand: b.config.FlatBootCommand(), + BootWait: b.config.BootWait, + SwitchName: b.config.SwitchName, + Ctx: b.config.ctx, + GroupInterval: b.config.BootConfig.BootGroupInterval, }, // configure the communicator ssh, winrm diff --git a/builder/parallels/common/step_type_boot_command.go b/builder/parallels/common/step_type_boot_command.go index ed21c049d..ca3771648 100644 --- a/builder/parallels/common/step_type_boot_command.go +++ b/builder/parallels/common/step_type_boot_command.go @@ -26,6 +26,7 @@ type StepTypeBootCommand struct { HostInterfaces []string VMName string Ctx interpolate.Context + GroupInterval int } // Run types the boot command by sending key scancodes into the VM. @@ -79,7 +80,7 @@ func (s *StepTypeBootCommand) Run(ctx context.Context, state multistep.StateBag) sendCodes := func(codes []string) error { return driver.SendKeyScanCodes(s.VMName, codes...) } - d := bootcommand.NewPCXTDriver(sendCodes, -1) + d := bootcommand.NewPCXTDriver(sendCodes, -1, s.GroupInterval) ui.Say("Typing the boot command...") command, err := interpolate.Render(s.BootCommand, &s.Ctx) diff --git a/builder/parallels/iso/builder.go b/builder/parallels/iso/builder.go index 9ba2002f7..9cf7f0405 100644 --- a/builder/parallels/iso/builder.go +++ b/builder/parallels/iso/builder.go @@ -192,6 +192,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe HostInterfaces: b.config.HostInterfaces, VMName: b.config.VMName, Ctx: b.config.ctx, + GroupInterval: b.config.BootConfig.BootGroupInterval, }, &communicator.StepConnect{ Config: &b.config.SSHConfig.Comm, diff --git a/builder/parallels/pvm/builder.go b/builder/parallels/pvm/builder.go index e36916092..331b71670 100644 --- a/builder/parallels/pvm/builder.go +++ b/builder/parallels/pvm/builder.go @@ -81,6 +81,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe HostInterfaces: []string{}, VMName: b.config.VMName, Ctx: b.config.ctx, + GroupInterval: b.config.BootConfig.BootGroupInterval, }, &communicator.StepConnect{ Config: &b.config.SSHConfig.Comm, diff --git a/builder/qemu/step_type_boot_command.go b/builder/qemu/step_type_boot_command.go index 79bcd1338..11ebf3621 100644 --- a/builder/qemu/step_type_boot_command.go +++ b/builder/qemu/step_type_boot_command.go @@ -95,7 +95,7 @@ func (s *stepTypeBootCommand) Run(ctx context.Context, state multistep.StateBag) config.VMName, } - d := bootcommand.NewVNCDriver(c) + d := bootcommand.NewVNCDriver(c, config.VNCConfig.BootKeyInterval) ui.Say("Typing the boot command over VNC...") command, err := interpolate.Render(config.VNCConfig.FlatBootCommand(), &configCtx) diff --git a/builder/virtualbox/common/step_type_boot_command.go b/builder/virtualbox/common/step_type_boot_command.go index 0effc3628..95c5219cd 100644 --- a/builder/virtualbox/common/step_type_boot_command.go +++ b/builder/virtualbox/common/step_type_boot_command.go @@ -21,10 +21,11 @@ type bootCommandTemplateData struct { } type StepTypeBootCommand struct { - BootCommand string - BootWait time.Duration - VMName string - Ctx interpolate.Context + BootCommand string + BootWait time.Duration + VMName string + Ctx interpolate.Context + GroupInterval int } func (s *StepTypeBootCommand) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { @@ -64,7 +65,7 @@ func (s *StepTypeBootCommand) Run(ctx context.Context, state multistep.StateBag) return driver.VBoxManage(args...) } - d := bootcommand.NewPCXTDriver(sendCodes, 25) + d := bootcommand.NewPCXTDriver(sendCodes, 25, s.GroupInterval) ui.Say("Typing the boot command...") command, err := interpolate.Render(s.BootCommand, &s.Ctx) diff --git a/builder/virtualbox/iso/builder.go b/builder/virtualbox/iso/builder.go index 2ea19e70f..b0a9cc5cf 100644 --- a/builder/virtualbox/iso/builder.go +++ b/builder/virtualbox/iso/builder.go @@ -53,6 +53,7 @@ type Config struct { KeepRegistered bool `mapstructure:"keep_registered"` SkipExport bool `mapstructure:"skip_export"` VMName string `mapstructure:"vm_name"` + KeyInterval int `mapstructure:"key_interval"` ctx interpolate.Context } @@ -121,6 +122,10 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { b.config.ISOInterface = "ide" } + if b.config.KeyInterval == 0 { + b.config.KeyInterval = -1 + } + if b.config.VMName == "" { b.config.VMName = fmt.Sprintf( "packer-%s-%d", b.config.PackerBuildName, interpolate.InitTime.Unix()) @@ -245,10 +250,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe Headless: b.config.Headless, }, &vboxcommon.StepTypeBootCommand{ - BootWait: b.config.BootWait, - BootCommand: b.config.FlatBootCommand(), - VMName: b.config.VMName, - Ctx: b.config.ctx, + BootWait: b.config.BootWait, + BootCommand: b.config.FlatBootCommand(), + VMName: b.config.VMName, + Ctx: b.config.ctx, + GroupInterval: b.config.BootConfig.BootGroupInterval, }, &communicator.StepConnect{ Config: &b.config.SSHConfig.Comm, diff --git a/builder/virtualbox/ovf/builder.go b/builder/virtualbox/ovf/builder.go index 09fd416a3..54c8dc013 100644 --- a/builder/virtualbox/ovf/builder.go +++ b/builder/virtualbox/ovf/builder.go @@ -106,10 +106,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe Headless: b.config.Headless, }, &vboxcommon.StepTypeBootCommand{ - BootWait: b.config.BootWait, - BootCommand: b.config.FlatBootCommand(), - VMName: b.config.VMName, - Ctx: b.config.ctx, + BootWait: b.config.BootWait, + BootCommand: b.config.FlatBootCommand(), + VMName: b.config.VMName, + Ctx: b.config.ctx, + GroupInterval: b.config.BootConfig.BootGroupInterval, }, &communicator.StepConnect{ Config: &b.config.SSHConfig.Comm, diff --git a/builder/vmware/common/step_type_boot_command.go b/builder/vmware/common/step_type_boot_command.go index 83d55ce11..c1514c272 100644 --- a/builder/vmware/common/step_type_boot_command.go +++ b/builder/vmware/common/step_type_boot_command.go @@ -30,6 +30,7 @@ type StepTypeBootCommand struct { BootWait time.Duration VMName string Ctx interpolate.Context + KeyInterval int } type bootCommandTemplateData struct { HTTPIP string @@ -115,7 +116,7 @@ func (s *StepTypeBootCommand) Run(ctx context.Context, state multistep.StateBag) s.VMName, } - d := bootcommand.NewVNCDriver(c) + d := bootcommand.NewVNCDriver(c, s.KeyInterval) ui.Say("Typing the boot command over VNC...") command, err := interpolate.Render(s.BootCommand, &s.Ctx) diff --git a/builder/vmware/iso/builder.go b/builder/vmware/iso/builder.go index 0944db927..3b2317d61 100644 --- a/builder/vmware/iso/builder.go +++ b/builder/vmware/iso/builder.go @@ -339,6 +339,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe BootCommand: b.config.FlatBootCommand(), VMName: b.config.VMName, Ctx: b.config.ctx, + KeyInterval: b.config.VNCConfig.BootKeyInterval, }, &communicator.StepConnect{ Config: &b.config.SSHConfig.Comm, diff --git a/builder/vmware/vmx/builder.go b/builder/vmware/vmx/builder.go index dbb74b7a1..d6d748c6b 100644 --- a/builder/vmware/vmx/builder.go +++ b/builder/vmware/vmx/builder.go @@ -97,6 +97,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe BootCommand: b.config.FlatBootCommand(), VMName: b.config.VMName, Ctx: b.config.ctx, + KeyInterval: b.config.VNCConfig.BootKeyInterval, }, &communicator.StepConnect{ Config: &b.config.SSHConfig.Comm, diff --git a/common/bootcommand/config.go b/common/bootcommand/config.go index 532c7c82c..f89d21715 100644 --- a/common/bootcommand/config.go +++ b/common/bootcommand/config.go @@ -11,6 +11,8 @@ import ( type BootConfig struct { RawBootWait string `mapstructure:"boot_wait"` BootCommand []string `mapstructure:"boot_command"` + // time in ms to wait between each group of 25 key presses + BootGroupInterval int `mapstructure:"boot_keygroup_interval"` BootWait time.Duration `` } @@ -18,12 +20,17 @@ type BootConfig struct { type VNCConfig struct { BootConfig `mapstructure:",squash"` DisableVNC bool `mapstructure:"disable_vnc"` + // time in ms to wait between each key press + BootKeyInterval int `mapstructure:"boot_key_interval"` } func (c *BootConfig) Prepare(ctx *interpolate.Context) (errs []error) { if c.RawBootWait == "" { c.RawBootWait = "10s" } + if c.BootGroupInterval == 0 { + c.BootGroupInterval = -1 + } if c.RawBootWait != "" { bw, err := time.ParseDuration(c.RawBootWait) if err != nil { @@ -55,6 +62,9 @@ func (c *VNCConfig) Prepare(ctx *interpolate.Context) (errs []error) { errs = append(errs, fmt.Errorf("A boot command cannot be used when vnc is disabled.")) } + if c.BootKeyInterval == 0 { + c.BootKeyInterval = -1 + } errs = append(errs, c.BootConfig.Prepare(ctx)...) return } diff --git a/common/bootcommand/pc_xt_driver.go b/common/bootcommand/pc_xt_driver.go index 7aca80852..11e9cb734 100644 --- a/common/bootcommand/pc_xt_driver.go +++ b/common/bootcommand/pc_xt_driver.go @@ -38,13 +38,17 @@ func (sc *scancode) makeBreak() []string { // NewPCXTDriver creates a new boot command driver for VMs that expect PC-XT // keyboard codes. `send` should send its argument to the VM. `chunkSize` should // be the maximum number of keyboard codes to send to `send` at one time. -func NewPCXTDriver(send SendCodeFunc, chunkSize int) *pcXTDriver { +func NewPCXTDriver(send SendCodeFunc, chunkSize int, interval int) *pcXTDriver { // We delay (default 100ms) between each input event to allow for CPU or // network latency. See PackerKeyEnv for tuning. keyInterval := common.PackerKeyDefault if delay, err := time.ParseDuration(os.Getenv(common.PackerKeyEnv)); err == nil { keyInterval = delay } + // Override interval based on builder-specific override + if interval >= 0 { + keyInterval = time.Duration(interval) * time.Millisecond + } // Scancodes reference: https://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html // https://www.win.tue.nl/~aeb/linux/kbd/scancodes-10.html // diff --git a/common/bootcommand/pc_xt_driver_test.go b/common/bootcommand/pc_xt_driver_test.go index cd0e04ec8..f814e64e9 100644 --- a/common/bootcommand/pc_xt_driver_test.go +++ b/common/bootcommand/pc_xt_driver_test.go @@ -79,7 +79,7 @@ func Test_pcxtSpecialOnOff(t *testing.T) { codes = c return nil } - d := NewPCXTDriver(sendCodes, -1) + d := NewPCXTDriver(sendCodes, -1, -1) seq, err := GenerateExpressionSequence(in) assert.NoError(t, err) err = seq.Do(context.Background(), d) @@ -95,7 +95,7 @@ func Test_pcxtSpecial(t *testing.T) { codes = c return nil } - d := NewPCXTDriver(sendCodes, -1) + d := NewPCXTDriver(sendCodes, -1, -1) seq, err := GenerateExpressionSequence(in) assert.NoError(t, err) err = seq.Do(context.Background(), d) @@ -114,7 +114,7 @@ func Test_flushes(t *testing.T) { actual = append(actual, c) return nil } - d := NewPCXTDriver(sendCodes, -1) + d := NewPCXTDriver(sendCodes, -1, -1) seq, err := GenerateExpressionSequence(in) assert.NoError(t, err) err = seq.Do(context.Background(), d) diff --git a/common/bootcommand/vnc_driver.go b/common/bootcommand/vnc_driver.go index dfe75b9b2..0983b923e 100644 --- a/common/bootcommand/vnc_driver.go +++ b/common/bootcommand/vnc_driver.go @@ -25,13 +25,17 @@ type vncDriver struct { err error } -func NewVNCDriver(c VNCKeyEvent) *vncDriver { +func NewVNCDriver(c VNCKeyEvent, interval int) *vncDriver { // We delay (default 100ms) between each key event to allow for CPU or // network latency. See PackerKeyEnv for tuning. keyInterval := common.PackerKeyDefault if delay, err := time.ParseDuration(os.Getenv(common.PackerKeyEnv)); err == nil { keyInterval = delay } + // override interval based on builder-specific override. + if interval >= 0 { + keyInterval = time.Duration(interval) * time.Millisecond + } // Scancodes reference: https://github.com/qemu/qemu/blob/master/ui/vnc_keysym.h sMap := make(map[string]uint32) diff --git a/common/bootcommand/vnc_driver_test.go b/common/bootcommand/vnc_driver_test.go index 11ca41669..d8bd4e71e 100644 --- a/common/bootcommand/vnc_driver_test.go +++ b/common/bootcommand/vnc_driver_test.go @@ -30,7 +30,7 @@ func Test_vncSpecialLookup(t *testing.T) { {0xFFE2, true}, } s := &sender{} - d := NewVNCDriver(s) + d := NewVNCDriver(s, -1) seq, err := GenerateExpressionSequence(in) assert.NoError(t, err) err = seq.Do(context.Background(), d) diff --git a/website/source/docs/builders/qemu.html.md.erb b/website/source/docs/builders/qemu.html.md.erb index 1d190b7ec..25c0d1bbd 100644 --- a/website/source/docs/builders/qemu.html.md.erb +++ b/website/source/docs/builders/qemu.html.md.erb @@ -121,7 +121,7 @@ Linux server and have not enabled X11 forwarding (`ssh -X`). upstream issue which can be tracked [here](https://github.com/intel/haxm/issues/20). - -> The `hvf` accelerator is new and experimental as of + -> The `hvf` accelerator is new and experimental as of [QEMU 2.12.0](https://wiki.qemu.org/ChangeLog/2.12#Host_support). You may encounter issues unrelated to Packer when using it. You may need to add [ "-global", "virtio-pci.disable-modern=on" ] to `qemuargs` depending on the @@ -386,8 +386,22 @@ machine, simulating a human actually typing the keyboard. -> Keystrokes are typed as separate key up/down events over VNC with a default 100ms delay. The delay alleviates issues with latency and CPU -contention. For local builds you can tune this delay by specifying -e.g. `PACKER_KEY_INTERVAL=10ms` to speed through the boot command. +contention. You can tune this delay on a per-builder basis by specifying +"boot_key_interval" in your Packer template, for example: + +``` +{ + "builders": [ + { + "type": "qemu", + "boot_key_interval": "10" + ... + } + ] +} +``` + +Note that this option will always be measured in milliseconds. <%= partial "partials/builders/boot-command" %> diff --git a/website/source/docs/builders/virtualbox-iso.html.md.erb b/website/source/docs/builders/virtualbox-iso.html.md.erb index 788f5e709..9277f44ac 100644 --- a/website/source/docs/builders/virtualbox-iso.html.md.erb +++ b/website/source/docs/builders/virtualbox-iso.html.md.erb @@ -337,8 +337,22 @@ template. The boot command is sent to the VM through the `VBoxManage` utility in as few invocations as possible. We send each character in groups of 25, with a default delay of 100ms between groups. The delay alleviates issues with latency and CPU -contention. If you notice missing keys, you can tune this delay by specifying e.g. -`PACKER_KEY_INTERVAL=500ms` to wait longer between each group of characters. +contention. If you notice missing keys, you can tune this delay by specifying +"boot_keygroup_interval" in your Packer template, for example: + +``` +{ + "builders": [ + { + "type": "virtualbox", + "boot_keygroup_interval": "500" + ... + } + ] +} +``` + +Note that this option will always be measured in milliseconds. <%= partial "partials/builders/boot-command" %> diff --git a/website/source/docs/builders/virtualbox-ovf.html.md.erb b/website/source/docs/builders/virtualbox-ovf.html.md.erb index ae4317240..aa929b823 100644 --- a/website/source/docs/builders/virtualbox-ovf.html.md.erb +++ b/website/source/docs/builders/virtualbox-ovf.html.md.erb @@ -300,8 +300,23 @@ template. The boot command is sent to the VM through the `VBoxManage` utility in as few invocations as possible. We send each character in groups of 25, with a default delay of 100ms between groups. The delay alleviates issues with latency and CPU -contention. If you notice missing keys, you can tune this delay by specifying e.g. -`PACKER_KEY_INTERVAL=500ms` to wait longer between each group of characters. +contention. If you notice missing keys, you can tune this delay by specifying +"boot_keygroup_interval" in your Packer template, for example: + +``` +{ + "builders": [ + { + "type": "virtualbox", + "boot_keygroup_interval": "500" + ... + } + ] +} +``` + +Note that this option will always be measured in milliseconds. + <%= partial "partials/builders/boot-command" %> diff --git a/website/source/docs/builders/vmware-iso.html.md.erb b/website/source/docs/builders/vmware-iso.html.md.erb index b42259ee8..613dbb4a2 100644 --- a/website/source/docs/builders/vmware-iso.html.md.erb +++ b/website/source/docs/builders/vmware-iso.html.md.erb @@ -412,7 +412,7 @@ builder. wish to bind to all interfaces use `0.0.0.0`. - `vnc_disable_password` (boolean) - Don't auto-generate a VNC password that - is used to secure the VNC communication with the VM. This must be set to + is used to secure the VNC communication with the VM. This must be set to `true` if building on ESXi 6.5 and 6.7 with VNC enabled. Defaults to `false`. @@ -439,8 +439,22 @@ machine, simulating a human actually typing the keyboard. -> Keystrokes are typed as separate key up/down events over VNC with a default 100ms delay. The delay alleviates issues with latency and CPU -contention. For local builds you can tune this delay by specifying -e.g. `PACKER_KEY_INTERVAL=10ms` to speed through the boot command. +contention. You can tune this delay on a per-builder basis by specifying +"boot_key_interval" in your Packer template, for example: + +``` +{ + "builders": [ + { + "type": "vmware-iso", + "boot_key_interval": "10" + ... + } + ] +} +``` + +Note that this option will always be measured in milliseconds. <%= partial "partials/builders/boot-command" %> diff --git a/website/source/docs/builders/vmware-vmx.html.md.erb b/website/source/docs/builders/vmware-vmx.html.md.erb index 5ce8ef4e3..78c6c94c1 100644 --- a/website/source/docs/builders/vmware-vmx.html.md.erb +++ b/website/source/docs/builders/vmware-vmx.html.md.erb @@ -215,8 +215,22 @@ machine, simulating a human actually typing the keyboard. -> Keystrokes are typed as separate key up/down events over VNC with a default 100ms delay. The delay alleviates issues with latency and CPU -contention. For local builds you can tune this delay by specifying -e.g. `PACKER_KEY_INTERVAL=10ms` to speed through the boot command. +contention. You can tune this delay on a per-builder basis by specifying +"boot_key_interval" in your Packer template, for example: + +``` +{ + "builders": [ + { + "type": "vmware-vmx", + "boot_key_interval": "10" + ... + } + ] +} +``` + +Note that this option will always be measured in milliseconds. <%= partial "partials/builders/boot-command" %> From 31d4f8af45e88b233995658097914d48f6e69247 Mon Sep 17 00:00:00 2001 From: Megan Marsh Date: Thu, 23 Aug 2018 13:16:01 -0700 Subject: [PATCH 2/2] use a time.Duration instead of a hardcoded ms --- .../hyperv/common/step_type_boot_command.go | 2 +- .../common/step_type_boot_command.go | 2 +- .../common/step_type_boot_command.go | 2 +- builder/virtualbox/iso/builder.go | 5 -- .../vmware/common/step_type_boot_command.go | 2 +- common/bootcommand/config.go | 48 ++++++++++++++----- common/bootcommand/pc_xt_driver.go | 6 +-- common/bootcommand/pc_xt_driver_test.go | 27 +++++++++-- common/bootcommand/vnc_driver.go | 6 +-- common/bootcommand/vnc_driver_test.go | 15 +++++- website/source/docs/builders/qemu.html.md.erb | 4 +- .../docs/builders/virtualbox-iso.html.md.erb | 4 +- .../docs/builders/virtualbox-ovf.html.md.erb | 5 +- .../docs/builders/vmware-iso.html.md.erb | 4 +- .../docs/builders/vmware-vmx.html.md.erb | 4 +- 15 files changed, 89 insertions(+), 47 deletions(-) diff --git a/builder/hyperv/common/step_type_boot_command.go b/builder/hyperv/common/step_type_boot_command.go index 19574243a..dc4b27c85 100644 --- a/builder/hyperv/common/step_type_boot_command.go +++ b/builder/hyperv/common/step_type_boot_command.go @@ -25,7 +25,7 @@ type StepTypeBootCommand struct { BootWait time.Duration SwitchName string Ctx interpolate.Context - GroupInterval int + GroupInterval time.Duration } func (s *StepTypeBootCommand) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { diff --git a/builder/parallels/common/step_type_boot_command.go b/builder/parallels/common/step_type_boot_command.go index ca3771648..4e1e47b20 100644 --- a/builder/parallels/common/step_type_boot_command.go +++ b/builder/parallels/common/step_type_boot_command.go @@ -26,7 +26,7 @@ type StepTypeBootCommand struct { HostInterfaces []string VMName string Ctx interpolate.Context - GroupInterval int + GroupInterval time.Duration } // Run types the boot command by sending key scancodes into the VM. diff --git a/builder/virtualbox/common/step_type_boot_command.go b/builder/virtualbox/common/step_type_boot_command.go index 95c5219cd..859e425ff 100644 --- a/builder/virtualbox/common/step_type_boot_command.go +++ b/builder/virtualbox/common/step_type_boot_command.go @@ -25,7 +25,7 @@ type StepTypeBootCommand struct { BootWait time.Duration VMName string Ctx interpolate.Context - GroupInterval int + GroupInterval time.Duration } func (s *StepTypeBootCommand) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { diff --git a/builder/virtualbox/iso/builder.go b/builder/virtualbox/iso/builder.go index b0a9cc5cf..5fe773b52 100644 --- a/builder/virtualbox/iso/builder.go +++ b/builder/virtualbox/iso/builder.go @@ -53,7 +53,6 @@ type Config struct { KeepRegistered bool `mapstructure:"keep_registered"` SkipExport bool `mapstructure:"skip_export"` VMName string `mapstructure:"vm_name"` - KeyInterval int `mapstructure:"key_interval"` ctx interpolate.Context } @@ -122,10 +121,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { b.config.ISOInterface = "ide" } - if b.config.KeyInterval == 0 { - b.config.KeyInterval = -1 - } - if b.config.VMName == "" { b.config.VMName = fmt.Sprintf( "packer-%s-%d", b.config.PackerBuildName, interpolate.InitTime.Unix()) diff --git a/builder/vmware/common/step_type_boot_command.go b/builder/vmware/common/step_type_boot_command.go index c1514c272..ac33fd24c 100644 --- a/builder/vmware/common/step_type_boot_command.go +++ b/builder/vmware/common/step_type_boot_command.go @@ -30,7 +30,7 @@ type StepTypeBootCommand struct { BootWait time.Duration VMName string Ctx interpolate.Context - KeyInterval int + KeyInterval time.Duration } type bootCommandTemplateData struct { HTTPIP string diff --git a/common/bootcommand/config.go b/common/bootcommand/config.go index f89d21715..d01e69624 100644 --- a/common/bootcommand/config.go +++ b/common/bootcommand/config.go @@ -9,28 +9,26 @@ import ( ) type BootConfig struct { - RawBootWait string `mapstructure:"boot_wait"` - BootCommand []string `mapstructure:"boot_command"` - // time in ms to wait between each group of 25 key presses - BootGroupInterval int `mapstructure:"boot_keygroup_interval"` - - BootWait time.Duration `` + RawBootGroupInterval string `mapstructure:"boot_keygroup_interval"` + RawBootWait string `mapstructure:"boot_wait"` + BootCommand []string `mapstructure:"boot_command"` + BootGroupInterval time.Duration `` + BootWait time.Duration `` } type VNCConfig struct { BootConfig `mapstructure:",squash"` DisableVNC bool `mapstructure:"disable_vnc"` // time in ms to wait between each key press - BootKeyInterval int `mapstructure:"boot_key_interval"` + RawBootKeyInterval string `mapstructure:"boot_key_interval"` + BootKeyInterval time.Duration `` } func (c *BootConfig) Prepare(ctx *interpolate.Context) (errs []error) { if c.RawBootWait == "" { c.RawBootWait = "10s" } - if c.BootGroupInterval == 0 { - c.BootGroupInterval = -1 - } + if c.RawBootWait != "" { bw, err := time.ParseDuration(c.RawBootWait) if err != nil { @@ -41,6 +39,20 @@ func (c *BootConfig) Prepare(ctx *interpolate.Context) (errs []error) { } } + if c.RawBootGroupInterval == "" { + c.RawBootGroupInterval = "0ms" + } + + if c.RawBootGroupInterval != "" { + bgi, err := time.ParseDuration(c.RawBootGroupInterval) + if err != nil { + errs = append( + errs, fmt.Errorf("Failed parsing boot_keygroup_interval: %s", err)) + } else { + c.BootGroupInterval = bgi + } + } + if c.BootCommand != nil { expSeq, err := GenerateExpressionSequence(c.FlatBootCommand()) if err != nil { @@ -62,9 +74,21 @@ func (c *VNCConfig) Prepare(ctx *interpolate.Context) (errs []error) { errs = append(errs, fmt.Errorf("A boot command cannot be used when vnc is disabled.")) } - if c.BootKeyInterval == 0 { - c.BootKeyInterval = -1 + + if c.RawBootKeyInterval == "" { + c.RawBootKeyInterval = "0ms" } + + if c.RawBootKeyInterval != "" { + bki, err := time.ParseDuration(c.RawBootKeyInterval) + if err != nil { + errs = append( + errs, fmt.Errorf("Failed parsing boot_key_interval: %s", err)) + } else { + c.BootKeyInterval = bki + } + } + errs = append(errs, c.BootConfig.Prepare(ctx)...) return } diff --git a/common/bootcommand/pc_xt_driver.go b/common/bootcommand/pc_xt_driver.go index 11e9cb734..2a3dcb746 100644 --- a/common/bootcommand/pc_xt_driver.go +++ b/common/bootcommand/pc_xt_driver.go @@ -38,7 +38,7 @@ func (sc *scancode) makeBreak() []string { // NewPCXTDriver creates a new boot command driver for VMs that expect PC-XT // keyboard codes. `send` should send its argument to the VM. `chunkSize` should // be the maximum number of keyboard codes to send to `send` at one time. -func NewPCXTDriver(send SendCodeFunc, chunkSize int, interval int) *pcXTDriver { +func NewPCXTDriver(send SendCodeFunc, chunkSize int, interval time.Duration) *pcXTDriver { // We delay (default 100ms) between each input event to allow for CPU or // network latency. See PackerKeyEnv for tuning. keyInterval := common.PackerKeyDefault @@ -46,8 +46,8 @@ func NewPCXTDriver(send SendCodeFunc, chunkSize int, interval int) *pcXTDriver { keyInterval = delay } // Override interval based on builder-specific override - if interval >= 0 { - keyInterval = time.Duration(interval) * time.Millisecond + if interval > time.Duration(0) { + keyInterval = interval } // Scancodes reference: https://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html // https://www.win.tue.nl/~aeb/linux/kbd/scancodes-10.html diff --git a/common/bootcommand/pc_xt_driver_test.go b/common/bootcommand/pc_xt_driver_test.go index f814e64e9..5133f7e85 100644 --- a/common/bootcommand/pc_xt_driver_test.go +++ b/common/bootcommand/pc_xt_driver_test.go @@ -3,6 +3,7 @@ package bootcommand import ( "context" "testing" + "time" "github.com/stretchr/testify/assert" ) @@ -79,7 +80,7 @@ func Test_pcxtSpecialOnOff(t *testing.T) { codes = c return nil } - d := NewPCXTDriver(sendCodes, -1, -1) + d := NewPCXTDriver(sendCodes, -1, time.Duration(0)) seq, err := GenerateExpressionSequence(in) assert.NoError(t, err) err = seq.Do(context.Background(), d) @@ -95,7 +96,7 @@ func Test_pcxtSpecial(t *testing.T) { codes = c return nil } - d := NewPCXTDriver(sendCodes, -1, -1) + d := NewPCXTDriver(sendCodes, -1, time.Duration(0)) seq, err := GenerateExpressionSequence(in) assert.NoError(t, err) err = seq.Do(context.Background(), d) @@ -114,10 +115,30 @@ func Test_flushes(t *testing.T) { actual = append(actual, c) return nil } - d := NewPCXTDriver(sendCodes, -1, -1) + d := NewPCXTDriver(sendCodes, -1, time.Duration(0)) seq, err := GenerateExpressionSequence(in) assert.NoError(t, err) err = seq.Do(context.Background(), d) assert.NoError(t, err) assert.Equal(t, expected, actual) } + +func Test_KeyIntervalNotGiven(t *testing.T) { + var codes []string + sendCodes := func(c []string) error { + codes = c + return nil + } + d := NewPCXTDriver(sendCodes, -1, time.Duration(0)) + assert.Equal(t, d.interval, time.Duration(100)*time.Millisecond) +} + +func Test_KeyIntervalGiven(t *testing.T) { + var codes []string + sendCodes := func(c []string) error { + codes = c + return nil + } + d := NewPCXTDriver(sendCodes, -1, time.Duration(5000)*time.Millisecond) + assert.Equal(t, d.interval, time.Duration(5000)*time.Millisecond) +} diff --git a/common/bootcommand/vnc_driver.go b/common/bootcommand/vnc_driver.go index 0983b923e..027bcffca 100644 --- a/common/bootcommand/vnc_driver.go +++ b/common/bootcommand/vnc_driver.go @@ -25,7 +25,7 @@ type vncDriver struct { err error } -func NewVNCDriver(c VNCKeyEvent, interval int) *vncDriver { +func NewVNCDriver(c VNCKeyEvent, interval time.Duration) *vncDriver { // We delay (default 100ms) between each key event to allow for CPU or // network latency. See PackerKeyEnv for tuning. keyInterval := common.PackerKeyDefault @@ -33,8 +33,8 @@ func NewVNCDriver(c VNCKeyEvent, interval int) *vncDriver { keyInterval = delay } // override interval based on builder-specific override. - if interval >= 0 { - keyInterval = time.Duration(interval) * time.Millisecond + if interval > time.Duration(0) { + keyInterval = interval } // Scancodes reference: https://github.com/qemu/qemu/blob/master/ui/vnc_keysym.h diff --git a/common/bootcommand/vnc_driver_test.go b/common/bootcommand/vnc_driver_test.go index d8bd4e71e..75b585fce 100644 --- a/common/bootcommand/vnc_driver_test.go +++ b/common/bootcommand/vnc_driver_test.go @@ -3,6 +3,7 @@ package bootcommand import ( "context" "testing" + "time" "github.com/stretchr/testify/assert" ) @@ -30,10 +31,22 @@ func Test_vncSpecialLookup(t *testing.T) { {0xFFE2, true}, } s := &sender{} - d := NewVNCDriver(s, -1) + d := NewVNCDriver(s, time.Duration(0)) seq, err := GenerateExpressionSequence(in) assert.NoError(t, err) err = seq.Do(context.Background(), d) assert.NoError(t, err) assert.Equal(t, expected, s.e) } + +func Test_vncIntervalNotGiven(t *testing.T) { + s := &sender{} + d := NewVNCDriver(s, time.Duration(0)) + assert.Equal(t, d.interval, time.Duration(100)*time.Millisecond) +} + +func Test_vncIntervalGiven(t *testing.T) { + s := &sender{} + d := NewVNCDriver(s, time.Duration(5000)*time.Millisecond) + assert.Equal(t, d.interval, time.Duration(5000)*time.Millisecond) +} diff --git a/website/source/docs/builders/qemu.html.md.erb b/website/source/docs/builders/qemu.html.md.erb index 25c0d1bbd..962b85c41 100644 --- a/website/source/docs/builders/qemu.html.md.erb +++ b/website/source/docs/builders/qemu.html.md.erb @@ -394,15 +394,13 @@ contention. You can tune this delay on a per-builder basis by specifying "builders": [ { "type": "qemu", - "boot_key_interval": "10" + "boot_key_interval": "10ms" ... } ] } ``` -Note that this option will always be measured in milliseconds. - <%= partial "partials/builders/boot-command" %> Example boot command. This is actually a working boot command used to start an diff --git a/website/source/docs/builders/virtualbox-iso.html.md.erb b/website/source/docs/builders/virtualbox-iso.html.md.erb index 9277f44ac..b97f9eb1c 100644 --- a/website/source/docs/builders/virtualbox-iso.html.md.erb +++ b/website/source/docs/builders/virtualbox-iso.html.md.erb @@ -345,15 +345,13 @@ contention. If you notice missing keys, you can tune this delay by specifying "builders": [ { "type": "virtualbox", - "boot_keygroup_interval": "500" + "boot_keygroup_interval": "500ms" ... } ] } ``` -Note that this option will always be measured in milliseconds. - <%= partial "partials/builders/boot-command" %> Example boot command. This is actually a working boot command used to start an diff --git a/website/source/docs/builders/virtualbox-ovf.html.md.erb b/website/source/docs/builders/virtualbox-ovf.html.md.erb index aa929b823..5981ad8cf 100644 --- a/website/source/docs/builders/virtualbox-ovf.html.md.erb +++ b/website/source/docs/builders/virtualbox-ovf.html.md.erb @@ -308,16 +308,13 @@ contention. If you notice missing keys, you can tune this delay by specifying "builders": [ { "type": "virtualbox", - "boot_keygroup_interval": "500" + "boot_keygroup_interval": "500ms", ... } ] } ``` -Note that this option will always be measured in milliseconds. - - <%= partial "partials/builders/boot-command" %> Example boot command. This is actually a working boot command used to start an diff --git a/website/source/docs/builders/vmware-iso.html.md.erb b/website/source/docs/builders/vmware-iso.html.md.erb index 613dbb4a2..2dcbd36cf 100644 --- a/website/source/docs/builders/vmware-iso.html.md.erb +++ b/website/source/docs/builders/vmware-iso.html.md.erb @@ -447,15 +447,13 @@ contention. You can tune this delay on a per-builder basis by specifying "builders": [ { "type": "vmware-iso", - "boot_key_interval": "10" + "boot_key_interval": "10ms" ... } ] } ``` -Note that this option will always be measured in milliseconds. - <%= partial "partials/builders/boot-command" %> -> **Note**: for the `HTTPIP` to be resolved correctly, your VM's network diff --git a/website/source/docs/builders/vmware-vmx.html.md.erb b/website/source/docs/builders/vmware-vmx.html.md.erb index 78c6c94c1..d597bb98d 100644 --- a/website/source/docs/builders/vmware-vmx.html.md.erb +++ b/website/source/docs/builders/vmware-vmx.html.md.erb @@ -223,15 +223,13 @@ contention. You can tune this delay on a per-builder basis by specifying "builders": [ { "type": "vmware-vmx", - "boot_key_interval": "10" + "boot_key_interval": "10ms" ... } ] } ``` -Note that this option will always be measured in milliseconds. - <%= partial "partials/builders/boot-command" %> Example boot command. This is actually a working boot command used to start an