VMware Fusion Tips and Tricks
Overview
This writeup came about as I was trying to figure out better ways to manage my at home lab environment. I have an old laptop I use as a VMware Fusion host and run a handful of VM's in it - Domain Controller, Web Applicaiton Proxy, ADFS, Cert Authority, etc.. One of my goals was to allow my laptop to utilize its own power management capabities to sleep durring after hours - and wake automatically in the morning so my VM's would be ready and wating for me as I finish up my morning cup of coffee. I was stuggeling with how to get them boot up and shut down at predefined times - cleanly - after doing a bit of reasearch i came across the vmrun command. This lets you manage your VM's in fusoin via the command line! With that in mind - i was able to write up a quick script to power them up in the morning and down again in the evening. Once I had that in had, i whipped up a quick Launchd agent, and macOS handles the rest for me.
VMware Fusion command line tool
As I mentioned in the overview, I had been toying this idea over in my head, use applescript, automator, etc.. to accomplish the start up / shut down operations on a scheduled basis. After some dutiful Google reasearch I came across a forum post mentioning a command line tool to view running Virtual Machines, and was curious as to whatelse the command supported.
To start off - lets jump to Terminal app and run the vmrun command with no arguments
vmrun
With just that simple command we can see there are a handful of arguments we can use with the vmrun command
and surprise! There is a pair of arguments, start and stop that look like will do exactly what I want. The one quirk I have seen with this vmrun command is how you address which vm to act against. Rather than just addressing it as a short friendly name you have to specifiy the path to the VM file.
So for me, i want to manage the power state of a VM called Windows 10 x64, a working start command looks like this:
vmrun -T fusion start /Users/davidpacold/Virtual\ Machines.localized/Windows\ 10\ x64.vmwarevm
conversely a working shutdown command looks like:
vmrun -T fusion stop /Users/davidpacold/Virtual\ Machines.localized/Windows\ 10\ x64.vmwarevm
That is the vmrun command, the-T argument specifies if this is going to be run against fusion or workstation, and then the action - start / stop - and finally the path to my vm file.
So now that I have my working comamnds to start and stop my vms, I want to do this on a scheduled basis.
Exploration into LaunchD
The first thing I am going to do is build a script to start up and shutdown my virtual machines, esstentially just a repeating list of commands above but for each vm. Pretty straightforward stuff here - here is my example script. After the first VM boots, I have a sleep of 150, which is about a 2 minute 30 second wait before it kicks off the next one.
#!/bin/sh
# this script starts my 2 Virtual Machines daily
vmrun -T fusion start /Users/davidpacold/Virtual\ Machines.localized/Windows\ 10\ x64.vmwarevm
sleep 150
vmrun -T fusion start /Users/davidpacold/Virtual\ Machines.localized/Windows\ 10\ x64-2.vmwarevm
Save this file, I called mine vmstart.sh
Now we want to make the file executable - head back to the Terminal
run the command:
chmod 755 vmstart.sh
The next step we are going to do is create a new plist file that will configure our LaunchD service. There are a number of ways to configure our jobs - a great resource i would encourage you to take a look at is: https://launchd.info for all the details on the service and configuration options.
For me, I am going to a pair of files in the ~/Library/LaunchAgents/ folder
touch ~/Library/LaunchAgents/com.davidpacold.vm.start.plist
Lets edit the file and add our configuration, my plist file looks like this. My configuration based on the calendar interval settings runs my vm start script daily @ 7 am
<?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">
<dict>
<key>Label</key>
<string>com.davidpacold.vm.start</string>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>7</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<key>StandardErrorPath</key>
<string>/Users/davidpacold/documents/script/err.log</string>
<key>StandardOutPath</key>
<string>/Users/davidpacold/documents/script/out.log</string>
<key>ProgramArguments</key>
<array>
<string>/Users/davidpacold/documents/startvm.bashrc</string>
</array>
</dict>
</plist>
Now Save the file
Now we will load the plist into the LaunchD service so that it executes on our requested schedule
Launchctl load ~/Library/LaunchAgents/com.davidpacold.start.vm.plist
To verify our plist was loaded successfully, run the command:
launchctl list | grep com.davidpacold