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(...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
|
||||
// properly. If there is any indication the driver can't function,
|
||||
// this will return an error.
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -73,16 +74,21 @@ func getConfigValueFromXpath(path, xpath string) (string, error) {
|
|||
|
||||
// Finds an application bundle by identifier (for "darwin" platform only)
|
||||
func getAppPath(bundleId string) (string, error) {
|
||||
var stdout bytes.Buffer
|
||||
|
||||
cmd := exec.Command("mdfind", "kMDItemCFBundleIdentifier ==", bundleId)
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
cmd.Stdout = &stdout
|
||||
if err := cmd.Run(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if string(out) == "" {
|
||||
|
||||
pathOutput := strings.TrimSpace(stdout.String())
|
||||
if pathOutput == "" {
|
||||
return "", fmt.Errorf(
|
||||
"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) {
|
||||
|
@ -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)
|
||||
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
|
||||
SendKeyScanCodesErrs []error
|
||||
|
||||
ToolsIsoPathCalled bool
|
||||
ToolsIsoPathFlavor string
|
||||
ToolsIsoPathResult string
|
||||
ToolsIsoPathErr error
|
||||
|
||||
MacName string
|
||||
MacReturn string
|
||||
MacError error
|
||||
|
@ -98,3 +103,9 @@ func (d *DriverMock) IpAddress(mac string) (string, error) {
|
|||
d.IpAddressMac = mac
|
||||
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,19 +7,19 @@ import (
|
|||
"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.
|
||||
//
|
||||
// Uses:
|
||||
// driver Driver
|
||||
// toolsPath string
|
||||
// parallels_tools_path string
|
||||
// ui packer.Ui
|
||||
// vmName string
|
||||
//
|
||||
// Produces:
|
||||
// attachedToolsIso boolean
|
||||
type StepAttachParallelsTools struct {
|
||||
ParallelsToolsHostPath string
|
||||
ParallelsToolsMode string
|
||||
ParallelsToolsMode string
|
||||
}
|
||||
|
||||
func (s *StepAttachParallelsTools) Run(state multistep.StateBag) multistep.StepAction {
|
||||
|
@ -33,12 +33,15 @@ func (s *StepAttachParallelsTools) Run(state multistep.StateBag) multistep.StepA
|
|||
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
|
||||
ui.Say("Attaching Parallels Tools ISO onto IDE controller...")
|
||||
command := []string{
|
||||
"set", vmName,
|
||||
"--device-add", "cdrom",
|
||||
"--image", s.ParallelsToolsHostPath,
|
||||
"--image", parallelsToolsPath,
|
||||
}
|
||||
if err := driver.Prlctl(command...); err != nil {
|
||||
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)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
vmName := state.Get("vmName").(string)
|
||||
|
||||
log.Println("Detaching Parallels Tools ISO...")
|
||||
|
@ -71,5 +75,8 @@ func (s *StepAttachParallelsTools) Cleanup(state multistep.StateBag) {
|
|||
"set", vmName,
|
||||
"--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"
|
||||
)
|
||||
|
||||
// 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 {
|
||||
Version string
|
||||
Flavor string
|
||||
}
|
||||
|
||||
// This step uploads the guest additions ISO to the VM.
|
||||
type StepUploadParallelsTools struct {
|
||||
ParallelsToolsHostPath string
|
||||
ParallelsToolsFlavor string
|
||||
ParallelsToolsGuestPath string
|
||||
ParallelsToolsMode string
|
||||
Tpl *packer.ConfigTemplate
|
||||
|
@ -22,7 +30,6 @@ type StepUploadParallelsTools struct {
|
|||
|
||||
func (s *StepUploadParallelsTools) Run(state multistep.StateBag) multistep.StepAction {
|
||||
comm := state.Get("communicator").(packer.Communicator)
|
||||
driver := state.Get("driver").(Driver)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
version, err := driver.Version()
|
||||
if err != nil {
|
||||
state.Put("error", fmt.Errorf("Error reading version for Parallels Tools upload: %s", err))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
// Get the Paralells Tools path on the host machine
|
||||
parallelsToolsPath := state.Get("parallels_tools_path").(string)
|
||||
|
||||
f, err := os.Open(s.ParallelsToolsHostPath)
|
||||
f, err := os.Open(parallelsToolsPath)
|
||||
if err != nil {
|
||||
state.Put("error", fmt.Errorf("Error opening Parallels Tools ISO: %s", err))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
tplData := &toolsPathTemplate{
|
||||
Version: version,
|
||||
Flavor: s.ParallelsToolsFlavor,
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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 {
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -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,32 +22,31 @@ type config struct {
|
|||
common.PackerConfig `mapstructure:",squash"`
|
||||
parallelscommon.FloppyConfig `mapstructure:",squash"`
|
||||
parallelscommon.OutputConfig `mapstructure:",squash"`
|
||||
parallelscommon.PrlctlConfig `mapstructure:",squash"`
|
||||
parallelscommon.PrlctlVersionConfig `mapstructure:",squash"`
|
||||
parallelscommon.RunConfig `mapstructure:",squash"`
|
||||
parallelscommon.ShutdownConfig `mapstructure:",squash"`
|
||||
parallelscommon.SSHConfig `mapstructure:",squash"`
|
||||
parallelscommon.PrlctlConfig `mapstructure:",squash"`
|
||||
parallelscommon.PrlctlVersionConfig `mapstructure:",squash"`
|
||||
parallelscommon.ToolsConfig `mapstructure:",squash"`
|
||||
|
||||
BootCommand []string `mapstructure:"boot_command"`
|
||||
DiskSize uint `mapstructure:"disk_size"`
|
||||
ParallelsToolsMode string `mapstructure:"parallels_tools_mode"`
|
||||
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"`
|
||||
HostInterfaces []string `mapstructure:"host_interfaces"`
|
||||
HTTPDir string `mapstructure:"http_directory"`
|
||||
HTTPPortMin uint `mapstructure:"http_port_min"`
|
||||
HTTPPortMax uint `mapstructure:"http_port_max"`
|
||||
ISOChecksum string `mapstructure:"iso_checksum"`
|
||||
ISOChecksumType string `mapstructure:"iso_checksum_type"`
|
||||
ISOUrls []string `mapstructure:"iso_urls"`
|
||||
VMName string `mapstructure:"vm_name"`
|
||||
BootCommand []string `mapstructure:"boot_command"`
|
||||
DiskSize uint `mapstructure:"disk_size"`
|
||||
GuestOSType string `mapstructure:"guest_os_type"`
|
||||
HardDriveInterface string `mapstructure:"hard_drive_interface"`
|
||||
HostInterfaces []string `mapstructure:"host_interfaces"`
|
||||
HTTPDir string `mapstructure:"http_directory"`
|
||||
HTTPPortMin uint `mapstructure:"http_port_min"`
|
||||
HTTPPortMax uint `mapstructure:"http_port_max"`
|
||||
ISOChecksum string `mapstructure:"iso_checksum"`
|
||||
ISOChecksumType string `mapstructure:"iso_checksum_type"`
|
||||
ISOUrls []string `mapstructure:"iso_urls"`
|
||||
VMName string `mapstructure:"vm_name"`
|
||||
|
||||
RawSingleISOUrl string `mapstructure:"iso_url"`
|
||||
|
||||
// Deprecated parameters
|
||||
GuestOSType string `mapstructure:"guest_os_type"`
|
||||
GuestOSDistribution string `mapstructure:"guest_os_distribution"`
|
||||
ParallelsToolsHostPath string `mapstructure:"parallels_tools_host_path"`
|
||||
|
||||
tpl *packer.ConfigTemplate
|
||||
}
|
||||
|
@ -71,34 +70,33 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
|
|||
errs = packer.MultiErrorAppend(
|
||||
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.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.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)
|
||||
|
||||
if b.config.DiskSize == 0 {
|
||||
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 == "" {
|
||||
b.config.HardDriveInterface = "sata"
|
||||
}
|
||||
|
||||
if b.config.GuestOSDistribution == "" {
|
||||
b.config.GuestOSDistribution = "other"
|
||||
if b.config.GuestOSType == "" {
|
||||
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 {
|
||||
|
@ -120,16 +118,13 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
|
|||
|
||||
// Errors
|
||||
templates := map[string]*string{
|
||||
"parallels_tools_mode": &b.config.ParallelsToolsMode,
|
||||
"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,
|
||||
"http_directory": &b.config.HTTPDir,
|
||||
"iso_checksum": &b.config.ISOChecksum,
|
||||
"iso_checksum_type": &b.config.ISOChecksumType,
|
||||
"iso_url": &b.config.RawSingleISOUrl,
|
||||
"vm_name": &b.config.VMName,
|
||||
"guest_os_type": &b.config.GuestOSType,
|
||||
"hard_drive_interface": &b.config.HardDriveInterface,
|
||||
"http_directory": &b.config.HTTPDir,
|
||||
"iso_checksum": &b.config.ISOChecksum,
|
||||
"iso_checksum_type": &b.config.ISOChecksumType,
|
||||
"iso_url": &b.config.RawSingleISOUrl,
|
||||
"vm_name": &b.config.VMName,
|
||||
}
|
||||
|
||||
for n, ptr := range templates {
|
||||
|
@ -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 {
|
||||
if err := b.config.tpl.Validate(command); err != nil {
|
||||
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
|
||||
if b.config.ISOChecksumType == "none" {
|
||||
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.")
|
||||
}
|
||||
|
||||
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 {
|
||||
return warnings, errs
|
||||
}
|
||||
|
@ -264,6 +235,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
}
|
||||
|
||||
steps := []multistep.Step{
|
||||
¶llelscommon.StepPrepareParallelsTools{
|
||||
ParallelsToolsFlavor: b.config.ParallelsToolsFlavor,
|
||||
ParallelsToolsMode: b.config.ParallelsToolsMode,
|
||||
},
|
||||
&common.StepDownload{
|
||||
Checksum: b.config.ISOChecksum,
|
||||
ChecksumType: b.config.ISOChecksumType,
|
||||
|
@ -283,8 +258,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
new(stepCreateDisk),
|
||||
new(stepAttachISO),
|
||||
¶llelscommon.StepAttachParallelsTools{
|
||||
ParallelsToolsHostPath: b.config.ParallelsToolsHostPath,
|
||||
ParallelsToolsMode: b.config.ParallelsToolsMode,
|
||||
ParallelsToolsMode: b.config.ParallelsToolsMode,
|
||||
},
|
||||
new(parallelscommon.StepAttachFloppy),
|
||||
¶llelscommon.StepPrlctl{
|
||||
|
@ -310,8 +284,8 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
Path: b.config.PrlctlVersionFile,
|
||||
},
|
||||
¶llelscommon.StepUploadParallelsTools{
|
||||
ParallelsToolsFlavor: b.config.ParallelsToolsFlavor,
|
||||
ParallelsToolsGuestPath: b.config.ParallelsToolsGuestPath,
|
||||
ParallelsToolsHostPath: b.config.ParallelsToolsHostPath,
|
||||
ParallelsToolsMode: b.config.ParallelsToolsMode,
|
||||
Tpl: b.config.tpl,
|
||||
},
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package iso
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/packer/builder/parallels/common"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
@ -9,11 +8,12 @@ import (
|
|||
|
||||
func testConfig() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"iso_checksum": "foo",
|
||||
"iso_checksum_type": "md5",
|
||||
"iso_url": "http://www.google.com/",
|
||||
"shutdown_command": "yes",
|
||||
"ssh_username": "foo",
|
||||
"iso_checksum": "foo",
|
||||
"iso_checksum_type": "md5",
|
||||
"iso_url": "http://www.google.com/",
|
||||
"shutdown_command": "yes",
|
||||
"ssh_username": "foo",
|
||||
"parallels_tools_flavor": "lin",
|
||||
|
||||
packer.BuildNameConfigKey: "foo",
|
||||
}
|
||||
|
@ -38,12 +38,8 @@ func TestBuilderPrepare_Defaults(t *testing.T) {
|
|||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
if b.config.ParallelsToolsMode != common.ParallelsToolsModeUpload {
|
||||
t.Errorf("bad parallels tools mode: %s", b.config.ParallelsToolsMode)
|
||||
}
|
||||
|
||||
if b.config.GuestOSDistribution != "other" {
|
||||
t.Errorf("bad guest OS distribution: %s", b.config.GuestOSDistribution)
|
||||
if b.config.GuestOSType != "other" {
|
||||
t.Errorf("bad guest OS type: %s", b.config.GuestOSType)
|
||||
}
|
||||
|
||||
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
|
||||
config := testConfig()
|
||||
delete(config, "guest_os_distribution")
|
||||
|
||||
// test default mode
|
||||
delete(config, "parallels_tools_mode")
|
||||
// Test deprecated parameter
|
||||
config["guest_os_distribution"] = "bolgenos"
|
||||
warns, err := b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
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 len(warns) == 0 {
|
||||
t.Fatalf("should have warning")
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
if b.config.ParallelsToolsMode != common.ParallelsToolsModeAttach {
|
||||
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)
|
||||
if b.config.GuestOSType != "bolgenos" {
|
||||
t.Fatalf("bad: %s", b.config.GuestOSType)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -434,3 +348,19 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) {
|
|||
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[0] = []string{
|
||||
"create", name,
|
||||
"--distribution", config.GuestOSDistribution,
|
||||
"--distribution", config.GuestOSType,
|
||||
"--dst", path,
|
||||
"--vmtype", "vm",
|
||||
}
|
||||
|
|
|
@ -47,6 +47,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
|
||||
// Build the steps.
|
||||
steps := []multistep.Step{
|
||||
¶llelscommon.StepPrepareParallelsTools{
|
||||
ParallelsToolsMode: b.config.ParallelsToolsMode,
|
||||
ParallelsToolsFlavor: b.config.ParallelsToolsFlavor,
|
||||
},
|
||||
¶llelscommon.StepOutputDir{
|
||||
Force: b.config.PackerForce,
|
||||
Path: b.config.OutputDir,
|
||||
|
@ -59,8 +63,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
SourcePath: b.config.SourcePath,
|
||||
},
|
||||
¶llelscommon.StepAttachParallelsTools{
|
||||
ParallelsToolsHostPath: b.config.ParallelsToolsHostPath,
|
||||
ParallelsToolsMode: b.config.ParallelsToolsMode,
|
||||
ParallelsToolsMode: b.config.ParallelsToolsMode,
|
||||
},
|
||||
new(parallelscommon.StepAttachFloppy),
|
||||
¶llelscommon.StepPrlctl{
|
||||
|
@ -86,8 +89,8 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
Path: b.config.PrlctlVersionFile,
|
||||
},
|
||||
¶llelscommon.StepUploadParallelsTools{
|
||||
ParallelsToolsFlavor: b.config.ParallelsToolsFlavor,
|
||||
ParallelsToolsGuestPath: b.config.ParallelsToolsGuestPath,
|
||||
ParallelsToolsHostPath: b.config.ParallelsToolsHostPath,
|
||||
ParallelsToolsMode: b.config.ParallelsToolsMode,
|
||||
Tpl: b.config.tpl,
|
||||
},
|
||||
|
|
|
@ -13,18 +13,16 @@ type Config struct {
|
|||
common.PackerConfig `mapstructure:",squash"`
|
||||
parallelscommon.FloppyConfig `mapstructure:",squash"`
|
||||
parallelscommon.OutputConfig `mapstructure:",squash"`
|
||||
parallelscommon.PrlctlConfig `mapstructure:",squash"`
|
||||
parallelscommon.PrlctlVersionConfig `mapstructure:",squash"`
|
||||
parallelscommon.RunConfig `mapstructure:",squash"`
|
||||
parallelscommon.SSHConfig `mapstructure:",squash"`
|
||||
parallelscommon.ShutdownConfig `mapstructure:",squash"`
|
||||
parallelscommon.PrlctlConfig `mapstructure:",squash"`
|
||||
parallelscommon.PrlctlVersionConfig `mapstructure:",squash"`
|
||||
parallelscommon.ToolsConfig `mapstructure:",squash"`
|
||||
|
||||
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"`
|
||||
VMName string `mapstructure:"vm_name"`
|
||||
BootCommand []string `mapstructure:"boot_command"`
|
||||
SourcePath string `mapstructure:"source_path"`
|
||||
VMName string `mapstructure:"vm_name"`
|
||||
|
||||
tpl *packer.ConfigTemplate
|
||||
}
|
||||
|
@ -42,19 +40,6 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
|||
}
|
||||
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 == "" {
|
||||
c.VMName = fmt.Sprintf("packer-%s-{{timestamp}}", c.PackerBuildName)
|
||||
}
|
||||
|
@ -63,18 +48,16 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
|||
errs := common.CheckUnusedConfig(md)
|
||||
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.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.ShutdownConfig.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.PrlctlVersionConfig.Prepare(c.tpl)...)
|
||||
errs = packer.MultiErrorAppend(errs, c.ToolsConfig.Prepare(c.tpl)...)
|
||||
|
||||
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,
|
||||
"vm_name": &c.VMName,
|
||||
"source_path": &c.SourcePath,
|
||||
"vm_name": &c.VMName,
|
||||
}
|
||||
|
||||
for n, ptr := range templates {
|
||||
|
@ -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 == "" {
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("source_path is required"))
|
||||
} else {
|
||||
|
|
|
@ -8,8 +8,9 @@ import (
|
|||
|
||||
func testConfig(t *testing.T) map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"ssh_username": "foo",
|
||||
"shutdown_command": "foo",
|
||||
"ssh_username": "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">
|
||||
{
|
||||
"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_checksum": "2cbe868812a871242cdcdd8f2fd6feb9",
|
||||
"iso_checksum_type": "md5",
|
||||
"parallels_tools_flavor": "lin"
|
||||
"ssh_username": "packer",
|
||||
"ssh_password": "packer",
|
||||
"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
|
||||
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:
|
||||
|
||||
* `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,
|
||||
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
|
||||
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 --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
|
||||
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
|
||||
of the build.
|
||||
|
||||
* `parallels_tools_guest_path` (string) - The path on the guest virtual machine
|
||||
where the Parallels tools ISO will be uploaded. By default this is
|
||||
"prl-tools.iso" which should upload into the login directory of the user.
|
||||
This is a configuration template where the `Version` variable is replaced
|
||||
with the prlctl version.
|
||||
* `parallels_tools_guest_path` (string) - The path in the VM to upload Parallels
|
||||
Tools. This only takes effect if `parallels_tools_mode` is not "disable".
|
||||
This is a [configuration template](/docs/templates/configuration-templates.html)
|
||||
that has a single valid variable: `Flavor`, which will be the value of
|
||||
`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
|
||||
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
|
||||
* `parallels_tools_mode` (string) - The method by which Parallels Tools are
|
||||
made available to the guest for installation. Valid options are "upload",
|
||||
"attach", or "disable". The functions of each of these should be
|
||||
self-explanatory. The default value is "upload".
|
||||
|
@ -260,20 +254,12 @@ an Ubuntu 12.04 installer:
|
|||
]
|
||||
</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
|
||||
In order to perform extra customization of the virtual machine, a template can
|
||||
define extra calls to `prlctl` to perform.
|
||||
[prlctl](http://download.parallels.com/desktop/v4/wl/docs/en/Parallels_Command_Line_Reference_Guide/)
|
||||
is the command-line interface to Parallels. It can be used to do things such as
|
||||
set RAM, CPUs, etc.
|
||||
[prlctl](http://download.parallels.com/desktop/v9/ga/docs/en_US/Parallels%20Command%20Line%20Reference%20Guide.pdf)
|
||||
is the command-line interface to Parallels Desktop. It can be used to configure
|
||||
the virtual machine, such as set RAM, CPUs, etc.
|
||||
|
||||
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
|
||||
|
|
|
@ -25,6 +25,7 @@ the settings here.
|
|||
<pre class="prettyprint">
|
||||
{
|
||||
"type": "parallels-pvm",
|
||||
"parallels_tools_flavor": "lin"
|
||||
"source_path": "source.pvm",
|
||||
"ssh_username": "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
|
||||
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:
|
||||
|
||||
* `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
|
||||
of the build.
|
||||
|
||||
* `parallels_tools_guest_path` (string) - The path on the guest virtual machine
|
||||
where the Parallels tools ISO will be uploaded. By default this is
|
||||
"prl-tools.iso" which should upload into the login directory of the user.
|
||||
This is a configuration template where the `Version` variable is replaced
|
||||
with the prlctl version.
|
||||
* `parallels_tools_guest_path` (string) - The path in the VM to upload Parallels
|
||||
Tools. This only takes effect if `parallels_tools_mode` is not "disable".
|
||||
This is a [configuration template](/docs/templates/configuration-templates.html)
|
||||
that has a single valid variable: `Flavor`, which will be the value of
|
||||
`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
|
||||
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
|
||||
* `parallels_tools_mode` (string) - The method by which Parallels Tools are
|
||||
made available to the guest for installation. Valid options are "upload",
|
||||
"attach", or "disable". The functions of each of these should be
|
||||
self-explanatory. The default value is "upload".
|
||||
|
@ -179,9 +180,9 @@ The available variables are:
|
|||
## prlctl Commands
|
||||
In order to perform extra customization of the virtual machine, a template can
|
||||
define extra calls to `prlctl` to perform.
|
||||
[prlctl](http://download.parallels.com/desktop/v4/wl/docs/en/Parallels_Command_Line_Reference_Guide/)
|
||||
is the command-line interface to Parallels. It can be used to do things such as
|
||||
set RAM, CPUs, etc.
|
||||
[prlctl](http://download.parallels.com/desktop/v9/ga/docs/en_US/Parallels%20Command%20Line%20Reference%20Guide.pdf)
|
||||
is the command-line interface to Parallels Desktop. It can be used to configure
|
||||
the virtual machine, such as set RAM, CPUs, etc.
|
||||
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue