packer-cn/builder/parallels/common/driver.go

144 lines
3.9 KiB
Go

package common
import (
"fmt"
"log"
"os/exec"
"runtime"
"strconv"
"strings"
)
// 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
// versions out of the builder steps, so sometimes the methods are
// extremely specific.
type Driver interface {
// Compact a virtual disk image.
CompactDisk(string) error
// Adds new CD/DVD drive to the VM and returns name of this device
DeviceAddCDROM(string, string) (string, error)
// Get path to the first virtual disk image
DiskPath(string) (string, error)
// Import a VM
Import(string, string, string, bool) error
// Checks if the VM with the given name is running.
IsRunning(string) (bool, error)
// Stop stops a running machine, forcefully.
Stop(string) error
// 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.
Verify() error
// Version reads the version of Parallels that is installed.
Version() (string, error)
// Send scancodes to the vm using the prltype python script.
SendKeyScanCodes(string, ...string) error
// Apply default configuration settings to the virtual machine
SetDefaultConfiguration(string) error
// Finds the MAC address of the NIC nic0
MAC(string) (string, error)
// Finds the IP address of a VM connected that uses DHCP by its MAC address
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
DHCPLeaseFile := "/Library/Preferences/Parallels/parallels_dhcp_leases"
if runtime.GOOS != "darwin" {
return nil, fmt.Errorf(
"Parallels builder works only on \"darwin\" platform!")
}
if prlctlPath == "" {
var err error
prlctlPath, err = exec.LookPath("prlctl")
if err != nil {
return nil, err
}
}
log.Printf("prlctl path: %s", prlctlPath)
if prlsrvctlPath == "" {
var err error
prlsrvctlPath, err = exec.LookPath("prlsrvctl")
if err != nil {
return nil, err
}
}
log.Printf("prlsrvctl path: %s", prlsrvctlPath)
drivers = map[string]Driver{
"11": &Parallels11Driver{
Parallels9Driver: Parallels9Driver{
PrlctlPath: prlctlPath,
PrlsrvctlPath: prlsrvctlPath,
dhcpLeaseFile: DHCPLeaseFile,
},
},
"10": &Parallels10Driver{
Parallels9Driver: Parallels9Driver{
PrlctlPath: prlctlPath,
PrlsrvctlPath: prlsrvctlPath,
dhcpLeaseFile: DHCPLeaseFile,
},
},
"9": &Parallels9Driver{
PrlctlPath: prlctlPath,
PrlsrvctlPath: prlsrvctlPath,
dhcpLeaseFile: DHCPLeaseFile,
},
}
for v, d := range drivers {
version, _ := d.Version()
if strings.HasPrefix(version, v) {
if err := d.Verify(); err != nil {
return nil, err
}
return d, nil
}
supportedVersions = append(supportedVersions, v)
}
latestDriver := 11
version, _ := drivers[strconv.Itoa(latestDriver)].Version()
majVer, _ := strconv.Atoi(strings.SplitN(version, ".", 2)[0])
log.Printf("Parallels version: %s", version)
if majVer > latestDriver {
log.Printf("Your version of Parallels Desktop for Mac is %s, Packer will use driver for version %d.", version, latestDriver)
return drivers[strconv.Itoa(latestDriver)], nil
}
return nil, fmt.Errorf(
"Unable to initialize any driver. Supported Parallels Desktop versions: "+
"%s\n", strings.Join(supportedVersions, ", "))
}