diff --git a/builder/parallels/common/driver.go b/builder/parallels/common/driver.go index c28f0f9f4..ab9693461 100644 --- a/builder/parallels/common/driver.go +++ b/builder/parallels/common/driver.go @@ -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, ", ")) } diff --git a/builder/parallels/common/driver_10.go b/builder/parallels/common/driver_10.go new file mode 100644 index 000000000..ae39240f4 --- /dev/null +++ b/builder/parallels/common/driver_10.go @@ -0,0 +1,6 @@ +package common + +// Parallels10Driver are inherited from Parallels9Driver. +type Parallels10Driver struct { + Parallels9Driver +} diff --git a/builder/parallels/common/driver_9.go b/builder/parallels/common/driver_9.go index 20255beb9..54e93a4bf 100644 --- a/builder/parallels/common/driver_9.go +++ b/builder/parallels/common/driver_9.go @@ -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 } diff --git a/builder/parallels/iso/builder.go b/builder/parallels/iso/builder.go index 3b940fdc9..0fa38d5fb 100644 --- a/builder/parallels/iso/builder.go +++ b/builder/parallels/iso/builder.go @@ -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, diff --git a/builder/parallels/iso/builder_test.go b/builder/parallels/iso/builder_test.go index ba9cecdd8..f20f544d6 100644 --- a/builder/parallels/iso/builder_test.go +++ b/builder/parallels/iso/builder_test.go @@ -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" { diff --git a/builder/parallels/iso/step_create_vm.go b/builder/parallels/iso/step_create_vm.go index b91503ef6..1b2468cfe 100644 --- a/builder/parallels/iso/step_create_vm.go +++ b/builder/parallels/iso/step_create_vm.go @@ -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",