Skip to content

Commit

Permalink
refactor: consolidate workstation driver
Browse files Browse the repository at this point in the history
- Consolidates `Workstation9Driver` and `Workstation10Driver` to `WorkstationrDriver` within `driver_workstation.go`.
- Addresses  the deprecation of `syscall.StringToUTF16Ptr` with `windows.UTF16PtrFromString` in `readRegString`.

Signed-off-by: Ryan Johnson <ryan@tenthirtyam.org>
  • Loading branch information
tenthirtyam committed Dec 7, 2024
1 parent 1c153d8 commit 5a339b7
Show file tree
Hide file tree
Showing 12 changed files with 556 additions and 536 deletions.
21 changes: 10 additions & 11 deletions builder/vmware/common/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ const (
fusionMinVersion = "13.5.0"

// VMware Workstation.
workstationProductName = "VMware Workstation"
workstationMinVersion = "17.5.0"
workstationProductName = "VMware Workstation"
workstationMinVersion = "17.5.0"
workstationInstallationPathKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\vmware.exe"
workstationRegistryKey = "SYSTEM\\CurrentControlSet\\services\\VMnetDHCP\\Parameters"

// VMware Workstation Player.
playerProductName = "VMware Workstation Player"
Expand Down Expand Up @@ -61,6 +63,7 @@ const (
appPlayer = "vmplayer"
appVdiskManager = "vmware-vdiskmanager"
appVmrun = "vmrun"
appVmware = "vmware"
appVmx = "vmware-vmx"
appQemuImg = "qemu-img"

Expand Down Expand Up @@ -109,7 +112,6 @@ var technicalPreview = regexp.MustCompile(technicalPreviewRegex)
// The VMware OVF Tool version.
var ovfToolVersion = regexp.MustCompile(ovfToolVersionRegex)

// A driver is able to talk to VMware, control virtual machines, etc.
type Driver interface {
// Clone clones the VMX and the disk to the destination path. The
// destination is a path to the VMX file. The disk will be copied
Expand Down Expand Up @@ -153,12 +155,12 @@ type Driver interface {
// paths within this function.
Verify() error

/// This is to establish a connection to the guest
// This is to establish a connection to the guest
CommHost(multistep.StateBag) (string, error)

/// These methods are generally implemented by the VmwareDriver
/// structure within this file. A driver implementation can
/// reimplement these, though, if it wants.
// These methods are generally implemented by the VmwareDriver
// structure within this file. A driver implementation can
// reimplement these, though, if it wants.
GetVmwareDriver() VmwareDriver

// Get the guest hw address for the vm
Expand Down Expand Up @@ -200,9 +202,8 @@ func NewDriver(dconfig *DriverConfig, config *SSHConfig, vmName string) (Driver,
fallthrough
case "windows":
drivers = []Driver{
NewWorkstation10Driver(config),
NewWorkstation9Driver(config),
NewPlayerDriver(config),
NewWorkstationDriver(config),
}
default:
return nil, fmt.Errorf("error finding a driver for %s", runtime.GOOS)
Expand Down Expand Up @@ -264,8 +265,6 @@ func runAndLog(cmd *exec.Cmd) (string, string, error) {
log.Printf("stdout: %s", stdoutString)
log.Printf("stderr: %s", stderrString)

// Replace these for Windows, we only want to deal with Unix
// style line endings.
returnStdout := strings.Replace(stdout.String(), "\r\n", "\n", -1)
returnStderr := strings.Replace(stderr.String(), "\r\n", "\n", -1)

Expand Down
7 changes: 5 additions & 2 deletions builder/vmware/common/driver_fusion.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import (
"github.com/hashicorp/packer-plugin-sdk/multistep"
)

// VMware Fusion

const fusionSuppressPlist = `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
Expand All @@ -26,7 +28,6 @@ const fusionSuppressPlist = `<?xml version="1.0" encoding="UTF-8"?>
</dict>
</plist>`

// FusionDriver is a driver for VMware Fusion for macOS.
type FusionDriver struct {
VmwareDriver

Expand Down Expand Up @@ -191,7 +192,9 @@ func (d *FusionDriver) Clone(dst, src string, linked bool, snapshot string) erro

func (d *FusionDriver) Verify() error {
fusionVersion, err := d.getFusionVersion()
log.Printf("[INFO] Checking %s version...", fusionProductName)

log.Printf("[INFO] Searching for %s...", fusionProductName)

if err != nil {
return fmt.Errorf("error getting %s version: %s", fusionProductName, err)
}
Expand Down
75 changes: 48 additions & 27 deletions builder/vmware/common/driver_player.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
"github.com/hashicorp/packer-plugin-sdk/multistep"
)

// VMware Workstation Player

// PlayerDriver is a driver for VMware Workstation Player.
type PlayerDriver struct {
VmwareDriver
Expand All @@ -28,12 +30,41 @@ type PlayerDriver struct {
SSHConfig *SSHConfig
}

// NewPlayerDriver creates a new PlayerDriver.
func NewPlayerDriver(config *SSHConfig) Driver {
return &PlayerDriver{
SSHConfig: config,
}
}

// GetVmwareDriver returns the VmwareDriver.
func (d *PlayerDriver) GetVmwareDriver() VmwareDriver {
return d.VmwareDriver
}

// Clone clones a virtual machine.
func (d *PlayerDriver) Clone(dst, src string, linked bool, snapshot string) error {
var cloneType string

if linked {
cloneType = cloneTypeLinked
} else {
cloneType = cloneTypeFull
}

args := []string{"-T", "ws", "clone", src, dst, cloneType}
if snapshot != "" {
args = append(args, "-snapshot", snapshot)
}
cmd := exec.Command(d.VmrunPath, args...)
if _, _, err := runAndLog(cmd); err != nil {
return err
}

return nil
}

// CompactDisk compacts a virtual machine disk based on the disk path.
func (d *PlayerDriver) CompactDisk(diskPath string) error {
if d.QemuImgPath != "" {
return d.qemuCompactDisk(diskPath)
Expand All @@ -52,6 +83,7 @@ func (d *PlayerDriver) CompactDisk(diskPath string) error {
return nil
}

// qemuCompactDisk compacts a virtual machine disk using qemu-img.
func (d *PlayerDriver) qemuCompactDisk(diskPath string) error {
cmd := exec.Command(d.QemuImgPath, "convert", "-f", "vmdk", "-O", "vmdk", "-o", "compat6", diskPath, diskPath+".new")
if _, _, err := runAndLog(cmd); err != nil {
Expand All @@ -69,6 +101,8 @@ func (d *PlayerDriver) qemuCompactDisk(diskPath string) error {
return nil
}

// CreateDisk creates a virtual machine disk based on the output path, size,
// adapter type, and type ID.
func (d *PlayerDriver) CreateDisk(output string, size string, adapter_type string, type_id string) error {
var cmd *exec.Cmd
if d.QemuImgPath != "" {
Expand All @@ -83,12 +117,15 @@ func (d *PlayerDriver) CreateDisk(output string, size string, adapter_type strin
return nil
}

// CreateSnapshot creates a snapshot of a virtual machine based on the .vmx
// file path and snapshot name.
func (d *PlayerDriver) CreateSnapshot(vmxPath string, snapshotName string) error {
cmd := exec.Command(d.VmrunPath, "-T", "player", "snapshot", vmxPath, snapshotName)
_, _, err := runAndLog(cmd)
return err
}

// IsRunning checks if a virtual machine is running based on the .vmx file path.
func (d *PlayerDriver) IsRunning(vmxPath string) (bool, error) {
vmxPath, err := filepath.Abs(vmxPath)
if err != nil {
Expand All @@ -110,10 +147,13 @@ func (d *PlayerDriver) IsRunning(vmxPath string) (bool, error) {
return false, nil
}

// CommHost returns the host address based on the SSH configuration.
func (d *PlayerDriver) CommHost(state multistep.StateBag) (string, error) {
return CommHost(d.SSHConfig)(state)
}

// Start powers on a virtual machine based on the .vmx file path and mode
// (headless or GUI).
func (d *PlayerDriver) Start(vmxPath string, headless bool) error {
guiArgument := guiArgumentNoGUI
if !headless {
Expand All @@ -128,6 +168,7 @@ func (d *PlayerDriver) Start(vmxPath string, headless bool) error {
return nil
}

// Stop powers off a virtual machine based on the .vmx file path.
func (d *PlayerDriver) Stop(vmxPath string) error {
cmd := exec.Command(d.VmrunPath, "-T", "player", "stop", vmxPath, "hard")
if _, _, err := runAndLog(cmd); err != nil {
Expand All @@ -143,10 +184,13 @@ func (d *PlayerDriver) Stop(vmxPath string) error {
return nil
}

// SuppressMessages suppresses messages for a virtual machine based on the .vmx
// file path.
func (d *PlayerDriver) SuppressMessages(vmxPath string) error {
return nil
}

// Verify checks if the VMware Workstation Player installation is valid.
func (d *PlayerDriver) Verify() error {
var err error

Expand Down Expand Up @@ -212,11 +256,11 @@ func (d *PlayerDriver) Verify() error {
}

d.VmwareDriver.DhcpConfPath = func(device string) string {
return playerVmDhcpConfPath(device)
return playerDhcpLeasesPath(device)
}

d.VmwareDriver.VmnetnatConfPath = func(device string) string {
return playerVmnetnatConfPath(device)
return playerNatConfPath(device)

Check failure on line 263 in builder/vmware/common/driver_player.go

View workflow job for this annotation

GitHub Actions / Windows Go tests

undefined: playerNatConfPath
}

d.VmwareDriver.NetworkMapper = func() (NetworkNameMapper, error) {
Expand Down Expand Up @@ -246,35 +290,12 @@ func (d *PlayerDriver) Verify() error {
return nil
}

// ToolsIsoPath returns the path to the VMware Tools ISO based on the flavor.
func (d *PlayerDriver) ToolsIsoPath(flavor string) string {
return playerToolsIsoPath(flavor)
}

// ToolsInstall installs VMware Tools.
func (d *PlayerDriver) ToolsInstall() error {
return nil
}

func (d *PlayerDriver) Clone(dst, src string, linked bool, snapshot string) error {
var cloneType string

if linked {
cloneType = cloneTypeLinked
} else {
cloneType = cloneTypeFull
}

args := []string{"-T", "ws", "clone", src, dst, cloneType}
if snapshot != "" {
args = append(args, "-snapshot", snapshot)
}
cmd := exec.Command(d.VmrunPath, args...)
if _, _, err := runAndLog(cmd); err != nil {
return err
}

return nil
}

func (d *PlayerDriver) GetVmwareDriver() VmwareDriver {
return d.VmwareDriver
}
35 changes: 24 additions & 11 deletions builder/vmware/common/driver_player_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,38 +18,44 @@ import (
"github.com/hashicorp/go-version"
)

// VMware Workstation Player for Linux.
// VMware Workstation Player on Linux

// playerFindVmplayer returns the path to the VMware Workstation Player executable.
func playerFindVmplayer() (string, error) {
return exec.LookPath(appPlayer)
}

// playerFindVmrun returns the path to the VMware VIX executable.
func playerFindVmrun() (string, error) {
return exec.LookPath(appVmrun)
}

// playerFindVdiskManager returns the path to the VMware Virtual Disk Manager
// executable.
func playerFindVdiskManager() (string, error) {
return exec.LookPath(appVdiskManager)
}

// playerFindQemuImg returns the path to the QEMU image utility.
func playerFindQemuImg() (string, error) {
return exec.LookPath(appQemuImg)
}

// playerToolsIsoPath returns the path to the VMware Tools ISO.
func playerToolsIsoPath(flavor string) string {
return "/usr/lib/vmware/isoimages/" + flavor + ".iso"
}

// Return the base path to configuration files.
// playerInstallationPath returns the path to the installation path.
func playerInstallationPath() (s string, err error) {
return "/etc/vmware", nil
}

// Helper function to find configuration paths
// playerFindConfigPath finds the configuration file in the device path.
func playerFindConfigPath(device string, paths []string) string {
base, err := playerInstallationPath()
if err != nil {
log.Printf("Error finding configuration root path: %s", err)
log.Printf("[WARN] Error finding %s installation path: %s", playerProductName, err)
return ""
}

Expand All @@ -61,39 +67,46 @@ func playerFindConfigPath(device string, paths []string) string {
}
}

log.Printf("Error finding configuration file in device path: %s", devicebase)
log.Printf("[WARN] Error finding configuration file in device path: %s", devicebase)
return ""
}

// playerDhcpLeasesPath returns the path to the DHCP leases file.
func playerDhcpLeasesPath(device string) string {
return playerFindConfigPath(device, GetDhcpLeasesPaths())
}

func playerVmDhcpConfPath(device string) string {
// playerDhcpConfPath returns the path to the DHCP configuration file.
func playerDhcpConfPath(device string) string {

Check failure on line 80 in builder/vmware/common/driver_player_unix.go

View workflow job for this annotation

GitHub Actions / Lint check

func `playerDhcpConfPath` is unused (unused)
return playerFindConfigPath(device, GetDhcpConfPaths())
}

func playerVmnetnatConfPath(device string) string {
// playerNatConfPath returns the path to the NAT configuration file.
func playerNatConfPath(device string) string {
base, err := playerInstallationPath()
if err != nil {
log.Printf("Error finding the configuration root path: %s", err)
log.Printf("[WARN] Error finding the NAT configuration file path: %s", err)
return ""
}
return filepath.Join(base, device, "nat/nat.conf")
return filepath.Join(base, device, netmapConfFile)
}

// playerNetmapConfPath returns the path to the network mapping configuration
// file.
func playerNetmapConfPath() string {
base, err := playerInstallationPath()
if err != nil {
log.Printf("Error finding the configuration root path: %s", err)
log.Printf("[WARN] Error finding the network mapping configuration file path: %s", err)
return ""
}
return filepath.Join(base, netmapConfFile)
}

// playerVerifyVersion verifies the VMware Workstation Player version
// against the required version.
func playerVerifyVersion(requiredVersion string) error {
if runtime.GOOS != osLinux {
return fmt.Errorf("driver is only supported on linux and windows, not %s", runtime.GOOS)
return fmt.Errorf("driver is only supported on Linux, not %s", runtime.GOOS)
}

// Using the default.
Expand Down
Loading

0 comments on commit 5a339b7

Please sign in to comment.