Hello
I would like to know how I can configure a native way to forbid that 2 VMs run together ?
Thank’s
Hello
I would like to know how I can configure a native way to forbid that 2 VMs run together ?
Thank’s
Last time I tried this, I was sucessfully able to prevent a qube to start with a libxl hook BUT I wasn’t able to allow it to start … so it’s just an idea:
If that helps for doing researches, this is called “anti affinity”, when you do not want 2 VM to run on the same host. In Qubes OS case, you just have a host group of 1 host.
Something like this in dom0 in executable /etc/libvirt/hooks/libxl
might do:
#!/bin/bash
set -e
qube_name="$1"
libvirt_operation="$2"
case $qube_name in
qube1)
blocker="qube2"
;;
qube2)
blocker="qube1"
;;
*)
exit
;;
esac
if [[ "$libvirt_operation" = "prepare" ]] ; then
(
exec 0</dev/null
exec 1>/dev/null
exec 2>/dev/null
if qvm-check --running -q $blocker; then
qvm-kill $qube_name
fi
) & disown
fi
I never presume to speak for the Qubes team.
When I comment in the Forum I speak for myself.
Well, I was trying to play again with the libxl hooks before @unman’s solution… So anyway, here’s my dirty script:
#!/usr/bin/env python3
import sys
from pathlib import Path
guest_name, operation = sys.argv[1:3]
OPERATIONS = ['prepare', 'release']
STATUS_ROOT = Path('/tmp')
STATUS_NAME = ".anti-affinity-status-for-{}-vm"
guest_names = [f"antiaffinity{x}" for x in range(3)]
# Hook checks
try:
guest_names.pop(guest_names.index(guest_name))
except ValueError:
sys.exit()
if operation not in OPERATIONS:
sys.exit()
# Status checks
status_path = STATUS_ROOT / STATUS_NAME.format(guest_name)
if operation == OPERATIONS[0]:
for other_name in guest_names:
other_path = STATUS_ROOT / STATUS_NAME.format(other_name)
if other_path.exists():
sys.exit(1)
status_path.touch()
elif operation == OPERATIONS[1]:
status_path.unlink(missing_ok=True)
It works with 2 or more guests and uses a file in /tmp
to check the status of any other guest listed in guest_names
… But using Qubes’ own tools maybe better (but longer?).
Instead of putting any script in a file called /etc/libvirt/hooks/libxl
, I recommend to put it into a file with any name, inside a directory called /etc/libvirt/hooks/libxl.d
. You have to create the directory, the file and check that the file is executable. Then, you can test it on command line:
/etc/libvirt/hooks/libxl.d/my-script.ext "$GUEST_NAME" prepare - -; echo "Exit status: $?"
Of course, replace $GUEST_NAME
by any guest name you want and you can use an other operation name instead of prepare
.
If the exit status is different from 0, the VM won’t start. If everything is alright, restart the libvirt daemon, as suggested here:
I was trying to achieve what @unman is doing but without the disown
part, thus the system was hanging indefinitely. Maybe because calling Qubes tools is like doing the forbidden calls as said in the libvirt’s docs?
Calling libvirt functions from within a hook script
A hook script must not call back into libvirt, as the libvirt daemon is already waiting for the script to exit.
A deadlock is likely to occur.
Hi
This solution works fine after 1 modification :
Replace if [[ "$libvirt_operation" = "prepare" ]] ; then
By if [[ "${libvirt_operation}" = "prepare" ]] ; then
This modification has directly worked to enter in the condition and kill next the vm.
Still thank’s for the solution
I don’t understand why this change fix anything. But I’m glad you got something working.
[user@dev shm]$ cat test.sh
#!/bin/bash
echo $SHELL
libvirt_operation="prepare"
if [[ "$libvirt_operation" = "prepare" ]] ; then
echo "it worked"
fi
if [[ "${libvirt_operation}" = "prepare" ]] ; then
echo "it worked"
fi
libvirt_operation="something else"
if [[ "$libvirt_operation" = "prepare" ]] ; then
echo "it worked"
else
echo "it's false"
fi
if [[ "${libvirt_operation}" = "prepare" ]] ; then
echo "it worked"
else
echo "it's false"
fi
[user@dev shm]$ bash test.sh
/bin/bash
it worked
it worked
it's false
it's false