Merge branch 'main' of https://github.com/community-scripts/ProxmoxVED
This commit is contained in:
commit
025d688be3
@ -196,11 +196,17 @@ ensure_usr_local_bin_persist() {
|
|||||||
|
|
||||||
download_with_progress() {
|
download_with_progress() {
|
||||||
# $1 url, $2 dest
|
# $1 url, $2 dest
|
||||||
local url="$1" out="$2" cl
|
local url="$1" out="$2" content_length
|
||||||
need_tool curl pv || return 1
|
need_tool curl pv || return 1
|
||||||
cl=$(curl -fsSLI "$url" 2>/dev/null | awk 'tolower($0) ~ /^content-length:/ {print $2}' | tr -d '\r')
|
|
||||||
if [ -n "$cl" ]; then
|
content_length=$(
|
||||||
curl -fsSL "$url" | pv -s "$cl" >"$out" || {
|
curl -fsSLI "$url" 2>/dev/null |
|
||||||
|
awk '(tolower($1) ~ /^content-length:/) && ($2 + 0 > 0) {print $2+0}' |
|
||||||
|
tail -1 | tr -cd '[:digit:]' || true
|
||||||
|
)
|
||||||
|
|
||||||
|
if [ -n "$content_length" ]; then
|
||||||
|
curl -fsSL "$url" | pv -s "$content_length" >"$out" || {
|
||||||
msg_error "Download failed: $url"
|
msg_error "Download failed: $url"
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
@ -277,7 +283,7 @@ fetch_and_deploy_gh_release() {
|
|||||||
# $1 app, $2 repo, [$3 mode], [$4 version], [$5 target], [$6 asset_pattern
|
# $1 app, $2 repo, [$3 mode], [$4 version], [$5 target], [$6 asset_pattern
|
||||||
local app="$1" repo="$2" mode="${3:-tarball}" version="${4:-latest}" target="${5:-/opt/$1}" pattern="${6:-}"
|
local app="$1" repo="$2" mode="${3:-tarball}" version="${4:-latest}" target="${5:-/opt/$1}" pattern="${6:-}"
|
||||||
local app_lc
|
local app_lc
|
||||||
app_lc="$(lower "$app" | tr -d ' ')"
|
app_lc=$(lower "$app" | tr -d ' ')
|
||||||
local vfile="$HOME/.${app_lc}"
|
local vfile="$HOME/.${app_lc}"
|
||||||
local json url filename tmpd unpack
|
local json url filename tmpd unpack
|
||||||
|
|
||||||
@ -288,7 +294,7 @@ fetch_and_deploy_gh_release() {
|
|||||||
need_tool curl jq tar || return 1
|
need_tool curl jq tar || return 1
|
||||||
[ "$mode" = "prebuild" ] || [ "$mode" = "singlefile" ] && need_tool unzip >/dev/null 2>&1 || true
|
[ "$mode" = "prebuild" ] || [ "$mode" = "singlefile" ] && need_tool unzip >/dev/null 2>&1 || true
|
||||||
|
|
||||||
tmpd="$(mktemp -d)" || return 1
|
tmpd=$(mktemp -d) || return 1
|
||||||
mkdir -p "$target"
|
mkdir -p "$target"
|
||||||
|
|
||||||
# Release JSON (with token/rate-limit handling)
|
# Release JSON (with token/rate-limit handling)
|
||||||
@ -305,10 +311,10 @@ fetch_and_deploy_gh_release() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
fi
|
fi
|
||||||
json="$(cat "$tmpd/release.json")"
|
json=$(cat "$tmpd/release.json")
|
||||||
|
|
||||||
# correct Version
|
# correct Version
|
||||||
version="$(printf '%s' "$json" | jq -r '.tag_name // empty')"
|
version=$(printf '%s' "$json" | jq -r '.tag_name // empty')
|
||||||
version="${version#v}"
|
version="${version#v}"
|
||||||
|
|
||||||
[ -z "$version" ] && {
|
[ -z "$version" ] && {
|
||||||
@ -317,9 +323,15 @@ fetch_and_deploy_gh_release() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get_url() {
|
||||||
|
printf '%s' "$json" | jq -r '.assets[].browser_download_url' |
|
||||||
|
awk -v p="$pattern" 'BEGIN{IGNORECASE=1} $0 ~ p {print; exit}' |
|
||||||
|
tr -d '[:cntrl:]'
|
||||||
|
}
|
||||||
|
|
||||||
case "$mode" in
|
case "$mode" in
|
||||||
tarball | source)
|
tarball | source)
|
||||||
url="$(printf '%s' "$json" | jq -r '.tarball_url // empty')"
|
url=$(printf '%s' "$json" | jq -r '.tarball_url // empty')
|
||||||
[ -z "$url" ] && url="https://github.com/$repo/archive/refs/tags/v$version.tar.gz"
|
[ -z "$url" ] && url="https://github.com/$repo/archive/refs/tags/v$version.tar.gz"
|
||||||
filename="${app_lc}-${version}.tar.gz"
|
filename="${app_lc}-${version}.tar.gz"
|
||||||
download_with_progress "$url" "$tmpd/$filename" || {
|
download_with_progress "$url" "$tmpd/$filename" || {
|
||||||
@ -331,7 +343,7 @@ fetch_and_deploy_gh_release() {
|
|||||||
rm -rf "$tmpd"
|
rm -rf "$tmpd"
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
unpack="$(find "$tmpd" -mindepth 1 -maxdepth 1 -type d | head -n1)"
|
unpack=$(find "$tmpd" -mindepth 1 -maxdepth 1 -type d | head -n1)
|
||||||
[ "${CLEAN_INSTALL:-0}" = "1" ] && rm -rf "${target:?}/"*
|
[ "${CLEAN_INSTALL:-0}" = "1" ] && rm -rf "${target:?}/"*
|
||||||
# copy content of unpack to target
|
# copy content of unpack to target
|
||||||
(cd "$unpack" && tar -cf - .) | (cd "$target" && tar -xf -) || {
|
(cd "$unpack" && tar -cf - .) | (cd "$target" && tar -xf -) || {
|
||||||
@ -342,7 +354,7 @@ fetch_and_deploy_gh_release() {
|
|||||||
;;
|
;;
|
||||||
binary)
|
binary)
|
||||||
[ -n "$pattern" ] || pattern="*.apk"
|
[ -n "$pattern" ] || pattern="*.apk"
|
||||||
url="$(printf '%s' "$json" | jq -r '.assets[].browser_download_url' | awk -v p="$pattern" 'BEGIN{IGNORECASE=1} $0 ~ p {print; exit}')"
|
url=$(get_url)
|
||||||
[ -z "$url" ] && {
|
[ -z "$url" ] && {
|
||||||
msg_error "binary asset not found for pattern: $pattern"
|
msg_error "binary asset not found for pattern: $pattern"
|
||||||
rm -rf "$tmpd"
|
rm -rf "$tmpd"
|
||||||
@ -374,10 +386,7 @@ fetch_and_deploy_gh_release() {
|
|||||||
rm -rf "$tmpd"
|
rm -rf "$tmpd"
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
url="$(printf '%s' "$json" | jq -r '.assets[].browser_download_url' | awk -v p="$pattern" '
|
url=$(get_url)
|
||||||
BEGIN{IGNORECASE=1}
|
|
||||||
$0 ~ p {print; exit}
|
|
||||||
')"
|
|
||||||
[ -z "$url" ] && {
|
[ -z "$url" ] && {
|
||||||
msg_error "asset not found for pattern: $pattern"
|
msg_error "asset not found for pattern: $pattern"
|
||||||
rm -rf "$tmpd"
|
rm -rf "$tmpd"
|
||||||
@ -411,7 +420,7 @@ fetch_and_deploy_gh_release() {
|
|||||||
[ "${CLEAN_INSTALL:-0}" = "1" ] && rm -rf "${target:?}/"*
|
[ "${CLEAN_INSTALL:-0}" = "1" ] && rm -rf "${target:?}/"*
|
||||||
# top-level folder strippen
|
# top-level folder strippen
|
||||||
if [ "$(find "$tmpd/unp" -mindepth 1 -maxdepth 1 -type d | wc -l)" -eq 1 ] && [ -z "$(find "$tmpd/unp" -mindepth 1 -maxdepth 1 -type f | head -n1)" ]; then
|
if [ "$(find "$tmpd/unp" -mindepth 1 -maxdepth 1 -type d | wc -l)" -eq 1 ] && [ -z "$(find "$tmpd/unp" -mindepth 1 -maxdepth 1 -type f | head -n1)" ]; then
|
||||||
unpack="$(find "$tmpd/unp" -mindepth 1 -maxdepth 1 -type d)"
|
unpack=$(find "$tmpd/unp" -mindepth 1 -maxdepth 1 -type d)
|
||||||
(cd "$unpack" && tar -cf - .) | (cd "$target" && tar -xf -) || {
|
(cd "$unpack" && tar -cf - .) | (cd "$target" && tar -xf -) || {
|
||||||
msg_error "copy failed"
|
msg_error "copy failed"
|
||||||
rm -rf "$tmpd"
|
rm -rf "$tmpd"
|
||||||
@ -431,10 +440,7 @@ fetch_and_deploy_gh_release() {
|
|||||||
rm -rf "$tmpd"
|
rm -rf "$tmpd"
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
url="$(printf '%s' "$json" | jq -r '.assets[].browser_download_url' | awk -v p="$pattern" '
|
url=$(get_url)
|
||||||
BEGIN{IGNORECASE=1}
|
|
||||||
$0 ~ p {print; exit}
|
|
||||||
')"
|
|
||||||
[ -z "$url" ] && {
|
[ -z "$url" ] && {
|
||||||
msg_error "asset not found for pattern: $pattern"
|
msg_error "asset not found for pattern: $pattern"
|
||||||
rm -rf "$tmpd"
|
rm -rf "$tmpd"
|
||||||
|
|||||||
380
misc/build.func
380
misc/build.func
@ -363,7 +363,7 @@ validate_hostname() {
|
|||||||
|
|
||||||
# Split by dots and validate each label
|
# Split by dots and validate each label
|
||||||
local IFS='.'
|
local IFS='.'
|
||||||
read -ra labels <<< "$hostname"
|
read -ra labels <<<"$hostname"
|
||||||
for label in "${labels[@]}"; do
|
for label in "${labels[@]}"; do
|
||||||
# Each label: 1-63 chars, alphanumeric, hyphens allowed (not at start/end)
|
# Each label: 1-63 chars, alphanumeric, hyphens allowed (not at start/end)
|
||||||
if [[ -z "$label" ]] || [[ ${#label} -gt 63 ]]; then
|
if [[ -z "$label" ]] || [[ ${#label} -gt 63 ]]; then
|
||||||
@ -467,7 +467,7 @@ validate_ipv6_address() {
|
|||||||
# Check that no segment exceeds 4 hex chars
|
# Check that no segment exceeds 4 hex chars
|
||||||
local IFS=':'
|
local IFS=':'
|
||||||
local -a segments
|
local -a segments
|
||||||
read -ra segments <<< "$addr"
|
read -ra segments <<<"$addr"
|
||||||
for seg in "${segments[@]}"; do
|
for seg in "${segments[@]}"; do
|
||||||
if [[ ${#seg} -gt 4 ]]; then
|
if [[ ${#seg} -gt 4 ]]; then
|
||||||
return 1
|
return 1
|
||||||
@ -517,14 +517,14 @@ validate_gateway_in_subnet() {
|
|||||||
|
|
||||||
# Convert IPs to integers
|
# Convert IPs to integers
|
||||||
local IFS='.'
|
local IFS='.'
|
||||||
read -r i1 i2 i3 i4 <<< "$ip"
|
read -r i1 i2 i3 i4 <<<"$ip"
|
||||||
read -r g1 g2 g3 g4 <<< "$gateway"
|
read -r g1 g2 g3 g4 <<<"$gateway"
|
||||||
|
|
||||||
local ip_int=$(( (i1 << 24) + (i2 << 16) + (i3 << 8) + i4 ))
|
local ip_int=$(((i1 << 24) + (i2 << 16) + (i3 << 8) + i4))
|
||||||
local gw_int=$(( (g1 << 24) + (g2 << 16) + (g3 << 8) + g4 ))
|
local gw_int=$(((g1 << 24) + (g2 << 16) + (g3 << 8) + g4))
|
||||||
|
|
||||||
# Check if both are in same network
|
# Check if both are in same network
|
||||||
if (( (ip_int & mask) != (gw_int & mask) )); then
|
if (((ip_int & mask) != (gw_int & mask))); then
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -1057,113 +1057,113 @@ load_vars_file() {
|
|||||||
# Validate values before setting (skip empty values - they use defaults)
|
# Validate values before setting (skip empty values - they use defaults)
|
||||||
if [[ -n "$var_val" ]]; then
|
if [[ -n "$var_val" ]]; then
|
||||||
case "$var_key" in
|
case "$var_key" in
|
||||||
var_mac)
|
var_mac)
|
||||||
if ! validate_mac_address "$var_val"; then
|
if ! validate_mac_address "$var_val"; then
|
||||||
msg_warn "Invalid MAC address '$var_val' in $file, ignoring"
|
msg_warn "Invalid MAC address '$var_val' in $file, ignoring"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
var_vlan)
|
||||||
|
if ! validate_vlan_tag "$var_val"; then
|
||||||
|
msg_warn "Invalid VLAN tag '$var_val' in $file (must be 1-4094), ignoring"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
var_mtu)
|
||||||
|
if ! validate_mtu "$var_val"; then
|
||||||
|
msg_warn "Invalid MTU '$var_val' in $file (must be 576-65535), ignoring"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
var_tags)
|
||||||
|
if ! validate_tags "$var_val"; then
|
||||||
|
msg_warn "Invalid tags '$var_val' in $file (alphanumeric, -, _, ; only), ignoring"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
var_timezone)
|
||||||
|
if ! validate_timezone "$var_val"; then
|
||||||
|
msg_warn "Invalid timezone '$var_val' in $file, ignoring"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
var_brg)
|
||||||
|
if ! validate_bridge "$var_val"; then
|
||||||
|
msg_warn "Bridge '$var_val' not found in $file, ignoring"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
var_gateway)
|
||||||
|
if ! validate_gateway_ip "$var_val"; then
|
||||||
|
msg_warn "Invalid gateway IP '$var_val' in $file, ignoring"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
var_hostname)
|
||||||
|
if ! validate_hostname "$var_val"; then
|
||||||
|
msg_warn "Invalid hostname '$var_val' in $file, ignoring"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
var_cpu)
|
||||||
|
if ! [[ "$var_val" =~ ^[0-9]+$ ]] || ((var_val < 1 || var_val > 128)); then
|
||||||
|
msg_warn "Invalid CPU count '$var_val' in $file (must be 1-128), ignoring"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
var_ram)
|
||||||
|
if ! [[ "$var_val" =~ ^[0-9]+$ ]] || ((var_val < 256)); then
|
||||||
|
msg_warn "Invalid RAM '$var_val' in $file (must be >= 256 MiB), ignoring"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
var_disk)
|
||||||
|
if ! [[ "$var_val" =~ ^[0-9]+$ ]] || ((var_val < 1)); then
|
||||||
|
msg_warn "Invalid disk size '$var_val' in $file (must be >= 1 GB), ignoring"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
var_unprivileged)
|
||||||
|
if [[ "$var_val" != "0" && "$var_val" != "1" ]]; then
|
||||||
|
msg_warn "Invalid unprivileged value '$var_val' in $file (must be 0 or 1), ignoring"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
var_nesting)
|
||||||
|
if [[ "$var_val" != "0" && "$var_val" != "1" ]]; then
|
||||||
|
msg_warn "Invalid nesting value '$var_val' in $file (must be 0 or 1), ignoring"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
var_keyctl)
|
||||||
|
if [[ "$var_val" != "0" && "$var_val" != "1" ]]; then
|
||||||
|
msg_warn "Invalid keyctl value '$var_val' in $file (must be 0 or 1), ignoring"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
var_net)
|
||||||
|
# var_net can be: dhcp, static IP/CIDR, or IP range
|
||||||
|
if [[ "$var_val" != "dhcp" ]]; then
|
||||||
|
if is_ip_range "$var_val"; then
|
||||||
|
: # IP range is valid, will be resolved at runtime
|
||||||
|
elif ! validate_ip_address "$var_val"; then
|
||||||
|
msg_warn "Invalid network '$var_val' in $file (must be dhcp or IP/CIDR), ignoring"
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
;;
|
fi
|
||||||
var_vlan)
|
;;
|
||||||
if ! validate_vlan_tag "$var_val"; then
|
var_fuse | var_tun | var_gpu | var_ssh | var_verbose | var_protection)
|
||||||
msg_warn "Invalid VLAN tag '$var_val' in $file (must be 1-4094), ignoring"
|
if [[ "$var_val" != "yes" && "$var_val" != "no" ]]; then
|
||||||
continue
|
msg_warn "Invalid boolean '$var_val' for $var_key in $file (must be yes/no), ignoring"
|
||||||
fi
|
continue
|
||||||
;;
|
fi
|
||||||
var_mtu)
|
;;
|
||||||
if ! validate_mtu "$var_val"; then
|
var_ipv6_method)
|
||||||
msg_warn "Invalid MTU '$var_val' in $file (must be 576-65535), ignoring"
|
if [[ "$var_val" != "auto" && "$var_val" != "dhcp" && "$var_val" != "static" && "$var_val" != "none" ]]; then
|
||||||
continue
|
msg_warn "Invalid IPv6 method '$var_val' in $file (must be auto/dhcp/static/none), ignoring"
|
||||||
fi
|
continue
|
||||||
;;
|
fi
|
||||||
var_tags)
|
;;
|
||||||
if ! validate_tags "$var_val"; then
|
|
||||||
msg_warn "Invalid tags '$var_val' in $file (alphanumeric, -, _, ; only), ignoring"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
var_timezone)
|
|
||||||
if ! validate_timezone "$var_val"; then
|
|
||||||
msg_warn "Invalid timezone '$var_val' in $file, ignoring"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
var_brg)
|
|
||||||
if ! validate_bridge "$var_val"; then
|
|
||||||
msg_warn "Bridge '$var_val' not found in $file, ignoring"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
var_gateway)
|
|
||||||
if ! validate_gateway_ip "$var_val"; then
|
|
||||||
msg_warn "Invalid gateway IP '$var_val' in $file, ignoring"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
var_hostname)
|
|
||||||
if ! validate_hostname "$var_val"; then
|
|
||||||
msg_warn "Invalid hostname '$var_val' in $file, ignoring"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
var_cpu)
|
|
||||||
if ! [[ "$var_val" =~ ^[0-9]+$ ]] || ((var_val < 1 || var_val > 128)); then
|
|
||||||
msg_warn "Invalid CPU count '$var_val' in $file (must be 1-128), ignoring"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
var_ram)
|
|
||||||
if ! [[ "$var_val" =~ ^[0-9]+$ ]] || ((var_val < 256)); then
|
|
||||||
msg_warn "Invalid RAM '$var_val' in $file (must be >= 256 MiB), ignoring"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
var_disk)
|
|
||||||
if ! [[ "$var_val" =~ ^[0-9]+$ ]] || ((var_val < 1)); then
|
|
||||||
msg_warn "Invalid disk size '$var_val' in $file (must be >= 1 GB), ignoring"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
var_unprivileged)
|
|
||||||
if [[ "$var_val" != "0" && "$var_val" != "1" ]]; then
|
|
||||||
msg_warn "Invalid unprivileged value '$var_val' in $file (must be 0 or 1), ignoring"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
var_nesting)
|
|
||||||
if [[ "$var_val" != "0" && "$var_val" != "1" ]]; then
|
|
||||||
msg_warn "Invalid nesting value '$var_val' in $file (must be 0 or 1), ignoring"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
var_keyctl)
|
|
||||||
if [[ "$var_val" != "0" && "$var_val" != "1" ]]; then
|
|
||||||
msg_warn "Invalid keyctl value '$var_val' in $file (must be 0 or 1), ignoring"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
var_net)
|
|
||||||
# var_net can be: dhcp, static IP/CIDR, or IP range
|
|
||||||
if [[ "$var_val" != "dhcp" ]]; then
|
|
||||||
if is_ip_range "$var_val"; then
|
|
||||||
: # IP range is valid, will be resolved at runtime
|
|
||||||
elif ! validate_ip_address "$var_val"; then
|
|
||||||
msg_warn "Invalid network '$var_val' in $file (must be dhcp or IP/CIDR), ignoring"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
var_fuse|var_tun|var_gpu|var_ssh|var_verbose|var_protection)
|
|
||||||
if [[ "$var_val" != "yes" && "$var_val" != "no" ]]; then
|
|
||||||
msg_warn "Invalid boolean '$var_val' for $var_key in $file (must be yes/no), ignoring"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
var_ipv6_method)
|
|
||||||
if [[ "$var_val" != "auto" && "$var_val" != "dhcp" && "$var_val" != "static" && "$var_val" != "none" ]]; then
|
|
||||||
msg_warn "Invalid IPv6 method '$var_val' in $file (must be auto/dhcp/static/none), ignoring"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -3086,21 +3086,29 @@ check_container_resources() {
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# check_container_storage()
|
# check_container_storage()
|
||||||
#
|
#
|
||||||
# - Checks /boot partition usage
|
# - Checks root (/) partition usage
|
||||||
# - Warns if usage >80% and asks user confirmation before proceeding
|
# - Warns if usage >80% and asks user confirmation before proceeding
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
check_container_storage() {
|
check_container_storage() {
|
||||||
total_size=$(df /boot --output=size | tail -n 1)
|
usage=$(df / -P | awk 'NR==2 {print $5}' | tr -d '%')
|
||||||
local used_size=$(df /boot --output=used | tail -n 1)
|
|
||||||
usage=$((100 * used_size / total_size))
|
if [ -z "$usage" ] || [ "$usage" -lt 0 ]; then
|
||||||
if ((usage > 80)); then
|
echo -e "${CROSS}${HOLD}${RD}Error: Failed to check disk usage.${CL}"
|
||||||
echo -e "${INFO}${HOLD} ${YWB}Warning: Storage is dangerously low (${usage}%).${CL}"
|
exit 1
|
||||||
echo -ne "Continue anyway? <y/N> "
|
fi
|
||||||
|
|
||||||
|
if [ "$usage" -gt 80 ]; then
|
||||||
|
echo -e "${INFO}${HOLD}${YWB}Warning: Storage is dangerously low (${usage}%).${CL}"
|
||||||
|
printf "Continue anyway? <y/N> "
|
||||||
read -r prompt
|
read -r prompt
|
||||||
if [[ ! ${prompt,,} =~ ^(y|yes)$ ]]; then
|
|
||||||
|
case "$prompt" in
|
||||||
|
[yY][eE][sS] | [yY]) ;;
|
||||||
|
*)
|
||||||
echo -e "${CROSS}${HOLD}${YWB}Exiting based on user input.${CL}"
|
echo -e "${CROSS}${HOLD}${YWB}Exiting based on user input.${CL}"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
;;
|
||||||
|
esac
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4023,91 +4031,91 @@ EOF'
|
|||||||
|
|
||||||
if read -t 60 -r response; then
|
if read -t 60 -r response; then
|
||||||
case "${response:-1}" in
|
case "${response:-1}" in
|
||||||
1)
|
1)
|
||||||
# Remove container
|
# Remove container
|
||||||
echo -e "\n${TAB}${HOLD}${YW}Removing container ${CTID}${CL}"
|
echo -e "\n${TAB}${HOLD}${YW}Removing container ${CTID}${CL}"
|
||||||
pct stop "$CTID" &>/dev/null || true
|
pct stop "$CTID" &>/dev/null || true
|
||||||
pct destroy "$CTID" &>/dev/null || true
|
pct destroy "$CTID" &>/dev/null || true
|
||||||
echo -e "${BFR}${CM}${GN}Container ${CTID} removed${CL}"
|
echo -e "${BFR}${CM}${GN}Container ${CTID} removed${CL}"
|
||||||
;;
|
;;
|
||||||
2)
|
2)
|
||||||
echo -e "\n${TAB}${YW}Container ${CTID} kept for debugging${CL}"
|
echo -e "\n${TAB}${YW}Container ${CTID} kept for debugging${CL}"
|
||||||
# Dev mode: Setup MOTD/SSH for debugging access to broken container
|
# Dev mode: Setup MOTD/SSH for debugging access to broken container
|
||||||
if [[ "${DEV_MODE_MOTD:-false}" == "true" ]]; then
|
if [[ "${DEV_MODE_MOTD:-false}" == "true" ]]; then
|
||||||
echo -e "${TAB}${HOLD}${DGN}Setting up MOTD and SSH for debugging...${CL}"
|
echo -e "${TAB}${HOLD}${DGN}Setting up MOTD and SSH for debugging...${CL}"
|
||||||
if pct exec "$CTID" -- bash -c "
|
if pct exec "$CTID" -- bash -c "
|
||||||
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/install.func)
|
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/install.func)
|
||||||
declare -f motd_ssh >/dev/null 2>&1 && motd_ssh || true
|
declare -f motd_ssh >/dev/null 2>&1 && motd_ssh || true
|
||||||
" >/dev/null 2>&1; then
|
" >/dev/null 2>&1; then
|
||||||
local ct_ip=$(pct exec "$CTID" ip a s dev eth0 2>/dev/null | awk '/inet / {print $2}' | cut -d/ -f1)
|
local ct_ip=$(pct exec "$CTID" ip a s dev eth0 2>/dev/null | awk '/inet / {print $2}' | cut -d/ -f1)
|
||||||
echo -e "${BFR}${CM}${GN}MOTD/SSH ready - SSH into container: ssh root@${ct_ip}${CL}"
|
echo -e "${BFR}${CM}${GN}MOTD/SSH ready - SSH into container: ssh root@${ct_ip}${CL}"
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
exit $install_exit_code
|
fi
|
||||||
;;
|
exit $install_exit_code
|
||||||
3)
|
;;
|
||||||
# Retry with verbose mode
|
3)
|
||||||
echo -e "\n${TAB}${HOLD}${YW}Removing container ${CTID} for rebuild...${CL}"
|
# Retry with verbose mode
|
||||||
|
echo -e "\n${TAB}${HOLD}${YW}Removing container ${CTID} for rebuild...${CL}"
|
||||||
|
pct stop "$CTID" &>/dev/null || true
|
||||||
|
pct destroy "$CTID" &>/dev/null || true
|
||||||
|
echo -e "${BFR}${CM}${GN}Container ${CTID} removed${CL}"
|
||||||
|
echo ""
|
||||||
|
# Get new container ID
|
||||||
|
local old_ctid="$CTID"
|
||||||
|
export CTID=$(get_valid_container_id "$CTID")
|
||||||
|
export VERBOSE="yes"
|
||||||
|
export var_verbose="yes"
|
||||||
|
|
||||||
|
# Show rebuild summary
|
||||||
|
echo -e "${YW}Rebuilding with preserved settings:${CL}"
|
||||||
|
echo -e " Container ID: ${old_ctid} → ${CTID}"
|
||||||
|
echo -e " RAM: ${RAM_SIZE} MiB | CPU: ${CORE_COUNT} cores | Disk: ${DISK_SIZE} GB"
|
||||||
|
echo -e " Network: ${NET:-dhcp} | Bridge: ${BRG:-vmbr0}"
|
||||||
|
echo -e " Verbose: ${GN}enabled${CL}"
|
||||||
|
echo ""
|
||||||
|
msg_info "Restarting installation..."
|
||||||
|
# Re-run build_container
|
||||||
|
build_container
|
||||||
|
return $?
|
||||||
|
;;
|
||||||
|
4)
|
||||||
|
if [[ "$is_oom" == true ]]; then
|
||||||
|
# Retry with more resources
|
||||||
|
echo -e "\n${TAB}${HOLD}${YW}Removing container ${CTID} for rebuild with more resources...${CL}"
|
||||||
pct stop "$CTID" &>/dev/null || true
|
pct stop "$CTID" &>/dev/null || true
|
||||||
pct destroy "$CTID" &>/dev/null || true
|
pct destroy "$CTID" &>/dev/null || true
|
||||||
echo -e "${BFR}${CM}${GN}Container ${CTID} removed${CL}"
|
echo -e "${BFR}${CM}${GN}Container ${CTID} removed${CL}"
|
||||||
echo ""
|
echo ""
|
||||||
# Get new container ID
|
# Get new container ID and increase resources
|
||||||
local old_ctid="$CTID"
|
local old_ctid="$CTID"
|
||||||
|
local old_ram="$RAM_SIZE"
|
||||||
|
local old_cpu="$CORE_COUNT"
|
||||||
export CTID=$(get_valid_container_id "$CTID")
|
export CTID=$(get_valid_container_id "$CTID")
|
||||||
export VERBOSE="yes"
|
export RAM_SIZE=$((RAM_SIZE * 3 / 2))
|
||||||
export var_verbose="yes"
|
export CORE_COUNT=$((CORE_COUNT + 1))
|
||||||
|
export var_ram="$RAM_SIZE"
|
||||||
|
export var_cpu="$CORE_COUNT"
|
||||||
|
|
||||||
# Show rebuild summary
|
# Show rebuild summary
|
||||||
echo -e "${YW}Rebuilding with preserved settings:${CL}"
|
echo -e "${YW}Rebuilding with increased resources:${CL}"
|
||||||
echo -e " Container ID: ${old_ctid} → ${CTID}"
|
echo -e " Container ID: ${old_ctid} → ${CTID}"
|
||||||
echo -e " RAM: ${RAM_SIZE} MiB | CPU: ${CORE_COUNT} cores | Disk: ${DISK_SIZE} GB"
|
echo -e " RAM: ${old_ram} → ${GN}${RAM_SIZE}${CL} MiB (+50%)"
|
||||||
echo -e " Network: ${NET:-dhcp} | Bridge: ${BRG:-vmbr0}"
|
echo -e " CPU: ${old_cpu} → ${GN}${CORE_COUNT}${CL} cores (+1)"
|
||||||
echo -e " Verbose: ${GN}enabled${CL}"
|
echo -e " Disk: ${DISK_SIZE} GB | Network: ${NET:-dhcp} | Bridge: ${BRG:-vmbr0}"
|
||||||
echo ""
|
echo ""
|
||||||
msg_info "Restarting installation..."
|
msg_info "Restarting installation..."
|
||||||
# Re-run build_container
|
# Re-run build_container
|
||||||
build_container
|
build_container
|
||||||
return $?
|
return $?
|
||||||
;;
|
else
|
||||||
4)
|
|
||||||
if [[ "$is_oom" == true ]]; then
|
|
||||||
# Retry with more resources
|
|
||||||
echo -e "\n${TAB}${HOLD}${YW}Removing container ${CTID} for rebuild with more resources...${CL}"
|
|
||||||
pct stop "$CTID" &>/dev/null || true
|
|
||||||
pct destroy "$CTID" &>/dev/null || true
|
|
||||||
echo -e "${BFR}${CM}${GN}Container ${CTID} removed${CL}"
|
|
||||||
echo ""
|
|
||||||
# Get new container ID and increase resources
|
|
||||||
local old_ctid="$CTID"
|
|
||||||
local old_ram="$RAM_SIZE"
|
|
||||||
local old_cpu="$CORE_COUNT"
|
|
||||||
export CTID=$(get_valid_container_id "$CTID")
|
|
||||||
export RAM_SIZE=$((RAM_SIZE * 3 / 2))
|
|
||||||
export CORE_COUNT=$((CORE_COUNT + 1))
|
|
||||||
export var_ram="$RAM_SIZE"
|
|
||||||
export var_cpu="$CORE_COUNT"
|
|
||||||
|
|
||||||
# Show rebuild summary
|
|
||||||
echo -e "${YW}Rebuilding with increased resources:${CL}"
|
|
||||||
echo -e " Container ID: ${old_ctid} → ${CTID}"
|
|
||||||
echo -e " RAM: ${old_ram} → ${GN}${RAM_SIZE}${CL} MiB (+50%)"
|
|
||||||
echo -e " CPU: ${old_cpu} → ${GN}${CORE_COUNT}${CL} cores (+1)"
|
|
||||||
echo -e " Disk: ${DISK_SIZE} GB | Network: ${NET:-dhcp} | Bridge: ${BRG:-vmbr0}"
|
|
||||||
echo ""
|
|
||||||
msg_info "Restarting installation..."
|
|
||||||
# Re-run build_container
|
|
||||||
build_container
|
|
||||||
return $?
|
|
||||||
else
|
|
||||||
echo -e "\n${TAB}${YW}Invalid option. Container ${CTID} kept.${CL}"
|
|
||||||
exit $install_exit_code
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo -e "\n${TAB}${YW}Invalid option. Container ${CTID} kept.${CL}"
|
echo -e "\n${TAB}${YW}Invalid option. Container ${CTID} kept.${CL}"
|
||||||
exit $install_exit_code
|
exit $install_exit_code
|
||||||
;;
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo -e "\n${TAB}${YW}Invalid option. Container ${CTID} kept.${CL}"
|
||||||
|
exit $install_exit_code
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
else
|
else
|
||||||
# Timeout - auto-remove
|
# Timeout - auto-remove
|
||||||
|
|||||||
@ -1692,7 +1692,11 @@ function download_with_progress() {
|
|||||||
|
|
||||||
# Content-Length aus HTTP-Header holen
|
# Content-Length aus HTTP-Header holen
|
||||||
local content_length
|
local content_length
|
||||||
content_length=$(curl -fsSLI "$url" | awk '/Content-Length/ {print $2}' | tr -d '\r' || true)
|
content_length=$(
|
||||||
|
curl -fsSLI "$url" 2>/dev/null |
|
||||||
|
awk '(tolower($1) ~ /^content-length:/) && ($2 + 0 > 0) {print $2+0}' |
|
||||||
|
tail -1 | tr -cd '[:digit:]' || true
|
||||||
|
)
|
||||||
|
|
||||||
if [[ -z "$content_length" ]]; then
|
if [[ -z "$content_length" ]]; then
|
||||||
if ! curl -fL# -o "$output" "$url"; then
|
if ! curl -fL# -o "$output" "$url"; then
|
||||||
@ -6205,4 +6209,3 @@ function fetch_and_deploy_archive() {
|
|||||||
msg_ok "Successfully deployed archive to $directory"
|
msg_ok "Successfully deployed archive to $directory"
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user