If you’ve been using Libvirt for a while, you might have found yourself needing to run a command on startup or shutdown of a VM. Libvirt has a hook system which allows you to do just this, but it is fairly complicated to get to work, not to mention it isn’t very modular.
We’ve created a drop-in hook helper in our VFIO-Tools project to de-complicate and streamline this process, while also adding more modularity and support for virtually unlimited drop-in scripts.
Read Also: Switching monitor inputs in software
The VFIO-Tools Hook Helper
Our hook helper is the first of many PCI passthrough and virtualization utilities we’ve got planned. It’s a simple drop-in script you put in your Libvirt configuration, unless you’ve already installed hooks in the past, it shouldn’t cause any conflicts with your existing configuration. You can get it from our VFIO-Tools repository on GitHub.
The hook helper itself is only a single script at the moment, so installation is simple. All you need to do is save this file in /etc/libvirt/hooks. By default, this directory does not exist, so we have to create it first:
sudo mkdir -p /etc/libvirt/hooks
Now, we have to download the hook helper.
If you already have hooks set up, the next step will overwrite your existing hooks.
If you don’t know if you’ve set up hooks, check if the file `/etc/libvirt/hooks/qemu` exists. Create a backup of it before proceeding, if it exists.
Run the following command to install the hook manager and make it executable:
sudo wget 'https://raw.githubusercontent.com/PassthroughPOST/VFIO-Tools/master/libvirt_hooks/qemu' \ -O /etc/libvirt/hooks/qemu sudo chmod +x /etc/libvirt/hooks/qemu
In order for Libvirt to recognize the file, we have to restart it:
sudo service libvirtd restart
That’s it, the hook helper is now installed.
So, how do we use it? Simple!
Libvirt calls hooks every time something noteworthy happens to a VM. You can find the full set of supported hooks on the libvirt website, but we’ll run you through the most important ones. First we need a bit of insight in how Libvirt handles hooks. When a hook fires, Libvirt calls the hook script like this:
/etc/libvirt/hooks/qemu $object $operation $sub-operation $extra_argument
In simpler terms it looks like this:
/etc/libvirt/hooks/qemu $vm_name $hook_name $sub_name $extra
This is pretty annoying to work with, so our hook manager calls hooks like this instead:
If this path exists, the hook manager searches for executable files in this directory. It’ll then execute every file it finds with the same arguments it itself got from Libvirt. For example, let’s assume we have a VM called “win10”. We want this VM to run a script called “script.sh” every time we start the VM.
To achieve this, we simply save the script in the following location:
We also make it executable:
sudo chmod +x /etc/libvirt/hooks/qemu.d/win10/prepare/begin/script.sh
Now, every time we start this VM, the hook will be called like this:
/etc/libvirt/hooks/qemu.d/win10/prepare/begin/script.sh win10 prepare begin -
You can create as many hook files like this as you want. You’re not just limited to bash scripts either. Anything you put in the hashbang should work.
The most important hooks are:
# Before a VM is started, before resources are allocated: /etc/libvirt/hooks/qemu.d/$vmname/prepare/begin/* # Before a VM is started, after resources are allocated: /etc/libvirt/hooks/qemu.d/$vmname/start/begin/* # After a VM has started up: /etc/libvirt/hooks/qemu.d/$vmname/started/begin/* # After a VM has shut down, before releasing its resources: /etc/libvirt/hooks/qemu.d/$vmname/stopped/end/* # After a VM has shut down, after resources are released: /etc/libvirt/hooks/qemu.d/$vmname/release/end/*
Join our discord to discuss the Hooks Helper with our dev team!
We’re excited to finally deliver VFIO-Tools and Hooks Helper — but developing them takes a lot of time and effort. Consider becoming a Patron to keep projects like these alive.