Improve delay between key events
- Can now tune delay using PACKER_KEY_INTERVAL - Added implementation to all of VMware and QEMU - Removed double delay for QEMU - Default key delay of 100ms (as before) - Added docs to QEMU and VMware pages
This commit is contained in:
parent
d0c64f90d5
commit
ee2d636840
|
@ -12,8 +12,10 @@ import (
|
|||
|
||||
"github.com/mitchellh/go-vnc"
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/common"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"github.com/mitchellh/packer/template/interpolate"
|
||||
"os"
|
||||
)
|
||||
|
||||
const KeyLeftShift uint32 = 0xFFE1
|
||||
|
@ -146,6 +148,14 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
shiftedChars := "~!@#$%^&*()_+{}|:\"<>?"
|
||||
waitRe := regexp.MustCompile(`^<wait([0-9hms]+)>`)
|
||||
|
||||
// Send the key events. We add a 100ms sleep after each key event
|
||||
// to deal with network latency and the OS responding to the keystroke.
|
||||
// It is kind of arbitrary but it is better than nothing.
|
||||
keyInterval := common.PackerKeyDefault
|
||||
if delay, err := time.ParseDuration(os.Getenv(common.PackerKeyEnv)); err == nil {
|
||||
keyInterval = delay
|
||||
}
|
||||
|
||||
// TODO(mitchellh): Ripe for optimizations of some point, perhaps.
|
||||
for len(original) > 0 {
|
||||
var keyCode uint32
|
||||
|
@ -157,11 +167,7 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
log.Printf("Special code '<leftAltOn>' found, replacing with: %d", keyCode)
|
||||
|
||||
c.KeyEvent(keyCode, true)
|
||||
time.Sleep(time.Second / 10)
|
||||
|
||||
// qemu is picky, so no matter what, wait a small period
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
time.Sleep(keyInterval)
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -171,11 +177,7 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
log.Printf("Special code '<leftCtrlOn>' found, replacing with: %d", keyCode)
|
||||
|
||||
c.KeyEvent(keyCode, true)
|
||||
time.Sleep(time.Second / 10)
|
||||
|
||||
// qemu is picky, so no matter what, wait a small period
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
time.Sleep(keyInterval)
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -185,11 +187,7 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
log.Printf("Special code '<leftShiftOn>' found, replacing with: %d", keyCode)
|
||||
|
||||
c.KeyEvent(keyCode, true)
|
||||
time.Sleep(time.Second / 10)
|
||||
|
||||
// qemu is picky, so no matter what, wait a small period
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
time.Sleep(keyInterval)
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -199,11 +197,7 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
log.Printf("Special code '<leftAltOff>' found, replacing with: %d", keyCode)
|
||||
|
||||
c.KeyEvent(keyCode, false)
|
||||
time.Sleep(time.Second / 10)
|
||||
|
||||
// qemu is picky, so no matter what, wait a small period
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
time.Sleep(keyInterval)
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -213,11 +207,7 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
log.Printf("Special code '<leftCtrlOff>' found, replacing with: %d", keyCode)
|
||||
|
||||
c.KeyEvent(keyCode, false)
|
||||
time.Sleep(time.Second / 10)
|
||||
|
||||
// qemu is picky, so no matter what, wait a small period
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
time.Sleep(keyInterval)
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -227,11 +217,7 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
log.Printf("Special code '<leftShiftOff>' found, replacing with: %d", keyCode)
|
||||
|
||||
c.KeyEvent(keyCode, false)
|
||||
time.Sleep(time.Second / 10)
|
||||
|
||||
// qemu is picky, so no matter what, wait a small period
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
time.Sleep(keyInterval)
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -241,11 +227,7 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
log.Printf("Special code '<rightAltOn>' found, replacing with: %d", keyCode)
|
||||
|
||||
c.KeyEvent(keyCode, true)
|
||||
time.Sleep(time.Second / 10)
|
||||
|
||||
// qemu is picky, so no matter what, wait a small period
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
time.Sleep(keyInterval)
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -255,11 +237,7 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
log.Printf("Special code '<rightCtrlOn>' found, replacing with: %d", keyCode)
|
||||
|
||||
c.KeyEvent(keyCode, true)
|
||||
time.Sleep(time.Second / 10)
|
||||
|
||||
// qemu is picky, so no matter what, wait a small period
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
time.Sleep(keyInterval)
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -269,11 +247,7 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
log.Printf("Special code '<rightShiftOn>' found, replacing with: %d", keyCode)
|
||||
|
||||
c.KeyEvent(keyCode, true)
|
||||
time.Sleep(time.Second / 10)
|
||||
|
||||
// qemu is picky, so no matter what, wait a small period
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
time.Sleep(keyInterval)
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -283,11 +257,7 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
log.Printf("Special code '<rightAltOff>' found, replacing with: %d", keyCode)
|
||||
|
||||
c.KeyEvent(keyCode, false)
|
||||
time.Sleep(time.Second / 10)
|
||||
|
||||
// qemu is picky, so no matter what, wait a small period
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
time.Sleep(keyInterval)
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -297,11 +267,7 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
log.Printf("Special code '<rightCtrlOff>' found, replacing with: %d", keyCode)
|
||||
|
||||
c.KeyEvent(keyCode, false)
|
||||
time.Sleep(time.Second / 10)
|
||||
|
||||
// qemu is picky, so no matter what, wait a small period
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
time.Sleep(keyInterval)
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -311,11 +277,7 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
log.Printf("Special code '<rightShiftOff>' found, replacing with: %d", keyCode)
|
||||
|
||||
c.KeyEvent(keyCode, false)
|
||||
time.Sleep(time.Second / 10)
|
||||
|
||||
// qemu is picky, so no matter what, wait a small period
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
time.Sleep(keyInterval)
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -373,15 +335,14 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
}
|
||||
|
||||
c.KeyEvent(keyCode, true)
|
||||
time.Sleep(time.Second / 10)
|
||||
time.Sleep(keyInterval)
|
||||
|
||||
c.KeyEvent(keyCode, false)
|
||||
time.Sleep(time.Second / 10)
|
||||
time.Sleep(keyInterval)
|
||||
|
||||
if keyShift {
|
||||
c.KeyEvent(KeyLeftShift, false)
|
||||
}
|
||||
|
||||
// qemu is picky, so no matter what, wait a small period
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
time.Sleep(keyInterval)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
|
||||
"github.com/mitchellh/go-vnc"
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/common"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"github.com/mitchellh/packer/template/interpolate"
|
||||
)
|
||||
|
@ -178,6 +179,14 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
|
||||
shiftedChars := "~!@#$%^&*()_+{}|:\"<>?"
|
||||
|
||||
// Send the key events. We add a 100ms sleep after each key event
|
||||
// to deal with network latency and the OS responding to the keystroke.
|
||||
// It is kind of arbitrary but it is better than nothing.
|
||||
keyInterval := common.PackerKeyDefault
|
||||
if delay, err := time.ParseDuration(os.Getenv(common.PackerKeyEnv)); err == nil {
|
||||
keyInterval = delay
|
||||
}
|
||||
|
||||
// TODO(mitchellh): Ripe for optimizations of some point, perhaps.
|
||||
for len(original) > 0 {
|
||||
var keyCode uint32
|
||||
|
@ -189,7 +198,7 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
log.Printf("Special code '<leftAltOn>' found, replacing with: %d", keyCode)
|
||||
|
||||
c.KeyEvent(keyCode, true)
|
||||
time.Sleep(time.Second / 10)
|
||||
time.Sleep(keyInterval)
|
||||
|
||||
continue
|
||||
}
|
||||
|
@ -200,7 +209,7 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
log.Printf("Special code '<leftCtrlOn>' found, replacing with: %d", keyCode)
|
||||
|
||||
c.KeyEvent(keyCode, true)
|
||||
time.Sleep(time.Second / 10)
|
||||
time.Sleep(keyInterval)
|
||||
|
||||
continue
|
||||
}
|
||||
|
@ -211,7 +220,7 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
log.Printf("Special code '<leftShiftOn>' found, replacing with: %d", keyCode)
|
||||
|
||||
c.KeyEvent(keyCode, true)
|
||||
time.Sleep(time.Second / 10)
|
||||
time.Sleep(keyInterval)
|
||||
|
||||
continue
|
||||
}
|
||||
|
@ -222,7 +231,7 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
log.Printf("Special code '<leftAltOff>' found, replacing with: %d", keyCode)
|
||||
|
||||
c.KeyEvent(keyCode, false)
|
||||
time.Sleep(time.Second / 10)
|
||||
time.Sleep(keyInterval)
|
||||
|
||||
continue
|
||||
}
|
||||
|
@ -233,7 +242,7 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
log.Printf("Special code '<leftCtrlOff>' found, replacing with: %d", keyCode)
|
||||
|
||||
c.KeyEvent(keyCode, false)
|
||||
time.Sleep(time.Second / 10)
|
||||
time.Sleep(keyInterval)
|
||||
|
||||
continue
|
||||
}
|
||||
|
@ -244,7 +253,7 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
log.Printf("Special code '<leftShiftOff>' found, replacing with: %d", keyCode)
|
||||
|
||||
c.KeyEvent(keyCode, false)
|
||||
time.Sleep(time.Second / 10)
|
||||
time.Sleep(keyInterval)
|
||||
|
||||
continue
|
||||
}
|
||||
|
@ -255,7 +264,7 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
log.Printf("Special code '<rightAltOn>' found, replacing with: %d", keyCode)
|
||||
|
||||
c.KeyEvent(keyCode, true)
|
||||
time.Sleep(time.Second / 10)
|
||||
time.Sleep(keyInterval)
|
||||
|
||||
continue
|
||||
}
|
||||
|
@ -266,7 +275,7 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
log.Printf("Special code '<rightCtrlOn>' found, replacing with: %d", keyCode)
|
||||
|
||||
c.KeyEvent(keyCode, true)
|
||||
time.Sleep(time.Second / 10)
|
||||
time.Sleep(keyInterval)
|
||||
|
||||
continue
|
||||
}
|
||||
|
@ -277,7 +286,7 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
log.Printf("Special code '<rightShiftOn>' found, replacing with: %d", keyCode)
|
||||
|
||||
c.KeyEvent(keyCode, true)
|
||||
time.Sleep(time.Second / 10)
|
||||
time.Sleep(keyInterval)
|
||||
|
||||
continue
|
||||
}
|
||||
|
@ -288,7 +297,7 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
log.Printf("Special code '<rightAltOff>' found, replacing with: %d", keyCode)
|
||||
|
||||
c.KeyEvent(keyCode, false)
|
||||
time.Sleep(time.Second / 10)
|
||||
time.Sleep(keyInterval)
|
||||
|
||||
continue
|
||||
}
|
||||
|
@ -299,7 +308,7 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
log.Printf("Special code '<rightCtrlOff>' found, replacing with: %d", keyCode)
|
||||
|
||||
c.KeyEvent(keyCode, false)
|
||||
time.Sleep(time.Second / 10)
|
||||
time.Sleep(keyInterval)
|
||||
|
||||
continue
|
||||
}
|
||||
|
@ -310,7 +319,7 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
log.Printf("Special code '<rightShiftOff>' found, replacing with: %d", keyCode)
|
||||
|
||||
c.KeyEvent(keyCode, false)
|
||||
time.Sleep(time.Second / 10)
|
||||
time.Sleep(keyInterval)
|
||||
|
||||
continue
|
||||
}
|
||||
|
@ -358,14 +367,6 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||
c.KeyEvent(KeyLeftShift, true)
|
||||
}
|
||||
|
||||
// Send the key events. We add a 100ms sleep after each key event
|
||||
// to deal with network latency and the OS responding to the keystroke.
|
||||
// It is kind of arbitrary but it is better than nothing.
|
||||
keyInterval := 100 * time.Millisecond
|
||||
if envInterval, err := time.ParseDuration(os.Getenv("PACKER_KEY_INTERVAL")); err == nil {
|
||||
keyInterval = envInterval
|
||||
}
|
||||
|
||||
c.KeyEvent(keyCode, true)
|
||||
time.Sleep(keyInterval)
|
||||
c.KeyEvent(keyCode, false)
|
||||
|
|
|
@ -23,7 +23,7 @@ import (
|
|||
dockerbuilder "github.com/mitchellh/packer/builder/docker"
|
||||
filebuilder "github.com/mitchellh/packer/builder/file"
|
||||
googlecomputebuilder "github.com/mitchellh/packer/builder/googlecompute"
|
||||
hypervbuilder "github.com/mitchellh/packer/builder/hyperv/iso"
|
||||
hypervisobuilder "github.com/mitchellh/packer/builder/hyperv/iso"
|
||||
nullbuilder "github.com/mitchellh/packer/builder/null"
|
||||
oneandonebuilder "github.com/mitchellh/packer/builder/oneandone"
|
||||
openstackbuilder "github.com/mitchellh/packer/builder/openstack"
|
||||
|
@ -36,7 +36,6 @@ import (
|
|||
virtualboxovfbuilder "github.com/mitchellh/packer/builder/virtualbox/ovf"
|
||||
vmwareisobuilder "github.com/mitchellh/packer/builder/vmware/iso"
|
||||
vmwarevmxbuilder "github.com/mitchellh/packer/builder/vmware/vmx"
|
||||
|
||||
amazonimportpostprocessor "github.com/mitchellh/packer/post-processor/amazon-import"
|
||||
artificepostprocessor "github.com/mitchellh/packer/post-processor/artifice"
|
||||
atlaspostprocessor "github.com/mitchellh/packer/post-processor/atlas"
|
||||
|
@ -52,11 +51,11 @@ import (
|
|||
vagrantpostprocessor "github.com/mitchellh/packer/post-processor/vagrant"
|
||||
vagrantcloudpostprocessor "github.com/mitchellh/packer/post-processor/vagrant-cloud"
|
||||
vspherepostprocessor "github.com/mitchellh/packer/post-processor/vsphere"
|
||||
|
||||
ansibleprovisioner "github.com/mitchellh/packer/provisioner/ansible"
|
||||
ansiblelocalprovisioner "github.com/mitchellh/packer/provisioner/ansible-local"
|
||||
chefclientprovisioner "github.com/mitchellh/packer/provisioner/chef-client"
|
||||
chefsoloprovisioner "github.com/mitchellh/packer/provisioner/chef-solo"
|
||||
convergeprovisioner "github.com/mitchellh/packer/provisioner/converge"
|
||||
fileprovisioner "github.com/mitchellh/packer/provisioner/file"
|
||||
powershellprovisioner "github.com/mitchellh/packer/provisioner/powershell"
|
||||
puppetmasterlessprovisioner "github.com/mitchellh/packer/provisioner/puppet-masterless"
|
||||
|
@ -83,7 +82,7 @@ var Builders = map[string]packer.Builder{
|
|||
"docker": new(dockerbuilder.Builder),
|
||||
"file": new(filebuilder.Builder),
|
||||
"googlecompute": new(googlecomputebuilder.Builder),
|
||||
"hyperv-iso": new(hypervbuilder.Builder),
|
||||
"hyperv-iso": new(hypervisobuilder.Builder),
|
||||
"null": new(nullbuilder.Builder),
|
||||
"oneandone": new(oneandonebuilder.Builder),
|
||||
"openstack": new(openstackbuilder.Builder),
|
||||
|
@ -103,6 +102,7 @@ var Provisioners = map[string]packer.Provisioner{
|
|||
"ansible-local": new(ansiblelocalprovisioner.Provisioner),
|
||||
"chef-client": new(chefclientprovisioner.Provisioner),
|
||||
"chef-solo": new(chefsoloprovisioner.Provisioner),
|
||||
"converge": new(convergeprovisioner.Provisioner),
|
||||
"file": new(fileprovisioner.Provisioner),
|
||||
"powershell": new(powershellprovisioner.Provisioner),
|
||||
"puppet-masterless": new(puppetmasterlessprovisioner.Provisioner),
|
||||
|
|
|
@ -7,8 +7,18 @@ import (
|
|||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// PackerKeyEnv is used to specify the key interval (delay) between keystrokes
|
||||
// sent to the VM, typically in boot commands. This is to prevent host CPU
|
||||
// utilization from causing key presses to be skipped or repeated incorrectly.
|
||||
const PackerKeyEnv = "PACKER_KEY_INTERVAL"
|
||||
|
||||
// PackerKeyDefault 100ms is appropriate for shared build infrastructure while a
|
||||
// shorter delay (e.g. 10ms) can be used on a workstation. See PackerKeyEnv.
|
||||
const PackerKeyDefault = 100 * time.Millisecond
|
||||
|
||||
// ScrubConfig is a helper that returns a string representation of
|
||||
// any struct with the given values stripped out.
|
||||
func ScrubConfig(target interface{}, values ...string) string {
|
||||
|
|
|
@ -357,9 +357,17 @@ all typed in sequence. It is an array only to improve readability within the
|
|||
template.
|
||||
|
||||
The boot command is "typed" character for character over a VNC connection to the
|
||||
machine, simulating a human actually typing the keyboard. There are a set of
|
||||
special keys available. If these are in your boot command, they will be replaced
|
||||
by the proper key:
|
||||
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
|
||||
`PACKER_KEY_INTERVAL` to speed through the boot command. For example:
|
||||
|
||||
PACKER_KEY_INTERVAL=10ms packer build packer.json
|
||||
|
||||
There are a set of special keys available. If these are in your boot
|
||||
command, they will be replaced by the proper key:
|
||||
|
||||
- `<bs>` - Backspace
|
||||
|
||||
|
|
|
@ -304,9 +304,15 @@ all typed in sequence. It is an array only to improve readability within the
|
|||
template.
|
||||
|
||||
The boot command is "typed" character for character over a VNC connection to the
|
||||
machine, simulating a human actually typing the keyboard. There are a set of
|
||||
special keys available. If these are in your boot command, they will be replaced
|
||||
by the proper key:
|
||||
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
|
||||
`PACKER_KEY_INTERVAL` to speed through the boot command. For example:
|
||||
|
||||
There are a set of special keys available. If these are in your boot
|
||||
command, they will be replaced by the proper key:
|
||||
|
||||
- `<bs>` - Backspace
|
||||
|
||||
|
|
|
@ -185,9 +185,15 @@ all typed in sequence. It is an array only to improve readability within the
|
|||
template.
|
||||
|
||||
The boot command is "typed" character for character over a VNC connection to the
|
||||
machine, simulating a human actually typing the keyboard. There are a set of
|
||||
special keys available. If these are in your boot command, they will be replaced
|
||||
by the proper key:
|
||||
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
|
||||
`PACKER_KEY_INTERVAL` to speed through the boot command. For example:
|
||||
|
||||
There are a set of special keys available. If these are in your boot
|
||||
command, they will be replaced by the proper key:
|
||||
|
||||
- `<bs>` - Backspace
|
||||
|
||||
|
|
Loading…
Reference in New Issue