Fix boot_command and update docs
This commit is contained in:
parent
ba767d1663
commit
65cfb880fd
|
@ -7,14 +7,24 @@ import (
|
|||
)
|
||||
|
||||
type KeyInput struct {
|
||||
Message string
|
||||
Scancode key.Code
|
||||
Alt bool
|
||||
Ctrl bool
|
||||
Shift bool
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) TypeOnKeyboard(spec types.UsbScanCodeSpec) (int32, error) {
|
||||
func (vm *VirtualMachine) TypeOnKeyboard(input KeyInput) (int32, error) {
|
||||
var spec types.UsbScanCodeSpec
|
||||
|
||||
spec.KeyEvents = append(spec.KeyEvents, types.UsbScanCodeSpecKeyEvent{
|
||||
UsbHidCode: int32(input.Scancode)<<16 | 7,
|
||||
Modifiers: &types.UsbScanCodeSpecModifierType{
|
||||
LeftControl: &input.Ctrl,
|
||||
LeftAlt: &input.Alt,
|
||||
LeftShift: &input.Shift,
|
||||
},
|
||||
})
|
||||
|
||||
req := &types.PutUsbScanCodes{
|
||||
This: vm.vm.Reference(),
|
||||
Spec: spec,
|
||||
|
|
|
@ -69,8 +69,9 @@ type FlatConfig struct {
|
|||
FloppyDirectories []string `mapstructure:"floppy_dirs" cty:"floppy_dirs" hcl:"floppy_dirs"`
|
||||
FloppyLabel *string `mapstructure:"floppy_label" cty:"floppy_label" hcl:"floppy_label"`
|
||||
BootOrder *string `mapstructure:"boot_order" cty:"boot_order" hcl:"boot_order"`
|
||||
BootCommand []string `mapstructure:"boot_command" cty:"boot_command" hcl:"boot_command"`
|
||||
BootGroupInterval *string `mapstructure:"boot_keygroup_interval" cty:"boot_keygroup_interval" hcl:"boot_keygroup_interval"`
|
||||
BootWait *string `mapstructure:"boot_wait" cty:"boot_wait" hcl:"boot_wait"`
|
||||
BootCommand []string `mapstructure:"boot_command" cty:"boot_command" hcl:"boot_command"`
|
||||
HTTPIP *string `mapstructure:"http_ip" cty:"http_ip" hcl:"http_ip"`
|
||||
WaitTimeout *string `mapstructure:"ip_wait_timeout" cty:"ip_wait_timeout" hcl:"ip_wait_timeout"`
|
||||
SettleTimeout *string `mapstructure:"ip_settle_timeout" cty:"ip_settle_timeout" hcl:"ip_settle_timeout"`
|
||||
|
@ -196,8 +197,9 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"floppy_dirs": &hcldec.AttrSpec{Name: "floppy_dirs", Type: cty.List(cty.String), Required: false},
|
||||
"floppy_label": &hcldec.AttrSpec{Name: "floppy_label", Type: cty.String, Required: false},
|
||||
"boot_order": &hcldec.AttrSpec{Name: "boot_order", Type: cty.String, Required: false},
|
||||
"boot_command": &hcldec.AttrSpec{Name: "boot_command", Type: cty.List(cty.String), Required: false},
|
||||
"boot_keygroup_interval": &hcldec.AttrSpec{Name: "boot_keygroup_interval", Type: cty.String, Required: false},
|
||||
"boot_wait": &hcldec.AttrSpec{Name: "boot_wait", Type: cty.String, Required: false},
|
||||
"boot_command": &hcldec.AttrSpec{Name: "boot_command", Type: cty.List(cty.String), Required: false},
|
||||
"http_ip": &hcldec.AttrSpec{Name: "http_ip", Type: cty.String, Required: false},
|
||||
"ip_wait_timeout": &hcldec.AttrSpec{Name: "ip_wait_timeout", Type: cty.String, Required: false},
|
||||
"ip_settle_timeout": &hcldec.AttrSpec{Name: "ip_settle_timeout", Type: cty.String, Required: false},
|
||||
|
|
|
@ -8,9 +8,7 @@ import (
|
|||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"golang.org/x/mobile/event/key"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -79,35 +77,26 @@ func (s *StepBootCommand) Run(ctx context.Context, state multistep.StateBag) mul
|
|||
ui.Say(fmt.Sprintf("HTTP server is working at http://%v:%v/", ip, port))
|
||||
}
|
||||
|
||||
sendCodes := func(codes []key.Code, downs []bool) error {
|
||||
var spec types.UsbScanCodeSpec
|
||||
sendCodes := func(code key.Code, down bool) error {
|
||||
var keyAlt, keyCtrl, keyShift bool
|
||||
|
||||
for i, code := range codes {
|
||||
var keyAlt, keyCtrl, keyShift bool
|
||||
|
||||
switch code {
|
||||
case key.CodeLeftAlt:
|
||||
// <leftAltOn>
|
||||
keyAlt = downs[i]
|
||||
case key.CodeLeftControl:
|
||||
// <leftCtrlOn>
|
||||
keyCtrl = downs[i]
|
||||
default:
|
||||
keyShift = downs[i]
|
||||
}
|
||||
|
||||
log.Printf("Sending code %s, shift %v", code, downs[i])
|
||||
spec.KeyEvents = append(spec.KeyEvents, types.UsbScanCodeSpecKeyEvent{
|
||||
UsbHidCode: int32(code)<<16 | 7,
|
||||
Modifiers: &types.UsbScanCodeSpecModifierType{
|
||||
LeftControl: &keyCtrl,
|
||||
LeftAlt: &keyAlt,
|
||||
LeftShift: &keyShift,
|
||||
},
|
||||
})
|
||||
switch code {
|
||||
case key.CodeLeftAlt:
|
||||
// <leftAltOn>
|
||||
keyAlt = down
|
||||
case key.CodeLeftControl:
|
||||
// <leftCtrlOn>
|
||||
keyCtrl = down
|
||||
default:
|
||||
keyShift = down
|
||||
}
|
||||
|
||||
_, err := vm.TypeOnKeyboard(spec)
|
||||
_, err := vm.TypeOnKeyboard(driver.KeyInput{
|
||||
Scancode: code,
|
||||
Ctrl: keyCtrl,
|
||||
Alt: keyAlt,
|
||||
Shift: keyShift,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error typing a boot command: %v", err)
|
||||
}
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
package iso
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"github.com/hashicorp/packer/builder/vsphere/driver"
|
||||
"github.com/hashicorp/packer/common/bootcommand"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStepBootCommand_Run(t *testing.T) {
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("ui", &packer.BasicUi{
|
||||
Reader: new(bytes.Buffer),
|
||||
Writer: new(bytes.Buffer),
|
||||
})
|
||||
state.Put("debug", false)
|
||||
state.Put("vm", new(driver.VirtualMachine))
|
||||
|
||||
state.Put("http_port", 2222)
|
||||
state.Put("http_ip", "0.0.0.0")
|
||||
|
||||
step := &StepBootCommand{
|
||||
Config: &BootConfig{
|
||||
BootConfig: bootcommand.BootConfig{
|
||||
BootCommand: []string{
|
||||
"<leftShiftOn><enter><wait><f6><wait><esc><wait>",
|
||||
"<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
|
||||
"<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
|
||||
"<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
|
||||
"<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
|
||||
"<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
|
||||
"<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
|
||||
"<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
|
||||
"<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
|
||||
"<bs><bs><bs>",
|
||||
"/install/vmlinuz",
|
||||
" initrd=/install/initrd.gz",
|
||||
" priority=critical",
|
||||
" locale=en_US",
|
||||
" file=/media/preseed_hardcoded_ip.cfg",
|
||||
" netcfg/get_ipaddress=0.0.0.0",
|
||||
" netcfg/get_gateway=0.0.0.0",
|
||||
"<enter>",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
step.Run(context.TODO(), state)
|
||||
}
|
|
@ -2,18 +2,19 @@ package bootcommand
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hashicorp/packer/builder/vsphere/driver"
|
||||
"github.com/hashicorp/packer/common"
|
||||
"golang.org/x/mobile/event/key"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"github.com/hashicorp/packer/builder/vsphere/driver"
|
||||
"github.com/hashicorp/packer/common"
|
||||
"golang.org/x/mobile/event/key"
|
||||
)
|
||||
|
||||
// SendUsbScanCodes will be called to send codes to the VM
|
||||
type SendUsbScanCodes func([]key.Code, []bool) error
|
||||
type SendUsbScanCodes func(k key.Code, down bool) error
|
||||
|
||||
type usbDriver struct {
|
||||
vm *driver.VirtualMachine
|
||||
|
@ -23,9 +24,6 @@ type usbDriver struct {
|
|||
specialMap map[string]key.Code
|
||||
scancodeMap map[rune]key.Code
|
||||
|
||||
codeBuffer []key.Code
|
||||
downBuffer []bool
|
||||
|
||||
// keyEvent can set this error which will prevent it from continuing
|
||||
err error
|
||||
}
|
||||
|
@ -103,25 +101,27 @@ func NewUSBDriver(send SendUsbScanCodes, interval time.Duration) *usbDriver {
|
|||
}
|
||||
}
|
||||
|
||||
// Flush sends codes to the vm
|
||||
func (d *usbDriver) Flush() error {
|
||||
defer func() {
|
||||
d.codeBuffer = nil
|
||||
}()
|
||||
|
||||
if err := d.sendImpl(d.codeBuffer, d.downBuffer); err != nil {
|
||||
func (d *usbDriver) keyEvent(k key.Code, down bool) error {
|
||||
if d.err != nil {
|
||||
return d.err
|
||||
}
|
||||
if err := d.sendImpl(k, down); err != nil {
|
||||
d.err = err
|
||||
return err
|
||||
}
|
||||
time.Sleep(d.interval)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *usbDriver) Flush() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *usbDriver) SendKey(k rune, action KeyAction) error {
|
||||
keyShift := unicode.IsUpper(k) || strings.ContainsRune(shiftedChars, k)
|
||||
keyCode := d.scancodeMap[k]
|
||||
log.Printf("Sending char '%c', code %s, shift %v", k, keyCode, keyShift)
|
||||
d.send(keyCode, keyShift)
|
||||
return d.err
|
||||
return d.keyEvent(keyCode, keyShift)
|
||||
}
|
||||
|
||||
func (d *usbDriver) SendSpecial(special string, action KeyAction) error {
|
||||
|
@ -133,18 +133,10 @@ func (d *usbDriver) SendSpecial(special string, action KeyAction) error {
|
|||
|
||||
switch action {
|
||||
case KeyOn:
|
||||
d.send(keyCode, true)
|
||||
d.keyEvent(keyCode, true)
|
||||
case KeyOff, KeyPress:
|
||||
d.send(keyCode, false)
|
||||
d.keyEvent(keyCode, false)
|
||||
}
|
||||
|
||||
return d.err
|
||||
}
|
||||
|
||||
// send stores the codes in an internal buffer. Use Flush to send them.
|
||||
func (d *usbDriver) send(code key.Code, down bool) {
|
||||
// slices to keep the input order
|
||||
d.codeBuffer = append(d.codeBuffer, code)
|
||||
d.downBuffer = append(d.downBuffer, down)
|
||||
|
||||
}
|
||||
|
|
|
@ -154,6 +154,11 @@ necessary for this build to succeed and can be found further down the page.
|
|||
|
||||
@include 'common/bootcommand/BootConfig.mdx'
|
||||
|
||||
Please note that for the Virtuabox builder, the IP address of the HTTP server
|
||||
Packer launches for you to access files like the preseed file in the example
|
||||
above (`{{ .HTTPIP }}`) is hardcoded to 10.0.2.2. If you change the network
|
||||
of your VM you must guarantee that you can still access this HTTP server.
|
||||
|
||||
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
|
||||
|
@ -176,35 +181,8 @@ contention. If you notice missing keys, you can tune this delay by specifying
|
|||
|
||||
@include 'common/bootcommand/BootConfig-not-required.mdx'
|
||||
|
||||
@include 'builders/boot-command.mdx'
|
||||
|
||||
@include 'builders/virtualbox-ssh-key-pair.mdx'
|
||||
|
||||
Example boot command. This is actually a working boot command used to start an
|
||||
Ubuntu 12.04 installer:
|
||||
|
||||
```text
|
||||
[
|
||||
"<esc><esc><enter><wait>",
|
||||
"/install/vmlinuz noapic ",
|
||||
"preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg ",
|
||||
"debian-installer=en_US auto locale=en_US kbd-chooser/method=us ",
|
||||
"hostname={{ .Name }} ",
|
||||
"fb=false debconf/frontend=noninteractive ",
|
||||
"keyboard-configuration/modelcode=SKIP keyboard-configuration/layout=USA ",
|
||||
"keyboard-configuration/variant=USA console-setup/ask_detect=false ",
|
||||
"initrd=/install/initrd.gz -- <enter>"
|
||||
]
|
||||
```
|
||||
|
||||
Please note that for the Virtuabox builder, the IP address of the HTTP server
|
||||
Packer launches for you to access files like the preseed file in the example
|
||||
above (`{{ .HTTPIP }}`) is hardcoded to 10.0.2.2. If you change the network
|
||||
of your VM you must guarantee that you can still access this HTTP server.
|
||||
|
||||
For more examples of various boot commands, see the sample projects from our
|
||||
[community templates page](/community-tools#templates).
|
||||
|
||||
## Guest Additions
|
||||
|
||||
Packer will automatically download the proper guest additions for the version of
|
||||
|
|
|
@ -145,6 +145,11 @@ necessary for this build to succeed and can be found further down the page.
|
|||
|
||||
@include 'common/bootcommand/BootConfig.mdx'
|
||||
|
||||
Please note that for the Virtuabox builder, the IP address of the HTTP server
|
||||
Packer launches for you to access files like the preseed file in the example
|
||||
above (`{{ .HTTPIP }}`) is hardcoded to 10.0.2.2. If you change the network
|
||||
of your VM you must guarantee that you can still access this HTTP server.
|
||||
|
||||
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
|
||||
|
@ -167,30 +172,8 @@ contention. If you notice missing keys, you can tune this delay by specifying
|
|||
|
||||
@include 'common/bootcommand/BootConfig-not-required.mdx'
|
||||
|
||||
@include 'builders/boot-command.mdx'
|
||||
|
||||
@include 'builders/virtualbox-ssh-key-pair.mdx'
|
||||
|
||||
Example boot command. This is actually a working boot command used to start an
|
||||
Ubuntu 12.04 installer:
|
||||
|
||||
```text
|
||||
[
|
||||
"<esc><esc><enter><wait>",
|
||||
"/install/vmlinuz noapic ",
|
||||
"preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg ",
|
||||
"debian-installer=en_US auto locale=en_US kbd-chooser/method=us ",
|
||||
"hostname={{ .Name }} ",
|
||||
"fb=false debconf/frontend=noninteractive ",
|
||||
"keyboard-configuration/modelcode=SKIP keyboard-configuration/layout=USA ",
|
||||
"keyboard-configuration/variant=USA console-setup/ask_detect=false ",
|
||||
"initrd=/install/initrd.gz -- <enter>"
|
||||
]
|
||||
```
|
||||
|
||||
For more examples of various boot commands, see the sample projects from our
|
||||
[community templates page](/community-tools#templates).
|
||||
|
||||
## Guest Additions
|
||||
|
||||
Packer will automatically download the proper guest additions for the version of
|
||||
|
|
|
@ -159,6 +159,11 @@ builder.
|
|||
|
||||
@include 'common/bootcommand/BootConfig.mdx'
|
||||
|
||||
Please note that for the Virtuabox builder, the IP address of the HTTP server
|
||||
Packer launches for you to access files like the preseed file in the example
|
||||
above (`{{ .HTTPIP }}`) is hardcoded to 10.0.2.2. If you change the network
|
||||
of your VM you must guarantee that you can still access this HTTP server.
|
||||
|
||||
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
|
||||
|
@ -181,34 +186,8 @@ contention. If you notice missing keys, you can tune this delay by specifying
|
|||
|
||||
@include 'common/bootcommand/BootConfig-not-required.mdx'
|
||||
|
||||
@include 'builders/boot-command.mdx'
|
||||
|
||||
@include 'builders/virtualbox-ssh-key-pair.mdx'
|
||||
|
||||
Example boot command. This is actually a working boot command used to start an
|
||||
Ubuntu 12.04 installer:
|
||||
|
||||
```text
|
||||
[
|
||||
"<esc><esc><enter><wait>",
|
||||
"/install/vmlinuz noapic ",
|
||||
"preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg ",
|
||||
"debian-installer=en_US auto locale=en_US kbd-chooser/method=us ",
|
||||
"hostname={{ .Name }} ",
|
||||
"fb=false debconf/frontend=noninteractive ",
|
||||
"keyboard-configuration/modelcode=SKIP keyboard-configuration/layout=USA ",
|
||||
"keyboard-configuration/variant=USA console-setup/ask_detect=false ",
|
||||
"initrd=/install/initrd.gz -- <enter>"
|
||||
]
|
||||
```
|
||||
|
||||
Please note that for the Virtuabox builder, the IP address of the HTTP server
|
||||
Packer launches for you to access files like the preseed file in the example
|
||||
above (`{{ .HTTPIP }}`) is hardcoded to 10.0.2.2. If you change the network
|
||||
of your VM you must guarantee that you can still access this HTTP server.
|
||||
|
||||
For more examples of various boot commands, see the sample projects from our
|
||||
[community templates page](/community-tools#templates).
|
||||
|
||||
## Guest Additions
|
||||
|
||||
|
|
|
@ -162,6 +162,31 @@ from the datastore. Example:
|
|||
|
||||
@include 'helper/communicator/WinRM-not-required.mdx'
|
||||
|
||||
## Boot Configuration
|
||||
|
||||
@include 'common/bootcommand/BootConfig.mdx'
|
||||
|
||||
We send each character to the VM with a default delay of 100ms between groups.
|
||||
The delay alleviates possible issues with latency and CPU
|
||||
contention. If you notice missing keys, you can tune this delay by specifying
|
||||
"boot_keygroup_interval" in your Packer template, for example:
|
||||
|
||||
```json
|
||||
{
|
||||
"builders": [
|
||||
{
|
||||
"type": "vsphere-iso",
|
||||
"boot_keygroup_interval": "500ms"
|
||||
...
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### Optional:
|
||||
|
||||
@include 'common/bootcommand/BootConfig-not-required.mdx'
|
||||
|
||||
## Working with Clusters
|
||||
|
||||
#### Standalone Hosts
|
||||
|
|
Loading…
Reference in New Issue