Permalink
Browse files

Typing boot command in terminal works!

  • Loading branch information...
1 parent 8a4818b commit e565f9b356b5e3f3271630fe335efd17e4cce912 @rickard-von-essen committed Mar 6, 2014
Showing with 328 additions and 78 deletions.
  1. +2 −0 Makefile
  2. +1 −8 README.md
  3. +3 −8 common/driver.go
  4. +28 −7 common/driver_9.go
  5. +0 −21 common/driver_9_vm.go
  6. +235 −0 cpp/prltype.cpp
  7. +15 −15 iso/builder.go
  8. +2 −1 iso/step_create_vm.go
  9. +40 −17 iso/step_type_boot_command.go
  10. +1 −1 scripts/compile.sh
  11. +1 −0 scripts/devcompile.sh
View
@@ -3,10 +3,12 @@ OK_COLOR=\033[32;01m
ERROR_COLOR=\033[31;01m
WARN_COLOR=\033[33;01m
DEPS = $(go list -f '{{range .TestImports}}{{.}} {{end}}' ./...)
+LDFLAGS=-framework ParallelsVirtualizationSDK
all: deps
@mkdir -p bin/
@echo "$(OK_COLOR)==> Building$(NO_COLOR)"
+ @gcc -o bin/prltype $(LDFLAGS) cpp/prltype.cpp
@bash --norc -i ./scripts/devcompile.sh
deps:
View
@@ -23,14 +23,7 @@ Install packer and add the following to ```~/.packerconfig```
}
}
```
-Then download and install this plugin. Since this depends on [Go Parallelles SDK - C API Wrapper](https://github.com/rickard-von-essen/goprlapi) which in turn requires [Parallels Virtualization SDK 9 for Mac](http://download.parallels.com//desktop/v9/pde.hf1/ParallelsVirtualizationSDK-9.0.24172.951362.dmg), download and install it first.
-
-```
-cd $GOPATH/src && git clone https://github.com/rickard-von-essen/packer-parallels
-cd github.com/rickard-von-essen/packer-parallels
-go get -u github.com/mitchellh/gox
-make
-```
+Then download and install this plugin. This depends on [Parallels Virtualization SDK 9 for Mac](http://download.parallels.com//desktop/v9/pde.hf1/ParallelsVirtualizationSDK-9.0.24172.951362.dmg), download and install it first.
## Issues
If you find any bugs please open a issue at [github](https://github.com/rickard-von-essen/packer-parallels/issues).
View
@@ -1,7 +1,6 @@
package common
import (
- "github.com/rickard-von-essen/goprlapi"
"log"
"os/exec"
)
@@ -42,8 +41,8 @@ type Driver interface {
// Version reads the version of Parallels that is installed.
Version() (string, error)
- // Get Virtual Machine abstraction
- GetVm(string) (DriverVm, error)
+ // Send scancodes to the vm using the prltype tool.
+ SendKeyScanCodes(string, ...string) error
}
func NewDriver() (Driver, error) {
@@ -57,12 +56,8 @@ func NewDriver() (Driver, error) {
}
}
- server, err := goprlapi.LoginLocal()
- if err != nil {
- return nil, err
- }
log.Printf("prlctl path: %s", prlctlPath)
- driver := &Parallels9Driver{prlctlPath, server}
+ driver := &Parallels9Driver{prlctlPath}
if err := driver.Verify(); err != nil {
return nil, err
}
View
@@ -3,7 +3,6 @@ package common
import (
"bytes"
"fmt"
- "github.com/rickard-von-essen/goprlapi"
"log"
"os/exec"
"regexp"
@@ -14,7 +13,6 @@ import (
type Parallels9Driver struct {
// This is the path to the "prlctl" application.
PrlctlPath string
- server goprlapi.Server
}
func (d *Parallels9Driver) CreateSATAController(vmName string, name string) error {
@@ -144,11 +142,34 @@ func (d *Parallels9Driver) Version() (string, error) {
return matches[0], nil
}
-func (d *Parallels9Driver) GetVm(vmName string) (DriverVm, error) {
- vm, err := d.server.GetVm(vmName)
- if err != nil {
- return nil, err
+func (d *Parallels9Driver) SendKeyScanCodes(vmName string, codes ...string) error {
+ var stdout, stderr bytes.Buffer
+
+ args := prepend(vmName, codes)
+ log.Printf("Executing prltype: %#v", args)
+ cmd := exec.Command("prltype", args...)
+ cmd.Stdout = &stdout
+ cmd.Stderr = &stderr
+ err := cmd.Run()
+
+ stdoutString := strings.TrimSpace(stdout.String())
+ stderrString := strings.TrimSpace(stderr.String())
+
+ if _, ok := err.(*exec.ExitError); ok {
+ err = fmt.Errorf("prltype error: %s", stderrString)
+ }
+
+ log.Printf("stdout: %s", stdoutString)
+ log.Printf("stderr: %s", stderrString)
+
+ return err
+}
+func prepend(head string, tail []string) []string {
+ tmp := make([]string, len(tail)+1)
+ for i := 0; i < len(tail); i++ {
+ tmp[i+1] = tail[i]
}
- return &Parallels9DriverVm{vm}, nil
+ tmp[0] = head
+ return tmp
}
View
@@ -1,21 +0,0 @@
-package common
-
-import (
- "github.com/rickard-von-essen/goprlapi"
-)
-
-type Parallels9DriverVm struct {
- vm goprlapi.VirtualMachine
-}
-
-func (v *Parallels9DriverVm) DisplayConnect() error {
- return v.vm.DisplayConnect()
-}
-
-func (v *Parallels9DriverVm) DisplayDisconnect() {
- v.vm.DisplayDisconnect()
-}
-
-func (v *Parallels9DriverVm) SendKeyScanCode(scancode uint32) error {
- return v.vm.SendKeyScanCode(scancode, 0)
-}
View
@@ -0,0 +1,235 @@
+#include "ParallelsVirtualizationSDK/Parallels.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+PRL_RESULT LoginLocal(PRL_HANDLE &hServer) {
+
+ PRL_HANDLE hJob, hJobResult = PRL_INVALID_HANDLE;
+ PRL_RESULT err, nJobReturnCode = PRL_ERR_UNINITIALIZED;
+
+ err = PrlApi_InitEx(PARALLELS_API_VER, PAM_DESKTOP, 0, 0);
+ if (PRL_FAILED(err)) {
+ fprintf(stderr, "PrlApi_InitEx returned with error: %s.\n", prl_result_to_string(err));
+ PrlApi_Deinit();
+ return err;
+ }
+ err = PrlSrv_Create(&hServer);
+ if (PRL_FAILED(err)) {
+ fprintf(stderr, "PrlSvr_Create failed, error: %s", prl_result_to_string(err));
+ PrlApi_Deinit();
+ return err;
+ }
+ hJob = PrlSrv_LoginLocal(hServer, NULL, NULL, PSL_NORMAL_SECURITY);
+ err = PrlJob_Wait(hJob, 1000);
+ if (PRL_FAILED(err)) {
+ fprintf(stderr, "PrlJob_Wait for PrlSrv_Login returned with error: %s\n", prl_result_to_string(err));
+ PrlHandle_Free(hJob);
+ PrlHandle_Free(hServer);
+ PrlApi_Deinit();
+ return err;
+ }
+ err = PrlJob_GetRetCode(hJob, &nJobReturnCode);
+ if (PRL_FAILED(err)) {
+ fprintf(stderr, "PrlJob_GetRetCode returned with error: %s\n", prl_result_to_string(err));
+ PrlHandle_Free(hJob);
+ PrlHandle_Free(hServer);
+ PrlApi_Deinit();
+ return err;
+ }
+ if (PRL_FAILED(nJobReturnCode)) {
+ PrlHandle_Free(hJob);
+ PrlHandle_Free(hServer);
+ fprintf(stderr, "Login job returned with error: %s\n", prl_result_to_string(nJobReturnCode));
+ PrlHandle_Free(hJob);
+ PrlHandle_Free(hServer);
+ PrlApi_Deinit();
+ return err;
+ }
+ return PRL_ERR_SUCCESS;
+}
+
+PRL_RESULT LogOff(PRL_HANDLE &hServer) {
+ PRL_HANDLE hJob, hJobResult = PRL_INVALID_HANDLE;
+ PRL_RESULT err, nJobReturnCode = PRL_ERR_UNINITIALIZED;
+
+ nanosleep((struct timespec[]){{1, 500000000}}, NULL);
+
+ hJob = PrlSrv_Logoff(hServer);
+ err = PrlJob_Wait(hJob, 1000);
+ if (PRL_FAILED(err)) {
+ fprintf(stderr, "PrlJob_Wait for PrlSrv_Logoff returned error: %s\n", prl_result_to_string(err));
+ PrlHandle_Free(hJob);
+ PrlHandle_Free(hServer);
+ PrlApi_Deinit();
+ return err;
+ }
+ err = PrlJob_GetRetCode(hJob, &nJobReturnCode);
+ if (PRL_FAILED(err)) {
+ fprintf(stderr, "PrlJob_GetRetCode failed for PrlSrv_Logoff with error: %s\n", prl_result_to_string(err));
+ PrlHandle_Free(hJob);
+ PrlHandle_Free(hServer);
+ PrlApi_Deinit();
+ return err;
+ }
+ if (PRL_FAILED(nJobReturnCode)) {
+ fprintf(stderr, "PrlSrv_Logoff failed with error: %s\n", prl_result_to_string(nJobReturnCode));
+ PrlHandle_Free(hJob);
+ PrlHandle_Free(hServer);
+ PrlApi_Deinit();
+ return err;
+ }
+ PrlHandle_Free(hJob);
+ PrlHandle_Free(hServer);
+ PrlApi_Deinit();
+ return PRL_ERR_SUCCESS;
+}
+
+PRL_RESULT GetVm(PRL_HANDLE &hRetVm, PRL_HANDLE &hServer, char* vmName ) {
+ PRL_HANDLE hJob, hJobResult = PRL_INVALID_HANDLE;
+ PRL_RESULT ret, nJobReturnCode = PRL_ERR_UNINITIALIZED;
+ hJob = PrlSrv_GetVmList(hServer);
+ ret = PrlJob_Wait(hJob, 10000);
+ if (PRL_FAILED(ret)) {
+ fprintf(stderr, "PrlJob_Wait for PrlSrv_GetVmList returned with error: %s\n",
+ prl_result_to_string(ret));
+ PrlHandle_Free(hJob);
+ return ret;
+ }
+ ret = PrlJob_GetRetCode(hJob, &nJobReturnCode);
+ if (PRL_FAILED(ret)) {
+ fprintf(stderr, "PrlJob_GetRetCode returned with error: %s\n", prl_result_to_string(ret));
+ PrlHandle_Free(hJob);
+ return ret;
+ }
+ if (PRL_FAILED(nJobReturnCode)) {
+ fprintf(stderr, "PrlSrv_GetVmList returned with error: %s\n",
+ prl_result_to_string(ret));
+ PrlHandle_Free(hJob);
+ return ret;
+ }
+ ret = PrlJob_GetResult(hJob, &hJobResult);
+ if (PRL_FAILED(ret)) {
+ fprintf(stderr, "PrlJob_GetResult returned with error: %s\n", prl_result_to_string(ret));
+ PrlHandle_Free(hJob);
+ return ret;
+ }
+ PrlHandle_Free(hJob);
+ PRL_UINT32 nParamsCount = 0;
+ ret = PrlResult_GetParamsCount(hJobResult, &nParamsCount);
+ for (PRL_UINT32 i = 0; i < nParamsCount; ++i)
+ {
+ PRL_HANDLE hVm = PRL_INVALID_HANDLE;
+ PrlResult_GetParamByIndex(hJobResult, i, &hVm);
+ char szVmNameReturned[1024];
+ PRL_UINT32 nBufSize = sizeof(szVmNameReturned);
+ ret = PrlVmCfg_GetName(hVm, szVmNameReturned, &nBufSize);
+ if (PRL_FAILED(ret)) {
+ fprintf(stderr, "PrlVmCfg_GetName returned with error (%s)\n",
+ prl_result_to_string(ret));
+ } else {
+ if (strcmp(vmName, szVmNameReturned) == 0) {
+ hRetVm = hVm;
+ return PRL_ERR_SUCCESS;
+ }
+ }
+ PrlHandle_Free(hVm);
+ }
+ fprintf(stderr, "No VM: \"%s\" was found!\n", vmName);
+ return PRL_ERR_OPERATION_FAILED;
+}
+
+PRL_RESULT ConnectToConsole( PRL_HANDLE vm ) {
+
+ PRL_RESULT err, nJobReturnCode = PRL_ERR_UNINITIALIZED;
+ PRL_HANDLE hJob = PrlDevDisplay_ConnectToVm( vm, PDCT_LOW_QUALITY_WITHOUT_COMPRESSION );
+ err = PrlJob_Wait(hJob, 10000);
+ if (PRL_FAILED(err)) {
+ fprintf(stderr, "PrlJob_Wait for PrlDevDisplay_ConnectToVm returned with error: %s\n",
+ prl_result_to_string(err));
+ PrlHandle_Free(hJob);
+ return err;
+ }
+ err = PrlJob_GetRetCode(hJob, &nJobReturnCode);
+ if (PRL_FAILED(err)) {
+ fprintf(stderr, "PrlJob_GetRetCode returned with error: %s\n", prl_result_to_string(err));
+ PrlHandle_Free(hJob);
+ return err;
+ }
+ if (PRL_FAILED(nJobReturnCode)) {
+ fprintf(stderr, "PrlDevDisplay_ConnectToVm returned with error: %s\n", prl_result_to_string(nJobReturnCode));
+ PrlHandle_Free(hJob);
+ return nJobReturnCode;
+ }
+
+ return PRL_ERR_SUCCESS;
+}
+
+PRL_RESULT DisconnectFromConsole( PRL_HANDLE vm ) {
+
+ PRL_RESULT err = PrlDevDisplay_DisconnectFromVm( vm );
+ if (PRL_FAILED(err)) {
+ fprintf(stderr, "PrlDevDisplay_DisconnectFromVm returned with error: %s\n", prl_result_to_string(err));
+ }
+ return err;
+}
+
+PRL_RESULT SendScanCode( PRL_HANDLE vm, int scanCode ) {
+ fprintf(stdout, " %d", scanCode);
+ nanosleep((struct timespec[]){{0, 20000000}}, NULL);
+ PRL_RESULT err;
+ if (scanCode < 0x80)
+ err = PrlDevKeyboard_SendKeyEvent( vm, scanCode, PKE_PRESS );
+ else
+ err = PrlDevKeyboard_SendKeyEvent( vm, scanCode - 0x80, PKE_RELEASE );
+ if (PRL_FAILED(err)) {
+ fprintf(stdout, "PrlDevKeyboard_SendKeyEvent returned with error: %s.\n", prl_result_to_string(err));
+ PrlApi_Deinit();
+ PrlHandle_Free( vm );
+ }
+ return err;
+}
+
+int main( int argc, char **argv ) {
+
+ if (argc < 2) {
+ fprintf(stdout, "Usage: prltype <vm-name> <scan-codes...>\nexample: prltype my-vm 30 158\n This will press and release \"a\" on vm \"my-vm\".\n");
+ return -1;
+ }
+
+ char vmName[100];
+ strcpy(vmName, argv[1]);
+ int scanCodes [argc - 1];
+ for (int i = 2; i < argc; i++) {
+ scanCodes[i - 2] = strtol(argv[i], NULL, 16);
+ //scanCodes[i - 2] = atoi(argv[i]);
+ }
+
+ PRL_HANDLE hServer, hVm = PRL_INVALID_HANDLE;
+ PRL_RESULT err;
+
+ err = LoginLocal(hServer);
+ if (PRL_FAILED(err))
+ return err;
+ err = GetVm(hVm, hServer, vmName);
+ if (PRL_FAILED(err))
+ return err;
+ err = ConnectToConsole(hVm);
+ if (PRL_FAILED(err))
+ return err;
+
+ fprintf(stdout, "Connected to console for VM: %s. Sending scancode(s) [", vmName);
+ for (int i = 0; i < argc - 2; i++) {
+ err = SendScanCode(hVm, scanCodes[i]);
+ if (PRL_FAILED(err))
+ return err;
+ }
+ fprintf(stdout, " ]\n\n");
+
+ err = DisconnectFromConsole(hVm);
+ if (PRL_FAILED(err))
+ return err;
+
+ LogOff( hServer );
+}
Oops, something went wrong.

0 comments on commit e565f9b

Please sign in to comment.