Parallels VM: Is there a way to run a script on the host when launching a VM

parallels-desktop

My Parallels VM is configured to use some network services on the host mac via the virtual network, but as the virtual network is not up when the mac host's services are started at boot they aren't listening on the virtual interface and the VM can't connect to them. After starting the VM I have to remember to manually restart those services on the mac host so that they are listening on the virtual network. It's annoying when I forget to do so…

I'd like to automate this process if possible. Is there any way to configure Parallels to run a shell script on the host after a VM is started and the virtual network is up? (Suggestions for how to run a startup script on the guest VM are not germane.)

Best Answer

Absent somebody pointing out a way to do this within Parallels itself, here's a solution using only native utilities - thanks @user3439894 for suggesting a Launch Agent!

  1. Create a /usr/local/bin/parallels_vm_starting shell script and chmod 755 it to make it executable:
#!/bin/bash

(
    echo "----------"
    date

    if /usr/bin/tty -s
    then
        echo "interactive"
    else
        # sleep for a bit to give things a chance to settle
        echo "background - let things settle"
        sleep 15
        date
    fi

    # Actions to perform when hosted VM starts up

    /usr/local/Homebrew/bin/brew services restart redis

    # etc. as needed

    date

) 2>&1 | tee -a /tmp/vm-startup.log
  1. Create a Launch Agent file ~/Library/LaunchAgents/parallels_vm_startup.plist with this content:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
        <string>parallels_vm_startup</string>
    <key>ProgramArguments</key>
        <array>
            <string>/usr/local/bin/parallels_vm_starting</string>
        </array>
    <key>WatchPaths</key>
        <array>
            <string>/Library/Preferences/Parallels/parallels_dhcp_leases</string>
        </array>
    <key>StandardOutPath</key>
        <string>/dev/null</string>
</dict>
</plist>

This will monitor the file /Library/Preferences/Parallels/parallels_dhcp_leases, which Parallels modifies when the VM starts (assuming the VM has networking enabled), and will execute the shell script when that happens.

Note: the DHCP leases file is regularly updated while the VM is up. If you only want to react to a VM being launched or shut down, monitor the file /Library/Preferences/Parallels/vmdirectorylist.desktop.xml instead.

  1. Activate the Agent: launchctl load ~/Library/LaunchAgents/parallels_vm_startup.plist