Refactor GPU passthrough logic in build.func
Some checks failed
Bump build.func Revision / bump-revision (push) Has been cancelled
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:
parent
6560a7c212
commit
633ca3edee
270
misc/build.func
270
misc/build.func
@ -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) echo 44 ;;
|
||||||
video) gid=44 ;;
|
render) echo 104 ;;
|
||||||
render) gid=104 ;;
|
*) echo 44 ;;
|
||||||
*) gid=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
|
local dev="$1" idx="$2"
|
||||||
configure_vaapi_device() {
|
|
||||||
local device="$1"
|
|
||||||
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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user