Merge pull request #1440 from legal90/master

Enhancements for Parallels builder
This commit is contained in:
Rickard von Essen 2014-08-26 00:49:52 +02:00
commit b0161f40fe
6 changed files with 65 additions and 31 deletions

View File

@ -1,8 +1,11 @@
package common
import (
"fmt"
"log"
"os/exec"
"runtime"
"strings"
)
// A driver is able to talk to Parallels and perform certain
@ -43,7 +46,14 @@ type Driver interface {
}
func NewDriver() (Driver, error) {
var drivers map[string]Driver
var prlctlPath string
var supportedVersions []string
if runtime.GOOS != "darwin" {
return nil, fmt.Errorf(
"Parallels builder works only on \"darwin\" platform!")
}
if prlctlPath == "" {
var err error
@ -54,10 +64,27 @@ func NewDriver() (Driver, error) {
}
log.Printf("prlctl path: %s", prlctlPath)
driver := &Parallels9Driver{prlctlPath}
if err := driver.Verify(); err != nil {
return nil, err
drivers = map[string]Driver{
"10": &Parallels10Driver{
Parallels9Driver: Parallels9Driver{
PrlctlPath: prlctlPath,
},
},
"9": &Parallels9Driver{
PrlctlPath: prlctlPath,
},
}
return driver, nil
for v, d := range drivers {
version, _ := d.Version()
if strings.HasPrefix(version, v) {
return d, nil
}
supportedVersions = append(supportedVersions, v)
}
return nil, fmt.Errorf(
"Unable to initialize any driver. Supported Parallels Desktop versions: "+
"%s\n", strings.Join(supportedVersions, ", "))
}

View File

@ -0,0 +1,6 @@
package common
// Parallels10Driver are inherited from Parallels9Driver.
type Parallels10Driver struct {
Parallels9Driver
}

View File

@ -13,7 +13,6 @@ import (
"github.com/going/toolkit/xmlpath"
)
// Driver supporting Parallels Desktop for Mac v. 9 & 10
type Parallels9Driver struct {
// This is the path to the "prlctl" application.
PrlctlPath string
@ -72,6 +71,20 @@ func getConfigValueFromXpath(path, xpath string) (string, error) {
return value, nil
}
// Finds an application bundle by identifier (for "darwin" platform only)
func getAppPath(bundleId string) (string, error) {
cmd := exec.Command("mdfind", "kMDItemCFBundleIdentifier ==", bundleId)
out, err := cmd.Output()
if err != nil {
return "", err
}
if string(out) == "" {
return "", fmt.Errorf(
"Could not detect Parallels Desktop! Make sure it is properly installed.")
}
return string(out), nil
}
func (d *Parallels9Driver) IsRunning(name string) (bool, error) {
var stdout bytes.Buffer
@ -136,32 +149,24 @@ func (d *Parallels9Driver) Prlctl(args ...string) error {
}
func (d *Parallels9Driver) Verify() error {
version, _ := d.Version()
if !(strings.HasPrefix(version, "9.") || strings.HasPrefix(version, "10.")) {
return fmt.Errorf("The packer-parallels builder plugin only supports Parallels Desktop v. 9 & 10. You have: %s!\n", version)
}
return nil
}
func (d *Parallels9Driver) Version() (string, error) {
var stdout bytes.Buffer
cmd := exec.Command(d.PrlctlPath, "--version")
cmd.Stdout = &stdout
if err := cmd.Run(); err != nil {
out, err := exec.Command(d.PrlctlPath, "--version").Output()
if err != nil {
return "", err
}
versionOutput := strings.TrimSpace(stdout.String())
re := regexp.MustCompile("prlctl version ([0-9\\.]+)")
verMatch := re.FindAllStringSubmatch(versionOutput, 1)
if len(verMatch) != 1 {
return "", fmt.Errorf("prlctl version not found!\n")
versionRe := regexp.MustCompile(`prlctl version (\d+\.\d+.\d+)`)
matches := versionRe.FindStringSubmatch(string(out))
if matches == nil {
return "", fmt.Errorf(
"Could not find Parallels Desktop version in output:\n%s", string(out))
}
version := verMatch[0][1]
log.Printf("prlctl version: %s\n", version)
version := matches[1]
log.Printf("Parallels Desktop version: %s", version)
return version, nil
}

View File

@ -33,7 +33,6 @@ type config struct {
ParallelsToolsMode string `mapstructure:"parallels_tools_mode"`
ParallelsToolsGuestPath string `mapstructure:"parallels_tools_guest_path"`
ParallelsToolsHostPath string `mapstructure:"parallels_tools_host_path"`
GuestOSType string `mapstructure:"guest_os_type"`
GuestOSDistribution string `mapstructure:"guest_os_distribution"`
HardDriveInterface string `mapstructure:"hard_drive_interface"`
HostInterfaces []string `mapstructure:"host_interfaces"`
@ -47,6 +46,9 @@ type config struct {
RawSingleISOUrl string `mapstructure:"iso_url"`
// Deprecated parameters
GuestOSType string `mapstructure:"guest_os_type"`
tpl *packer.ConfigTemplate
}
@ -95,10 +97,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
b.config.HardDriveInterface = "sata"
}
if b.config.GuestOSType == "" {
b.config.GuestOSType = "other"
}
if b.config.GuestOSDistribution == "" {
b.config.GuestOSDistribution = "other"
}
@ -125,7 +123,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
"parallels_tools_mode": &b.config.ParallelsToolsMode,
"parallels_tools_host_path": &b.config.ParallelsToolsHostPath,
"parallels_tools_guest_path": &b.config.ParallelsToolsGuestPath,
"guest_os_type": &b.config.GuestOSType,
"guest_os_distribution": &b.config.GuestOSDistribution,
"hard_drive_interface": &b.config.HardDriveInterface,
"http_directory": &b.config.HTTPDir,

View File

@ -42,8 +42,8 @@ func TestBuilderPrepare_Defaults(t *testing.T) {
t.Errorf("bad parallels tools mode: %s", b.config.ParallelsToolsMode)
}
if b.config.GuestOSType != "other" {
t.Errorf("bad guest OS type: %s", b.config.GuestOSType)
if b.config.GuestOSDistribution != "other" {
t.Errorf("bad guest OS distribution: %s", b.config.GuestOSDistribution)
}
if b.config.VMName != "packer-foo" {

View File

@ -28,7 +28,6 @@ func (s *stepCreateVM) Run(state multistep.StateBag) multistep.StepAction {
commands := make([][]string, 8)
commands[0] = []string{
"create", name,
"--ostype", config.GuestOSType,
"--distribution", config.GuestOSDistribution,
"--dst", path,
"--vmtype", "vm",