Initial Commit
This commit is contained in:
commit
c896225cbd
|
@ -0,0 +1,33 @@
|
||||||
|
# Maintainer: David Thurstenson (thurstylark@gmail.com)
|
||||||
|
pkgname=libvirt-usb-hotplug
|
||||||
|
pkgver=0.1
|
||||||
|
pkgrel=1
|
||||||
|
pkgdesc="Attach and detach USB devices from libvirt guests based on udev rules"
|
||||||
|
arch=(any)
|
||||||
|
url="https://git.thurstylark.com/libvirt-usb-hotplug.git"
|
||||||
|
license=('GPL')
|
||||||
|
depends=('systemd'
|
||||||
|
'udev'
|
||||||
|
'libvirt')
|
||||||
|
backup=()
|
||||||
|
source=("libvirt-usb-hotplug.bash"
|
||||||
|
"libvirt-usb-hotplug.conf"
|
||||||
|
"libvirt-usb-hotplug.rules"
|
||||||
|
"libvirt-usb-hotplug@.service"
|
||||||
|
)
|
||||||
|
sha256sums=()
|
||||||
|
|
||||||
|
package() {
|
||||||
|
install -Dm755 \
|
||||||
|
"${srcdir}"/libvirt-usb-hotplug.bash \
|
||||||
|
"${pkgdir}"/usr/bin/libvirt-usb-hotplug
|
||||||
|
install -Dm644 \
|
||||||
|
"${srcdir}"/libvirt-usb-hotplug.conf \
|
||||||
|
"${pkgdir}"/etc/libvirt-usb-hotplug.conf
|
||||||
|
install -Dm644 \
|
||||||
|
"${srcdir}"/libvirt-usb-hotplug.rules \
|
||||||
|
"${pkgdir}"/usr/lib/udev/rules.d/99-libvirt-usb-hotplug.rules
|
||||||
|
install -Dm644 \
|
||||||
|
"${srcdir}"/libvirt-usb-hotplug@.service \
|
||||||
|
"${pkgdir}"/usr/lib/systemd/system/libvirt-usb-hotplug@.service
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# libvirt-usb-hotplug.bash
|
||||||
|
|
||||||
|
# This script can be used to hotplug USB devices to libvirt virtual
|
||||||
|
# machines from udev rules with systemd services.
|
||||||
|
|
||||||
|
# References:
|
||||||
|
# - https://github.com/olavmrk/usb-libvirt-hotplug
|
||||||
|
# - http://kicherer.org/joomla/index.php/en/blog/48-automatic-hotplugging-of-usb-devices-for-libvirt-managed-vms
|
||||||
|
# - https://blog.tjll.net/systemd-for-device-activation-and-media-archiving/
|
||||||
|
|
||||||
|
|
||||||
|
# Abort script execution on errors
|
||||||
|
set -e
|
||||||
|
|
||||||
|
readvars() {
|
||||||
|
PROG="$(basename "$0")"
|
||||||
|
ACTION=$1
|
||||||
|
IFS='_' read DOMAIN ID_VENDOR_ID ID_MODEL_ID <<< "$2"
|
||||||
|
|
||||||
|
if [ -z "${DOMAIN}" ]; then
|
||||||
|
echo "Missing libvirt domain parameter for ${PROG}." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
findmatch() {
|
||||||
|
# Iterate through devlist to find match
|
||||||
|
for i in "${devlist[@]}"; do
|
||||||
|
# If we find a match, return successfully
|
||||||
|
[ "${ID_VENDOR_ID}:${ID_MODEL_ID}" = "$i" ] && return 0
|
||||||
|
# If a match can't be found, keep looping
|
||||||
|
continue
|
||||||
|
done
|
||||||
|
# If no match was found, return unsuccessfully
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
case ${ACTION} in
|
||||||
|
add)
|
||||||
|
readvars
|
||||||
|
COMMAND='attach-device'
|
||||||
|
;;
|
||||||
|
remove)
|
||||||
|
readvars
|
||||||
|
COMMAND='detach-device'
|
||||||
|
;;
|
||||||
|
match)
|
||||||
|
# This section is responsible for determining if the corresponding udev rule
|
||||||
|
# matches against the device in question. Udev watches exit code to determine
|
||||||
|
# if a match was made.
|
||||||
|
#
|
||||||
|
# Ref: udev(7) manpage
|
||||||
|
|
||||||
|
# Read the config file
|
||||||
|
source /etc/libvirt-usb-hotplug.conf
|
||||||
|
|
||||||
|
# If we should match against any usb device, just exit successfully
|
||||||
|
[ "$matchall" = "true" ] && exit 0
|
||||||
|
|
||||||
|
# If the devlist array is empty, no matches can be made
|
||||||
|
[ ${#devlist[@]} = 0 ] && exit 1
|
||||||
|
|
||||||
|
# If targetdomain is unset or empty, exit unsuccessfully
|
||||||
|
[ ! -v targetdomain ] && exit 1
|
||||||
|
[ "$targetdomain" = "" ] && exit 1
|
||||||
|
# Print the targetdomain so it can be picked back up by the udev rule
|
||||||
|
printf "%s" "$targetdomain"
|
||||||
|
|
||||||
|
case $listmode in
|
||||||
|
whitelist)
|
||||||
|
# findmatch() returns 0 if match found, and 1 if match not found
|
||||||
|
findmatch
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
blacklist)
|
||||||
|
# Reverse the exit status of findmatch() for blacklist mode
|
||||||
|
! findmatch
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# If listmode is unset, or set improperly, exit unsuccessfully
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Invalid script ACTION: ${ACTION}" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Run the appropriate virsh-command, and ask it to read the update XML from stdin.
|
||||||
|
echo "Running virsh ${COMMAND} ${DOMAIN} --persistent for USB vendor=0x${ID_VENDOR_ID} product=0x${ID_MODEL_ID}:" >&2
|
||||||
|
(virsh "${COMMAND}" "${DOMAIN}" /dev/stdin --persistent || true) <<END
|
||||||
|
<hostdev mode='subsystem' type='usb' managed='yes'>
|
||||||
|
<source startupPolicy='optional'>
|
||||||
|
<vendor id='0x${ID_VENDOR_ID}' />
|
||||||
|
<product id='0x${ID_MODEL_ID}' />
|
||||||
|
</source>
|
||||||
|
</hostdev>
|
||||||
|
END
|
|
@ -0,0 +1,25 @@
|
||||||
|
# libvirt-usb-hotplug.conf
|
||||||
|
|
||||||
|
# Name of libvirt domain to which the device in question will be attached
|
||||||
|
# Default if unset: <none> (disables matching)
|
||||||
|
targetdomain=win10
|
||||||
|
|
||||||
|
# Match against every usb device
|
||||||
|
# Valid values: true, false
|
||||||
|
# Default if unset: false
|
||||||
|
matchall=true
|
||||||
|
|
||||||
|
# Should the list be a whitelist, or blacklist?
|
||||||
|
# Valid values: whitelist, blacklist
|
||||||
|
# Default if unset: <none> (disables matching)
|
||||||
|
listmode=blacklist
|
||||||
|
|
||||||
|
# List of devices to match against
|
||||||
|
# Value format: '<vendor_id>:<device_id>'
|
||||||
|
devlist=(
|
||||||
|
'0b05:1872' # ASUSTek Computer, Inc. AURA LED Controller
|
||||||
|
'0b05:185c' # ASUSTek Computer, Inc. Bluetooth Radio
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# vim: set ft=bash:
|
|
@ -0,0 +1,13 @@
|
||||||
|
# libvirt-usb-hotplug.rules
|
||||||
|
|
||||||
|
ACTION=="add", \
|
||||||
|
SUBSYSTEM=="usb", \
|
||||||
|
PROGRAM=="/usr/bin/libvirt-usb-hotplug match" \
|
||||||
|
SYMLINK+="libvirt_%c_%E{ID_VENDOR_ID}_%E{ID_MODEL_ID}", \
|
||||||
|
TAG+="systemd", \
|
||||||
|
ENV{SYSTEMD_WANTS}="libvirt_%c_%E{ID_VENDOR_ID}_%E{ID_MODEL_ID}"
|
||||||
|
|
||||||
|
ACTION=="remove", \
|
||||||
|
SUBSYSTEM=="usb", \
|
||||||
|
ENV{PRODUCT}=="46d/c215/*", \
|
||||||
|
TAG+="systemd"
|
|
@ -0,0 +1,15 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Libvirt guest usb hotplug: %I
|
||||||
|
After=libvirtd.service
|
||||||
|
BindsTo=dev-libvirt_%i.device
|
||||||
|
After=dev-libvirt_%i.device
|
||||||
|
Requisite=dev-libvirt_%i.device
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
RemainAfterExit=yes
|
||||||
|
ExecStart=/usr/bin/libvirt-usb-hotplug add %I
|
||||||
|
ExecStop=/usr/bin/libvirt-usb-hotplug remove %I
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=dev-libvirt_%i.device
|
Loading…
Reference in New Issue