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

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

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