Skip to content

Commit ee948ac

Browse files
authored
refactor: consolidate workstation driver (#232)
- 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>
1 parent a48b4c1 commit ee948ac

10 files changed

Lines changed: 477 additions & 463 deletions

builder/vmware/common/driver.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ const (
3535
// Reference: dub.sh/vmw-ws-personal-use
3636
// Version 17.6.2 removed the license key requirement for commercial, educational, and personal use.
3737
// References: dub.sh/vmw-ws-free, dub.sh/vmw-ws-176-rn
38+
workstationInstallationPathKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\vmware.exe"
39+
workstationDhcpRegistryKey = "SYSTEM\\CurrentControlSet\\services\\VMnetDHCP\\Parameters"
3840

3941
// VMware Workstation Player.
4042
playerProductName = "VMware Workstation Player"
@@ -58,6 +60,7 @@ const (
5860
// Operating systems.
5961
osWindows = "windows"
6062
osLinux = "linux"
63+
osMacOS = "darwin"
6164

6265
// Clone types.
6366
cloneTypeLinked = "linked"
@@ -72,6 +75,7 @@ const (
7275
appPlayer = "vmplayer"
7376
appVdiskManager = "vmware-vdiskmanager"
7477
appVmrun = "vmrun"
78+
appVmware = "vmware"
7579
appVmx = "vmware-vmx"
7680
appQemuImg = "qemu-img"
7781

@@ -206,8 +210,7 @@ func NewDriver(dconfig *DriverConfig, config *SSHConfig, vmName string) (Driver,
206210
fallthrough
207211
case "windows":
208212
drivers = []Driver{
209-
NewWorkstation10Driver(config),
210-
NewWorkstation9Driver(config),
213+
NewWorkstationDriver(config),
211214
NewPlayerDriver(config),
212215
}
213216
default:

builder/vmware/common/driver_player_unix.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ import (
2020

2121
// VMware Workstation Player on Linux
2222

23+
// These variables are defined to silence unused constant warnings.
24+
// They reference the Windows-only registry constants that are not used in Unix environments.
25+
var (
26+
_ = playerInstallationPathKey
27+
_ = playerDhcpRegistryKey
28+
)
29+
2330
// playerFindVmplayer returns the path to the VMware Workstation Player executable.
2431
func playerFindVmplayer() (string, error) {
2532
return exec.LookPath(appPlayer)

builder/vmware/common/driver_workstation9.go renamed to builder/vmware/common/driver_workstation.go

Lines changed: 104 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ import (
1818
"github.com/hashicorp/packer-plugin-sdk/multistep"
1919
)
2020

21-
// Template for the network mapper configuration file, 'netmap.conf'.
21+
// VMware Workstation
22+
23+
// netmapTemplate is a template for the network mapper configuration file.
2224
// This file is used to map network devices to their respective network names.
2325
// This template is used to generate the file if the default file does not
2426
// exist on the system.
@@ -52,29 +54,53 @@ type NetmapConfig struct {
5254
Device string
5355
}
5456

55-
// Workstation9Driver is a driver that can run VMware Workstation 9
56-
type Workstation9Driver struct {
57+
// WorkstationDriver is a driver for VMware Workstation.
58+
type WorkstationDriver struct {
5759
VmwareDriver
5860

5961
AppPath string
6062
VdiskManagerPath string
6163
VmrunPath string
6264

63-
// SSHConfig are the SSH settings for the Fusion VM
6465
SSHConfig *SSHConfig
6566
}
6667

67-
func NewWorkstation9Driver(config *SSHConfig) Driver {
68-
return &Workstation9Driver{
68+
// NewWorkstationDriver creates a new WorkstationDriver.
69+
func NewWorkstationDriver(config *SSHConfig) Driver {
70+
return &WorkstationDriver{
6971
SSHConfig: config,
7072
}
7173
}
7274

73-
func (d *Workstation9Driver) Clone(dst, src string, linked bool, snapshot string) error {
74-
return errors.New("linked clones are not supported on this version")
75+
// GetVmwareDriver returns the VmwareDriver.
76+
func (d *WorkstationDriver) GetVmwareDriver() VmwareDriver {
77+
return d.VmwareDriver
78+
}
79+
80+
// Clone clones a virtual machine.
81+
func (d *WorkstationDriver) Clone(dst, src string, linked bool, snapshot string) error {
82+
83+
var cloneType string
84+
if linked {
85+
cloneType = cloneTypeLinked
86+
} else {
87+
cloneType = cloneTypeFull
88+
}
89+
90+
args := []string{"-T", "ws", "clone", src, dst, cloneType}
91+
if snapshot != "" {
92+
args = append(args, "-snapshot", snapshot)
93+
}
94+
cmd := exec.Command(d.VmrunPath, args...)
95+
if _, _, err := runAndLog(cmd); err != nil {
96+
return err
97+
}
98+
99+
return nil
75100
}
76101

77-
func (d *Workstation9Driver) CompactDisk(diskPath string) error {
102+
// CompactDisk compacts a virtual machine disk based on the disk path.
103+
func (d *WorkstationDriver) CompactDisk(diskPath string) error {
78104
defragCmd := exec.Command(d.VdiskManagerPath, "-d", diskPath)
79105
if _, _, err := runAndLog(defragCmd); err != nil {
80106
return err
@@ -88,22 +114,27 @@ func (d *Workstation9Driver) CompactDisk(diskPath string) error {
88114
return nil
89115
}
90116

91-
func (d *Workstation9Driver) CreateDisk(output string, size string, adapterType string, typeId string) error {
92-
cmd := exec.Command(d.VdiskManagerPath, "-c", "-s", size, "-a", adapterType, "-t", typeId, output)
117+
// CreateDisk creates a virtual machine disk based on the output path, size,
118+
// adapter type, and type ID.
119+
func (d *WorkstationDriver) CreateDisk(output string, size string, adapter_type string, type_id string) error {
120+
cmd := exec.Command(d.VdiskManagerPath, "-c", "-s", size, "-a", adapter_type, "-t", type_id, output)
93121
if _, _, err := runAndLog(cmd); err != nil {
94122
return err
95123
}
96124

97125
return nil
98126
}
99127

100-
func (d *Workstation9Driver) CreateSnapshot(vmxPath string, snapshotName string) error {
128+
// CreateSnapshot creates a snapshot of a virtual machine based on the .vmx
129+
// file path and snapshot name.
130+
func (d *WorkstationDriver) CreateSnapshot(vmxPath string, snapshotName string) error {
101131
cmd := exec.Command(d.VmrunPath, "-T", "ws", "snapshot", vmxPath, snapshotName)
102132
_, _, err := runAndLog(cmd)
103133
return err
104134
}
105135

106-
func (d *Workstation9Driver) IsRunning(vmxPath string) (bool, error) {
136+
// IsRunning checks if a virtual machine is running based on the .vmx file path.
137+
func (d *WorkstationDriver) IsRunning(vmxPath string) (bool, error) {
107138
vmxPath, err := filepath.Abs(vmxPath)
108139
if err != nil {
109140
return false, err
@@ -124,14 +155,17 @@ func (d *Workstation9Driver) IsRunning(vmxPath string) (bool, error) {
124155
return false, nil
125156
}
126157

127-
func (d *Workstation9Driver) CommHost(state multistep.StateBag) (string, error) {
158+
// CommHost returns the host address based on the SSH configuration.
159+
func (d *WorkstationDriver) CommHost(state multistep.StateBag) (string, error) {
128160
return CommHost(d.SSHConfig)(state)
129161
}
130162

131-
func (d *Workstation9Driver) Start(vmxPath string, headless bool) error {
132-
guiArgument := "gui"
133-
if headless {
134-
guiArgument = "nogui"
163+
// Start powers on a virtual machine based on the .vmx file path and mode
164+
// (headless or GUI).
165+
func (d *WorkstationDriver) Start(vmxPath string, headless bool) error {
166+
guiArgument := guiArgumentNoGUI
167+
if !headless {
168+
guiArgument = guiArgumentGUI
135169
}
136170

137171
cmd := exec.Command(d.VmrunPath, "-T", "ws", "start", vmxPath, guiArgument)
@@ -142,56 +176,64 @@ func (d *Workstation9Driver) Start(vmxPath string, headless bool) error {
142176
return nil
143177
}
144178

145-
func (d *Workstation9Driver) Stop(vmxPath string) error {
179+
// Stop powers off a virtual machine based on the .vmx file path.
180+
func (d *WorkstationDriver) Stop(vmxPath string) error {
146181
cmd := exec.Command(d.VmrunPath, "-T", "ws", "stop", vmxPath, "hard")
147182
if _, _, err := runAndLog(cmd); err != nil {
183+
// Check if the virtual machine is running. If not, it is stopped.
184+
running, runningErr := d.IsRunning(vmxPath)
185+
if runningErr == nil && !running {
186+
return nil
187+
}
148188
return err
149189
}
150190

151191
return nil
152192
}
153193

154-
func (d *Workstation9Driver) SuppressMessages(vmxPath string) error {
194+
// SuppressMessages suppresses messages for a virtual machine based on the .vmx
195+
// file path.
196+
func (d *WorkstationDriver) SuppressMessages(vmxPath string) error {
155197
return nil
156198
}
157199

158-
func (d *Workstation9Driver) Verify() error {
159-
var err error
160-
if d.AppPath == "" {
161-
if d.AppPath, err = workstationFindVMware(); err != nil {
162-
return err
200+
// Verify checks if the VMware Workstation installation is valid.
201+
func (d *WorkstationDriver) Verify() error {
202+
log.Printf("[INFO] Searching for %s...", workstationProductName)
203+
204+
if err := workstationVerifyVersion(workstationMinVersionObj.String()); err != nil {
205+
return fmt.Errorf("version verification failed: %s", err)
206+
}
207+
208+
components := map[string]*string{
209+
appVmware: &d.AppPath,
210+
appVmrun: &d.VmrunPath,
211+
appVdiskManager: &d.VdiskManagerPath,
212+
}
213+
214+
for name, path := range components {
215+
if *path == "" {
216+
var finderFunc func() (string, error)
217+
switch name {
218+
case appVmware:
219+
finderFunc = workstationFindVMware
220+
case appVmrun:
221+
finderFunc = workstationFindVmrun
222+
case appVdiskManager:
223+
finderFunc = workstationFindVdiskManager
224+
default:
225+
return fmt.Errorf("unknown component: %s", name)
226+
}
227+
228+
if foundPath, err := finderFunc(); err != nil {
229+
return fmt.Errorf("%s not found: %s", name, err)
230+
} else {
231+
*path = foundPath
232+
log.Printf("[INFO] - %s found at: %s", name, *path)
233+
}
163234
}
164235
}
165236

166-
if d.VmrunPath == "" {
167-
if d.VmrunPath, err = workstationFindVmrun(); err != nil {
168-
return err
169-
}
170-
}
171-
172-
if d.VdiskManagerPath == "" {
173-
if d.VdiskManagerPath, err = workstationFindVdiskManager(); err != nil {
174-
return err
175-
}
176-
}
177-
178-
log.Printf("[INFO] VMware app path: %s", d.AppPath)
179-
log.Printf("[INFO] vmrun path: %s", d.VmrunPath)
180-
log.Printf("[INFO] vdisk-manager path: %s", d.VdiskManagerPath)
181-
182-
if _, err := os.Stat(d.AppPath); err != nil {
183-
return fmt.Errorf("application not found: %s", d.AppPath)
184-
}
185-
186-
if _, err := os.Stat(d.VmrunPath); err != nil {
187-
return fmt.Errorf("'vmrun' not found in path: %s", d.VmrunPath)
188-
}
189-
190-
if _, err := os.Stat(d.VdiskManagerPath); err != nil {
191-
return fmt.Errorf("'vmware-vdiskmanager' not found in path: %s", d.VdiskManagerPath)
192-
}
193-
194-
// Check to see if it APPEARS to be licensed.
195237
if err := workstationCheckLicense(); err != nil {
196238
return err
197239
}
@@ -206,7 +248,7 @@ func (d *Workstation9Driver) Verify() error {
206248
}
207249

208250
d.VmnetnatConfPath = func(device string) string {
209-
return workstationVmnetnatConfPath(device)
251+
return workstationNatConfPath(device)
210252
}
211253

212254
d.NetworkMapper = func() (NetworkNameMapper, error) {
@@ -242,18 +284,16 @@ func (d *Workstation9Driver) Verify() error {
242284
return nil
243285
}
244286

245-
func (d *Workstation9Driver) ToolsIsoPath(flavor string) string {
287+
// ToolsIsoPath returns the path to the VMware Tools ISO based on the flavor.
288+
func (d *WorkstationDriver) ToolsIsoPath(flavor string) string {
246289
return workstationToolsIsoPath(flavor)
247290
}
248291

249-
func (d *Workstation9Driver) ToolsInstall() error {
292+
// ToolsInstall installs VMware Tools.
293+
func (d *WorkstationDriver) ToolsInstall() error {
250294
return nil
251295
}
252296

253-
func (d *Workstation9Driver) GetVmwareDriver() VmwareDriver {
254-
return d.VmwareDriver
255-
}
256-
257297
// checkNetmapConfExists checks if the network mapper configuration file exists.
258298
// If not, if attempts to generate the file using generateNetmapConfig.
259299
func checkNetmapConfExists() (NetworkNameMapper, error) {
@@ -272,10 +312,10 @@ func checkNetmapConfExists() (NetworkNameMapper, error) {
272312
return nil, fmt.Errorf("error determining network mappings from files %w", err)
273313
}
274314

275-
log.Printf("A network mapper configuration file does not exist in the default path: %s", pathNetmap)
315+
log.Printf("[INFO] A network mapper configuration file does not exist in the default path: %s", pathNetmap)
276316

277317
// The file does not exist, check the alternate configuration path.
278-
libpath, _ := workstationVMwareRoot()
318+
libpath, _ := workstationInstallationPath()
279319
pathNetworking := filepath.Join(libpath, "networking")
280320
log.Printf("[INFO] Checking alternate path for network mapper configuration file: %s", pathNetworking)
281321
_, err = os.Stat(pathNetworking)
@@ -336,7 +376,7 @@ func generateNetmapConfig() (string, error) {
336376

337377
var pathNetmap string
338378
for _, basePath := range paths {
339-
path := filepath.Join(basePath, "netmap.conf")
379+
path := filepath.Join(basePath, netmapConfFile)
340380
if err := os.MkdirAll(basePath, 0755); err != nil {
341381
continue // Skip to the next path on error.
342382
}

builder/vmware/common/driver_workstation10.go

Lines changed: 0 additions & 56 deletions
This file was deleted.

0 commit comments

Comments
 (0)