Normally in an enterprise environment you could use something like PowerChute to allow a networked UPS to send out a signal letting your hosts know to shutdown gracefully before the battery runs out of power. At home though I just have a single VMware ESXI host running on an Intel NUC using a small APC UPS which only has a USB connector.

Doing some research it looked like there wasn't a good way to handle communication with the UPS from the ESXI host itself, so after connecting it with a USB cable to the UPS I enabled the USB passthrough and connected it to my Ansible VM. The USB passthrough is pretty straightforward, under the settings for the VM just select Add other device and then USB device. A new USB device will show up in the settings and, assuming the UPS is detected correctly, select it from the pull down. You can then check to see that the guest detected it with dmesg.

Select USB device from the Add other device menu
Then assign the new USB device to the UPS in the drop down menu

Now that the guest had attached the UPS USB connection I installed APCUPSD, "a daemon for controlling APC UPSes"

sudo apt-get install apcupsd

The configuration file  is located at /etc/apcupsd/apcupsd.conf on Ubuntu and needs configuration for a few options to point it to the UPS.

The basic settings that need to be configured are:

UPSCABLE usb
UPSTYPE usb
DEVICE

Below in the default config file are options regarding the location of scripts to trigger from when the UPS enters a specific state and timing options that can be customized depending on the load on the battery and tolerance for a short power interruption.

Once the basic configuration is in place apcaccess status will pull basic information from the UPS. APCUPSD includes a test program to, sudo apctest but before running this the APCUPSD service must be stopped first.

Once APCUPSD is configured I added a script to call an Ansible playbook to  /etc/apcupsd/doshutdown

This script will run the short Ansible playbook below which connects to the VMware ESXI host and perform a safe shutdown.

This involves enabling ssh access on the host so for safety I loaded my public key on the ESXI host and set the sshd configuration to not allow password logins.

One final consideration is to make sure that the necessary networking equipment can run from battery power to relay any needed requests which seems obvious but I have seen plenty of environments where this was overlooked and shutdown requests don't make it to the intended destination.