-
Notifications
You must be signed in to change notification settings - Fork 40
/
Copy pathlibvirt_hooks_setup.sh
executable file
·151 lines (120 loc) · 3.68 KB
/
libvirt_hooks_setup.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#!/bin/sh
INIT_SYSTEM="runit" # systemd, openrc, runit
GPU="nvidia" # nvidia, amd
DISPLAY_MANAGER="yes" # yes, no
WINDOW_MANAGER="niri" # required if not using display manager
START_WINDOW_MANAGER="dbus-run-session niri --session" # not sure if this works
GPU_PCI="pci_0000_01_00_0"
GPU_AUDIO_PCI="pci_0000_01_00_1"
VM_NAME="win10" # name of VM set during creation
mkdir -pv tmp
sudo_cmd="sudo"
if command -v doas >/dev/null; then
sudo_cmd="doas"
fi
start_service() {
case $INIT_SYSTEM in
"systemd") echo "systemctl start $1";;
"openrc") echo "rc-service $1 start";;
"runit") echo "sv up $1";;
esac
}
stop_service() {
case $INIT_SYSTEM in
"systemd") echo "systemctl stop $1";;
"openrc") echo "openrc $1 stop";;
"runit") echo "sv down $1";;
esac
}
cat > ./tmp/qemu_hook<< "EOF"
#!/bin/bash
GUEST_NAME="$1"
HOOK_NAME="$2"
STATE_NAME="$3"
MISC="${@:4}"
BASEDIR="$(dirname $0)"
HOOKPATH="$BASEDIR/qemu.d/$GUEST_NAME/$HOOK_NAME/$STATE_NAME"
set -e # If a script exits with an error, we should as well.
if [ -f "$HOOKPATH" ]; then
eval \""$HOOKPATH"\" "$@"
elif [ -d "$HOOKPATH" ]; then
while read file; do
eval \""$file"\" "$@"
done <<< "$(find -L "$HOOKPATH" -maxdepth 1 -type f -executable -print;)"
fi
EOF
if [ "$DISPLAY_MANAGER" = "yes" ]; then
# TODO: use service provided by package if display-manager is not valid service
dm_start=$(start_service "display-manager")
dm_stop=$(stop_service "display-manager")
if [ "$INIT_SYSTEM" = "systemd" ]; then
plasma_stop="systemctl --user -M $USER@ stop plasma"
fi
else
dm_stop="pkill -x $WINDOW_MANAGER"
dm_start="su -l $USER -c $START_WINDOW_MANAGER"
fi
if [ "$GPU" = "amd" ]; then
gpu_modules="amdgpu"
elif [ "$GPU" = "nvidia" ]; then
gpu_modules="nvidia_drm nvidia_modeset nvidia_uvm nvidia"
fi
cat > ./tmp/libvirt_hook_start.sh<< EOF
#!/bin/bash
set -x
$dm_stop
$plasma_stop
# Unbind VTconsoles
echo 0 > /sys/class/vtconsole/vtcon0/bind
echo 0 > /sys/class/vtconsole/vtcon1/bind
# Unbind EFI Framebuffer
echo efi-framebuffer.0 > /sys/bus/platform/drivers/efi-framebuffer/unbind
modprobe -r $gpu_modules
virsh nodedev-detach $GPU_PCI
virsh nodedev-detach $GPU_AUDIO_PCI
modprobe vfio-pci
EOF
cat > ./tmp/libvirt_hook_stop.sh<< EOF
#!/bin/bash
set -x
# Attach GPU devices to host
virsh nodedev-reattach $GPU_PCI
virsh nodedev-reattach $GPU_AUDIO_PCI
# Unload vfio module
modprobe -r vfio-pci
# Rebind framebuffer to host
echo "efi-framebuffer.0" > /sys/bus/platform/drivers/efi-framebuffer/bind
# Load NVIDIA kernel modules
$(for module in $gpu_modules; do
echo "modprobe $module"
done)
# Bind VTconsoles
echo 1 > /sys/class/vtconsole/vtcon0/bind
echo 1 > /sys/class/vtconsole/vtcon1/bind
$dm_start
EOF
get_yes_no_input() {
while true; do
echo -n "$1 (yes/no): "
read yn
case $yn in
[Yy]* ) return 0;;
[Nn]* ) return 1;;
* ) echo "Please answer yes or no.";;
esac
done
}
chmod +x -v tmp/qemu_hook
chmod +x -v tmp/libvirt_hook_start.sh
chmod +x -v tmp/libvirt_hook_stop.sh
if get_yes_no_input "Want me to copy hooks files?"; then
$sudo_cmd mkdir -pv /etc/libvirt/hooks
$sudo_cmd mkdir -pv /etc/libvirt/hooks/qemu.d/$VM_NAME/prepare/begin
$sudo_cmd mkdir -pv /etc/libvirt/hooks/qemu.d/$VM_NAME/release/end
$sudo_cmd cp -v --preserve ./tmp/qemu_hook /etc/libvirt/hooks/qemu
$sudo_cmd cp -v --preserve ./tmp/libvirt_hook_start.sh /etc/libvirt/hooks/qemu.d/$VM_NAME/prepare/begin/start.sh
$sudo_cmd cp -v --preserve ./tmp/libvirt_hook_stop.sh /etc/libvirt/hooks/qemu.d/$VM_NAME/release/end/stop.sh
echo "\033[1;32m✓ DONE \033[0m"
else
echo "\033[1;32m✓ You can manually copy hooks from tmp directory.\033[0m"
fi