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

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

Launchctl load ~/Library/LaunchAgents/com.davidpacold.start.vm.plist

launchctl list | grep com.davidpacold