Bootcommand Fix For Proxmox Builder (#9885)
This commit is contained in:
parent
caf65781d7
commit
c032d463d3
|
@ -2,6 +2,7 @@ package proxmox
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
|
@ -10,23 +11,33 @@ import (
|
|||
)
|
||||
|
||||
type proxmoxDriver struct {
|
||||
client commandTyper
|
||||
vmRef *proxmox.VmRef
|
||||
specialMap map[string]string
|
||||
runeMap map[rune]string
|
||||
interval time.Duration
|
||||
client commandTyper
|
||||
vmRef *proxmox.VmRef
|
||||
specialMap map[string]string
|
||||
runeMap map[rune]string
|
||||
interval time.Duration
|
||||
specialBuffer []string
|
||||
normalBuffer []string
|
||||
}
|
||||
|
||||
func NewProxmoxDriver(c commandTyper, vmRef *proxmox.VmRef, interval time.Duration) *proxmoxDriver {
|
||||
// Mappings for packer shorthand to qemu qkeycodes
|
||||
sMap := map[string]string{
|
||||
"spacebar": "spc",
|
||||
"bs": "backspace",
|
||||
"del": "delete",
|
||||
"return": "ret",
|
||||
"enter": "ret",
|
||||
"pageUp": "pgup",
|
||||
"pageDown": "pgdn",
|
||||
"spacebar": "spc",
|
||||
"bs": "backspace",
|
||||
"del": "delete",
|
||||
"return": "ret",
|
||||
"enter": "ret",
|
||||
"pageUp": "pgup",
|
||||
"pageDown": "pgdn",
|
||||
"leftshift": "shift",
|
||||
"rightshift": "shift",
|
||||
"leftalt": "alt",
|
||||
"rightalt": "alt_r",
|
||||
"leftctrl": "ctrl",
|
||||
"rightctrl": "ctrl_r",
|
||||
"leftsuper": "meta_l",
|
||||
"rightsuper": "meta_r",
|
||||
}
|
||||
// Mappings for runes that need to be translated to special qkeycodes
|
||||
// Taken from https://github.com/qemu/qemu/blob/master/pc-bios/keymaps/en-us
|
||||
|
@ -78,18 +89,26 @@ func NewProxmoxDriver(c commandTyper, vmRef *proxmox.VmRef, interval time.Durati
|
|||
}
|
||||
|
||||
func (p *proxmoxDriver) SendKey(key rune, action bootcommand.KeyAction) error {
|
||||
if special, ok := p.runeMap[key]; ok {
|
||||
return p.send(special)
|
||||
switch action.String() {
|
||||
case "Press":
|
||||
if special, ok := p.runeMap[key]; ok {
|
||||
return p.send(special)
|
||||
}
|
||||
var keys string
|
||||
if unicode.IsUpper(key) {
|
||||
keys = fmt.Sprintf("shift-%c", unicode.ToLower(key))
|
||||
} else {
|
||||
keys = fmt.Sprintf("%c", key)
|
||||
}
|
||||
return p.send(keys)
|
||||
case "On":
|
||||
key := fmt.Sprintf("%c", key)
|
||||
p.normalBuffer = addKeyToBuffer(p.normalBuffer, key)
|
||||
case "Off":
|
||||
key := fmt.Sprintf("%c", key)
|
||||
p.normalBuffer = removeKeyFromBuffer(p.normalBuffer, key)
|
||||
}
|
||||
|
||||
var keys string
|
||||
if unicode.IsUpper(key) {
|
||||
keys = fmt.Sprintf("shift-%c", unicode.ToLower(key))
|
||||
} else {
|
||||
keys = fmt.Sprintf("%c", key)
|
||||
}
|
||||
|
||||
return p.send(keys)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *proxmoxDriver) SendSpecial(special string, action bootcommand.KeyAction) error {
|
||||
|
@ -97,18 +116,48 @@ func (p *proxmoxDriver) SendSpecial(special string, action bootcommand.KeyAction
|
|||
if replacement, ok := p.specialMap[special]; ok {
|
||||
keys = replacement
|
||||
}
|
||||
|
||||
return p.send(keys)
|
||||
switch action.String() {
|
||||
case "Press":
|
||||
return p.send(keys)
|
||||
case "On":
|
||||
p.specialBuffer = addKeyToBuffer(p.specialBuffer, keys)
|
||||
case "Off":
|
||||
p.specialBuffer = removeKeyFromBuffer(p.specialBuffer, keys)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *proxmoxDriver) send(keys string) error {
|
||||
err := p.client.Sendkey(p.vmRef, keys)
|
||||
func (p *proxmoxDriver) send(key string) error {
|
||||
keys := append(p.specialBuffer, p.normalBuffer...)
|
||||
keys = append(keys, key)
|
||||
keyEventString := bufferToKeyEvent(keys)
|
||||
err := p.client.Sendkey(p.vmRef, keyEventString)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
time.Sleep(p.interval)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *proxmoxDriver) Flush() error { return nil }
|
||||
|
||||
func bufferToKeyEvent(keys []string) string {
|
||||
return strings.Join(keys, "-")
|
||||
}
|
||||
func addKeyToBuffer(buffer []string, key string) []string {
|
||||
for _, value := range buffer {
|
||||
if value == key {
|
||||
return buffer
|
||||
}
|
||||
}
|
||||
return append(buffer, key)
|
||||
}
|
||||
func removeKeyFromBuffer(buffer []string, key string) []string {
|
||||
for index, value := range buffer {
|
||||
if value == key {
|
||||
buffer[index] = buffer[len(buffer)-1]
|
||||
return buffer[:len(buffer)-1]
|
||||
}
|
||||
}
|
||||
return buffer
|
||||
}
|
||||
|
|
|
@ -52,6 +52,34 @@ func TestTypeBootCommand(t *testing.T) {
|
|||
expectedKeysSent: "shift-hellospcshift-worldspc2dot0fooshift-1barshift-2baz",
|
||||
expectedAction: multistep.ActionContinue,
|
||||
},
|
||||
{
|
||||
name: "holding and releasing keys",
|
||||
builderConfig: &Config{BootConfig: bootcommand.BootConfig{BootCommand: []string{"<leftShiftOn>hello<rightAltOn>world<leftShiftOff><rightAltOff>"}}},
|
||||
expectCallSendkey: true,
|
||||
expectedKeysSent: "shift-hshift-eshift-lshift-lshift-oshift-alt_r-wshift-alt_r-oshift-alt_r-rshift-alt_r-lshift-alt_r-d",
|
||||
expectedAction: multistep.ActionContinue,
|
||||
},
|
||||
{
|
||||
name: "holding multiple alphabetical keys and shift",
|
||||
builderConfig: &Config{BootConfig: bootcommand.BootConfig{BootCommand: []string{"<cOn><leftShiftOn>n<leftShiftOff><cOff>"}}},
|
||||
expectCallSendkey: true,
|
||||
expectedKeysSent: "shift-c-n",
|
||||
expectedAction: multistep.ActionContinue,
|
||||
},
|
||||
{
|
||||
name: "noop keystrokes",
|
||||
builderConfig: &Config{BootConfig: bootcommand.BootConfig{BootCommand: []string{"<cOn><leftShiftOn><cOff><leftAltOn><leftShiftOff><leftAltOff>"}}},
|
||||
expectCallSendkey: true,
|
||||
expectedKeysSent: "",
|
||||
expectedAction: multistep.ActionContinue,
|
||||
},
|
||||
{
|
||||
name: "noop keystrokes mixed",
|
||||
builderConfig: &Config{BootConfig: bootcommand.BootConfig{BootCommand: []string{"<cOn><leftShiftOn><cOff>h<leftShiftOff>"}}},
|
||||
expectCallSendkey: true,
|
||||
expectedKeysSent: "shift-h",
|
||||
expectedAction: multistep.ActionContinue,
|
||||
},
|
||||
{
|
||||
name: "without boot command sendkey should not be called",
|
||||
builderConfig: &Config{BootConfig: bootcommand.BootConfig{BootCommand: []string{}}},
|
||||
|
|
Loading…
Reference in New Issue