From 16b82d6d15653730a500b27a71850789ef1c1cdd Mon Sep 17 00:00:00 2001 From: JessThrysoee Date: Fri, 12 Sep 2014 00:44:22 +0200 Subject: [PATCH] builder/parallels: Bundle python version of prltype Uses the Python API from Parallels Virtualization SDK to write boot commands. This eliminates a 3rd party requirement and makes it easier for people not using homebrew to get started with packer. --- builder/parallels/common/driver.go | 2 +- builder/parallels/common/driver_9.go | 23 +++++- builder/parallels/common/prltype.go | 76 +++++++++++++++++++ .../common/step_type_boot_command.go | 4 +- .../docs/builders/parallels-iso.html.markdown | 10 +-- .../docs/builders/parallels-pvm.html.markdown | 10 +-- .../docs/builders/parallels.html.markdown | 13 +--- 7 files changed, 113 insertions(+), 25 deletions(-) create mode 100644 builder/parallels/common/prltype.go diff --git a/builder/parallels/common/driver.go b/builder/parallels/common/driver.go index d612e622483..babc38c32b7 100644 --- a/builder/parallels/common/driver.go +++ b/builder/parallels/common/driver.go @@ -38,7 +38,7 @@ type Driver interface { // Version reads the version of Parallels that is installed. Version() (string, error) - // Send scancodes to the vm using the prltype tool. + // Send scancodes to the vm using the prltype python script. SendKeyScanCodes(string, ...string) error // Finds the MAC address of the NIC nic0 diff --git a/builder/parallels/common/driver_9.go b/builder/parallels/common/driver_9.go index cc500e04204..97002cb86eb 100644 --- a/builder/parallels/common/driver_9.go +++ b/builder/parallels/common/driver_9.go @@ -3,6 +3,7 @@ package common import ( "bytes" "fmt" + "io/ioutil" "log" "os" "os/exec" @@ -182,11 +183,29 @@ func (d *Parallels9Driver) Version() (string, error) { func (d *Parallels9Driver) SendKeyScanCodes(vmName string, codes ...string) error { var stdout, stderr bytes.Buffer + if codes == nil || len(codes) == 0 { + log.Printf("No scan codes to send") + return nil + } + + f, err := ioutil.TempFile("", "prltype") + if err != nil { + return err + } + defer os.Remove(f.Name()) + + script := []byte(Prltype) + _, err = f.Write(script) + if err != nil { + return err + } + args := prepend(vmName, codes) - cmd := exec.Command("prltype", args...) + args = prepend(f.Name(), args) + cmd := exec.Command("/usr/bin/python", args...) cmd.Stdout = &stdout cmd.Stderr = &stderr - err := cmd.Run() + err = cmd.Run() stdoutString := strings.TrimSpace(stdout.String()) stderrString := strings.TrimSpace(stderr.String()) diff --git a/builder/parallels/common/prltype.go b/builder/parallels/common/prltype.go new file mode 100644 index 00000000000..bd99e0a13a0 --- /dev/null +++ b/builder/parallels/common/prltype.go @@ -0,0 +1,76 @@ +package common + +const Prltype string = ` +import sys +import prlsdkapi + +## +def main(): + if len(sys.argv) < 3: + print "Usage: prltype VM_NAME SCANCODE..." + sys.exit(1) + + vm_name = sys.argv[1] + scancodes = sys.argv[2:] + + server = login() + vm, vm_io = connect(server, vm_name) + + send(scancodes, vm, vm_io) + + disconnect(server, vm, vm_io) + +## +def login(): + prlsdkapi.prlsdk.InitializeSDK(prlsdkapi.prlsdk.consts.PAM_DESKTOP_MAC) + server = prlsdkapi.Server() + login_job=server.login_local() + login_job.wait() + + return server + +## +def connect(server, vm_name): + vm_list_job = server.get_vm_list() + result = vm_list_job.wait() + + vm_list = [result.get_param_by_index(i) for i in range(result.get_params_count())] + vm = [vm for vm in vm_list if vm.get_name() == vm_name] + + if not vm: + vm_names = [vm.get_name() for vm in vm_list] + raise Exception("%s: No such VM. Available VM's are:\n%s" % (vm_name, "\n".join(vm_names))) + + vm = vm[0] + + vm_io = prlsdkapi.VmIO() + vm_io.connect_to_vm(vm).wait() + + return (vm, vm_io) + +## +def disconnect(server, vm, vm_io): + if vm and vm_io: + vm_io.disconnect_from_vm(vm) + + if server: + server.logoff() + + prlsdkapi.deinit_sdk + +## +def send(scancodes, vm, vm_io): + timeout = 10 + consts = prlsdkapi.prlsdk.consts + + for scancode in scancodes: + c = int(scancode, 16) + if (c < 128): + vm_io.send_key_event(vm, (c,), consts.PKE_PRESS, timeout) + else: + vm_io.send_key_event(vm, (c - 128,) , consts.PKE_RELEASE, timeout) + +## +if __name__ == "__main__": + main() +` diff --git a/builder/parallels/common/step_type_boot_command.go b/builder/parallels/common/step_type_boot_command.go index 44037157764..dbc224d1835 100644 --- a/builder/parallels/common/step_type_boot_command.go +++ b/builder/parallels/common/step_type_boot_command.go @@ -20,8 +20,8 @@ type bootCommandTemplateData struct { Name string } -// This step "types" the boot command into the VM via prltype, built on the -// Parallels Virtualization SDK - C API. +// This step "types" the boot command into the VM via the prltype script, built on the +// Parallels Virtualization SDK - Python API. // // Uses: // driver Driver diff --git a/website/source/docs/builders/parallels-iso.html.markdown b/website/source/docs/builders/parallels-iso.html.markdown index 9f8cb44005e..1345d81553d 100644 --- a/website/source/docs/builders/parallels-iso.html.markdown +++ b/website/source/docs/builders/parallels-iso.html.markdown @@ -212,11 +212,11 @@ As documented above, the `boot_command` is an array of strings. The strings are all typed in sequence. It is an array only to improve readability within the template. -The boot command is "typed" character for character using the `prltype` (part -of prl-utils, see [Parallels Builder](/docs/builders/parallels.html)) -command connected 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: +The boot command is "typed" character for character (using the Parallels +Virtualization SDK, see [Parallels Builder](/docs/builders/parallels.html)) +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: * `` and `` - Simulates an actual "enter" or "return" keypress. diff --git a/website/source/docs/builders/parallels-pvm.html.markdown b/website/source/docs/builders/parallels-pvm.html.markdown index 82f3fdda302..f4af02eb80f 100644 --- a/website/source/docs/builders/parallels-pvm.html.markdown +++ b/website/source/docs/builders/parallels-pvm.html.markdown @@ -161,11 +161,11 @@ As documented above, the `boot_command` is an array of strings. The strings are all typed in sequence. It is an array only to improve readability within the template. -The boot command is "typed" character for character using the `prltype` (part -of prl-utils, see [Parallels Builder](/docs/builders/parallels.html)) -command connected 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: +The boot command is "typed" character for character (using the Parallels +Virtualization SDK, see [Parallels Builder](/docs/builders/parallels.html)) +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: * `` and `` - Simulates an actual "enter" or "return" keypress. diff --git a/website/source/docs/builders/parallels.html.markdown b/website/source/docs/builders/parallels.html.markdown index 89a7840b47b..98a1f999429 100644 --- a/website/source/docs/builders/parallels.html.markdown +++ b/website/source/docs/builders/parallels.html.markdown @@ -26,14 +26,7 @@ Packer supports the following Parallels builders: ## Requirements -In addition to [Parallels Desktop for Mac](http://www.parallels.com/products/desktop/) this requires: +In addition to [Parallels Desktop for Mac](http://www.parallels.com/products/desktop/) this requires the +[Parallels Virtualization SDK](http://www.parallels.com/downloads/desktop/). -- [Parallels Virtualization SDK 9 for Mac](http://download.parallels.com//desktop/v9/pde.hf1/ParallelsVirtualizationSDK-9.0.24172.951362.dmg) -- [prl-utils](https://github.com/rickard-von-essen/prl-utils/) - -The SDK can be installed by downloading and following the instructions in the dmg. The easiest way to install _prl-utils_ is using [Homebrew](http://brew.sh/) - - ``` - brew tap rickard-von-essen/homebrew-formulae - brew install --HEAD prl-utils - ``` +The SDK can be installed by downloading and following the instructions in the dmg.