Improve locale and template handling for LXC builds

Adds explicit locale package installation and locale setup for Debian, Ubuntu, Devuan, RHEL-based, openSUSE, and openEuler containers to ensure proper locale generation on minimal templates. Refines template pattern matching for CentOS Stream and Gentoo, and deduplicates openSUSE handling. Also, refactors misc/core.func for consistent indentation and minor logic improvements.
This commit is contained in:
CanbiZ 2026-01-12 13:58:25 +01:00
parent 79b8a934f2
commit 47b4ea5c40
2 changed files with 482 additions and 444 deletions

View File

@ -3246,6 +3246,9 @@ EOF'
;; ;;
debian | ubuntu | devuan) debian | ubuntu | devuan)
# First install locales package (required for locale-gen on minimal templates)
pct exec "$CTID" -- bash -c "apt-get update >/dev/null && apt-get install -y locales >/dev/null 2>&1 || true"
# Locale setup for Debian-based # Locale setup for Debian-based
pct exec "$CTID" -- bash -c "sed -i '/$LANG/ s/^# //' /etc/locale.gen 2>/dev/null || true" pct exec "$CTID" -- bash -c "sed -i '/$LANG/ s/^# //' /etc/locale.gen 2>/dev/null || true"
pct exec "$CTID" -- bash -c "locale_line=\$(grep -v '^#' /etc/locale.gen 2>/dev/null | grep -E '^[a-zA-Z]' | awk '{print \$1}' | head -n 1) && \ pct exec "$CTID" -- bash -c "locale_line=\$(grep -v '^#' /etc/locale.gen 2>/dev/null | grep -E '^[a-zA-Z]' | awk '{print \$1}' | head -n 1) && \
@ -3272,18 +3275,33 @@ EOF'
fedora | rockylinux | almalinux | centos) fedora | rockylinux | almalinux | centos)
# RHEL-based: Fedora, Rocky, AlmaLinux, CentOS # RHEL-based: Fedora, Rocky, AlmaLinux, CentOS
pct exec "$CTID" -- bash -c "dnf install -y curl sudo mc jq procps-ng >/dev/null 2>&1 || yum install -y curl sudo mc jq procps-ng >/dev/null 2>&1" || { # Install base packages including glibc-langpack for locale support
pct exec "$CTID" -- bash -c "dnf install -y curl sudo mc jq procps-ng glibc-langpack-en >/dev/null 2>&1 || yum install -y curl sudo mc jq procps-ng >/dev/null 2>&1" || {
msg_error "dnf/yum base packages installation failed" msg_error "dnf/yum base packages installation failed"
exit 1 exit 1
} }
# Set locale for RHEL-based systems
pct exec "$CTID" -- bash -c "localectl set-locale LANG=en_US.UTF-8 2>/dev/null || echo 'LANG=en_US.UTF-8' > /etc/locale.conf" || true
# Timezone setup for RHEL
if [[ -z "${tz:-}" ]]; then
tz=$(timedatectl show --property=Timezone --value 2>/dev/null || echo "Etc/UTC")
fi
[[ "${tz:-}" == Etc/* ]] && tz="UTC"
if pct exec "$CTID" -- test -e "/usr/share/zoneinfo/$tz"; then
pct exec "$CTID" -- bash -c "timedatectl set-timezone '$tz' 2>/dev/null || ln -sf '/usr/share/zoneinfo/$tz' /etc/localtime" || true
fi
;; ;;
opensuse) opensuse)
# openSUSE # openSUSE - add locale package and setup
pct exec "$CTID" -- bash -c "zypper --non-interactive install curl sudo mc jq >/dev/null" || { pct exec "$CTID" -- bash -c "zypper --non-interactive install curl sudo mc jq glibc-locale >/dev/null" || {
msg_error "zypper base packages installation failed" msg_error "zypper base packages installation failed"
exit 1 exit 1
} }
# Set locale for openSUSE
pct exec "$CTID" -- bash -c "localectl set-locale LANG=en_US.UTF-8 2>/dev/null || echo 'LANG=en_US.UTF-8' > /etc/locale.conf" || true
;; ;;
gentoo) gentoo)
@ -3295,10 +3313,23 @@ EOF'
openeuler) openeuler)
# openEuler (RHEL-compatible) # openEuler (RHEL-compatible)
pct exec "$CTID" -- bash -c "dnf install -y curl sudo mc jq >/dev/null" || { # Note: openEuler may fail pct create due to missing /etc/redhat-release - this is a PVE limitation
pct exec "$CTID" -- bash -c "dnf install -y curl sudo mc jq glibc-langpack-en >/dev/null" || {
msg_error "dnf base packages installation failed" msg_error "dnf base packages installation failed"
exit 1 exit 1
} }
# Set locale
pct exec "$CTID" -- bash -c "echo 'LANG=en_US.UTF-8' > /etc/locale.conf" || true
;;
opensuse)
# openSUSE - add locale package and setup
pct exec "$CTID" -- bash -c "zypper --non-interactive install curl sudo mc jq glibc-locale >/dev/null" || {
msg_error "zypper base packages installation failed"
exit 1
}
# Set locale for openSUSE
pct exec "$CTID" -- bash -c "localectl set-locale LANG=en_US.UTF-8 2>/dev/null || echo 'LANG=en_US.UTF-8' > /etc/locale.conf" || true
;; ;;
*) *)
@ -3845,12 +3876,19 @@ create_lxc_container() {
# Template discovery & validation # Template discovery & validation
# Supported OS types (pveam available): alpine, almalinux, centos, debian, # Supported OS types (pveam available): alpine, almalinux, centos, debian,
# devuan, fedora, gentoo, openeuler, opensuse, rockylinux, ubuntu # devuan, fedora, gentoo, openeuler, opensuse, rockylinux, ubuntu
# Template naming conventions:
# - Debian/Ubuntu/Devuan: <os>-<version>-standard_<date>_<arch>.tar.zst
# - Alpine/Fedora/Rocky/CentOS/AlmaLinux/openEuler: <os>-<version>-default_<date>_<arch>.tar.xz
# - Gentoo: gentoo-current-openrc-<date>_<arch>.tar.xz (version IS 'current')
# - openSUSE: opensuse-<version>-default_<date>_<arch>.tar.xz
# - CentOS: centos-<version>-stream-default_<date>_<arch>.tar.xz (note: stream in name)
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
TEMPLATE_SEARCH="${PCT_OSTYPE}-${PCT_OSVERSION:-}" TEMPLATE_SEARCH="${PCT_OSTYPE}-${PCT_OSVERSION:-}"
case "$PCT_OSTYPE" in case "$PCT_OSTYPE" in
debian | ubuntu | devuan) TEMPLATE_PATTERN="-standard_" ;; debian | ubuntu | devuan) TEMPLATE_PATTERN="-standard_" ;;
alpine | fedora | rocky | rockylinux | centos | almalinux | openeuler) TEMPLATE_PATTERN="-default_" ;; alpine | fedora | rockylinux | almalinux | openeuler) TEMPLATE_PATTERN="-default_" ;;
gentoo) TEMPLATE_PATTERN="-current-openrc" ;; centos) TEMPLATE_PATTERN="-stream-default_" ;;
gentoo) TEMPLATE_PATTERN="-openrc-" ;; # Pattern after gentoo-current
opensuse) TEMPLATE_PATTERN="-default_" ;; opensuse) TEMPLATE_PATTERN="-default_" ;;
*) TEMPLATE_PATTERN="" ;; *) TEMPLATE_PATTERN="" ;;
esac esac

View File

@ -523,9 +523,9 @@ msg_info() {
if ! declare -p MSG_INFO_SHOWN &>/dev/null || ! declare -A MSG_INFO_SHOWN &>/dev/null; then if ! declare -p MSG_INFO_SHOWN &>/dev/null || ! declare -A MSG_INFO_SHOWN &>/dev/null; then
declare -gA MSG_INFO_SHOWN=() declare -gA MSG_INFO_SHOWN=()
fi fi
# Sanitize message for use as associative array key (remove ANSI codes) # Sanitize message for use as associative array key (remove ANSI codes and special chars)
local sanitized_msg local sanitized_msg
sanitized_msg=$(printf '%s' "$msg" | sed 's/\x1b\[[0-9;]*m//g') sanitized_msg=$(printf '%s' "$msg" | sed 's/\x1b\[[0-9;]*m//g; s/[^a-zA-Z0-9_]/_/g')
[[ -n "${MSG_INFO_SHOWN["$sanitized_msg"]+x}" ]] && return [[ -n "${MSG_INFO_SHOWN["$sanitized_msg"]+x}" ]] && return
MSG_INFO_SHOWN["$sanitized_msg"]=1 MSG_INFO_SHOWN["$sanitized_msg"]=1
@ -572,10 +572,10 @@ msg_ok() {
stop_spinner stop_spinner
clear_line clear_line
echo -e "$CM ${GN}${msg}${CL}" echo -e "$CM ${GN}${msg}${CL}"
# Sanitize message for use as associative array key (remove ANSI codes) # Sanitize message for use as associative array key (remove ANSI codes and special chars)
local sanitized_msg local sanitized_msg
sanitized_msg=$(printf '%s' "$msg" | sed 's/\x1b\[[0-9;]*m//g') sanitized_msg=$(printf '%s' "$msg" | sed 's/\x1b\[[0-9;]*m//g; s/[^a-zA-Z0-9_]/_/g')
unset MSG_INFO_SHOWN["$sanitized_msg"] unset 'MSG_INFO_SHOWN['"$sanitized_msg"']' 2>/dev/null || true
} }
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------