Merge pull request #4292 from legal90/prl-fix-style
Parallels: Fix style warnings
This commit is contained in:
commit
bbe3f26ed2
|
@ -2,13 +2,14 @@ package common
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
||||
"github.com/mitchellh/packer/packer"
|
||||
)
|
||||
|
||||
// This is the common builder ID to all of these artifacts.
|
||||
// BuilderId is the common builder ID to all of these artifacts.
|
||||
const BuilderId = "packer.parallels"
|
||||
|
||||
// These are the extensions of files and directories that are unnecessary for the function
|
||||
|
|
|
@ -25,7 +25,7 @@ func TestNewArtifact(t *testing.T) {
|
|||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if err := os.Mkdir(filepath.Join(td, "b"), 0755); err != nil {
|
||||
if err = os.Mkdir(filepath.Join(td, "b"), 0755); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// A driver is able to talk to Parallels and perform certain
|
||||
// Driver is the interface that talks to Parallels and performs certain
|
||||
// operations with it. Some of the operations on here may seem overly
|
||||
// specific, but they were built specifically in mind to handle features
|
||||
// of the Parallels builder for Packer, and to abstract differences in
|
||||
|
@ -20,7 +20,7 @@ type Driver interface {
|
|||
CompactDisk(string) error
|
||||
|
||||
// Adds new CD/DVD drive to the VM and returns name of this device
|
||||
DeviceAddCdRom(string, string) (string, error)
|
||||
DeviceAddCDROM(string, string) (string, error)
|
||||
|
||||
// Get path to the first virtual disk image
|
||||
DiskPath(string) (string, error)
|
||||
|
@ -38,7 +38,7 @@ type Driver interface {
|
|||
Prlctl(...string) error
|
||||
|
||||
// Get the path to the Parallels Tools ISO for the given flavor.
|
||||
ToolsIsoPath(string) (string, error)
|
||||
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,
|
||||
|
@ -55,18 +55,20 @@ type Driver interface {
|
|||
SetDefaultConfiguration(string) error
|
||||
|
||||
// Finds the MAC address of the NIC nic0
|
||||
Mac(string) (string, error)
|
||||
MAC(string) (string, error)
|
||||
|
||||
// Finds the IP address of a VM connected that uses DHCP by its MAC address
|
||||
IpAddress(string) (string, error)
|
||||
IPAddress(string) (string, error)
|
||||
}
|
||||
|
||||
// NewDriver returns a new driver implementation for this version of Parallels
|
||||
// Desktop, or an error if the driver couldn't be initialized.
|
||||
func NewDriver() (Driver, error) {
|
||||
var drivers map[string]Driver
|
||||
var prlctlPath string
|
||||
var prlsrvctlPath string
|
||||
var supportedVersions []string
|
||||
dhcp_lease_file := "/Library/Preferences/Parallels/parallels_dhcp_leases"
|
||||
DHCPLeaseFile := "/Library/Preferences/Parallels/parallels_dhcp_leases"
|
||||
|
||||
if runtime.GOOS != "darwin" {
|
||||
return nil, fmt.Errorf(
|
||||
|
@ -96,22 +98,22 @@ func NewDriver() (Driver, error) {
|
|||
drivers = map[string]Driver{
|
||||
"11": &Parallels11Driver{
|
||||
Parallels9Driver: Parallels9Driver{
|
||||
PrlctlPath: prlctlPath,
|
||||
PrlsrvctlPath: prlsrvctlPath,
|
||||
dhcp_lease_file: dhcp_lease_file,
|
||||
PrlctlPath: prlctlPath,
|
||||
PrlsrvctlPath: prlsrvctlPath,
|
||||
dhcpLeaseFile: DHCPLeaseFile,
|
||||
},
|
||||
},
|
||||
"10": &Parallels10Driver{
|
||||
Parallels9Driver: Parallels9Driver{
|
||||
PrlctlPath: prlctlPath,
|
||||
PrlsrvctlPath: prlsrvctlPath,
|
||||
dhcp_lease_file: dhcp_lease_file,
|
||||
PrlctlPath: prlctlPath,
|
||||
PrlsrvctlPath: prlsrvctlPath,
|
||||
dhcpLeaseFile: DHCPLeaseFile,
|
||||
},
|
||||
},
|
||||
"9": &Parallels9Driver{
|
||||
PrlctlPath: prlctlPath,
|
||||
PrlsrvctlPath: prlsrvctlPath,
|
||||
dhcp_lease_file: dhcp_lease_file,
|
||||
PrlctlPath: prlctlPath,
|
||||
PrlsrvctlPath: prlsrvctlPath,
|
||||
dhcpLeaseFile: DHCPLeaseFile,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package common
|
||||
|
||||
// Parallels10Driver are inherited from Parallels9Driver.
|
||||
// Used for Parallels v 10 & 11
|
||||
type Parallels10Driver struct {
|
||||
Parallels9Driver
|
||||
}
|
||||
|
||||
// SetDefaultConfiguration applies pre-defined default settings to the VM config.
|
||||
func (d *Parallels10Driver) SetDefaultConfiguration(vmName string) error {
|
||||
commands := make([][]string, 12)
|
||||
commands[0] = []string{"set", vmName, "--cpus", "1"}
|
||||
|
|
|
@ -12,6 +12,7 @@ type Parallels11Driver struct {
|
|||
Parallels9Driver
|
||||
}
|
||||
|
||||
// Verify raises an error if the builder could not be used on that host machine.
|
||||
func (d *Parallels11Driver) Verify() error {
|
||||
|
||||
stdout, err := exec.Command(d.PrlsrvctlPath, "info", "--license").Output()
|
||||
|
@ -24,18 +25,18 @@ func (d *Parallels11Driver) Verify() error {
|
|||
if matches == nil {
|
||||
return fmt.Errorf(
|
||||
"Could not determine your Parallels Desktop edition using: %s info --license", d.PrlsrvctlPath)
|
||||
} else {
|
||||
switch matches[1] {
|
||||
case "pro", "business":
|
||||
break
|
||||
default:
|
||||
return fmt.Errorf("Packer can be used only with Parallels Desktop 11 Pro or Business edition. You use: %s edition", matches[1])
|
||||
}
|
||||
}
|
||||
switch matches[1] {
|
||||
case "pro", "business":
|
||||
break
|
||||
default:
|
||||
return fmt.Errorf("Packer can be used only with Parallels Desktop 11 Pro or Business edition. You use: %s edition", matches[1])
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetDefaultConfiguration applies pre-defined default settings to the VM config.
|
||||
func (d *Parallels11Driver) SetDefaultConfiguration(vmName string) error {
|
||||
commands := make([][]string, 12)
|
||||
commands[0] = []string{"set", vmName, "--cpus", "1"}
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
"gopkg.in/xmlpath.v2"
|
||||
)
|
||||
|
||||
// Parallels9Driver is a base type for Parallels builders.
|
||||
type Parallels9Driver struct {
|
||||
// This is the path to the "prlctl" application.
|
||||
PrlctlPath string
|
||||
|
@ -24,48 +25,51 @@ type Parallels9Driver struct {
|
|||
PrlsrvctlPath string
|
||||
|
||||
// The path to the parallels_dhcp_leases file
|
||||
dhcp_lease_file string
|
||||
dhcpLeaseFile string
|
||||
}
|
||||
|
||||
func (d *Parallels9Driver) Import(name, srcPath, dstDir string, reassignMac bool) error {
|
||||
|
||||
// Import creates a clone of the source VM and reassigns the MAC address if needed.
|
||||
func (d *Parallels9Driver) Import(name, srcPath, dstDir string, reassignMAC bool) error {
|
||||
err := d.Prlctl("register", srcPath, "--preserve-uuid")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
srcId, err := getVmId(srcPath)
|
||||
srcID, err := getVMID(srcPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
srcMac := "auto"
|
||||
if !reassignMac {
|
||||
srcMac, err = getFirtsMacAddress(srcPath)
|
||||
srcMAC := "auto"
|
||||
if !reassignMAC {
|
||||
srcMAC, err = getFirtsMACAddress(srcPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = d.Prlctl("clone", srcId, "--name", name, "--dst", dstDir)
|
||||
err = d.Prlctl("clone", srcID, "--name", name, "--dst", dstDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = d.Prlctl("unregister", srcId)
|
||||
err = d.Prlctl("unregister", srcID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = d.Prlctl("set", name, "--device-set", "net0", "--mac", srcMac)
|
||||
err = d.Prlctl("set", name, "--device-set", "net0", "--mac", srcMAC)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getVmId(path string) (string, error) {
|
||||
func getVMID(path string) (string, error) {
|
||||
return getConfigValueFromXpath(path, "/ParallelsVirtualMachine/Identification/VmUuid")
|
||||
}
|
||||
|
||||
func getFirtsMacAddress(path string) (string, error) {
|
||||
func getFirtsMACAddress(path string) (string, error) {
|
||||
return getConfigValueFromXpath(path, "/ParallelsVirtualMachine/Hardware/NetworkAdapter[@id='0']/MAC")
|
||||
}
|
||||
|
||||
|
@ -84,10 +88,10 @@ func getConfigValueFromXpath(path, xpath string) (string, error) {
|
|||
}
|
||||
|
||||
// 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)
|
||||
cmd.Stdout = &stdout
|
||||
if err := cmd.Run(); err != nil {
|
||||
return "", err
|
||||
|
@ -108,6 +112,7 @@ func getAppPath(bundleId string) (string, error) {
|
|||
return pathOutput, nil
|
||||
}
|
||||
|
||||
// CompactDisk performs the compation of the specified virtual disk image.
|
||||
func (d *Parallels9Driver) CompactDisk(diskPath string) error {
|
||||
prlDiskToolPath, err := exec.LookPath("prl_disk_tool")
|
||||
if err != nil {
|
||||
|
@ -135,7 +140,8 @@ func (d *Parallels9Driver) CompactDisk(diskPath string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *Parallels9Driver) DeviceAddCdRom(name string, image string) (string, error) {
|
||||
// DeviceAddCDROM adds a virtual CDROM device and attaches the specified image.
|
||||
func (d *Parallels9Driver) DeviceAddCDROM(name string, image string) (string, error) {
|
||||
command := []string{
|
||||
"set", name,
|
||||
"--device-add", "cdrom",
|
||||
|
@ -154,27 +160,29 @@ func (d *Parallels9Driver) DeviceAddCdRom(name string, image string) (string, er
|
|||
"Could not determine cdrom device name in the output:\n%s", string(out))
|
||||
}
|
||||
|
||||
device_name := matches[1]
|
||||
return device_name, nil
|
||||
deviceName := matches[1]
|
||||
return deviceName, nil
|
||||
}
|
||||
|
||||
// DiskPath returns a full path to the first virtual disk drive.
|
||||
func (d *Parallels9Driver) DiskPath(name string) (string, error) {
|
||||
out, err := exec.Command(d.PrlctlPath, "list", "-i", name).Output()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
hddRe := regexp.MustCompile("hdd0.* image='(.*)' type=*")
|
||||
matches := hddRe.FindStringSubmatch(string(out))
|
||||
HDDRe := regexp.MustCompile("hdd0.* image='(.*)' type=*")
|
||||
matches := HDDRe.FindStringSubmatch(string(out))
|
||||
if matches == nil {
|
||||
return "", fmt.Errorf(
|
||||
"Could not determine hdd image path in the output:\n%s", string(out))
|
||||
}
|
||||
|
||||
hdd_path := matches[1]
|
||||
return hdd_path, nil
|
||||
HDDPath := matches[1]
|
||||
return HDDPath, nil
|
||||
}
|
||||
|
||||
// IsRunning determines whether the VM is running or not.
|
||||
func (d *Parallels9Driver) IsRunning(name string) (bool, error) {
|
||||
var stdout bytes.Buffer
|
||||
|
||||
|
@ -205,6 +213,7 @@ func (d *Parallels9Driver) IsRunning(name string) (bool, error) {
|
|||
return false, nil
|
||||
}
|
||||
|
||||
// Stop forcibly stops the VM.
|
||||
func (d *Parallels9Driver) Stop(name string) error {
|
||||
if err := d.Prlctl("stop", name); err != nil {
|
||||
return err
|
||||
|
@ -216,6 +225,7 @@ func (d *Parallels9Driver) Stop(name string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Prlctl executes the specified "prlctl" command.
|
||||
func (d *Parallels9Driver) Prlctl(args ...string) error {
|
||||
var stdout, stderr bytes.Buffer
|
||||
|
||||
|
@ -238,10 +248,12 @@ func (d *Parallels9Driver) Prlctl(args ...string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// Verify raises an error if the builder could not be used on that host machine.
|
||||
func (d *Parallels9Driver) Verify() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Version returns the version of Parallels Desktop installed on that host.
|
||||
func (d *Parallels9Driver) Version() (string, error) {
|
||||
out, err := exec.Command(d.PrlctlPath, "--version").Output()
|
||||
if err != nil {
|
||||
|
@ -260,6 +272,8 @@ func (d *Parallels9Driver) Version() (string, error) {
|
|||
return version, nil
|
||||
}
|
||||
|
||||
// SendKeyScanCodes sends the specified scancodes as key events to the VM.
|
||||
// It is performed using "Prltype" script (refer to "prltype.go").
|
||||
func (d *Parallels9Driver) SendKeyScanCodes(vmName string, codes ...string) error {
|
||||
var stdout, stderr bytes.Buffer
|
||||
|
||||
|
@ -309,6 +323,7 @@ func prepend(head string, tail []string) []string {
|
|||
return tmp
|
||||
}
|
||||
|
||||
// SetDefaultConfiguration applies pre-defined default settings to the VM config.
|
||||
func (d *Parallels9Driver) SetDefaultConfiguration(vmName string) error {
|
||||
commands := make([][]string, 7)
|
||||
commands[0] = []string{"set", vmName, "--cpus", "1"}
|
||||
|
@ -328,7 +343,8 @@ func (d *Parallels9Driver) SetDefaultConfiguration(vmName string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *Parallels9Driver) Mac(vmName string) (string, error) {
|
||||
// MAC returns the MAC address of the VM's first network interface.
|
||||
func (d *Parallels9Driver) MAC(vmName string) (string, error) {
|
||||
var stdout bytes.Buffer
|
||||
|
||||
cmd := exec.Command(d.PrlctlPath, "list", "-i", vmName)
|
||||
|
@ -351,26 +367,26 @@ func (d *Parallels9Driver) Mac(vmName string) (string, error) {
|
|||
return mac, nil
|
||||
}
|
||||
|
||||
// Finds the IP address of a VM connected that uses DHCP by its MAC address
|
||||
// IPAddress finds the IP address of a VM connected that uses DHCP by its MAC address
|
||||
//
|
||||
// Parses the file /Library/Preferences/Parallels/parallels_dhcp_leases
|
||||
// file contain a list of DHCP leases given by Parallels Desktop
|
||||
// Example line:
|
||||
// 10.211.55.181="1418921112,1800,001c42f593fb,ff42f593fb000100011c25b9ff001c42f593fb"
|
||||
// IP Address ="Lease expiry, Lease time, MAC, MAC or DUID"
|
||||
func (d *Parallels9Driver) IpAddress(mac string) (string, error) {
|
||||
func (d *Parallels9Driver) IPAddress(mac string) (string, error) {
|
||||
|
||||
if len(mac) != 12 {
|
||||
return "", fmt.Errorf("Not a valid MAC address: %s. It should be exactly 12 digits.", mac)
|
||||
}
|
||||
|
||||
leases, err := ioutil.ReadFile(d.dhcp_lease_file)
|
||||
leases, err := ioutil.ReadFile(d.dhcpLeaseFile)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
re := regexp.MustCompile("(.*)=\"(.*),(.*)," + strings.ToLower(mac) + ",.*\"")
|
||||
mostRecentIp := ""
|
||||
mostRecentIP := ""
|
||||
mostRecentLease := uint64(0)
|
||||
for _, l := range re.FindAllStringSubmatch(string(leases), -1) {
|
||||
ip := l[1]
|
||||
|
@ -378,20 +394,22 @@ func (d *Parallels9Driver) IpAddress(mac string) (string, error) {
|
|||
leaseTime, _ := strconv.ParseUint(l[3], 10, 32)
|
||||
log.Printf("Found lease: %s for MAC: %s, expiring at %d, leased for %d s.\n", ip, mac, expiry, leaseTime)
|
||||
if mostRecentLease <= expiry-leaseTime {
|
||||
mostRecentIp = ip
|
||||
mostRecentIP = ip
|
||||
mostRecentLease = expiry - leaseTime
|
||||
}
|
||||
}
|
||||
|
||||
if len(mostRecentIp) == 0 {
|
||||
return "", fmt.Errorf("IP lease not found for MAC address %s in: %s\n", mac, d.dhcp_lease_file)
|
||||
if len(mostRecentIP) == 0 {
|
||||
return "", fmt.Errorf("IP lease not found for MAC address %s in: %s\n", mac, d.dhcpLeaseFile)
|
||||
}
|
||||
|
||||
log.Printf("Found IP lease: %s for MAC address %s\n", mostRecentIp, mac)
|
||||
return mostRecentIp, nil
|
||||
log.Printf("Found IP lease: %s for MAC address %s\n", mostRecentIP, mac)
|
||||
return mostRecentIP, nil
|
||||
}
|
||||
|
||||
func (d *Parallels9Driver) ToolsIsoPath(k string) (string, error) {
|
||||
// ToolsISOPath returns a full path to the Parallels Tools ISO for the specified guest
|
||||
// OS type. The following OS types are supported: "win", "lin", "mac", "other".
|
||||
func (d *Parallels9Driver) ToolsISOPath(k string) (string, error) {
|
||||
appPath, err := getAppPath("com.parallels.desktop.console")
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
|
|
@ -10,7 +10,7 @@ func TestParallels9Driver_impl(t *testing.T) {
|
|||
var _ Driver = new(Parallels9Driver)
|
||||
}
|
||||
|
||||
func TestIpAddress(t *testing.T) {
|
||||
func TestIPAddress(t *testing.T) {
|
||||
tf, err := ioutil.TempFile("", "packer")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
|
@ -18,11 +18,11 @@ func TestIpAddress(t *testing.T) {
|
|||
defer os.Remove(tf.Name())
|
||||
|
||||
d := Parallels9Driver{
|
||||
dhcp_lease_file: tf.Name(),
|
||||
dhcpLeaseFile: tf.Name(),
|
||||
}
|
||||
|
||||
// No lease should be found in an empty file
|
||||
ip, err := d.IpAddress("123456789012")
|
||||
ip, err := d.IPAddress("123456789012")
|
||||
if err == nil {
|
||||
t.Fatalf("Found IP: \"%v\". No IP should be found!\n", ip)
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ func TestIpAddress(t *testing.T) {
|
|||
10.211.55.254="1411712008,1800,001c42a51419,01001c42a51419"
|
||||
`)
|
||||
ioutil.WriteFile(tf.Name(), c, 0666)
|
||||
ip, err = d.IpAddress("001C4235240c")
|
||||
ip, err = d.IPAddress("001C4235240c")
|
||||
if err != nil {
|
||||
t.Fatalf("Error: %v\n", err)
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ func TestIpAddress(t *testing.T) {
|
|||
10.211.55.254="1411712008,1800,001c42a51419,01001c42a51419"
|
||||
`)
|
||||
ioutil.WriteFile(tf.Name(), c, 0666)
|
||||
ip, err = d.IpAddress("001c4235240c")
|
||||
ip, err = d.IPAddress("001c4235240c")
|
||||
if err != nil {
|
||||
t.Fatalf("Error: %v\n", err)
|
||||
}
|
||||
|
|
|
@ -9,11 +9,11 @@ type DriverMock struct {
|
|||
CompactDiskPath string
|
||||
CompactDiskErr error
|
||||
|
||||
DeviceAddCdRomCalled bool
|
||||
DeviceAddCdRomName string
|
||||
DeviceAddCdRomImage string
|
||||
DeviceAddCdRomResult string
|
||||
DeviceAddCdRomErr error
|
||||
DeviceAddCDROMCalled bool
|
||||
DeviceAddCDROMName string
|
||||
DeviceAddCDROMImage string
|
||||
DeviceAddCDROMResult string
|
||||
DeviceAddCDROMErr error
|
||||
|
||||
DiskPathCalled bool
|
||||
DiskPathName string
|
||||
|
@ -49,18 +49,18 @@ type DriverMock struct {
|
|||
SetDefaultConfigurationCalled bool
|
||||
SetDefaultConfigurationError error
|
||||
|
||||
ToolsIsoPathCalled bool
|
||||
ToolsIsoPathFlavor string
|
||||
ToolsIsoPathResult string
|
||||
ToolsIsoPathErr error
|
||||
ToolsISOPathCalled bool
|
||||
ToolsISOPathFlavor string
|
||||
ToolsISOPathResult string
|
||||
ToolsISOPathErr error
|
||||
|
||||
MacName string
|
||||
MacReturn string
|
||||
MacError error
|
||||
MACName string
|
||||
MACReturn string
|
||||
MACError error
|
||||
|
||||
IpAddressMac string
|
||||
IpAddressReturn string
|
||||
IpAddressError error
|
||||
IPAddressMAC string
|
||||
IPAddressReturn string
|
||||
IPAddressError error
|
||||
}
|
||||
|
||||
func (d *DriverMock) CompactDisk(path string) error {
|
||||
|
@ -69,11 +69,11 @@ func (d *DriverMock) CompactDisk(path string) error {
|
|||
return d.CompactDiskErr
|
||||
}
|
||||
|
||||
func (d *DriverMock) DeviceAddCdRom(name string, image string) (string, error) {
|
||||
d.DeviceAddCdRomCalled = true
|
||||
d.DeviceAddCdRomName = name
|
||||
d.DeviceAddCdRomImage = image
|
||||
return d.DeviceAddCdRomResult, d.DeviceAddCdRomErr
|
||||
func (d *DriverMock) DeviceAddCDROM(name string, image string) (string, error) {
|
||||
d.DeviceAddCDROMCalled = true
|
||||
d.DeviceAddCDROMName = name
|
||||
d.DeviceAddCDROMImage = image
|
||||
return d.DeviceAddCDROMResult, d.DeviceAddCDROMErr
|
||||
}
|
||||
|
||||
func (d *DriverMock) DiskPath(name string) (string, error) {
|
||||
|
@ -82,7 +82,7 @@ func (d *DriverMock) DiskPath(name string) (string, error) {
|
|||
return d.DiskPathResult, d.DiskPathErr
|
||||
}
|
||||
|
||||
func (d *DriverMock) Import(name, srcPath, dstPath string, reassignMac bool) error {
|
||||
func (d *DriverMock) Import(name, srcPath, dstPath string, reassignMAC bool) error {
|
||||
d.ImportCalled = true
|
||||
d.ImportName = name
|
||||
d.ImportSrcPath = srcPath
|
||||
|
@ -136,18 +136,18 @@ func (d *DriverMock) SetDefaultConfiguration(name string) error {
|
|||
return d.SetDefaultConfigurationError
|
||||
}
|
||||
|
||||
func (d *DriverMock) Mac(name string) (string, error) {
|
||||
d.MacName = name
|
||||
return d.MacReturn, d.MacError
|
||||
func (d *DriverMock) MAC(name string) (string, error) {
|
||||
d.MACName = name
|
||||
return d.MACReturn, d.MACError
|
||||
}
|
||||
|
||||
func (d *DriverMock) IpAddress(mac string) (string, error) {
|
||||
d.IpAddressMac = mac
|
||||
return d.IpAddressReturn, d.IpAddressError
|
||||
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
|
||||
func (d *DriverMock) ToolsISOPath(flavor string) (string, error) {
|
||||
d.ToolsISOPathCalled = true
|
||||
d.ToolsISOPathFlavor = flavor
|
||||
return d.ToolsISOPathResult, d.ToolsISOPathErr
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package common
|
||||
|
||||
// Interface to help find the host IP that is available from within
|
||||
// HostIPFinder allows to find the host IP that is available from within
|
||||
// the Parallels virtual machines.
|
||||
type HostIPFinder interface {
|
||||
HostIP() (string, error)
|
||||
|
|
|
@ -13,6 +13,8 @@ type IfconfigIPFinder struct {
|
|||
Devices []string
|
||||
}
|
||||
|
||||
// HostIP returns the host's IP address or an error if it could not be found
|
||||
// from the `ifconfig` output.
|
||||
func (f *IfconfigIPFinder) HostIP() (string, error) {
|
||||
var ifconfigPath string
|
||||
|
||||
|
@ -50,5 +52,5 @@ func (f *IfconfigIPFinder) HostIP() (string, error) {
|
|||
}
|
||||
}
|
||||
}
|
||||
return "", errors.New("IP not found in ifconfig output...")
|
||||
return "", errors.New("IP not found in ifconfig output")
|
||||
}
|
||||
|
|
|
@ -9,10 +9,12 @@ import (
|
|||
"github.com/mitchellh/packer/template/interpolate"
|
||||
)
|
||||
|
||||
// OutputConfig contains the configuration for builder's output.
|
||||
type OutputConfig struct {
|
||||
OutputDir string `mapstructure:"output_directory"`
|
||||
}
|
||||
|
||||
// Prepare configures the output directory or returns an error if it already exists.
|
||||
func (c *OutputConfig) Prepare(ctx *interpolate.Context, pc *common.PackerConfig) []error {
|
||||
if c.OutputDir == "" {
|
||||
c.OutputDir = fmt.Sprintf("output-%s", pc.PackerBuildName)
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/packer/common"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/mitchellh/packer/common"
|
||||
)
|
||||
|
||||
func TestOutputConfigPrepare(t *testing.T) {
|
||||
|
|
|
@ -4,10 +4,13 @@ import (
|
|||
"github.com/mitchellh/packer/template/interpolate"
|
||||
)
|
||||
|
||||
// PrlctlConfig contains the configuration for running "prlctl" commands
|
||||
// before the VM start.
|
||||
type PrlctlConfig struct {
|
||||
Prlctl [][]string `mapstructure:"prlctl"`
|
||||
}
|
||||
|
||||
// Prepare sets the default value of "Prlctl" property.
|
||||
func (c *PrlctlConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
if c.Prlctl == nil {
|
||||
c.Prlctl = make([][]string, 0)
|
||||
|
|
|
@ -4,10 +4,13 @@ import (
|
|||
"github.com/mitchellh/packer/template/interpolate"
|
||||
)
|
||||
|
||||
// PrlctlPostConfig contains the configuration for running "prlctl" commands
|
||||
// in the end of artifact build.
|
||||
type PrlctlPostConfig struct {
|
||||
PrlctlPost [][]string `mapstructure:"prlctl_post"`
|
||||
}
|
||||
|
||||
// Prepare sets the default value of "PrlctlPost" property.
|
||||
func (c *PrlctlPostConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
if c.PrlctlPost == nil {
|
||||
c.PrlctlPost = make([][]string, 0)
|
||||
|
|
|
@ -4,10 +4,12 @@ import (
|
|||
"github.com/mitchellh/packer/template/interpolate"
|
||||
)
|
||||
|
||||
// PrlctlVersionConfig contains the configuration for `prlctl` version.
|
||||
type PrlctlVersionConfig struct {
|
||||
PrlctlVersionFile string `mapstructure:"prlctl_version_file"`
|
||||
}
|
||||
|
||||
// Prepare sets the default value of "PrlctlVersionFile" property.
|
||||
func (c *PrlctlVersionConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
if c.PrlctlVersionFile == "" {
|
||||
c.PrlctlVersionFile = ".prlctl_version"
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package common
|
||||
|
||||
// Prltype is a Python scrypt allowin to send scancodes to the VM. It requires
|
||||
// the module "prlsdkapi", which is bundled to Parallels Virtualization SDK.
|
||||
const Prltype string = `
|
||||
import sys
|
||||
import prlsdkapi
|
||||
|
|
|
@ -7,12 +7,14 @@ import (
|
|||
"github.com/mitchellh/packer/template/interpolate"
|
||||
)
|
||||
|
||||
// RunConfig contains the configuration for VM run.
|
||||
type RunConfig struct {
|
||||
RawBootWait string `mapstructure:"boot_wait"`
|
||||
|
||||
BootWait time.Duration ``
|
||||
}
|
||||
|
||||
// Prepare sets the configuration for VM run.
|
||||
func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
if c.RawBootWait == "" {
|
||||
c.RawBootWait = "10s"
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/mitchellh/packer/template/interpolate"
|
||||
)
|
||||
|
||||
// ShutdownConfig contains the configuration for VM shutdown.
|
||||
type ShutdownConfig struct {
|
||||
ShutdownCommand string `mapstructure:"shutdown_command"`
|
||||
RawShutdownTimeout string `mapstructure:"shutdown_timeout"`
|
||||
|
@ -14,6 +15,7 @@ type ShutdownConfig struct {
|
|||
ShutdownTimeout time.Duration ``
|
||||
}
|
||||
|
||||
// Prepare sets default values to the VM shutdown configuration.
|
||||
func (c *ShutdownConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
if c.RawShutdownTimeout == "" {
|
||||
c.RawShutdownTimeout = "5m"
|
||||
|
|
|
@ -7,16 +7,17 @@ import (
|
|||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// CommHost returns the VM's IP address which should be used to access it by SSH.
|
||||
func CommHost(state multistep.StateBag) (string, error) {
|
||||
vmName := state.Get("vmName").(string)
|
||||
driver := state.Get("driver").(Driver)
|
||||
|
||||
mac, err := driver.Mac(vmName)
|
||||
mac, err := driver.MAC(vmName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ip, err := driver.IpAddress(mac)
|
||||
ip, err := driver.IPAddress(mac)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -24,6 +25,7 @@ func CommHost(state multistep.StateBag) (string, error) {
|
|||
return ip, nil
|
||||
}
|
||||
|
||||
// SSHConfigFunc returns SSH credentials to access the VM by SSH.
|
||||
func SSHConfigFunc(config SSHConfig) func(multistep.StateBag) (*ssh.ClientConfig, error) {
|
||||
return func(state multistep.StateBag) (*ssh.ClientConfig, error) {
|
||||
auth := []ssh.AuthMethod{
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/mitchellh/packer/template/interpolate"
|
||||
)
|
||||
|
||||
// SSHConfig contains the configuration for SSH communicator.
|
||||
type SSHConfig struct {
|
||||
Comm communicator.Config `mapstructure:",squash"`
|
||||
|
||||
|
@ -15,6 +16,7 @@ type SSHConfig struct {
|
|||
SSHWaitTimeout time.Duration `mapstructure:"ssh_wait_timeout"`
|
||||
}
|
||||
|
||||
// Prepare sets the default values for SSH communicator properties.
|
||||
func (c *SSHConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
// TODO: backwards compatibility, write fixer instead
|
||||
if c.SSHWaitTimeout != 0 {
|
||||
|
|
|
@ -2,12 +2,13 @@ package common
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"log"
|
||||
)
|
||||
|
||||
// This step attaches a floppy to the virtual machine.
|
||||
// StepAttachFloppy is a step that attaches a floppy to the virtual machine.
|
||||
//
|
||||
// Uses:
|
||||
// driver Driver
|
||||
|
@ -19,6 +20,8 @@ type StepAttachFloppy struct {
|
|||
floppyPath string
|
||||
}
|
||||
|
||||
// Run adds a virtual FDD device to the VM and attaches the image.
|
||||
// If the image is not specified, then this step will be skipped.
|
||||
func (s *StepAttachFloppy) Run(state multistep.StateBag) multistep.StepAction {
|
||||
// Determine if we even have a floppy disk to attach
|
||||
var floppyPath string
|
||||
|
@ -35,22 +38,22 @@ func (s *StepAttachFloppy) Run(state multistep.StateBag) multistep.StepAction {
|
|||
|
||||
ui.Say("Deleting any current floppy disk...")
|
||||
// Delete the floppy disk controller
|
||||
del_command := []string{
|
||||
delCommand := []string{
|
||||
"set", vmName,
|
||||
"--device-del", "fdd0",
|
||||
}
|
||||
// This will almost certainly fail with 'The fdd0 device does not exist.'
|
||||
driver.Prlctl(del_command...)
|
||||
driver.Prlctl(delCommand...)
|
||||
|
||||
ui.Say("Attaching floppy disk...")
|
||||
// Attaching the floppy disk
|
||||
add_command := []string{
|
||||
addCommand := []string{
|
||||
"set", vmName,
|
||||
"--device-add", "fdd",
|
||||
"--image", floppyPath,
|
||||
"--connect",
|
||||
}
|
||||
if err := driver.Prlctl(add_command...); err != nil {
|
||||
if err := driver.Prlctl(addCommand...); err != nil {
|
||||
state.Put("error", fmt.Errorf("Error adding floppy: %s", err))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
@ -61,6 +64,7 @@ func (s *StepAttachFloppy) Run(state multistep.StateBag) multistep.StepAction {
|
|||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
// Cleanup removes the virtual FDD device attached to the VM.
|
||||
func (s *StepAttachFloppy) Cleanup(state multistep.StateBag) {
|
||||
driver := state.Get("driver").(Driver)
|
||||
vmName := state.Get("vmName").(string)
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/multistep"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
func TestStepAttachFloppy_impl(t *testing.T) {
|
||||
|
|
|
@ -2,13 +2,14 @@ package common
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"log"
|
||||
)
|
||||
|
||||
// This step attaches the Parallels Tools as an inserted CD onto
|
||||
// the virtual machine.
|
||||
// StepAttachParallelsTools is a step that attaches Parallels Tools ISO image
|
||||
// as an inserted CD onto the virtual machine.
|
||||
//
|
||||
// Uses:
|
||||
// driver Driver
|
||||
|
@ -22,6 +23,8 @@ type StepAttachParallelsTools struct {
|
|||
ParallelsToolsMode string
|
||||
}
|
||||
|
||||
// Run adds a virtual CD-ROM device to the VM and attaches Parallels Tools ISO image.
|
||||
// If ISO image is not specified, then this step will be skipped.
|
||||
func (s *StepAttachParallelsTools) Run(state multistep.StateBag) multistep.StepAction {
|
||||
driver := state.Get("driver").(Driver)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
@ -39,10 +42,10 @@ func (s *StepAttachParallelsTools) Run(state multistep.StateBag) multistep.StepA
|
|||
// Attach the guest additions to the computer
|
||||
ui.Say("Attaching Parallels Tools ISO to the new CD/DVD drive...")
|
||||
|
||||
cdrom, err := driver.DeviceAddCdRom(vmName, parallelsToolsPath)
|
||||
cdrom, err := driver.DeviceAddCDROM(vmName, parallelsToolsPath)
|
||||
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error attaching Parallels Tools ISO: %s", err)
|
||||
err = fmt.Errorf("Error attaching Parallels Tools ISO: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
|
@ -54,6 +57,7 @@ func (s *StepAttachParallelsTools) Run(state multistep.StateBag) multistep.StepA
|
|||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
// Cleanup removes the virtual CD-ROM device attached to the VM.
|
||||
func (s *StepAttachParallelsTools) Cleanup(state multistep.StateBag) {
|
||||
if s.cdromDevice == "" {
|
||||
return
|
||||
|
|
|
@ -2,12 +2,13 @@ package common
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
)
|
||||
|
||||
// This step removes all empty blocks from expanding Parallels virtual disks
|
||||
// and reduces the result disk size
|
||||
// StepCompactDisk is a step that removes all empty blocks from expanding
|
||||
// Parallels virtual disks and reduces the result disk size
|
||||
//
|
||||
// Uses:
|
||||
// driver Driver
|
||||
|
@ -20,6 +21,7 @@ type StepCompactDisk struct {
|
|||
Skip bool
|
||||
}
|
||||
|
||||
// Run runs the compaction of the virtual disk attached to the VM.
|
||||
func (s *StepCompactDisk) Run(state multistep.StateBag) multistep.StepAction {
|
||||
driver := state.Get("driver").(Driver)
|
||||
vmName := state.Get("vmName").(string)
|
||||
|
@ -33,7 +35,7 @@ func (s *StepCompactDisk) Run(state multistep.StateBag) multistep.StepAction {
|
|||
ui.Say("Compacting the disk image")
|
||||
diskPath, err := driver.DiskPath(vmName)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error detecting virtual disk path: %s", err)
|
||||
err = fmt.Errorf("Error detecting virtual disk path: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
|
@ -48,4 +50,5 @@ func (s *StepCompactDisk) Run(state multistep.StateBag) multistep.StepAction {
|
|||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
// Cleanup does nothing.
|
||||
func (*StepCompactDisk) Cleanup(multistep.StateBag) {}
|
||||
|
|
|
@ -20,6 +20,7 @@ type StepOutputDir struct {
|
|||
success bool
|
||||
}
|
||||
|
||||
// Run sets up the output directory.
|
||||
func (s *StepOutputDir) Run(state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
|
@ -48,6 +49,7 @@ func (s *StepOutputDir) Run(state multistep.StateBag) multistep.StepAction {
|
|||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
// Cleanup deletes the output directory.
|
||||
func (s *StepOutputDir) Cleanup(state multistep.StateBag) {
|
||||
_, cancelled := state.GetOk(multistep.StateCancelled)
|
||||
_, halted := state.GetOk(multistep.StateHalted)
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/multistep"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
func testStepOutputDir(t *testing.T) *StepOutputDir {
|
||||
|
|
|
@ -2,11 +2,13 @@ package common
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/mitchellh/multistep"
|
||||
"os"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
// This step prepares parameters related to Parallels Tools.
|
||||
// StepPrepareParallelsTools is a step that prepares parameters related
|
||||
// to Parallels Tools.
|
||||
//
|
||||
// Uses:
|
||||
// driver Driver
|
||||
|
@ -18,6 +20,7 @@ type StepPrepareParallelsTools struct {
|
|||
ParallelsToolsMode string
|
||||
}
|
||||
|
||||
// Run sets the value of "parallels_tools_path".
|
||||
func (s *StepPrepareParallelsTools) Run(state multistep.StateBag) multistep.StepAction {
|
||||
driver := state.Get("driver").(Driver)
|
||||
|
||||
|
@ -25,7 +28,7 @@ func (s *StepPrepareParallelsTools) Run(state multistep.StateBag) multistep.Step
|
|||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
path, err := driver.ToolsIsoPath(s.ParallelsToolsFlavor)
|
||||
path, err := driver.ToolsISOPath(s.ParallelsToolsFlavor)
|
||||
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
|
@ -44,4 +47,5 @@ func (s *StepPrepareParallelsTools) Run(state multistep.StateBag) multistep.Step
|
|||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
// Cleanup does nothing.
|
||||
func (s *StepPrepareParallelsTools) Cleanup(multistep.StateBag) {}
|
||||
|
|
|
@ -29,7 +29,7 @@ func TestStepPrepareParallelsTools(t *testing.T) {
|
|||
driver := state.Get("driver").(*DriverMock)
|
||||
|
||||
// Mock results
|
||||
driver.ToolsIsoPathResult = tf.Name()
|
||||
driver.ToolsISOPathResult = tf.Name()
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(state); action != multistep.ActionContinue {
|
||||
|
@ -40,11 +40,11 @@ func TestStepPrepareParallelsTools(t *testing.T) {
|
|||
}
|
||||
|
||||
// Test the driver
|
||||
if !driver.ToolsIsoPathCalled {
|
||||
if !driver.ToolsISOPathCalled {
|
||||
t.Fatal("tools iso path should be called")
|
||||
}
|
||||
if driver.ToolsIsoPathFlavor != "foo" {
|
||||
t.Fatalf("bad: %#v", driver.ToolsIsoPathFlavor)
|
||||
if driver.ToolsISOPathFlavor != "foo" {
|
||||
t.Fatalf("bad: %#v", driver.ToolsISOPathFlavor)
|
||||
}
|
||||
|
||||
// Test the resulting state
|
||||
|
@ -75,8 +75,8 @@ func TestStepPrepareParallelsTools_disabled(t *testing.T) {
|
|||
}
|
||||
|
||||
// Test the driver
|
||||
if driver.ToolsIsoPathCalled {
|
||||
t.Fatal("tools iso path should NOT be called")
|
||||
if driver.ToolsISOPathCalled {
|
||||
t.Fatal("tools ISO path should NOT be called")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,7 @@ func TestStepPrepareParallelsTools_nonExist(t *testing.T) {
|
|||
driver := state.Get("driver").(*DriverMock)
|
||||
|
||||
// Mock results
|
||||
driver.ToolsIsoPathResult = "foo"
|
||||
driver.ToolsISOPathResult = "foo"
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(state); action != multistep.ActionHalt {
|
||||
|
@ -101,11 +101,11 @@ func TestStepPrepareParallelsTools_nonExist(t *testing.T) {
|
|||
}
|
||||
|
||||
// Test the driver
|
||||
if !driver.ToolsIsoPathCalled {
|
||||
if !driver.ToolsISOPathCalled {
|
||||
t.Fatal("tools iso path should be called")
|
||||
}
|
||||
if driver.ToolsIsoPathFlavor != "foo" {
|
||||
t.Fatalf("bad: %#v", driver.ToolsIsoPathFlavor)
|
||||
if driver.ToolsISOPathFlavor != "foo" {
|
||||
t.Fatalf("bad: %#v", driver.ToolsISOPathFlavor)
|
||||
}
|
||||
|
||||
// Test the resulting state
|
||||
|
|
|
@ -13,8 +13,8 @@ type commandTemplate struct {
|
|||
Name string
|
||||
}
|
||||
|
||||
// This step executes additional prlctl commands as specified by the
|
||||
// template.
|
||||
// StepPrlctl is a step that executes additional `prlctl` commands as specified.
|
||||
// by the template.
|
||||
//
|
||||
// Uses:
|
||||
// driver Driver
|
||||
|
@ -27,6 +27,7 @@ type StepPrlctl struct {
|
|||
Ctx interpolate.Context
|
||||
}
|
||||
|
||||
// Run executes `prlctl` commands.
|
||||
func (s *StepPrlctl) Run(state multistep.StateBag) multistep.StepAction {
|
||||
driver := state.Get("driver").(Driver)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
@ -48,7 +49,7 @@ func (s *StepPrlctl) Run(state multistep.StateBag) multistep.StepAction {
|
|||
var err error
|
||||
command[i], err = interpolate.Render(arg, &s.Ctx)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error preparing prlctl command: %s", err)
|
||||
err = fmt.Errorf("Error preparing prlctl command: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
|
@ -57,7 +58,7 @@ func (s *StepPrlctl) Run(state multistep.StateBag) multistep.StepAction {
|
|||
|
||||
ui.Message(fmt.Sprintf("Executing: prlctl %s", strings.Join(command, " ")))
|
||||
if err := driver.Prlctl(command...); err != nil {
|
||||
err := fmt.Errorf("Error executing command: %s", err)
|
||||
err = fmt.Errorf("Error executing command: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
|
@ -67,4 +68,5 @@ func (s *StepPrlctl) Run(state multistep.StateBag) multistep.StepAction {
|
|||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
// Cleanup does nothing.
|
||||
func (s *StepPrlctl) Cleanup(state multistep.StateBag) {}
|
||||
|
|
|
@ -2,12 +2,13 @@ package common
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"time"
|
||||
)
|
||||
|
||||
// This step starts the virtual machine.
|
||||
// StepRun is a step that starts the virtual machine.
|
||||
//
|
||||
// Uses:
|
||||
// driver Driver
|
||||
|
@ -21,6 +22,7 @@ type StepRun struct {
|
|||
vmName string
|
||||
}
|
||||
|
||||
// Run starts the VM.
|
||||
func (s *StepRun) Run(state multistep.StateBag) multistep.StepAction {
|
||||
driver := state.Get("driver").(Driver)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
@ -29,7 +31,7 @@ func (s *StepRun) Run(state multistep.StateBag) multistep.StepAction {
|
|||
ui.Say("Starting the virtual machine...")
|
||||
command := []string{"start", vmName}
|
||||
if err := driver.Prlctl(command...); err != nil {
|
||||
err := fmt.Errorf("Error starting VM: %s", err)
|
||||
err = fmt.Errorf("Error starting VM: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
|
@ -56,6 +58,7 @@ func (s *StepRun) Run(state multistep.StateBag) multistep.StepAction {
|
|||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
// Cleanup stops the VM.
|
||||
func (s *StepRun) Cleanup(state multistep.StateBag) {
|
||||
if s.vmName == "" {
|
||||
return
|
||||
|
|
|
@ -3,14 +3,15 @@ package common
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
)
|
||||
|
||||
// This step shuts down the machine. It first attempts to do so gracefully,
|
||||
// but ultimately forcefully shuts it down if that fails.
|
||||
// StepShutdown is a step that shuts down the machine. It first attempts to do
|
||||
// so gracefully, but ultimately forcefully shuts it down if that fails.
|
||||
//
|
||||
// Uses:
|
||||
// communicator packer.Communicator
|
||||
|
@ -25,6 +26,7 @@ type StepShutdown struct {
|
|||
Timeout time.Duration
|
||||
}
|
||||
|
||||
// Run shuts down the VM.
|
||||
func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction {
|
||||
comm := state.Get("communicator").(packer.Communicator)
|
||||
driver := state.Get("driver").(Driver)
|
||||
|
@ -36,7 +38,7 @@ func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction {
|
|||
log.Printf("Executing shutdown command: %s", s.Command)
|
||||
cmd := &packer.RemoteCmd{Command: s.Command}
|
||||
if err := cmd.StartWithUi(comm, ui); err != nil {
|
||||
err := fmt.Errorf("Failed to send shutdown command: %s", err)
|
||||
err = fmt.Errorf("Failed to send shutdown command: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
|
@ -64,7 +66,7 @@ func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction {
|
|||
} else {
|
||||
ui.Say("Halting the virtual machine...")
|
||||
if err := driver.Stop(vmName); err != nil {
|
||||
err := fmt.Errorf("Error stopping VM: %s", err)
|
||||
err = fmt.Errorf("Error stopping VM: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
|
@ -75,4 +77,5 @@ func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction {
|
|||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
// Cleanup does nothing.
|
||||
func (s *StepShutdown) Cleanup(state multistep.StateBag) {}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
)
|
||||
|
||||
func TestStepShutdown_impl(t *testing.T) {
|
||||
|
|
|
@ -2,9 +2,10 @@ package common
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testState(t *testing.T) multistep.StateBag {
|
||||
|
|
|
@ -13,16 +13,14 @@ import (
|
|||
"github.com/mitchellh/packer/template/interpolate"
|
||||
)
|
||||
|
||||
const KeyLeftShift uint32 = 0xFFE1
|
||||
|
||||
type bootCommandTemplateData struct {
|
||||
HTTPIP string
|
||||
HTTPPort uint
|
||||
Name string
|
||||
}
|
||||
|
||||
// This step "types" the boot command into the VM via the prltype script, built on the
|
||||
// Parallels Virtualization SDK - Python API.
|
||||
// StepTypeBootCommand is a step that "types" the boot command into the VM via
|
||||
// the prltype script, built on the Parallels Virtualization SDK - Python API.
|
||||
//
|
||||
// Uses:
|
||||
// driver Driver
|
||||
|
@ -39,6 +37,7 @@ type StepTypeBootCommand struct {
|
|||
Ctx interpolate.Context
|
||||
}
|
||||
|
||||
// Run types the boot command by sending key scancodes into the VM.
|
||||
func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction {
|
||||
debug := state.Get("debug").(bool)
|
||||
httpPort := state.Get("http_port").(uint)
|
||||
|
@ -50,7 +49,7 @@ func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction
|
|||
pauseFn = state.Get("pauseFn").(multistep.DebugPauseFn)
|
||||
}
|
||||
|
||||
hostIp := "0.0.0.0"
|
||||
hostIP := "0.0.0.0"
|
||||
|
||||
if len(s.HostInterfaces) > 0 {
|
||||
// Determine the host IP
|
||||
|
@ -58,18 +57,18 @@ func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction
|
|||
|
||||
ip, err := ipFinder.HostIP()
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error detecting host IP: %s", err)
|
||||
err = fmt.Errorf("Error detecting host IP: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
hostIp = ip
|
||||
hostIP = ip
|
||||
}
|
||||
|
||||
ui.Say(fmt.Sprintf("Host IP for the Parallels machine: %s", hostIp))
|
||||
ui.Say(fmt.Sprintf("Host IP for the Parallels machine: %s", hostIP))
|
||||
|
||||
s.Ctx.Data = &bootCommandTemplateData{
|
||||
hostIp,
|
||||
hostIP,
|
||||
httpPort,
|
||||
s.VMName,
|
||||
}
|
||||
|
@ -78,7 +77,7 @@ func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction
|
|||
for i, command := range s.BootCommand {
|
||||
command, err := interpolate.Render(command, &s.Ctx)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error preparing boot command: %s", err)
|
||||
err = fmt.Errorf("Error preparing boot command: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
|
@ -88,7 +87,7 @@ func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction
|
|||
for _, code := range scancodes(command) {
|
||||
if code == "wait" {
|
||||
if err := driver.SendKeyScanCodes(s.VMName, codes...); err != nil {
|
||||
err := fmt.Errorf("Error sending boot command: %s", err)
|
||||
err = fmt.Errorf("Error sending boot command: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
|
@ -100,7 +99,7 @@ func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction
|
|||
|
||||
if code == "wait5" {
|
||||
if err := driver.SendKeyScanCodes(s.VMName, codes...); err != nil {
|
||||
err := fmt.Errorf("Error sending boot command: %s", err)
|
||||
err = fmt.Errorf("Error sending boot command: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
|
@ -112,7 +111,7 @@ func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction
|
|||
|
||||
if code == "wait10" {
|
||||
if err := driver.SendKeyScanCodes(s.VMName, codes...); err != nil {
|
||||
err := fmt.Errorf("Error sending boot command: %s", err)
|
||||
err = fmt.Errorf("Error sending boot command: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
|
@ -136,7 +135,7 @@ func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction
|
|||
|
||||
log.Printf("Sending scancodes: %#v", codes)
|
||||
if err := driver.SendKeyScanCodes(s.VMName, codes...); err != nil {
|
||||
err := fmt.Errorf("Error sending boot command: %s", err)
|
||||
err = fmt.Errorf("Error sending boot command: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
|
@ -146,6 +145,7 @@ func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction
|
|||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
// Cleanup does nothing.
|
||||
func (*StepTypeBootCommand) Cleanup(multistep.StateBag) {}
|
||||
|
||||
func scancodes(message string) []string {
|
||||
|
@ -208,12 +208,12 @@ func scancodes(message string) []string {
|
|||
|
||||
scancodeMap := make(map[rune]uint)
|
||||
for chars, start := range scancodeIndex {
|
||||
var i uint = 0
|
||||
var i uint
|
||||
for len(chars) > 0 {
|
||||
r, size := utf8.DecodeRuneInString(chars)
|
||||
chars = chars[size:]
|
||||
scancodeMap[r] = start + i
|
||||
i += 1
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
)
|
||||
|
||||
func TestStepTypeBootCommand(t *testing.T) {
|
||||
|
|
|
@ -22,7 +22,13 @@ type toolsPathTemplate struct {
|
|||
Flavor string
|
||||
}
|
||||
|
||||
// This step uploads the guest additions ISO to the VM.
|
||||
// StepUploadParallelsTools is a step that uploads the Parallels Tools ISO
|
||||
// to the VM.
|
||||
//
|
||||
// Uses:
|
||||
// communicator packer.Communicator
|
||||
// parallels_tools_path string
|
||||
// ui packer.Ui
|
||||
type StepUploadParallelsTools struct {
|
||||
ParallelsToolsFlavor string
|
||||
ParallelsToolsGuestPath string
|
||||
|
@ -30,6 +36,7 @@ type StepUploadParallelsTools struct {
|
|||
Ctx interpolate.Context
|
||||
}
|
||||
|
||||
// Run uploads the Parallels Tools ISO to the VM.
|
||||
func (s *StepUploadParallelsTools) Run(state multistep.StateBag) multistep.StepAction {
|
||||
comm := state.Get("communicator").(packer.Communicator)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
@ -56,7 +63,7 @@ func (s *StepUploadParallelsTools) Run(state multistep.StateBag) multistep.StepA
|
|||
|
||||
s.ParallelsToolsGuestPath, err = interpolate.Render(s.ParallelsToolsGuestPath, &s.Ctx)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error preparing Parallels Tools path: %s", err)
|
||||
err = fmt.Errorf("Error preparing Parallels Tools path: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
|
@ -65,7 +72,7 @@ func (s *StepUploadParallelsTools) Run(state multistep.StateBag) multistep.StepA
|
|||
ui.Say(fmt.Sprintf("Uploading Parallels Tools for '%s' to path: '%s'",
|
||||
s.ParallelsToolsFlavor, s.ParallelsToolsGuestPath))
|
||||
if err := comm.Upload(s.ParallelsToolsGuestPath, f, nil); err != nil {
|
||||
err := 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
|
||||
|
@ -74,4 +81,5 @@ func (s *StepUploadParallelsTools) Run(state multistep.StateBag) multistep.StepA
|
|||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
// Cleanup does nothing.
|
||||
func (s *StepUploadParallelsTools) Cleanup(state multistep.StateBag) {}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStepUploadParallelsTools_impl(t *testing.T) {
|
||||
|
|
|
@ -3,17 +3,24 @@ package common
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"log"
|
||||
)
|
||||
|
||||
// This step uploads a file containing the Parallels version, which
|
||||
// can be useful for various provisioning reasons.
|
||||
// StepUploadVersion is a step that uploads a file containing the version of
|
||||
// Parallels Desktop, which can be useful for various provisioning reasons.
|
||||
//
|
||||
// Uses:
|
||||
// communicator packer.Communicator
|
||||
// driver Driver
|
||||
// ui packer.Ui
|
||||
type StepUploadVersion struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
// Run uploads a file containing the version of Parallels Desktop.
|
||||
func (s *StepUploadVersion) Run(state multistep.StateBag) multistep.StepAction {
|
||||
comm := state.Get("communicator").(packer.Communicator)
|
||||
driver := state.Get("driver").(Driver)
|
||||
|
@ -41,4 +48,5 @@ func (s *StepUploadVersion) Run(state multistep.StateBag) multistep.StepAction {
|
|||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
// Cleanup does nothing.
|
||||
func (s *StepUploadVersion) Cleanup(state multistep.StateBag) {}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStepUploadVersion_impl(t *testing.T) {
|
||||
|
|
|
@ -15,12 +15,14 @@ const (
|
|||
ParallelsToolsModeUpload = "upload"
|
||||
)
|
||||
|
||||
// ToolsConfig contains the builder configuration related to Parallels Tools.
|
||||
type ToolsConfig struct {
|
||||
ParallelsToolsFlavor string `mapstructure:"parallels_tools_flavor"`
|
||||
ParallelsToolsGuestPath string `mapstructure:"parallels_tools_guest_path"`
|
||||
ParallelsToolsMode string `mapstructure:"parallels_tools_mode"`
|
||||
}
|
||||
|
||||
// Prepare validates & sets up configuration options related to Parallels Tools.
|
||||
func (c *ToolsConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
if c.ParallelsToolsMode == "" {
|
||||
c.ParallelsToolsMode = ParallelsToolsModeUpload
|
||||
|
@ -53,7 +55,7 @@ func (c *ToolsConfig) Prepare(ctx *interpolate.Context) []error {
|
|||
|
||||
if c.ParallelsToolsFlavor == "" {
|
||||
if c.ParallelsToolsMode != ParallelsToolsModeDisable {
|
||||
errs = append(errs, errors.New("parallels_tools_flavor must be specified."))
|
||||
errs = append(errs, errors.New("parallels_tools_flavor must be specified"))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,17 +2,18 @@ package iso
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
parallelscommon "github.com/mitchellh/packer/builder/parallels/common"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"log"
|
||||
)
|
||||
|
||||
// This step attaches the ISO to the virtual machine.
|
||||
//
|
||||
// Uses:
|
||||
// driver Driver
|
||||
// isoPath string
|
||||
// iso_path string
|
||||
// ui packer.Ui
|
||||
// vmName string
|
||||
//
|
||||
|
|
|
@ -2,10 +2,11 @@ package iso
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
parallelscommon "github.com/mitchellh/packer/builder/parallels/common"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// This step creates the virtual disk that will be used as the
|
||||
|
|
|
@ -2,6 +2,7 @@ package iso
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
parallelscommon "github.com/mitchellh/packer/builder/parallels/common"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
|
|
|
@ -27,7 +27,7 @@ type Config struct {
|
|||
BootCommand []string `mapstructure:"boot_command"`
|
||||
SourcePath string `mapstructure:"source_path"`
|
||||
VMName string `mapstructure:"vm_name"`
|
||||
ReassignMac bool `mapstructure:"reassign_mac"`
|
||||
ReassignMAC bool `mapstructure:"reassign_mac"`
|
||||
|
||||
ctx interpolate.Context
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package pvm
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
parallelscommon "github.com/mitchellh/packer/builder/parallels/common"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
|
@ -20,7 +21,7 @@ func (s *StepImport) Run(state multistep.StateBag) multistep.StepAction {
|
|||
config := state.Get("config").(*Config)
|
||||
|
||||
ui.Say(fmt.Sprintf("Importing VM: %s", s.SourcePath))
|
||||
if err := driver.Import(s.Name, s.SourcePath, config.OutputDir, config.ReassignMac); err != nil {
|
||||
if err := driver.Import(s.Name, s.SourcePath, config.OutputDir, config.ReassignMAC); err != nil {
|
||||
err := fmt.Errorf("Error importing VM: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
|
|
|
@ -2,10 +2,11 @@ package pvm
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
parallelscommon "github.com/mitchellh/packer/builder/parallels/common"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testState(t *testing.T) multistep.StateBag {
|
||||
|
|
Loading…
Reference in New Issue