Merge pull request #1455 from legal90/prl-tools-flavor
builder/parallels: Detect path to Parallels Tools ISO automatically
This commit is contained in:
commit
d9e8676ec5
|
@ -27,6 +27,9 @@ type Driver interface {
|
||||||
// Prlctl executes the given Prlctl command
|
// Prlctl executes the given Prlctl command
|
||||||
Prlctl(...string) error
|
Prlctl(...string) error
|
||||||
|
|
||||||
|
// Get the path to the Parallels Tools ISO for the given flavor.
|
||||||
|
ToolsIsoPath(string) (string, error)
|
||||||
|
|
||||||
// Verify checks to make sure that this driver should function
|
// Verify checks to make sure that this driver should function
|
||||||
// properly. If there is any indication the driver can't function,
|
// properly. If there is any indication the driver can't function,
|
||||||
// this will return an error.
|
// this will return an error.
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -73,16 +74,21 @@ func getConfigValueFromXpath(path, xpath string) (string, error) {
|
||||||
|
|
||||||
// Finds an application bundle by identifier (for "darwin" platform only)
|
// Finds an application bundle by identifier (for "darwin" platform only)
|
||||||
func getAppPath(bundleId string) (string, error) {
|
func getAppPath(bundleId string) (string, error) {
|
||||||
|
var stdout bytes.Buffer
|
||||||
|
|
||||||
cmd := exec.Command("mdfind", "kMDItemCFBundleIdentifier ==", bundleId)
|
cmd := exec.Command("mdfind", "kMDItemCFBundleIdentifier ==", bundleId)
|
||||||
out, err := cmd.Output()
|
cmd.Stdout = &stdout
|
||||||
if err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
if string(out) == "" {
|
|
||||||
|
pathOutput := strings.TrimSpace(stdout.String())
|
||||||
|
if pathOutput == "" {
|
||||||
return "", fmt.Errorf(
|
return "", fmt.Errorf(
|
||||||
"Could not detect Parallels Desktop! Make sure it is properly installed.")
|
"Could not detect Parallels Desktop! Make sure it is properly installed.")
|
||||||
}
|
}
|
||||||
return string(out), nil
|
|
||||||
|
return pathOutput, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Parallels9Driver) IsRunning(name string) (bool, error) {
|
func (d *Parallels9Driver) IsRunning(name string) (bool, error) {
|
||||||
|
@ -251,3 +257,14 @@ func (d *Parallels9Driver) IpAddress(mac string) (string, error) {
|
||||||
log.Printf("Found IP lease: %s for MAC address %s\n", ip, mac)
|
log.Printf("Found IP lease: %s for MAC address %s\n", ip, mac)
|
||||||
return ip, nil
|
return ip, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Parallels9Driver) ToolsIsoPath(k string) (string, error) {
|
||||||
|
appPath, err := getAppPath("com.parallels.desktop.console")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
toolsPath := filepath.Join(appPath, "Contents", "Resources", "Tools", "prl-tools-"+k+".iso")
|
||||||
|
log.Printf("Parallels Tools path: '%s'", toolsPath)
|
||||||
|
return toolsPath, nil
|
||||||
|
}
|
||||||
|
|
|
@ -31,6 +31,11 @@ type DriverMock struct {
|
||||||
SendKeyScanCodesCalls [][]string
|
SendKeyScanCodesCalls [][]string
|
||||||
SendKeyScanCodesErrs []error
|
SendKeyScanCodesErrs []error
|
||||||
|
|
||||||
|
ToolsIsoPathCalled bool
|
||||||
|
ToolsIsoPathFlavor string
|
||||||
|
ToolsIsoPathResult string
|
||||||
|
ToolsIsoPathErr error
|
||||||
|
|
||||||
MacName string
|
MacName string
|
||||||
MacReturn string
|
MacReturn string
|
||||||
MacError error
|
MacError error
|
||||||
|
@ -98,3 +103,9 @@ func (d *DriverMock) IpAddress(mac string) (string, error) {
|
||||||
d.IpAddressMac = mac
|
d.IpAddressMac = mac
|
||||||
return d.IpAddressReturn, d.IpAddressError
|
return d.IpAddressReturn, d.IpAddressError
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *DriverMock) ToolsIsoPath(flavor string) (string, error) {
|
||||||
|
d.ToolsIsoPathCalled = true
|
||||||
|
d.ToolsIsoPathFlavor = flavor
|
||||||
|
return d.ToolsIsoPathResult, d.ToolsIsoPathErr
|
||||||
|
}
|
||||||
|
|
|
@ -7,18 +7,18 @@ import (
|
||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This step attaches the Parallels Tools as a inserted CD onto
|
// This step attaches the Parallels Tools as an inserted CD onto
|
||||||
// the virtual machine.
|
// the virtual machine.
|
||||||
//
|
//
|
||||||
// Uses:
|
// Uses:
|
||||||
// driver Driver
|
// driver Driver
|
||||||
// toolsPath string
|
// parallels_tools_path string
|
||||||
// ui packer.Ui
|
// ui packer.Ui
|
||||||
// vmName string
|
// vmName string
|
||||||
//
|
//
|
||||||
// Produces:
|
// Produces:
|
||||||
|
// attachedToolsIso boolean
|
||||||
type StepAttachParallelsTools struct {
|
type StepAttachParallelsTools struct {
|
||||||
ParallelsToolsHostPath string
|
|
||||||
ParallelsToolsMode string
|
ParallelsToolsMode string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,12 +33,15 @@ func (s *StepAttachParallelsTools) Run(state multistep.StateBag) multistep.StepA
|
||||||
return multistep.ActionContinue
|
return multistep.ActionContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the Paralells Tools path on the host machine
|
||||||
|
parallelsToolsPath := state.Get("parallels_tools_path").(string)
|
||||||
|
|
||||||
// Attach the guest additions to the computer
|
// Attach the guest additions to the computer
|
||||||
ui.Say("Attaching Parallels Tools ISO onto IDE controller...")
|
ui.Say("Attaching Parallels Tools ISO onto IDE controller...")
|
||||||
command := []string{
|
command := []string{
|
||||||
"set", vmName,
|
"set", vmName,
|
||||||
"--device-add", "cdrom",
|
"--device-add", "cdrom",
|
||||||
"--image", s.ParallelsToolsHostPath,
|
"--image", parallelsToolsPath,
|
||||||
}
|
}
|
||||||
if err := driver.Prlctl(command...); err != nil {
|
if err := driver.Prlctl(command...); err != nil {
|
||||||
err := fmt.Errorf("Error attaching Parallels Tools: %s", err)
|
err := fmt.Errorf("Error attaching Parallels Tools: %s", err)
|
||||||
|
@ -59,6 +62,7 @@ func (s *StepAttachParallelsTools) Cleanup(state multistep.StateBag) {
|
||||||
}
|
}
|
||||||
|
|
||||||
driver := state.Get("driver").(Driver)
|
driver := state.Get("driver").(Driver)
|
||||||
|
ui := state.Get("ui").(packer.Ui)
|
||||||
vmName := state.Get("vmName").(string)
|
vmName := state.Get("vmName").(string)
|
||||||
|
|
||||||
log.Println("Detaching Parallels Tools ISO...")
|
log.Println("Detaching Parallels Tools ISO...")
|
||||||
|
@ -71,5 +75,8 @@ func (s *StepAttachParallelsTools) Cleanup(state multistep.StateBag) {
|
||||||
"set", vmName,
|
"set", vmName,
|
||||||
"--device-del", cdDevice,
|
"--device-del", cdDevice,
|
||||||
}
|
}
|
||||||
driver.Prlctl(command...)
|
|
||||||
|
if err := driver.Prlctl(command...); err != nil {
|
||||||
|
ui.Error(fmt.Sprintf("Error detaching Parallels Tools ISO: %s", err))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/mitchellh/multistep"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This step prepares parameters related to Parallels Tools.
|
||||||
|
//
|
||||||
|
// Uses:
|
||||||
|
// driver Driver
|
||||||
|
//
|
||||||
|
// Produces:
|
||||||
|
// parallels_tools_path string
|
||||||
|
type StepPrepareParallelsTools struct {
|
||||||
|
ParallelsToolsFlavor string
|
||||||
|
ParallelsToolsMode string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StepPrepareParallelsTools) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
|
driver := state.Get("driver").(Driver)
|
||||||
|
|
||||||
|
if s.ParallelsToolsMode == ParallelsToolsModeDisable {
|
||||||
|
return multistep.ActionContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
path, err := driver.ToolsIsoPath(s.ParallelsToolsFlavor)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
state.Put("error", err)
|
||||||
|
return multistep.ActionHalt
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := os.Stat(path); err != nil {
|
||||||
|
state.Put("error", fmt.Errorf(
|
||||||
|
"Couldn't find Parallels Tools for the '%s' flavor! Please, check the\n"+
|
||||||
|
"value of 'parallels_tools_flavor'. Valid flavors are: 'win', 'lin',\n"+
|
||||||
|
"'mac', 'os2' and 'other'", s.ParallelsToolsFlavor))
|
||||||
|
return multistep.ActionHalt
|
||||||
|
}
|
||||||
|
|
||||||
|
state.Put("parallels_tools_path", path)
|
||||||
|
return multistep.ActionContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StepPrepareParallelsTools) Cleanup(multistep.StateBag) {}
|
|
@ -0,0 +1,115 @@
|
||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/mitchellh/multistep"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStepPrepareParallelsTools_impl(t *testing.T) {
|
||||||
|
var _ multistep.Step = new(StepPrepareParallelsTools)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStepPrepareParallelsTools(t *testing.T) {
|
||||||
|
tf, err := ioutil.TempFile("", "packer")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
tf.Close()
|
||||||
|
defer os.Remove(tf.Name())
|
||||||
|
|
||||||
|
state := testState(t)
|
||||||
|
step := &StepPrepareParallelsTools{
|
||||||
|
ParallelsToolsMode: "",
|
||||||
|
ParallelsToolsFlavor: "foo",
|
||||||
|
}
|
||||||
|
|
||||||
|
driver := state.Get("driver").(*DriverMock)
|
||||||
|
|
||||||
|
// Mock results
|
||||||
|
driver.ToolsIsoPathResult = tf.Name()
|
||||||
|
|
||||||
|
// Test the run
|
||||||
|
if action := step.Run(state); action != multistep.ActionContinue {
|
||||||
|
t.Fatalf("bad action: %#v", action)
|
||||||
|
}
|
||||||
|
if _, ok := state.GetOk("error"); ok {
|
||||||
|
t.Fatal("should NOT have error")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test the driver
|
||||||
|
if !driver.ToolsIsoPathCalled {
|
||||||
|
t.Fatal("tools iso path should be called")
|
||||||
|
}
|
||||||
|
if driver.ToolsIsoPathFlavor != "foo" {
|
||||||
|
t.Fatalf("bad: %#v", driver.ToolsIsoPathFlavor)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test the resulting state
|
||||||
|
path, ok := state.GetOk("parallels_tools_path")
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("should have parallels_tools_path")
|
||||||
|
}
|
||||||
|
if path != tf.Name() {
|
||||||
|
t.Fatalf("bad: %#v", path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStepPrepareParallelsTools_disabled(t *testing.T) {
|
||||||
|
state := testState(t)
|
||||||
|
step := &StepPrepareParallelsTools{
|
||||||
|
ParallelsToolsFlavor: "foo",
|
||||||
|
ParallelsToolsMode: ParallelsToolsModeDisable,
|
||||||
|
}
|
||||||
|
|
||||||
|
driver := state.Get("driver").(*DriverMock)
|
||||||
|
|
||||||
|
// Test the run
|
||||||
|
if action := step.Run(state); action != multistep.ActionContinue {
|
||||||
|
t.Fatalf("bad action: %#v", action)
|
||||||
|
}
|
||||||
|
if _, ok := state.GetOk("error"); ok {
|
||||||
|
t.Fatal("should NOT have error")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test the driver
|
||||||
|
if driver.ToolsIsoPathCalled {
|
||||||
|
t.Fatal("tools iso path should NOT be called")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStepPrepareParallelsTools_nonExist(t *testing.T) {
|
||||||
|
state := testState(t)
|
||||||
|
step := &StepPrepareParallelsTools{
|
||||||
|
ParallelsToolsFlavor: "foo",
|
||||||
|
ParallelsToolsMode: "",
|
||||||
|
}
|
||||||
|
|
||||||
|
driver := state.Get("driver").(*DriverMock)
|
||||||
|
|
||||||
|
// Mock results
|
||||||
|
driver.ToolsIsoPathResult = "foo"
|
||||||
|
|
||||||
|
// Test the run
|
||||||
|
if action := step.Run(state); action != multistep.ActionHalt {
|
||||||
|
t.Fatalf("bad action: %#v", action)
|
||||||
|
}
|
||||||
|
if _, ok := state.GetOk("error"); !ok {
|
||||||
|
t.Fatal("should have error")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test the driver
|
||||||
|
if !driver.ToolsIsoPathCalled {
|
||||||
|
t.Fatal("tools iso path should be called")
|
||||||
|
}
|
||||||
|
if driver.ToolsIsoPathFlavor != "foo" {
|
||||||
|
t.Fatalf("bad: %#v", driver.ToolsIsoPathFlavor)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test the resulting state
|
||||||
|
if _, ok := state.GetOk("parallels_tools_path"); ok {
|
||||||
|
t.Fatal("should NOT have parallels_tools_path")
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,13 +8,21 @@ import (
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// This step uploads the Parallels Tools ISO to the virtual machine.
|
||||||
|
//
|
||||||
|
// Uses:
|
||||||
|
// communicator packer.Communicator
|
||||||
|
// parallels_tools_path string
|
||||||
|
// ui packer.Ui
|
||||||
|
//
|
||||||
|
// Produces:
|
||||||
type toolsPathTemplate struct {
|
type toolsPathTemplate struct {
|
||||||
Version string
|
Flavor string
|
||||||
}
|
}
|
||||||
|
|
||||||
// This step uploads the guest additions ISO to the VM.
|
// This step uploads the guest additions ISO to the VM.
|
||||||
type StepUploadParallelsTools struct {
|
type StepUploadParallelsTools struct {
|
||||||
ParallelsToolsHostPath string
|
ParallelsToolsFlavor string
|
||||||
ParallelsToolsGuestPath string
|
ParallelsToolsGuestPath string
|
||||||
ParallelsToolsMode string
|
ParallelsToolsMode string
|
||||||
Tpl *packer.ConfigTemplate
|
Tpl *packer.ConfigTemplate
|
||||||
|
@ -22,7 +30,6 @@ type StepUploadParallelsTools struct {
|
||||||
|
|
||||||
func (s *StepUploadParallelsTools) Run(state multistep.StateBag) multistep.StepAction {
|
func (s *StepUploadParallelsTools) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
comm := state.Get("communicator").(packer.Communicator)
|
comm := state.Get("communicator").(packer.Communicator)
|
||||||
driver := state.Get("driver").(Driver)
|
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
// If we're attaching then don't do this, since we attached.
|
// If we're attaching then don't do this, since we attached.
|
||||||
|
@ -31,20 +38,18 @@ func (s *StepUploadParallelsTools) Run(state multistep.StateBag) multistep.StepA
|
||||||
return multistep.ActionContinue
|
return multistep.ActionContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
version, err := driver.Version()
|
// Get the Paralells Tools path on the host machine
|
||||||
if err != nil {
|
parallelsToolsPath := state.Get("parallels_tools_path").(string)
|
||||||
state.Put("error", fmt.Errorf("Error reading version for Parallels Tools upload: %s", err))
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := os.Open(s.ParallelsToolsHostPath)
|
f, err := os.Open(parallelsToolsPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
state.Put("error", fmt.Errorf("Error opening Parallels Tools ISO: %s", err))
|
state.Put("error", fmt.Errorf("Error opening Parallels Tools ISO: %s", err))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
tplData := &toolsPathTemplate{
|
tplData := &toolsPathTemplate{
|
||||||
Version: version,
|
Flavor: s.ParallelsToolsFlavor,
|
||||||
}
|
}
|
||||||
|
|
||||||
s.ParallelsToolsGuestPath, err = s.Tpl.Process(s.ParallelsToolsGuestPath, tplData)
|
s.ParallelsToolsGuestPath, err = s.Tpl.Process(s.ParallelsToolsGuestPath, tplData)
|
||||||
|
@ -55,9 +60,12 @@ func (s *StepUploadParallelsTools) Run(state multistep.StateBag) multistep.StepA
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.Say("Uploading Parallels Tools ISO...")
|
ui.Say(fmt.Sprintf("Uploading Parallels Tools for '%s' to path: '%s'",
|
||||||
|
s.ParallelsToolsFlavor, s.ParallelsToolsGuestPath))
|
||||||
if err := comm.Upload(s.ParallelsToolsGuestPath, f); err != nil {
|
if err := comm.Upload(s.ParallelsToolsGuestPath, f); err != nil {
|
||||||
state.Put("error", fmt.Errorf("Error uploading Parallels Tools: %s", err))
|
err := fmt.Errorf("Error uploading Parallels Tools: %s", err)
|
||||||
|
state.Put("error", err)
|
||||||
|
ui.Error(err.Error())
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/mitchellh/packer/packer"
|
||||||
|
"text/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
// These are the different valid mode values for "parallels_tools_mode" which
|
||||||
|
// determine how guest additions are delivered to the guest.
|
||||||
|
const (
|
||||||
|
ParallelsToolsModeDisable string = "disable"
|
||||||
|
ParallelsToolsModeAttach = "attach"
|
||||||
|
ParallelsToolsModeUpload = "upload"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ToolsConfig struct {
|
||||||
|
ParallelsToolsFlavor string `mapstructure:"parallels_tools_flavor"`
|
||||||
|
ParallelsToolsGuestPath string `mapstructure:"parallels_tools_guest_path"`
|
||||||
|
ParallelsToolsMode string `mapstructure:"parallels_tools_mode"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ToolsConfig) Prepare(t *packer.ConfigTemplate) []error {
|
||||||
|
if c.ParallelsToolsMode == "" {
|
||||||
|
c.ParallelsToolsMode = ParallelsToolsModeUpload
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.ParallelsToolsGuestPath == "" {
|
||||||
|
c.ParallelsToolsGuestPath = "prl-tools-{{.Flavor}}.iso"
|
||||||
|
}
|
||||||
|
|
||||||
|
templates := map[string]*string{
|
||||||
|
"parallels_tools_flavor": &c.ParallelsToolsFlavor,
|
||||||
|
"parallels_tools_mode": &c.ParallelsToolsMode,
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
errs := make([]error, 0)
|
||||||
|
for n, ptr := range templates {
|
||||||
|
*ptr, err = t.Process(*ptr, nil)
|
||||||
|
if err != nil {
|
||||||
|
errs = append(errs, fmt.Errorf("Error processing %s: %s", n, err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := template.New("path").Parse(c.ParallelsToolsGuestPath); err != nil {
|
||||||
|
errs = append(errs, fmt.Errorf("parallels_tools_guest_path invalid: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
validMode := false
|
||||||
|
validModes := []string{
|
||||||
|
ParallelsToolsModeDisable,
|
||||||
|
ParallelsToolsModeAttach,
|
||||||
|
ParallelsToolsModeUpload,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, mode := range validModes {
|
||||||
|
if c.ParallelsToolsMode == mode {
|
||||||
|
validMode = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !validMode {
|
||||||
|
errs = append(errs,
|
||||||
|
fmt.Errorf("parallels_tools_mode is invalid. Must be one of: %v",
|
||||||
|
validModes))
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.ParallelsToolsFlavor == "" {
|
||||||
|
if c.ParallelsToolsMode != ParallelsToolsModeDisable {
|
||||||
|
errs = append(errs, errors.New("parallels_tools_flavor must be specified."))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return errs
|
||||||
|
}
|
|
@ -0,0 +1,123 @@
|
||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func testToolsConfig() *ToolsConfig {
|
||||||
|
return &ToolsConfig{
|
||||||
|
ParallelsToolsFlavor: "foo",
|
||||||
|
ParallelsToolsGuestPath: "foo",
|
||||||
|
ParallelsToolsMode: "attach",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToolsConfigPrepare(t *testing.T) {
|
||||||
|
c := testToolsConfig()
|
||||||
|
errs := c.Prepare(testConfigTemplate(t))
|
||||||
|
if len(errs) > 0 {
|
||||||
|
t.Fatalf("bad err: %#v", errs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToolsConfigPrepare_ParallelsToolsMode(t *testing.T) {
|
||||||
|
var c *ToolsConfig
|
||||||
|
var errs []error
|
||||||
|
|
||||||
|
// Test default mode
|
||||||
|
c = testToolsConfig()
|
||||||
|
c.ParallelsToolsMode = ""
|
||||||
|
errs = c.Prepare(testConfigTemplate(t))
|
||||||
|
if len(errs) > 0 {
|
||||||
|
t.Fatalf("should not have error: %#v", errs)
|
||||||
|
}
|
||||||
|
if c.ParallelsToolsMode != ParallelsToolsModeUpload {
|
||||||
|
t.Errorf("bad parallels tools mode: %s", c.ParallelsToolsMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test another mode
|
||||||
|
c = testToolsConfig()
|
||||||
|
c.ParallelsToolsMode = "attach"
|
||||||
|
errs = c.Prepare(testConfigTemplate(t))
|
||||||
|
if len(errs) > 0 {
|
||||||
|
t.Fatalf("should not have error: %#v", errs)
|
||||||
|
}
|
||||||
|
if c.ParallelsToolsMode != ParallelsToolsModeAttach {
|
||||||
|
t.Fatalf("bad mode: %s", c.ParallelsToolsMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test invalid mode
|
||||||
|
c = testToolsConfig()
|
||||||
|
c.ParallelsToolsMode = "invalid_mode"
|
||||||
|
errs = c.Prepare(testConfigTemplate(t))
|
||||||
|
if len(errs) == 0 {
|
||||||
|
t.Fatal("should have error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToolsConfigPrepare_ParallelsToolsGuestPath(t *testing.T) {
|
||||||
|
var c *ToolsConfig
|
||||||
|
var errs []error
|
||||||
|
|
||||||
|
// Test default path
|
||||||
|
c = testToolsConfig()
|
||||||
|
c.ParallelsToolsGuestPath = ""
|
||||||
|
errs = c.Prepare(testConfigTemplate(t))
|
||||||
|
if len(errs) > 0 {
|
||||||
|
t.Fatalf("should not have error: %#v", errs)
|
||||||
|
}
|
||||||
|
if c.ParallelsToolsGuestPath == "" {
|
||||||
|
t.Fatal("should not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test with a bad value
|
||||||
|
c = testToolsConfig()
|
||||||
|
c.ParallelsToolsGuestPath = "{{{nope}"
|
||||||
|
errs = c.Prepare(testConfigTemplate(t))
|
||||||
|
if len(errs) == 0 {
|
||||||
|
t.Fatal("should have error")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test with a good one
|
||||||
|
c = testToolsConfig()
|
||||||
|
c.ParallelsToolsGuestPath = "foo"
|
||||||
|
errs = c.Prepare(testConfigTemplate(t))
|
||||||
|
if len(errs) > 0 {
|
||||||
|
t.Fatalf("should not have error: %s", errs)
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.ParallelsToolsGuestPath != "foo" {
|
||||||
|
t.Fatalf("bad guest path: %s", c.ParallelsToolsGuestPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToolsConfigPrepare_ParallelsToolsFlavor(t *testing.T) {
|
||||||
|
var c *ToolsConfig
|
||||||
|
var errs []error
|
||||||
|
|
||||||
|
// Test with a default value
|
||||||
|
c = testToolsConfig()
|
||||||
|
c.ParallelsToolsFlavor = ""
|
||||||
|
errs = c.Prepare(testConfigTemplate(t))
|
||||||
|
if len(errs) == 0 {
|
||||||
|
t.Fatal("should have error")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test with an bad value
|
||||||
|
c = testToolsConfig()
|
||||||
|
c.ParallelsToolsMode = "attach"
|
||||||
|
c.ParallelsToolsFlavor = ""
|
||||||
|
errs = c.Prepare(testConfigTemplate(t))
|
||||||
|
if len(errs) == 0 {
|
||||||
|
t.Fatal("should have error")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test with a good one
|
||||||
|
c = testToolsConfig()
|
||||||
|
c.ParallelsToolsMode = "disable"
|
||||||
|
c.ParallelsToolsFlavor = ""
|
||||||
|
errs = c.Prepare(testConfigTemplate(t))
|
||||||
|
if len(errs) > 0 {
|
||||||
|
t.Fatalf("should not have error: %s", errs)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +0,0 @@
|
||||||
package common
|
|
||||||
|
|
||||||
// These are the different valid mode values for "parallels_tools_mode" which
|
|
||||||
// determine how guest additions are delivered to the guest.
|
|
||||||
const (
|
|
||||||
ParallelsToolsModeDisable string = "disable"
|
|
||||||
ParallelsToolsModeAttach = "attach"
|
|
||||||
ParallelsToolsModeUpload = "upload"
|
|
||||||
)
|
|
|
@ -22,18 +22,16 @@ type config struct {
|
||||||
common.PackerConfig `mapstructure:",squash"`
|
common.PackerConfig `mapstructure:",squash"`
|
||||||
parallelscommon.FloppyConfig `mapstructure:",squash"`
|
parallelscommon.FloppyConfig `mapstructure:",squash"`
|
||||||
parallelscommon.OutputConfig `mapstructure:",squash"`
|
parallelscommon.OutputConfig `mapstructure:",squash"`
|
||||||
|
parallelscommon.PrlctlConfig `mapstructure:",squash"`
|
||||||
|
parallelscommon.PrlctlVersionConfig `mapstructure:",squash"`
|
||||||
parallelscommon.RunConfig `mapstructure:",squash"`
|
parallelscommon.RunConfig `mapstructure:",squash"`
|
||||||
parallelscommon.ShutdownConfig `mapstructure:",squash"`
|
parallelscommon.ShutdownConfig `mapstructure:",squash"`
|
||||||
parallelscommon.SSHConfig `mapstructure:",squash"`
|
parallelscommon.SSHConfig `mapstructure:",squash"`
|
||||||
parallelscommon.PrlctlConfig `mapstructure:",squash"`
|
parallelscommon.ToolsConfig `mapstructure:",squash"`
|
||||||
parallelscommon.PrlctlVersionConfig `mapstructure:",squash"`
|
|
||||||
|
|
||||||
BootCommand []string `mapstructure:"boot_command"`
|
BootCommand []string `mapstructure:"boot_command"`
|
||||||
DiskSize uint `mapstructure:"disk_size"`
|
DiskSize uint `mapstructure:"disk_size"`
|
||||||
ParallelsToolsMode string `mapstructure:"parallels_tools_mode"`
|
GuestOSType string `mapstructure:"guest_os_type"`
|
||||||
ParallelsToolsGuestPath string `mapstructure:"parallels_tools_guest_path"`
|
|
||||||
ParallelsToolsHostPath string `mapstructure:"parallels_tools_host_path"`
|
|
||||||
GuestOSDistribution string `mapstructure:"guest_os_distribution"`
|
|
||||||
HardDriveInterface string `mapstructure:"hard_drive_interface"`
|
HardDriveInterface string `mapstructure:"hard_drive_interface"`
|
||||||
HostInterfaces []string `mapstructure:"host_interfaces"`
|
HostInterfaces []string `mapstructure:"host_interfaces"`
|
||||||
HTTPDir string `mapstructure:"http_directory"`
|
HTTPDir string `mapstructure:"http_directory"`
|
||||||
|
@ -47,7 +45,8 @@ type config struct {
|
||||||
RawSingleISOUrl string `mapstructure:"iso_url"`
|
RawSingleISOUrl string `mapstructure:"iso_url"`
|
||||||
|
|
||||||
// Deprecated parameters
|
// Deprecated parameters
|
||||||
GuestOSType string `mapstructure:"guest_os_type"`
|
GuestOSDistribution string `mapstructure:"guest_os_distribution"`
|
||||||
|
ParallelsToolsHostPath string `mapstructure:"parallels_tools_host_path"`
|
||||||
|
|
||||||
tpl *packer.ConfigTemplate
|
tpl *packer.ConfigTemplate
|
||||||
}
|
}
|
||||||
|
@ -71,34 +70,33 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
|
||||||
errs = packer.MultiErrorAppend(
|
errs = packer.MultiErrorAppend(
|
||||||
errs, b.config.OutputConfig.Prepare(b.config.tpl, &b.config.PackerConfig)...)
|
errs, b.config.OutputConfig.Prepare(b.config.tpl, &b.config.PackerConfig)...)
|
||||||
errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(b.config.tpl)...)
|
errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(b.config.tpl)...)
|
||||||
errs = packer.MultiErrorAppend(errs, b.config.ShutdownConfig.Prepare(b.config.tpl)...)
|
|
||||||
errs = packer.MultiErrorAppend(errs, b.config.SSHConfig.Prepare(b.config.tpl)...)
|
|
||||||
errs = packer.MultiErrorAppend(errs, b.config.PrlctlConfig.Prepare(b.config.tpl)...)
|
errs = packer.MultiErrorAppend(errs, b.config.PrlctlConfig.Prepare(b.config.tpl)...)
|
||||||
errs = packer.MultiErrorAppend(errs, b.config.PrlctlVersionConfig.Prepare(b.config.tpl)...)
|
errs = packer.MultiErrorAppend(errs, b.config.PrlctlVersionConfig.Prepare(b.config.tpl)...)
|
||||||
|
errs = packer.MultiErrorAppend(errs, b.config.ShutdownConfig.Prepare(b.config.tpl)...)
|
||||||
|
errs = packer.MultiErrorAppend(errs, b.config.SSHConfig.Prepare(b.config.tpl)...)
|
||||||
|
errs = packer.MultiErrorAppend(errs, b.config.ToolsConfig.Prepare(b.config.tpl)...)
|
||||||
warnings := make([]string, 0)
|
warnings := make([]string, 0)
|
||||||
|
|
||||||
if b.config.DiskSize == 0 {
|
if b.config.DiskSize == 0 {
|
||||||
b.config.DiskSize = 40000
|
b.config.DiskSize = 40000
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.config.ParallelsToolsMode == "" {
|
|
||||||
b.config.ParallelsToolsMode = "upload"
|
|
||||||
}
|
|
||||||
|
|
||||||
if b.config.ParallelsToolsGuestPath == "" {
|
|
||||||
b.config.ParallelsToolsGuestPath = "prl-tools.iso"
|
|
||||||
}
|
|
||||||
|
|
||||||
if b.config.ParallelsToolsHostPath == "" {
|
|
||||||
b.config.ParallelsToolsHostPath = "/Applications/Parallels Desktop.app/Contents/Resources/Tools/prl-tools-other.iso"
|
|
||||||
}
|
|
||||||
|
|
||||||
if b.config.HardDriveInterface == "" {
|
if b.config.HardDriveInterface == "" {
|
||||||
b.config.HardDriveInterface = "sata"
|
b.config.HardDriveInterface = "sata"
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.config.GuestOSDistribution == "" {
|
if b.config.GuestOSType == "" {
|
||||||
b.config.GuestOSDistribution = "other"
|
b.config.GuestOSType = "other"
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.config.GuestOSDistribution != "" {
|
||||||
|
// Compatibility with older templates:
|
||||||
|
// Use value of 'guest_os_distribution' if it is defined.
|
||||||
|
b.config.GuestOSType = b.config.GuestOSDistribution
|
||||||
|
warnings = append(warnings,
|
||||||
|
"A 'guest_os_distribution' has been completely replaced with 'guest_os_type'\n"+
|
||||||
|
"It is recommended to remove it and assign the previous value to 'guest_os_type'.\n"+
|
||||||
|
"Run it to see all available values: `prlctl create x -d list` ")
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.config.HTTPPortMin == 0 {
|
if b.config.HTTPPortMin == 0 {
|
||||||
|
@ -120,10 +118,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
|
||||||
|
|
||||||
// Errors
|
// Errors
|
||||||
templates := map[string]*string{
|
templates := map[string]*string{
|
||||||
"parallels_tools_mode": &b.config.ParallelsToolsMode,
|
"guest_os_type": &b.config.GuestOSType,
|
||||||
"parallels_tools_host_path": &b.config.ParallelsToolsHostPath,
|
|
||||||
"parallels_tools_guest_path": &b.config.ParallelsToolsGuestPath,
|
|
||||||
"guest_os_distribution": &b.config.GuestOSDistribution,
|
|
||||||
"hard_drive_interface": &b.config.HardDriveInterface,
|
"hard_drive_interface": &b.config.HardDriveInterface,
|
||||||
"http_directory": &b.config.HTTPDir,
|
"http_directory": &b.config.HTTPDir,
|
||||||
"iso_checksum": &b.config.ISOChecksum,
|
"iso_checksum": &b.config.ISOChecksum,
|
||||||
|
@ -150,17 +145,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
validates := map[string]*string{
|
|
||||||
"parallels_tools_guest_path": &b.config.ParallelsToolsGuestPath,
|
|
||||||
}
|
|
||||||
|
|
||||||
for n, ptr := range validates {
|
|
||||||
if err := b.config.tpl.Validate(*ptr); err != nil {
|
|
||||||
errs = packer.MultiErrorAppend(
|
|
||||||
errs, fmt.Errorf("Error parsing %s: %s", n, err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, command := range b.config.BootCommand {
|
for i, command := range b.config.BootCommand {
|
||||||
if err := b.config.tpl.Validate(command); err != nil {
|
if err := b.config.tpl.Validate(command); err != nil {
|
||||||
errs = packer.MultiErrorAppend(errs,
|
errs = packer.MultiErrorAppend(errs,
|
||||||
|
@ -217,25 +201,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
validMode := false
|
|
||||||
validModes := []string{
|
|
||||||
parallelscommon.ParallelsToolsModeDisable,
|
|
||||||
parallelscommon.ParallelsToolsModeAttach,
|
|
||||||
parallelscommon.ParallelsToolsModeUpload,
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, mode := range validModes {
|
|
||||||
if b.config.ParallelsToolsMode == mode {
|
|
||||||
validMode = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !validMode {
|
|
||||||
errs = packer.MultiErrorAppend(errs,
|
|
||||||
fmt.Errorf("parallels_tools_mode is invalid. Must be one of: %v", validModes))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Warnings
|
// Warnings
|
||||||
if b.config.ISOChecksumType == "none" {
|
if b.config.ISOChecksumType == "none" {
|
||||||
warnings = append(warnings,
|
warnings = append(warnings,
|
||||||
|
@ -249,6 +214,12 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
|
||||||
"will forcibly halt the virtual machine, which may result in data loss.")
|
"will forcibly halt the virtual machine, which may result in data loss.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if b.config.ParallelsToolsHostPath != "" {
|
||||||
|
warnings = append(warnings,
|
||||||
|
"A 'parallels_tools_host_path' has been deprecated and not in use anymore\n"+
|
||||||
|
"You can remove it from your Packer template.")
|
||||||
|
}
|
||||||
|
|
||||||
if errs != nil && len(errs.Errors) > 0 {
|
if errs != nil && len(errs.Errors) > 0 {
|
||||||
return warnings, errs
|
return warnings, errs
|
||||||
}
|
}
|
||||||
|
@ -264,6 +235,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
||||||
}
|
}
|
||||||
|
|
||||||
steps := []multistep.Step{
|
steps := []multistep.Step{
|
||||||
|
¶llelscommon.StepPrepareParallelsTools{
|
||||||
|
ParallelsToolsFlavor: b.config.ParallelsToolsFlavor,
|
||||||
|
ParallelsToolsMode: b.config.ParallelsToolsMode,
|
||||||
|
},
|
||||||
&common.StepDownload{
|
&common.StepDownload{
|
||||||
Checksum: b.config.ISOChecksum,
|
Checksum: b.config.ISOChecksum,
|
||||||
ChecksumType: b.config.ISOChecksumType,
|
ChecksumType: b.config.ISOChecksumType,
|
||||||
|
@ -283,7 +258,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
||||||
new(stepCreateDisk),
|
new(stepCreateDisk),
|
||||||
new(stepAttachISO),
|
new(stepAttachISO),
|
||||||
¶llelscommon.StepAttachParallelsTools{
|
¶llelscommon.StepAttachParallelsTools{
|
||||||
ParallelsToolsHostPath: b.config.ParallelsToolsHostPath,
|
|
||||||
ParallelsToolsMode: b.config.ParallelsToolsMode,
|
ParallelsToolsMode: b.config.ParallelsToolsMode,
|
||||||
},
|
},
|
||||||
new(parallelscommon.StepAttachFloppy),
|
new(parallelscommon.StepAttachFloppy),
|
||||||
|
@ -310,8 +284,8 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
||||||
Path: b.config.PrlctlVersionFile,
|
Path: b.config.PrlctlVersionFile,
|
||||||
},
|
},
|
||||||
¶llelscommon.StepUploadParallelsTools{
|
¶llelscommon.StepUploadParallelsTools{
|
||||||
|
ParallelsToolsFlavor: b.config.ParallelsToolsFlavor,
|
||||||
ParallelsToolsGuestPath: b.config.ParallelsToolsGuestPath,
|
ParallelsToolsGuestPath: b.config.ParallelsToolsGuestPath,
|
||||||
ParallelsToolsHostPath: b.config.ParallelsToolsHostPath,
|
|
||||||
ParallelsToolsMode: b.config.ParallelsToolsMode,
|
ParallelsToolsMode: b.config.ParallelsToolsMode,
|
||||||
Tpl: b.config.tpl,
|
Tpl: b.config.tpl,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package iso
|
package iso
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/mitchellh/packer/builder/parallels/common"
|
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -14,6 +13,7 @@ func testConfig() map[string]interface{} {
|
||||||
"iso_url": "http://www.google.com/",
|
"iso_url": "http://www.google.com/",
|
||||||
"shutdown_command": "yes",
|
"shutdown_command": "yes",
|
||||||
"ssh_username": "foo",
|
"ssh_username": "foo",
|
||||||
|
"parallels_tools_flavor": "lin",
|
||||||
|
|
||||||
packer.BuildNameConfigKey: "foo",
|
packer.BuildNameConfigKey: "foo",
|
||||||
}
|
}
|
||||||
|
@ -38,12 +38,8 @@ func TestBuilderPrepare_Defaults(t *testing.T) {
|
||||||
t.Fatalf("should not have error: %s", err)
|
t.Fatalf("should not have error: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.config.ParallelsToolsMode != common.ParallelsToolsModeUpload {
|
if b.config.GuestOSType != "other" {
|
||||||
t.Errorf("bad parallels tools mode: %s", b.config.ParallelsToolsMode)
|
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" {
|
if b.config.VMName != "packer-foo" {
|
||||||
|
@ -83,104 +79,22 @@ func TestBuilderPrepare_DiskSize(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBuilderPrepare_ParallelsToolsMode(t *testing.T) {
|
func TestBuilderPrepare_GuestOSType(t *testing.T) {
|
||||||
var b Builder
|
var b Builder
|
||||||
config := testConfig()
|
config := testConfig()
|
||||||
|
delete(config, "guest_os_distribution")
|
||||||
|
|
||||||
// test default mode
|
// Test deprecated parameter
|
||||||
delete(config, "parallels_tools_mode")
|
config["guest_os_distribution"] = "bolgenos"
|
||||||
warns, err := b.Prepare(config)
|
warns, err := b.Prepare(config)
|
||||||
if len(warns) > 0 {
|
if len(warns) == 0 {
|
||||||
t.Fatalf("bad: %#v", warns)
|
t.Fatalf("should have warning")
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("bad err: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test another mode
|
|
||||||
config["parallels_tools_mode"] = "attach"
|
|
||||||
b = Builder{}
|
|
||||||
warns, err = b.Prepare(config)
|
|
||||||
if len(warns) > 0 {
|
|
||||||
t.Fatalf("bad: %#v", warns)
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("should not have error: %s", err)
|
t.Fatalf("should not have error: %s", err)
|
||||||
}
|
}
|
||||||
|
if b.config.GuestOSType != "bolgenos" {
|
||||||
if b.config.ParallelsToolsMode != common.ParallelsToolsModeAttach {
|
t.Fatalf("bad: %s", b.config.GuestOSType)
|
||||||
t.Fatalf("bad: %s", b.config.ParallelsToolsMode)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test bad mode
|
|
||||||
config["parllels_tools_mode"] = "teleport"
|
|
||||||
b = Builder{}
|
|
||||||
warns, err = b.Prepare(config)
|
|
||||||
if len(warns) > 0 {
|
|
||||||
t.Fatalf("bad: %#v", warns)
|
|
||||||
}
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("should error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuilderPrepare_ParallelsToolsGuestPath(t *testing.T) {
|
|
||||||
var b Builder
|
|
||||||
config := testConfig()
|
|
||||||
|
|
||||||
delete(config, "parallesl_tools_guest_path")
|
|
||||||
warns, err := b.Prepare(config)
|
|
||||||
if len(warns) > 0 {
|
|
||||||
t.Fatalf("bad: %#v", warns)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("bad err: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if b.config.ParallelsToolsGuestPath != "prl-tools.iso" {
|
|
||||||
t.Fatalf("bad: %s", b.config.ParallelsToolsGuestPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
config["parallels_tools_guest_path"] = "foo"
|
|
||||||
b = Builder{}
|
|
||||||
warns, err = b.Prepare(config)
|
|
||||||
if len(warns) > 0 {
|
|
||||||
t.Fatalf("bad: %#v", warns)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("should not have error: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if b.config.ParallelsToolsGuestPath != "foo" {
|
|
||||||
t.Fatalf("bad size: %s", b.config.ParallelsToolsGuestPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuilderPrepare_ParallelsToolsHostPath(t *testing.T) {
|
|
||||||
var b Builder
|
|
||||||
config := testConfig()
|
|
||||||
|
|
||||||
config["parallels_tools_host_path"] = ""
|
|
||||||
warns, err := b.Prepare(config)
|
|
||||||
if len(warns) > 0 {
|
|
||||||
t.Fatalf("bad: %#v", warns)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("err: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if b.config.ParallelsToolsHostPath != "/Applications/Parallels Desktop.app/Contents/Resources/Tools/prl-tools-other.iso" {
|
|
||||||
t.Fatalf("bad: %s", b.config.ParallelsToolsHostPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
config["parallels_tools_host_path"] = "./prl-tools-lin.iso"
|
|
||||||
b = Builder{}
|
|
||||||
warns, err = b.Prepare(config)
|
|
||||||
if len(warns) > 0 {
|
|
||||||
t.Fatalf("bad: %#v", warns)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("should not have error: %s", err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -434,3 +348,19 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) {
|
||||||
t.Fatalf("bad: %#v", b.config.ISOUrls)
|
t.Fatalf("bad: %#v", b.config.ISOUrls)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBuilderPrepare_ParallelsToolsHostPath(t *testing.T) {
|
||||||
|
var b Builder
|
||||||
|
config := testConfig()
|
||||||
|
delete(config, "parallels_tools_host_path")
|
||||||
|
|
||||||
|
// Test that it is deprecated
|
||||||
|
config["parallels_tools_host_path"] = "/path/to/iso"
|
||||||
|
warns, err := b.Prepare(config)
|
||||||
|
if len(warns) == 0 {
|
||||||
|
t.Fatalf("should have warning")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("should not have error: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ func (s *stepCreateVM) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
commands := make([][]string, 8)
|
commands := make([][]string, 8)
|
||||||
commands[0] = []string{
|
commands[0] = []string{
|
||||||
"create", name,
|
"create", name,
|
||||||
"--distribution", config.GuestOSDistribution,
|
"--distribution", config.GuestOSType,
|
||||||
"--dst", path,
|
"--dst", path,
|
||||||
"--vmtype", "vm",
|
"--vmtype", "vm",
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
||||||
|
|
||||||
// Build the steps.
|
// Build the steps.
|
||||||
steps := []multistep.Step{
|
steps := []multistep.Step{
|
||||||
|
¶llelscommon.StepPrepareParallelsTools{
|
||||||
|
ParallelsToolsMode: b.config.ParallelsToolsMode,
|
||||||
|
ParallelsToolsFlavor: b.config.ParallelsToolsFlavor,
|
||||||
|
},
|
||||||
¶llelscommon.StepOutputDir{
|
¶llelscommon.StepOutputDir{
|
||||||
Force: b.config.PackerForce,
|
Force: b.config.PackerForce,
|
||||||
Path: b.config.OutputDir,
|
Path: b.config.OutputDir,
|
||||||
|
@ -59,7 +63,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
||||||
SourcePath: b.config.SourcePath,
|
SourcePath: b.config.SourcePath,
|
||||||
},
|
},
|
||||||
¶llelscommon.StepAttachParallelsTools{
|
¶llelscommon.StepAttachParallelsTools{
|
||||||
ParallelsToolsHostPath: b.config.ParallelsToolsHostPath,
|
|
||||||
ParallelsToolsMode: b.config.ParallelsToolsMode,
|
ParallelsToolsMode: b.config.ParallelsToolsMode,
|
||||||
},
|
},
|
||||||
new(parallelscommon.StepAttachFloppy),
|
new(parallelscommon.StepAttachFloppy),
|
||||||
|
@ -86,8 +89,8 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
||||||
Path: b.config.PrlctlVersionFile,
|
Path: b.config.PrlctlVersionFile,
|
||||||
},
|
},
|
||||||
¶llelscommon.StepUploadParallelsTools{
|
¶llelscommon.StepUploadParallelsTools{
|
||||||
|
ParallelsToolsFlavor: b.config.ParallelsToolsFlavor,
|
||||||
ParallelsToolsGuestPath: b.config.ParallelsToolsGuestPath,
|
ParallelsToolsGuestPath: b.config.ParallelsToolsGuestPath,
|
||||||
ParallelsToolsHostPath: b.config.ParallelsToolsHostPath,
|
|
||||||
ParallelsToolsMode: b.config.ParallelsToolsMode,
|
ParallelsToolsMode: b.config.ParallelsToolsMode,
|
||||||
Tpl: b.config.tpl,
|
Tpl: b.config.tpl,
|
||||||
},
|
},
|
||||||
|
|
|
@ -13,16 +13,14 @@ type Config struct {
|
||||||
common.PackerConfig `mapstructure:",squash"`
|
common.PackerConfig `mapstructure:",squash"`
|
||||||
parallelscommon.FloppyConfig `mapstructure:",squash"`
|
parallelscommon.FloppyConfig `mapstructure:",squash"`
|
||||||
parallelscommon.OutputConfig `mapstructure:",squash"`
|
parallelscommon.OutputConfig `mapstructure:",squash"`
|
||||||
|
parallelscommon.PrlctlConfig `mapstructure:",squash"`
|
||||||
|
parallelscommon.PrlctlVersionConfig `mapstructure:",squash"`
|
||||||
parallelscommon.RunConfig `mapstructure:",squash"`
|
parallelscommon.RunConfig `mapstructure:",squash"`
|
||||||
parallelscommon.SSHConfig `mapstructure:",squash"`
|
parallelscommon.SSHConfig `mapstructure:",squash"`
|
||||||
parallelscommon.ShutdownConfig `mapstructure:",squash"`
|
parallelscommon.ShutdownConfig `mapstructure:",squash"`
|
||||||
parallelscommon.PrlctlConfig `mapstructure:",squash"`
|
parallelscommon.ToolsConfig `mapstructure:",squash"`
|
||||||
parallelscommon.PrlctlVersionConfig `mapstructure:",squash"`
|
|
||||||
|
|
||||||
BootCommand []string `mapstructure:"boot_command"`
|
BootCommand []string `mapstructure:"boot_command"`
|
||||||
ParallelsToolsMode string `mapstructure:"parallels_tools_mode"`
|
|
||||||
ParallelsToolsGuestPath string `mapstructure:"parallels_tools_guest_path"`
|
|
||||||
ParallelsToolsHostPath string `mapstructure:"parallels_tools_host_path"`
|
|
||||||
SourcePath string `mapstructure:"source_path"`
|
SourcePath string `mapstructure:"source_path"`
|
||||||
VMName string `mapstructure:"vm_name"`
|
VMName string `mapstructure:"vm_name"`
|
||||||
|
|
||||||
|
@ -42,19 +40,6 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
||||||
}
|
}
|
||||||
c.tpl.UserVars = c.PackerUserVars
|
c.tpl.UserVars = c.PackerUserVars
|
||||||
|
|
||||||
// Defaults
|
|
||||||
if c.ParallelsToolsMode == "" {
|
|
||||||
c.ParallelsToolsMode = "disable"
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.ParallelsToolsGuestPath == "" {
|
|
||||||
c.ParallelsToolsGuestPath = "prl-tools.iso"
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.ParallelsToolsHostPath == "" {
|
|
||||||
c.ParallelsToolsHostPath = "/Applications/Parallels Desktop.app/Contents/Resources/Tools/prl-tools-other.iso"
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.VMName == "" {
|
if c.VMName == "" {
|
||||||
c.VMName = fmt.Sprintf("packer-%s-{{timestamp}}", c.PackerBuildName)
|
c.VMName = fmt.Sprintf("packer-%s-{{timestamp}}", c.PackerBuildName)
|
||||||
}
|
}
|
||||||
|
@ -63,16 +48,14 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
||||||
errs := common.CheckUnusedConfig(md)
|
errs := common.CheckUnusedConfig(md)
|
||||||
errs = packer.MultiErrorAppend(errs, c.FloppyConfig.Prepare(c.tpl)...)
|
errs = packer.MultiErrorAppend(errs, c.FloppyConfig.Prepare(c.tpl)...)
|
||||||
errs = packer.MultiErrorAppend(errs, c.OutputConfig.Prepare(c.tpl, &c.PackerConfig)...)
|
errs = packer.MultiErrorAppend(errs, c.OutputConfig.Prepare(c.tpl, &c.PackerConfig)...)
|
||||||
|
errs = packer.MultiErrorAppend(errs, c.PrlctlConfig.Prepare(c.tpl)...)
|
||||||
|
errs = packer.MultiErrorAppend(errs, c.PrlctlVersionConfig.Prepare(c.tpl)...)
|
||||||
errs = packer.MultiErrorAppend(errs, c.RunConfig.Prepare(c.tpl)...)
|
errs = packer.MultiErrorAppend(errs, c.RunConfig.Prepare(c.tpl)...)
|
||||||
errs = packer.MultiErrorAppend(errs, c.ShutdownConfig.Prepare(c.tpl)...)
|
errs = packer.MultiErrorAppend(errs, c.ShutdownConfig.Prepare(c.tpl)...)
|
||||||
errs = packer.MultiErrorAppend(errs, c.SSHConfig.Prepare(c.tpl)...)
|
errs = packer.MultiErrorAppend(errs, c.SSHConfig.Prepare(c.tpl)...)
|
||||||
errs = packer.MultiErrorAppend(errs, c.PrlctlConfig.Prepare(c.tpl)...)
|
errs = packer.MultiErrorAppend(errs, c.ToolsConfig.Prepare(c.tpl)...)
|
||||||
errs = packer.MultiErrorAppend(errs, c.PrlctlVersionConfig.Prepare(c.tpl)...)
|
|
||||||
|
|
||||||
templates := map[string]*string{
|
templates := map[string]*string{
|
||||||
"parallels_tools_mode": &c.ParallelsToolsMode,
|
|
||||||
"parallels_tools_host_paht": &c.ParallelsToolsHostPath,
|
|
||||||
"parallels_tools_guest_path": &c.ParallelsToolsGuestPath,
|
|
||||||
"source_path": &c.SourcePath,
|
"source_path": &c.SourcePath,
|
||||||
"vm_name": &c.VMName,
|
"vm_name": &c.VMName,
|
||||||
}
|
}
|
||||||
|
@ -93,25 +76,6 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
validMode := false
|
|
||||||
validModes := []string{
|
|
||||||
parallelscommon.ParallelsToolsModeDisable,
|
|
||||||
parallelscommon.ParallelsToolsModeAttach,
|
|
||||||
parallelscommon.ParallelsToolsModeUpload,
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, mode := range validModes {
|
|
||||||
if c.ParallelsToolsMode == mode {
|
|
||||||
validMode = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !validMode {
|
|
||||||
errs = packer.MultiErrorAppend(errs,
|
|
||||||
fmt.Errorf("parallels_tools_mode is invalid. Must be one of: %v", validModes))
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.SourcePath == "" {
|
if c.SourcePath == "" {
|
||||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("source_path is required"))
|
errs = packer.MultiErrorAppend(errs, fmt.Errorf("source_path is required"))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -10,6 +10,7 @@ func testConfig(t *testing.T) map[string]interface{} {
|
||||||
return map[string]interface{}{
|
return map[string]interface{}{
|
||||||
"ssh_username": "foo",
|
"ssh_username": "foo",
|
||||||
"shutdown_command": "foo",
|
"shutdown_command": "foo",
|
||||||
|
"parallels_tools_flavor": "lin",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,10 +26,11 @@ Ubuntu to self-install. Still, the example serves to show the basic configuratio
|
||||||
<pre class="prettyprint">
|
<pre class="prettyprint">
|
||||||
{
|
{
|
||||||
"type": "parallels-iso",
|
"type": "parallels-iso",
|
||||||
"guest_os_type": "Ubuntu_64",
|
"guest_os_type": "ubuntu",
|
||||||
"iso_url": "http://releases.ubuntu.com/12.04/ubuntu-12.04.3-server-amd64.iso",
|
"iso_url": "http://releases.ubuntu.com/12.04/ubuntu-12.04.3-server-amd64.iso",
|
||||||
"iso_checksum": "2cbe868812a871242cdcdd8f2fd6feb9",
|
"iso_checksum": "2cbe868812a871242cdcdd8f2fd6feb9",
|
||||||
"iso_checksum_type": "md5",
|
"iso_checksum_type": "md5",
|
||||||
|
"parallels_tools_flavor": "lin"
|
||||||
"ssh_username": "packer",
|
"ssh_username": "packer",
|
||||||
"ssh_password": "packer",
|
"ssh_password": "packer",
|
||||||
"ssh_wait_timeout": "30s",
|
"ssh_wait_timeout": "30s",
|
||||||
|
@ -68,6 +69,10 @@ each category, the available options are alphabetized and described.
|
||||||
* `ssh_username` (string) - The username to use to SSH into the machine
|
* `ssh_username` (string) - The username to use to SSH into the machine
|
||||||
once the OS is installed.
|
once the OS is installed.
|
||||||
|
|
||||||
|
* `parallels_tools_flavor` (string) - The flavor of the Parallels Tools ISO to
|
||||||
|
install into the VM. Valid values are "win", "lin", "mac", "os2" and "other".
|
||||||
|
This can be ommited only if `parallels_tools_mode` is "disable".
|
||||||
|
|
||||||
### Optional:
|
### Optional:
|
||||||
|
|
||||||
* `boot_command` (array of strings) - This is an array of commands to type
|
* `boot_command` (array of strings) - This is an array of commands to type
|
||||||
|
@ -96,17 +101,10 @@ each category, the available options are alphabetized and described.
|
||||||
characters (*, ?, and []) are allowed. Directory names are also allowed,
|
characters (*, ?, and []) are allowed. Directory names are also allowed,
|
||||||
which will add all the files found in the directory to the floppy.
|
which will add all the files found in the directory to the floppy.
|
||||||
|
|
||||||
* `guest_os_distribution` (string) - The guest OS distribution being
|
|
||||||
installed. By default this is "other", but you can get dramatic
|
|
||||||
performance improvements by setting this to the proper value. To
|
|
||||||
view all available values for this run `prlctl create x --distribution list`.
|
|
||||||
Setting the correct value hints to Parallels how to optimize the virtual
|
|
||||||
hardware to work best with that operating system.
|
|
||||||
|
|
||||||
* `guest_os_type` (string) - The guest OS type being installed. By default
|
* `guest_os_type` (string) - The guest OS type being installed. By default
|
||||||
this is "other", but you can get _dramatic_ performance improvements by
|
this is "other", but you can get _dramatic_ performance improvements by
|
||||||
setting this to the proper value. To view all available values for this
|
setting this to the proper value. To view all available values for this
|
||||||
run `prlctl create x --ostype list`. Setting the correct value hints to
|
run `prlctl create x --distribution list`. Setting the correct value hints to
|
||||||
Parallels Desktop how to optimize the virtual hardware to work best with
|
Parallels Desktop how to optimize the virtual hardware to work best with
|
||||||
that operating system.
|
that operating system.
|
||||||
|
|
||||||
|
@ -148,18 +146,14 @@ each category, the available options are alphabetized and described.
|
||||||
By default this is "output-BUILDNAME" where "BUILDNAME" is the name
|
By default this is "output-BUILDNAME" where "BUILDNAME" is the name
|
||||||
of the build.
|
of the build.
|
||||||
|
|
||||||
* `parallels_tools_guest_path` (string) - The path on the guest virtual machine
|
* `parallels_tools_guest_path` (string) - The path in the VM to upload Parallels
|
||||||
where the Parallels tools ISO will be uploaded. By default this is
|
Tools. This only takes effect if `parallels_tools_mode` is not "disable".
|
||||||
"prl-tools.iso" which should upload into the login directory of the user.
|
This is a [configuration template](/docs/templates/configuration-templates.html)
|
||||||
This is a configuration template where the `Version` variable is replaced
|
that has a single valid variable: `Flavor`, which will be the value of
|
||||||
with the prlctl version.
|
`parallels_tools_flavor`. By default the upload path is set to
|
||||||
|
`prl-tools-{{.Flavor}}.iso`.
|
||||||
|
|
||||||
* `parallels_tools_host_path` (string) - The path to the Parallels Tools ISO to
|
* `parallels_tools_mode` (string) - The method by which Parallels Tools are
|
||||||
upload. By default the Parallels builder will use the "other" OS tools ISO from
|
|
||||||
the Parallels installation:
|
|
||||||
"/Applications/Parallels Desktop.app/Contents/Resources/Tools/prl-tools-other.iso"
|
|
||||||
|
|
||||||
* `parallels_tools_mode` (string) - The method by which Parallels tools are
|
|
||||||
made available to the guest for installation. Valid options are "upload",
|
made available to the guest for installation. Valid options are "upload",
|
||||||
"attach", or "disable". The functions of each of these should be
|
"attach", or "disable". The functions of each of these should be
|
||||||
self-explanatory. The default value is "upload".
|
self-explanatory. The default value is "upload".
|
||||||
|
@ -260,20 +254,12 @@ an Ubuntu 12.04 installer:
|
||||||
]
|
]
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
## Parallels Tools
|
|
||||||
After the virtual machine is up and the operating system is installed, Packer
|
|
||||||
uploads the Parallels Tools into the virtual machine. The path where they are
|
|
||||||
uploaded is controllable by `parallels_tools_path`, and defaults to
|
|
||||||
"prl-tools.iso". Without an absolute path, it is uploaded to the home directory
|
|
||||||
of the SSH user. Parallels Tools ISO's can be found in:
|
|
||||||
"/Applications/Parallels Desktop.app/Contents/Resources/Tools/"
|
|
||||||
|
|
||||||
## prlctl Commands
|
## prlctl Commands
|
||||||
In order to perform extra customization of the virtual machine, a template can
|
In order to perform extra customization of the virtual machine, a template can
|
||||||
define extra calls to `prlctl` to perform.
|
define extra calls to `prlctl` to perform.
|
||||||
[prlctl](http://download.parallels.com/desktop/v4/wl/docs/en/Parallels_Command_Line_Reference_Guide/)
|
[prlctl](http://download.parallels.com/desktop/v9/ga/docs/en_US/Parallels%20Command%20Line%20Reference%20Guide.pdf)
|
||||||
is the command-line interface to Parallels. It can be used to do things such as
|
is the command-line interface to Parallels Desktop. It can be used to configure
|
||||||
set RAM, CPUs, etc.
|
the virtual machine, such as set RAM, CPUs, etc.
|
||||||
|
|
||||||
Extra `prlctl` commands are defined in the template in the `prlctl` section.
|
Extra `prlctl` commands are defined in the template in the `prlctl` section.
|
||||||
An example is shown below that sets the memory and number of CPUs within the
|
An example is shown below that sets the memory and number of CPUs within the
|
||||||
|
|
|
@ -25,6 +25,7 @@ the settings here.
|
||||||
<pre class="prettyprint">
|
<pre class="prettyprint">
|
||||||
{
|
{
|
||||||
"type": "parallels-pvm",
|
"type": "parallels-pvm",
|
||||||
|
"parallels_tools_flavor": "lin"
|
||||||
"source_path": "source.pvm",
|
"source_path": "source.pvm",
|
||||||
"ssh_username": "packer",
|
"ssh_username": "packer",
|
||||||
"ssh_password": "packer",
|
"ssh_password": "packer",
|
||||||
|
@ -51,6 +52,10 @@ each category, the available options are alphabetized and described.
|
||||||
* `ssh_username` (string) - The username to use to SSH into the machine
|
* `ssh_username` (string) - The username to use to SSH into the machine
|
||||||
once the OS is installed.
|
once the OS is installed.
|
||||||
|
|
||||||
|
* `parallels_tools_flavor` (string) - The flavor of the Parallels Tools ISO to
|
||||||
|
install into the VM. Valid values are "win", "lin", "mac", "os2" and "other".
|
||||||
|
This can be ommited only if `parallels_tools_mode` is "disable".
|
||||||
|
|
||||||
### Optional:
|
### Optional:
|
||||||
|
|
||||||
* `boot_command` (array of strings) - This is an array of commands to type
|
* `boot_command` (array of strings) - This is an array of commands to type
|
||||||
|
@ -80,18 +85,14 @@ each category, the available options are alphabetized and described.
|
||||||
By default this is "output-BUILDNAME" where "BUILDNAME" is the name
|
By default this is "output-BUILDNAME" where "BUILDNAME" is the name
|
||||||
of the build.
|
of the build.
|
||||||
|
|
||||||
* `parallels_tools_guest_path` (string) - The path on the guest virtual machine
|
* `parallels_tools_guest_path` (string) - The path in the VM to upload Parallels
|
||||||
where the Parallels tools ISO will be uploaded. By default this is
|
Tools. This only takes effect if `parallels_tools_mode` is not "disable".
|
||||||
"prl-tools.iso" which should upload into the login directory of the user.
|
This is a [configuration template](/docs/templates/configuration-templates.html)
|
||||||
This is a configuration template where the `Version` variable is replaced
|
that has a single valid variable: `Flavor`, which will be the value of
|
||||||
with the prlctl version.
|
`parallels_tools_flavor`. By default the upload path is set to
|
||||||
|
`prl-tools-{{.Flavor}}.iso`.
|
||||||
|
|
||||||
* `parallels_tools_host_path` (string) - The path to the Parallels Tools ISO to
|
* `parallels_tools_mode` (string) - The method by which Parallels Tools are
|
||||||
upload. By default the Parallels builder will use the "other" OS tools ISO from
|
|
||||||
the Parallels installation:
|
|
||||||
"/Applications/Parallels Desktop.app/Contents/Resources/Tools/prl-tools-other.iso"
|
|
||||||
|
|
||||||
* `parallels_tools_mode` (string) - The method by which Parallels tools are
|
|
||||||
made available to the guest for installation. Valid options are "upload",
|
made available to the guest for installation. Valid options are "upload",
|
||||||
"attach", or "disable". The functions of each of these should be
|
"attach", or "disable". The functions of each of these should be
|
||||||
self-explanatory. The default value is "upload".
|
self-explanatory. The default value is "upload".
|
||||||
|
@ -179,9 +180,9 @@ The available variables are:
|
||||||
## prlctl Commands
|
## prlctl Commands
|
||||||
In order to perform extra customization of the virtual machine, a template can
|
In order to perform extra customization of the virtual machine, a template can
|
||||||
define extra calls to `prlctl` to perform.
|
define extra calls to `prlctl` to perform.
|
||||||
[prlctl](http://download.parallels.com/desktop/v4/wl/docs/en/Parallels_Command_Line_Reference_Guide/)
|
[prlctl](http://download.parallels.com/desktop/v9/ga/docs/en_US/Parallels%20Command%20Line%20Reference%20Guide.pdf)
|
||||||
is the command-line interface to Parallels. It can be used to do things such as
|
is the command-line interface to Parallels Desktop. It can be used to configure
|
||||||
set RAM, CPUs, etc.
|
the virtual machine, such as set RAM, CPUs, etc.
|
||||||
|
|
||||||
Extra `prlctl` commands are defined in the template in the `prlctl` section.
|
Extra `prlctl` commands are defined in the template in the `prlctl` section.
|
||||||
An example is shown below that sets the memory and number of CPUs within the
|
An example is shown below that sets the memory and number of CPUs within the
|
||||||
|
|
Loading…
Reference in New Issue