Refactor GPU passthrough logic in build.func
Some checks failed
Bump build.func Revision / bump-revision (push) Has been cancelled

Simplifies and streamlines GPU passthrough configuration for LXC containers, consolidating device detection, selection, and userland package installation. Reduces code duplication, improves readability, and adds direct verification steps for VAAPI and NVIDIA support after installation.
This commit is contained in:
CanbiZ 2025-09-29 10:48:25 +02:00
parent 6560a7c212
commit 633ca3edee

View File

@ -2170,16 +2170,13 @@ build_container() {
# Get device GID dynamically # Get device GID dynamically
get_device_gid() { get_device_gid() {
local group="$1" local group="$1"
local gid gid=$(getent group "$group" | cut -d: -f3)
gid=$(getent group "$group" 2>/dev/null | cut -d: -f3) [[ -n "$gid" ]] && echo "$gid" && return
if [[ -z "$gid" ]]; then
case "$group" in case "$group" in
video) gid=44 ;; video) echo 44 ;;
render) gid=104 ;; render) echo 104 ;;
*) gid=44 ;; *) echo 44 ;;
esac esac
fi
echo "$gid"
} }
# Check if app needs GPU # Check if app needs GPU
@ -2192,24 +2189,18 @@ build_container() {
} }
# Detect available GPU devices # Detect available GPU devices
is_gpu_app() {
local app="${1,,}"
for gpu in "${GPU_APPS[@]}"; do
[[ "$gpu" == "$app" ]] && return 0
done
return 1
}
detect_gpu_devices() { detect_gpu_devices() {
VAAPI_DEVICES=() VAAPI_DEVICES=(); NVIDIA_DEVICES=()
NVIDIA_DEVICES=() for d in /dev/dri/renderD* /dev/dri/card*; do [[ -e $d ]] && VAAPI_DEVICES+=("$d"); done
for d in /dev/nvidia*; do [[ -e $d ]] && NVIDIA_DEVICES+=("$d"); done
# VAAPI / Intel / AMD
for device in /dev/dri/renderD* /dev/dri/card*; do
[[ -e "$device" ]] || continue
VAAPI_DEVICES+=("$device")
done
# NVIDIA
for device in /dev/nvidia*; do
[[ -e "$device" ]] || continue
NVIDIA_DEVICES+=("$device")
done
msg_debug "Detected VAAPI devices: ${VAAPI_DEVICES[*]:-(none)}"
msg_debug "Detected NVIDIA devices: ${NVIDIA_DEVICES[*]:-(none)}"
} }
# Configure USB passthrough for privileged containers # Configure USB passthrough for privileged containers
@ -2233,142 +2224,64 @@ lxc.mount.entry: /dev/ttyACM1 dev/ttyACM1 none bind,optional,create=
EOF EOF
msg_ok "USB passthrough configured" msg_ok "USB passthrough configured"
} }
# Configure VAAPI device
configure_vaapi_device() { configure_vaapi_device() {
local device="$1" local dev="$1" idx="$2"
local dev_index="$2"
if [[ "$CT_TYPE" == "0" ]]; then if [[ "$CT_TYPE" == "0" ]]; then
# Privileged container major=$(stat -c '%t' "$dev"); minor=$(stat -c '%T' "$dev")
local major minor echo "lxc.cgroup2.devices.allow: c $((0x$major)):$((0x$minor)) rwm" >>"$LXC_CONFIG"
major=$(stat -c '%t' "$device") echo "lxc.mount.entry: $dev dev/$(basename "$dev") none bind,optional,create=file" >>"$LXC_CONFIG"
minor=$(stat -c '%T' "$device")
major=$((0x$major))
minor=$((0x$minor))
echo "lxc.cgroup2.devices.allow: c $major:$minor rwm" >>"$LXC_CONFIG"
echo "lxc.mount.entry: $device dev/$(basename "$device") none bind,optional,create=file" >>"$LXC_CONFIG"
else else
# Unprivileged container [[ "$dev" =~ renderD ]] && gid=$(get_device_gid "render") || gid=$(get_device_gid "video")
local gid echo "dev$idx: $dev,gid=$gid" >>"$LXC_CONFIG"
if [[ "$device" =~ renderD ]]; then
gid=$(get_device_gid "render")
else
gid=$(get_device_gid "video")
fi
echo "dev${dev_index}: $device,gid=$gid" >>"$LXC_CONFIG"
fi fi
} }
# Configure NVIDIA devices
configure_nvidia_devices() { configure_nvidia_devices() {
for device in "${NVIDIA_DEVICES[@]}"; do for dev in "${NVIDIA_DEVICES[@]}"; do
if [[ "$CT_TYPE" == "0" ]]; then if [[ "$CT_TYPE" == "0" ]]; then
local major minor major=$(stat -c '%t' "$dev"); minor=$(stat -c '%T' "$dev")
major=$(stat -c '%t' "$device") echo "lxc.cgroup2.devices.allow: c $((0x$major)):$((0x$minor)) rwm" >>"$LXC_CONFIG"
minor=$(stat -c '%T' "$device") echo "lxc.mount.entry: $dev dev/$(basename "$dev") none bind,optional,create=file" >>"$LXC_CONFIG"
major=$((0x$major))
minor=$((0x$minor))
echo "lxc.cgroup2.devices.allow: c $major:$minor rwm" >>"$LXC_CONFIG"
echo "lxc.mount.entry: $device dev/$(basename "$device") none bind,optional,create=file" >>"$LXC_CONFIG"
else else
msg_warn "NVIDIA passthrough to unprivileged container may require additional configuration" msg_warn "NVIDIA passthrough on unprivileged CT may fail"
fi fi
done done
[[ -d /dev/dri && "$CT_TYPE" == "0" ]] && echo "lxc.mount.entry: /dev/dri dev/dri none bind,optional,create=dir" >>"$LXC_CONFIG"
if [[ -d /dev/dri ]] && [[ "$CT_TYPE" == "0" ]]; then
echo "lxc.mount.entry: /dev/dri dev/dri none bind,optional,create=dir" >>"$LXC_CONFIG"
fi
} }
# Main GPU configuration logic
configure_gpu_passthrough() { configure_gpu_passthrough() {
detect_gpu_devices detect_gpu_devices
local should=false
if [[ "$CT_TYPE" == "0" ]] || is_gpu_app "$APP"; then should=true; fi
[[ "$should" == "false" ]] && return
# Check if we should configure GPU if [[ ${#VAAPI_DEVICES[@]} -eq 0 && ${#NVIDIA_DEVICES[@]} -eq 0 ]]; then
local should_configure=false msg_info "No GPU devices found"; return
if [[ "$CT_TYPE" == "0" ]] || is_gpu_app "$APP"; then
should_configure=true
fi fi
if [[ "$should_configure" == "false" ]]; then local choices=() selected=()
return 0 [[ ${#VAAPI_DEVICES[@]} -gt 0 ]] && choices+=("VAAPI" "Intel/AMD GPU" "OFF")
fi [[ ${#NVIDIA_DEVICES[@]} -gt 0 ]] && choices+=("NVIDIA" "NVIDIA GPU" "OFF")
# No GPU devices available
if [[ ${#VAAPI_DEVICES[@]} -eq 0 ]] && [[ ${#NVIDIA_DEVICES[@]} -eq 0 ]]; then
msg_info "No GPU devices detected on host"
return 0
fi
# Build selection options
local choices=()
local SELECTED_GPUS=()
if [[ ${#VAAPI_DEVICES[@]} -gt 0 ]]; then
choices+=("VAAPI" "Intel/AMD GPU (${#VAAPI_DEVICES[@]} devices)" "OFF")
fi
if [[ ${#NVIDIA_DEVICES[@]} -gt 0 ]]; then
choices+=("NVIDIA" "NVIDIA GPU (${#NVIDIA_DEVICES[@]} devices)" "OFF")
fi
# Auto-select if only one type available
if [[ ${#choices[@]} -eq 3 ]]; then if [[ ${#choices[@]} -eq 3 ]]; then
SELECTED_GPUS=("${choices[0]}") selected=("VAAPI")
msg_info "Auto-configuring ${choices[0]} GPU passthrough" elif [[ ${#choices[@]} -eq 6 ]]; then
elif [[ ${#choices[@]} -gt 3 ]]; then read -rp "Multiple GPUs found (VAAPI/NVIDIA). Which passthrough? " sel
# Show selection dialog [[ "$sel" =~ VAAPI|vaapi ]] && selected=("VAAPI")
local selected [[ "$sel" =~ NVIDIA|nvidia ]] && selected=("NVIDIA")
selected=$(whiptail --title "GPU Passthrough Selection" \
--checklist "Multiple GPU types detected. Select which to pass through:" \
12 60 $((${#choices[@]} / 3)) \
"${choices[@]}" 3>&1 1>&2 2>&3) || {
msg_info "GPU passthrough skipped"
return 0
}
for item in $selected; do
SELECTED_GPUS+=("${item//\"/}")
done
fi fi
# Apply configuration for selected GPUs local idx=0
local dev_index=0 for s in "${selected[@]}"; do
for gpu_type in "${SELECTED_GPUS[@]}"; do case "$s" in
case "$gpu_type" in VAAPI) for d in "${VAAPI_DEVICES[@]}"; do configure_vaapi_device "$d" "$idx"; idx=$((idx+1)); done; export ENABLE_VAAPI=1 ;;
VAAPI) NVIDIA) configure_nvidia_devices; export ENABLE_NVIDIA=1 ;;
msg_info "Configuring VAAPI passthrough (${#VAAPI_DEVICES[@]} devices)"
for device in "${VAAPI_DEVICES[@]}"; do
configure_vaapi_device "$device" "$dev_index"
: "${dev_index:=0}"
dev_index=$((dev_index + 1))
done
if [[ "$CT_TYPE" == "0" ]] && [[ -d /dev/dri ]]; then
echo "lxc.mount.entry: /dev/dri dev/dri none bind,optional,create=dir" >>"$LXC_CONFIG"
fi
export ENABLE_VAAPI=1
;;
NVIDIA)
msg_info "Configuring NVIDIA passthrough"
configure_nvidia_devices
export ENABLE_NVIDIA=1
;;
esac esac
done done
[[ ${#selected[@]} -gt 0 ]] && msg_ok "GPU passthrough configured"
[[ ${#SELECTED_GPUS[@]} -gt 0 ]] && msg_ok "GPU passthrough configured"
} }
# ------------------------------------------------------------------------------
# Apply all hardware passthrough configurations
# ------------------------------------------------------------------------------
# USB passthrough (automatic for privileged)
configure_usb_passthrough configure_usb_passthrough
# GPU passthrough (based on container type and app)
configure_gpu_passthrough configure_gpu_passthrough
# TUN device passthrough # TUN device passthrough
@ -2438,67 +2351,30 @@ EOF
fi fi
fi fi
# # Install GPU userland packages install_gpu_userland() {
# install_gpu_userland() { local gpu="$1"
# local gpu_type="$1" if [[ "$var_os" == "alpine" ]]; then
case "$gpu" in
VAAPI) pct exec "$CTID" -- apk add mesa-dri-gallium mesa-va-gallium intel-media-driver libva-utils ;;
NVIDIA) msg_warn "NVIDIA drivers not in Alpine repos" ;;
esac
else
case "$gpu" in
VAAPI) pct exec "$CTID" -- bash -c "apt-get update && apt-get install -y intel-media-va-driver-non-free mesa-va-drivers vainfo" ;;
NVIDIA) pct exec "$CTID" -- bash -c "apt-get update && apt-get install -y nvidia-driver nvidia-utils libnvidia-encode1" ;;
esac
fi
}
# if [ "$var_os" == "alpine" ]; then if [[ "${ENABLE_VAAPI:-0}" == "1" ]]; then
# case "$gpu_type" in install_gpu_userland "VAAPI"
# VAAPI) pct exec "$CTID" -- bash -c "chgrp video /dev/dri && chmod 755 /dev/dri && chmod 660 /dev/dri/*"
# msg_info "Installing VAAPI packages in Alpine container" pct exec "$CTID" -- vainfo >/dev/null 2>&1 && msg_ok "VAAPI verified" || msg_warn "VAAPI failed"
# pct exec "$CTID" -- ash -c ' fi
# apk add --no-cache \ if [[ "${ENABLE_NVIDIA:-0}" == "1" ]]; then
# mesa-dri-gallium \ install_gpu_userland "NVIDIA"
# mesa-va-gallium \ pct exec "$CTID" -- nvidia-smi >/dev/null 2>&1 && msg_ok "NVIDIA verified" || msg_warn "NVIDIA failed"
# intel-media-driver \ fi
# libva-utils >/dev/null 2>&1
# ' || msg_warn "Some VAAPI packages may not be available in Alpine"
# ;;
# NVIDIA)
# msg_warn "NVIDIA drivers are not readily available in Alpine Linux"
# ;;
# esac
# else
# case "$gpu_type" in
# VAAPI)
# msg_info "Installing VAAPI userland packages"
# pct exec "$CTID" -- bash -c '
# . /etc/os-release || true
# if [[ "${VERSION_CODENAME:-}" == "trixie" ]]; then
# cat >/etc/apt/sources.list.d/non-free.sources <<EOF
# Types: deb deb-src
# URIs: http://deb.debian.org/debian
# Suites: trixie trixie-updates trixie-security
# Components: non-free non-free-firmware
# EOF
# fi
# apt-get update >/dev/null 2>&1
# DEBIAN_FRONTEND=noninteractive apt-get install -y \
# intel-media-va-driver-non-free \
# mesa-va-drivers \
# libvpl2 \
# vainfo \
# ocl-icd-libopencl1 \
# mesa-opencl-icd \
# intel-gpu-tools >/dev/null 2>&1
# ' && msg_ok "VAAPI userland installed" || msg_warn "Some VAAPI packages failed to install"
# ;;
# NVIDIA)
# msg_info "Installing NVIDIA userland packages"
# pct exec "$CTID" -- bash -c '
# apt-get update >/dev/null 2>&1
# DEBIAN_FRONTEND=noninteractive apt-get install -y \
# nvidia-driver \
# nvidia-utils \
# libnvidia-encode1 \
# libcuda1 >/dev/null 2>&1
# ' && msg_ok "NVIDIA userland installed" || msg_warn "Some NVIDIA packages failed to install"
# ;;
# esac
# fi
# }
# Customize container
msg_info "Customizing LXC Container" msg_info "Customizing LXC Container"
# # Install GPU userland if configured # # Install GPU userland if configured