From 65cfb880fda682c3c3d41f3179b145c1a631ed41 Mon Sep 17 00:00:00 2001 From: Moss Date: Fri, 12 Jun 2020 12:42:00 +0200 Subject: [PATCH] Fix boot_command and update docs --- builder/vsphere/driver/vm_keyboard.go | 14 ++++- builder/vsphere/iso/config.hcl2spec.go | 6 ++- builder/vsphere/iso/step_boot_command.go | 45 ++++++---------- builder/vsphere/iso/step_boot_command_test.go | 52 ------------------- common/bootcommand/usb_driver.go | 44 +++++++--------- .../pages/docs/builders/virtualbox/iso.mdx | 32 ++---------- .../pages/docs/builders/virtualbox/ovf.mdx | 27 ++-------- website/pages/docs/builders/virtualbox/vm.mdx | 31 ++--------- .../docs/builders/vmware/vsphere-iso.mdx | 25 +++++++++ 9 files changed, 91 insertions(+), 185 deletions(-) delete mode 100644 builder/vsphere/iso/step_boot_command_test.go diff --git a/builder/vsphere/driver/vm_keyboard.go b/builder/vsphere/driver/vm_keyboard.go index 4cf41af5b..b11041225 100644 --- a/builder/vsphere/driver/vm_keyboard.go +++ b/builder/vsphere/driver/vm_keyboard.go @@ -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, diff --git a/builder/vsphere/iso/config.hcl2spec.go b/builder/vsphere/iso/config.hcl2spec.go index 3c0803818..11158f58c 100644 --- a/builder/vsphere/iso/config.hcl2spec.go +++ b/builder/vsphere/iso/config.hcl2spec.go @@ -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}, diff --git a/builder/vsphere/iso/step_boot_command.go b/builder/vsphere/iso/step_boot_command.go index b002ca3ad..200fc6d6b 100644 --- a/builder/vsphere/iso/step_boot_command.go +++ b/builder/vsphere/iso/step_boot_command.go @@ -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: - // - keyAlt = downs[i] - case key.CodeLeftControl: - // - 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: + // + keyAlt = down + case key.CodeLeftControl: + // + 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) } diff --git a/builder/vsphere/iso/step_boot_command_test.go b/builder/vsphere/iso/step_boot_command_test.go deleted file mode 100644 index 1e52b3f11..000000000 --- a/builder/vsphere/iso/step_boot_command_test.go +++ /dev/null @@ -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{ - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "/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", - "", - }, - }, - }, - } - step.Run(context.TODO(), state) -} diff --git a/common/bootcommand/usb_driver.go b/common/bootcommand/usb_driver.go index cde3e95ec..6ea6291ff 100644 --- a/common/bootcommand/usb_driver.go +++ b/common/bootcommand/usb_driver.go @@ -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) - -} diff --git a/website/pages/docs/builders/virtualbox/iso.mdx b/website/pages/docs/builders/virtualbox/iso.mdx index 7618be1b0..941fd0297 100644 --- a/website/pages/docs/builders/virtualbox/iso.mdx +++ b/website/pages/docs/builders/virtualbox/iso.mdx @@ -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 -[ - "", - "/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 -- " -] -``` - -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 diff --git a/website/pages/docs/builders/virtualbox/ovf.mdx b/website/pages/docs/builders/virtualbox/ovf.mdx index 856cb158c..3f556c12e 100644 --- a/website/pages/docs/builders/virtualbox/ovf.mdx +++ b/website/pages/docs/builders/virtualbox/ovf.mdx @@ -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 -[ - "", - "/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 -- " -] -``` - -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 diff --git a/website/pages/docs/builders/virtualbox/vm.mdx b/website/pages/docs/builders/virtualbox/vm.mdx index f491e4f0f..90a3bc151 100644 --- a/website/pages/docs/builders/virtualbox/vm.mdx +++ b/website/pages/docs/builders/virtualbox/vm.mdx @@ -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 -[ - "", - "/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 -- " -] -``` - -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 diff --git a/website/pages/docs/builders/vmware/vsphere-iso.mdx b/website/pages/docs/builders/vmware/vsphere-iso.mdx index cd204c54e..6aa4a6bb0 100644 --- a/website/pages/docs/builders/vmware/vsphere-iso.mdx +++ b/website/pages/docs/builders/vmware/vsphere-iso.mdx @@ -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