Merge pull request #6616 from hashicorp/fix_6496

added new template variables to replace PACKER_KEY_INTERVAL with tuna…
This commit is contained in:
Megan Marsh 2018-08-23 13:21:31 -07:00 committed by GitHub
commit 7f518cc2d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 199 additions and 51 deletions

View File

@ -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 time.Duration
}
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)

View File

@ -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

View File

@ -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

View File

@ -26,6 +26,7 @@ type StepTypeBootCommand struct {
HostInterfaces []string
VMName string
Ctx interpolate.Context
GroupInterval time.Duration
}
// 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)

View File

@ -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,

View File

@ -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,

View File

@ -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)

View File

@ -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 time.Duration
}
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)

View File

@ -245,10 +245,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,

View File

@ -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,

View File

@ -30,6 +30,7 @@ type StepTypeBootCommand struct {
BootWait time.Duration
VMName string
Ctx interpolate.Context
KeyInterval time.Duration
}
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)

View File

@ -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,

View File

@ -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,

View File

@ -9,21 +9,26 @@ import (
)
type BootConfig struct {
RawBootWait string `mapstructure:"boot_wait"`
BootCommand []string `mapstructure:"boot_command"`
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
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.RawBootWait != "" {
bw, err := time.ParseDuration(c.RawBootWait)
if err != nil {
@ -34,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 {
@ -55,6 +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.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
}

View File

@ -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 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
if delay, err := time.ParseDuration(os.Getenv(common.PackerKeyEnv)); err == nil {
keyInterval = delay
}
// Override interval based on builder-specific override
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
//

View File

@ -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)
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)
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)
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)
}

View File

@ -25,13 +25,17 @@ type vncDriver struct {
err error
}
func NewVNCDriver(c VNCKeyEvent) *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
if delay, err := time.ParseDuration(os.Getenv(common.PackerKeyEnv)); err == nil {
keyInterval = delay
}
// override interval based on builder-specific override.
if interval > time.Duration(0) {
keyInterval = interval
}
// Scancodes reference: https://github.com/qemu/qemu/blob/master/ui/vnc_keysym.h
sMap := make(map[string]uint32)

View File

@ -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)
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)
}

View File

@ -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,20 @@ 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": "10ms"
...
}
]
}
```
<%= partial "partials/builders/boot-command" %>

View File

@ -337,8 +337,20 @@ 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": "500ms"
...
}
]
}
```
<%= partial "partials/builders/boot-command" %>

View File

@ -300,8 +300,20 @@ 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": "500ms",
...
}
]
}
```
<%= partial "partials/builders/boot-command" %>

View File

@ -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,20 @@ machine, simulating a human actually typing the keyboard.
-&gt; 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": "10ms"
...
}
]
}
```
<%= partial "partials/builders/boot-command" %>

View File

@ -215,8 +215,20 @@ machine, simulating a human actually typing the keyboard.
-&gt; 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": "10ms"
...
}
]
}
```
<%= partial "partials/builders/boot-command" %>