{"action":"closed","issue":{"url":"https://api.github.com/repos/hashicorp/packer/issues/5635","repository_url":"https://api.github.com/repos/hashicorp/packer","labels_url":"https://api.github.com/repos/hashicorp/packer/issues/5635/labels{/name}","comments_url":"https://api.github.com/repos/hashicorp/packer/issues/5635/comments","events_url":"https://api.github.com/repos/hashicorp/packer/issues/5635/events","html_url":"https://github.com/hashicorp/packer/issues/5635","id":276801255,"number":5635,"title":"boot_command scancodes warped for macOS guests","user":{"login":"mcandre","id":5316,"avatar_url":"https://avatars1.githubusercontent.com/u/5316?v=4","gravatar_id":"","url":"https://api.github.com/users/mcandre","html_url":"https://github.com/mcandre","followers_url":"https://api.github.com/users/mcandre/followers","following_url":"https://api.github.com/users/mcandre/following{/other_user}","gists_url":"https://api.github.com/users/mcandre/gists{/gist_id}","starred_url":"https://api.github.com/users/mcandre/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mcandre/subscriptions","organizations_url":"https://api.github.com/users/mcandre/orgs","repos_url":"https://api.github.com/users/mcandre/repos","events_url":"https://api.github.com/users/mcandre/events{/privacy}","received_events_url":"https://api.github.com/users/mcandre/received_events","type":"User","site_admin":false},"labels":[{"id":33051538,"url":"https://api.github.com/repos/hashicorp/packer/labels/bug","name":"bug","color":"f7c6c7","default":true},{"id":126744621,"url":"https://api.github.com/repos/hashicorp/packer/labels/builder/virtualbox","name":"builder/virtualbox","color":"d4c5f9","default":false},{"id":483188343,"url":"https://api.github.com/repos/hashicorp/packer/labels/help%20wanted","name":"help wanted","color":"fbca04","default":true},{"id":45643873,"url":"https://api.github.com/repos/hashicorp/packer/labels/need-more-info","name":"need-more-info","color":"fbca04","default":false}],"state":"closed","locked":false,"assignee":{"login":"kikitux","id":1255709,"avatar_url":"https://avatars2.githubusercontent.com/u/1255709?v=4","gravatar_id":"","url":"https://api.github.com/users/kikitux","html_url":"https://github.com/kikitux","followers_url":"https://api.github.com/users/kikitux/followers","following_url":"https://api.github.com/users/kikitux/following{/other_user}","gists_url":"https://api.github.com/users/kikitux/gists{/gist_id}","starred_url":"https://api.github.com/users/kikitux/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kikitux/subscriptions","organizations_url":"https://api.github.com/users/kikitux/orgs","repos_url":"https://api.github.com/users/kikitux/repos","events_url":"https://api.github.com/users/kikitux/events{/privacy}","received_events_url":"https://api.github.com/users/kikitux/received_events","type":"User","site_admin":false},"assignees":[{"login":"kikitux","id":1255709,"avatar_url":"https://avatars2.githubusercontent.com/u/1255709?v=4","gravatar_id":"","url":"https://api.github.com/users/kikitux","html_url":"https://github.com/kikitux","followers_url":"https://api.github.com/users/kikitux/followers","following_url":"https://api.github.com/users/kikitux/following{/other_user}","gists_url":"https://api.github.com/users/kikitux/gists{/gist_id}","starred_url":"https://api.github.com/users/kikitux/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kikitux/subscriptions","organizations_url":"https://api.github.com/users/kikitux/orgs","repos_url":"https://api.github.com/users/kikitux/repos","events_url":"https://api.github.com/users/kikitux/events{/privacy}","received_events_url":"https://api.github.com/users/kikitux/received_events","type":"User","site_admin":false}],"milestone":null,"comments":3,"created_at":"2017-11-26T05:33:05Z","updated_at":"2018-04-19T17:42:37Z","closed_at":"2018-04-19T17:42:37Z","author_association":"CONTRIBUTOR","body":"macOS guests do not follow Linux keyboard scancodes, but have their own scancode mapping:\r\n\r\nhttps://developer.apple.com/legacy/library/documentation/mac/pdf/MacintoshToolboxEssentials.pdf\r\n\r\nSpecifically:\r\n\r\nhttps://github.com/phracker/MacOSX-SDKs/blob/master/MacOSX10.6.sdk/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Events.h#L267-L315\r\n\r\nFor example, `boot_command: [\"<down><wait>\"]` currently fails to work in macOS guests, as packer attempts to translate `<down>` into the scancode `[0x50 0xd0]`, which macOS interprets at F19, no such scancode. Rather, for macOS guests, `<down>` should use scancode `[0x30]`.\r\n\r\nInterestingly enough, when the user manually presses the Down arrow key with a macOS guest in VirtualBox, the key is correctly sent to the VM. Even other keys like `Command` with no `boot_command` equivalent at all can be sent to the VM when input by a human. It's just when packer tries to formulate scancodes that things get messed up, because the packer codebase hardcodes Linux scancodes instead of dispatching scancode tables based on the guest OS type, or a scancode/keyboard JSON key, or whatever.\r\n\r\nNote that scancode selection is probably *not* needed for builders that send keys via VNC, such as `qemu` and `vmware`, nor for builders that do not use `boot_command` at all, such as `docker`, `lxd`, and `lxc`. I think VNC-based boot_command builders are probably safe, though I'll test my macos box with them just to be sure. Other builders like `virtualbox`, `hyperv`, and `parallels` make the mistake of assuming an IBM keyboard guest, using the wrong scancodes for non-PC VM's.\r\n\r\nSome of this hardcoded incorrect scancode tables and duplicated code madness could be improved by abstracting `boot_command` handling. Right now, each builder appears to implement a lot of code to handle keyboard input, that could be better written in terms of (Go) interfaces. Maybe something like a base `keyboardinput.go`:\r\n\r\n```go\r\ntype AbstractKeyboardInput string\r\n\r\nconst (\r\n\tInputSleep AbstractKeyboardInput = \"InputSleep\"\r\n\tInputSleep5 = \"InputSleep5\"\r\n\tInputSleep10 = \"InputSleep10\"\r\n\tInputA = \"InputA\"\r\n\tInputB = \"InputB\"\r\n\t...\r\n\tInputDown = \"InputDown\"\r\n\t...\r\n)\r\n\r\ntype ScancodeSet = string\r\n\r\nconst (\r\n\tIBMScancodeSet ScancodeSet = \"IBMScancodeSet\"\r\n\tAppleScancodeSet = \"AppleScancodeSet\"\r\n\tVNCScancodeSet = \"VNCScancodeSet\"\r\n)\r\n\r\nfunc parse_boot_command(command string) []AbstractKeyboardInput {\r\n\t...\r\n}\r\n\r\ntype TimedScancodes = (time.Duration, []byte)\r\n\r\n// Given an abstract representation of some keyboard input,\r\n// potentially with intermittent sleep timers, and a scancode table;\r\n// Return the appropriate scancode array for the input,\r\n// with an associated delay before the key should be sent.\r\n// Zero indicates no delay, positive indicates a delay.\r\nfunc translate_input(input AbstractKeyboardInput, sset ScancodeSet) TimedScancodes {\r\n\t...\r\n}\r\n\r\ntype KeyboardHandler interface {\r\n\tExecute(ts TimedScancodes)\r\n}\r\n```\r\n\r\nAnd then each individual builder would implement `Execute(input AbstractKeyboardInput)` according to the particular hypervisor's details. Now parsing and scancode translation are handled with reusable base code, and the particular sleep commands and keycode byte delivery methods can be implemented with less code for the individual builders.\r\n\r\nCould packer offer a JSON key to configure scancode sets? The default could be `\"scancodes\": \"ibm\"`, as this represents most modern Linux/Microsoft keyboards. Maybe add a `\"scancodes\": \"apple\"` for Apple keyboards? Of course, builders that send keys via VNC should probably configure this as `\"scancodes\": \"vnc\"`, or even reject this configuration entirely.\r\n\r\nI realize that macOS guests are obscure in the virtualization community, so it's not always easy to spot these edge cases. For testing purposes, I have a work in progress \"macos\" branch of my [packer-templates](https://github.com/mcandre/packer-templates/tree/macos) project to try to pack a macOS Vagrant box. I managed to generate an installer ISO and issue an `<enter>` key in `boot_command`, but then when I try to submit some `<down>` keys to navigate through the installer UI to Disk Utility, I get this scancode mismatch and I'm scratching my head thinking of ways to hack around it. If I can find a way to space apart VBoxManage commands in `vboxmanage`, maybe even get the timing right with a `packer build -debug` trick, then hopefully I can work around this scancode issue while waiting for a fix."}}
{"actor":{"display_login":"mcandre"}}