Commit 16b82d6d authored by JessThrysoee's avatar JessThrysoee

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.
parent 5e4ffb56
...@@ -38,7 +38,7 @@ type Driver interface { ...@@ -38,7 +38,7 @@ type Driver interface {
// Version reads the version of Parallels that is installed. // Version reads the version of Parallels that is installed.
Version() (string, error) 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 SendKeyScanCodes(string, ...string) error
// Finds the MAC address of the NIC nic0 // Finds the MAC address of the NIC nic0
......
...@@ -3,6 +3,7 @@ package common ...@@ -3,6 +3,7 @@ package common
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"io/ioutil"
"log" "log"
"os" "os"
"os/exec" "os/exec"
...@@ -182,11 +183,29 @@ func (d *Parallels9Driver) Version() (string, error) { ...@@ -182,11 +183,29 @@ func (d *Parallels9Driver) Version() (string, error) {
func (d *Parallels9Driver) SendKeyScanCodes(vmName string, codes ...string) error { func (d *Parallels9Driver) SendKeyScanCodes(vmName string, codes ...string) error {
var stdout, stderr bytes.Buffer 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) 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.Stdout = &stdout
cmd.Stderr = &stderr cmd.Stderr = &stderr
err := cmd.Run() err = cmd.Run()
stdoutString := strings.TrimSpace(stdout.String()) stdoutString := strings.TrimSpace(stdout.String())
stderrString := strings.TrimSpace(stderr.String()) stderrString := strings.TrimSpace(stderr.String())
......
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()
`
...@@ -20,8 +20,8 @@ type bootCommandTemplateData struct { ...@@ -20,8 +20,8 @@ type bootCommandTemplateData struct {
Name string Name string
} }
// This step "types" the boot command into the VM via prltype, built on the // This step "types" the boot command into the VM via the prltype script, built on the
// Parallels Virtualization SDK - C API. // Parallels Virtualization SDK - Python API.
// //
// Uses: // Uses:
// driver Driver // driver Driver
......
...@@ -212,11 +212,11 @@ As documented above, the `boot_command` is an array of strings. The ...@@ -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 strings are all typed in sequence. It is an array only to improve readability
within the template. within the template.
The boot command is "typed" character for character using the `prltype` (part The boot command is "typed" character for character (using the Parallels
of prl-utils, see [Parallels Builder](/docs/builders/parallels.html)) Virtualization SDK, see [Parallels Builder](/docs/builders/parallels.html))
command connected to the machine, simulating a human actually typing the simulating a human actually typing the keyboard. There are a set of special
keyboard. There are a set of special keys available. If these are in your keys available. If these are in your boot command, they will be replaced by
boot command, they will be replaced by the proper key: the proper key:
* `<enter>` and `<return>` - Simulates an actual "enter" or "return" keypress. * `<enter>` and `<return>` - Simulates an actual "enter" or "return" keypress.
......
...@@ -161,11 +161,11 @@ As documented above, the `boot_command` is an array of strings. The ...@@ -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 strings are all typed in sequence. It is an array only to improve readability
within the template. within the template.
The boot command is "typed" character for character using the `prltype` (part The boot command is "typed" character for character (using the Parallels
of prl-utils, see [Parallels Builder](/docs/builders/parallels.html)) Virtualization SDK, see [Parallels Builder](/docs/builders/parallels.html))
command connected to the machine, simulating a human actually typing the simulating a human actually typing the keyboard. There are a set of special
keyboard. There are a set of special keys available. If these are in your keys available. If these are in your boot command, they will be replaced by
boot command, they will be replaced by the proper key: the proper key:
* `<enter>` and `<return>` - Simulates an actual "enter" or "return" keypress. * `<enter>` and `<return>` - Simulates an actual "enter" or "return" keypress.
......
...@@ -26,14 +26,7 @@ Packer supports the following Parallels builders: ...@@ -26,14 +26,7 @@ Packer supports the following Parallels builders:
## Requirements ## 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) The SDK can be installed by downloading and following the instructions in the 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
```
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment