mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2026-02-18 03:03:25 +01:00
Compare commits
9 Commits
main
...
feature/ex
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7aa04b838 | ||
|
|
f39024c930 | ||
|
|
33884f6228 | ||
|
|
c4449aa041 | ||
|
|
476b50b4e2 | ||
|
|
fac5c5ebf6 | ||
|
|
61e535d3ec | ||
|
|
6989d98214 | ||
|
|
ce5b7986ac |
@@ -11,6 +11,13 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
|
||||
load_functions
|
||||
catch_errors
|
||||
|
||||
# Persist diagnostics setting inside container (exported from build.func)
|
||||
# so addon scripts running later can find the user's choice
|
||||
if [[ ! -f /usr/local/community-scripts/diagnostics ]]; then
|
||||
mkdir -p /usr/local/community-scripts
|
||||
echo "DIAGNOSTICS=${DIAGNOSTICS:-no}" >/usr/local/community-scripts/diagnostics
|
||||
fi
|
||||
|
||||
# Get LXC IP address (must be called INSIDE container, after network is up)
|
||||
get_lxc_ip
|
||||
|
||||
@@ -30,7 +37,7 @@ post_progress_to_api() {
|
||||
|
||||
curl -fsS -m 5 -X POST "https://telemetry.community-scripts.org/telemetry" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"random_id\":\"${RANDOM_UUID}\",\"type\":\"lxc\",\"nsapp\":\"${app:-unknown}\",\"status\":\"configuring\"}" &>/dev/null || true
|
||||
-d "{\"random_id\":\"${RANDOM_UUID}\",\"execution_id\":\"${EXECUTION_ID:-${RANDOM_UUID}}\",\"type\":\"lxc\",\"nsapp\":\"${app:-unknown}\",\"status\":\"configuring\"}" &>/dev/null || true
|
||||
}
|
||||
|
||||
# This function enables IPv6 if it's not disabled and sets verbose mode
|
||||
|
||||
@@ -552,6 +552,7 @@ post_to_api() {
|
||||
cat <<EOF
|
||||
{
|
||||
"random_id": "${RANDOM_UUID}",
|
||||
"execution_id": "${EXECUTION_ID:-${RANDOM_UUID}}",
|
||||
"type": "lxc",
|
||||
"nsapp": "${NSAPP:-unknown}",
|
||||
"status": "installing",
|
||||
@@ -656,6 +657,7 @@ post_to_api_vm() {
|
||||
cat <<EOF
|
||||
{
|
||||
"random_id": "${RANDOM_UUID}",
|
||||
"execution_id": "${EXECUTION_ID:-${RANDOM_UUID}}",
|
||||
"type": "vm",
|
||||
"nsapp": "${NSAPP:-unknown}",
|
||||
"status": "installing",
|
||||
@@ -788,6 +790,7 @@ post_update_to_api() {
|
||||
cat <<EOF
|
||||
{
|
||||
"random_id": "${RANDOM_UUID}",
|
||||
"execution_id": "${EXECUTION_ID:-${RANDOM_UUID}}",
|
||||
"type": "${TELEMETRY_TYPE:-lxc}",
|
||||
"nsapp": "${NSAPP:-unknown}",
|
||||
"status": "${pb_status}",
|
||||
@@ -830,6 +833,7 @@ EOF
|
||||
cat <<EOF
|
||||
{
|
||||
"random_id": "${RANDOM_UUID}",
|
||||
"execution_id": "${EXECUTION_ID:-${RANDOM_UUID}}",
|
||||
"type": "${TELEMETRY_TYPE:-lxc}",
|
||||
"nsapp": "${NSAPP:-unknown}",
|
||||
"status": "${pb_status}",
|
||||
@@ -872,6 +876,7 @@ EOF
|
||||
cat <<EOF
|
||||
{
|
||||
"random_id": "${RANDOM_UUID}",
|
||||
"execution_id": "${EXECUTION_ID:-${RANDOM_UUID}}",
|
||||
"type": "${TELEMETRY_TYPE:-lxc}",
|
||||
"nsapp": "${NSAPP:-unknown}",
|
||||
"status": "${pb_status}",
|
||||
@@ -1001,7 +1006,7 @@ _telemetry_report_exit() {
|
||||
# Lazy name resolution: use explicit name, fall back to $APP, then "unknown"
|
||||
local name="${TELEMETRY_TOOL_NAME:-${APP:-unknown}}"
|
||||
|
||||
if [[ "${TELEMETRY_TOOL_TYPE:-tool}" == "addon" ]]; then
|
||||
if [[ "${TELEMETRY_TOOL_TYPE:-pve}" == "addon" ]]; then
|
||||
post_addon_to_api "$name" "$status" "$ec"
|
||||
else
|
||||
post_tool_to_api "$name" "$status" "$ec"
|
||||
@@ -1013,19 +1018,20 @@ _telemetry_report_exit() {
|
||||
#
|
||||
# - One-line telemetry setup for tools/addon scripts
|
||||
# - Reads DIAGNOSTICS from /usr/local/community-scripts/diagnostics
|
||||
# (persisted on PVE host during first build, and inside containers by install.func)
|
||||
# - Starts install timer for duration tracking
|
||||
# - Sets EXIT trap to automatically report success/failure on script exit
|
||||
# - Arguments:
|
||||
# * $1: tool_name (optional, falls back to $APP at exit time)
|
||||
# * $2: type ("tool" for PVE host scripts, "addon" for container addons)
|
||||
# * $2: type ("pve" for PVE host scripts, "addon" for container addons)
|
||||
# - Usage:
|
||||
# source <(curl -fsSL .../misc/api.func) 2>/dev/null || true
|
||||
# init_tool_telemetry "post-pve-install" "tool"
|
||||
# init_tool_telemetry "post-pve-install" "pve"
|
||||
# init_tool_telemetry "" "addon" # uses $APP at exit time
|
||||
# ------------------------------------------------------------------------------
|
||||
init_tool_telemetry() {
|
||||
local name="${1:-}"
|
||||
local type="${2:-tool}"
|
||||
local type="${2:-pve}"
|
||||
|
||||
[[ -n "$name" ]] && TELEMETRY_TOOL_NAME="$name"
|
||||
TELEMETRY_TOOL_TYPE="$type"
|
||||
@@ -1088,7 +1094,8 @@ post_tool_to_api() {
|
||||
cat <<EOF
|
||||
{
|
||||
"random_id": "${uuid}",
|
||||
"type": "tool",
|
||||
"execution_id": "${EXECUTION_ID:-${uuid}}",
|
||||
"type": "pve",
|
||||
"nsapp": "${tool_name}",
|
||||
"status": "${status}",
|
||||
"exit_code": ${exit_code},
|
||||
@@ -1155,6 +1162,7 @@ post_addon_to_api() {
|
||||
cat <<EOF
|
||||
{
|
||||
"random_id": "${uuid}",
|
||||
"execution_id": "${EXECUTION_ID:-${uuid}}",
|
||||
"type": "addon",
|
||||
"nsapp": "${addon_name}",
|
||||
"status": "${status}",
|
||||
@@ -1246,6 +1254,7 @@ post_update_to_api_extended() {
|
||||
cat <<EOF
|
||||
{
|
||||
"random_id": "${RANDOM_UUID}",
|
||||
"execution_id": "${EXECUTION_ID:-${RANDOM_UUID}}",
|
||||
"type": "${TELEMETRY_TYPE:-lxc}",
|
||||
"nsapp": "${NSAPP:-unknown}",
|
||||
"status": "${pb_status}",
|
||||
|
||||
153
misc/build.func
153
misc/build.func
@@ -42,9 +42,10 @@ variables() {
|
||||
var_install="${NSAPP}-install" # sets the var_install variable by appending "-install" to the value of NSAPP.
|
||||
INTEGER='^[0-9]+([.][0-9]+)?$' # it defines the INTEGER regular expression pattern.
|
||||
PVEHOST_NAME=$(hostname) # gets the Proxmox Hostname and sets it to Uppercase
|
||||
DIAGNOSTICS="yes" # sets the DIAGNOSTICS variable to "yes", used for the API call.
|
||||
DIAGNOSTICS="no" # Safe default: no telemetry until user consents via diagnostics_check()
|
||||
METHOD="default" # sets the METHOD variable to "default", used for the API call.
|
||||
RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)" # generates a random UUID and sets it to the RANDOM_UUID variable.
|
||||
EXECUTION_ID="${RANDOM_UUID}" # Unique execution ID for telemetry record identification (unique-indexed in PocketBase)
|
||||
SESSION_ID="${RANDOM_UUID:0:8}" # Short session ID (first 8 chars of UUID) for log files
|
||||
BUILD_LOG="/tmp/create-lxc-${SESSION_ID}.log" # Host-side container creation log
|
||||
combined_log="/tmp/install-${SESSION_ID}-combined.log" # Combined log (build + install) for failed installations
|
||||
@@ -2787,93 +2788,85 @@ Advanced:
|
||||
# diagnostics_check()
|
||||
#
|
||||
# - Ensures diagnostics config file exists at /usr/local/community-scripts/diagnostics
|
||||
# - Asks user whether to send anonymous diagnostic data
|
||||
# - Asks user whether to send anonymous diagnostic data (first run only)
|
||||
# - Saves DIAGNOSTICS=yes/no in the config file
|
||||
# - Creates file if missing with default DIAGNOSTICS=yes
|
||||
# - Reads current diagnostics setting from file
|
||||
# - Reads current diagnostics setting from existing file
|
||||
# - Sets global DIAGNOSTICS variable for API telemetry opt-in/out
|
||||
# ------------------------------------------------------------------------------
|
||||
diagnostics_check() {
|
||||
if ! [ -d "/usr/local/community-scripts" ]; then
|
||||
mkdir -p /usr/local/community-scripts
|
||||
local config_dir="/usr/local/community-scripts"
|
||||
local config_file="${config_dir}/diagnostics"
|
||||
|
||||
mkdir -p "$config_dir"
|
||||
|
||||
if [[ -f "$config_file" ]]; then
|
||||
DIAGNOSTICS=$(awk -F '=' '/^DIAGNOSTICS/ {print $2}' "$config_file") || true
|
||||
DIAGNOSTICS="${DIAGNOSTICS:-no}"
|
||||
return
|
||||
fi
|
||||
|
||||
if ! [ -f "/usr/local/community-scripts/diagnostics" ]; then
|
||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "DIAGNOSTICS" --yesno "Send Diagnostics of LXC Installation?\n\n(This only transmits data without user data, just RAM, CPU, LXC name, ...)" 10 58); then
|
||||
cat <<EOF >/usr/local/community-scripts/diagnostics
|
||||
DIAGNOSTICS=yes
|
||||
local result
|
||||
result=$(whiptail --backtitle "Proxmox VE Helper Scripts" \
|
||||
--title "TELEMETRY & DIAGNOSTICS" \
|
||||
--ok-button "Confirm" --cancel-button "Exit" \
|
||||
--radiolist "\nHelp improve Community-Scripts by sharing anonymous data.\n\nWhat we collect:\n - Container resources (CPU, RAM, disk), OS & PVE version\n - Application name, install method and status\n\nWhat we DON'T collect:\n - No IP addresses, hostnames, or personal data\n\nYou can change this anytime in the Settings menu.\nPrivacy: https://github.com/community-scripts/telemetry-service/blob/main/docs/PRIVACY.md\n\nUse SPACE to select, ENTER to confirm." 22 76 2 \
|
||||
"yes" "Yes, share anonymous data" OFF \
|
||||
"no" "No, opt out" OFF \
|
||||
3>&1 1>&2 2>&3) || result="no"
|
||||
|
||||
#This file is used to store the diagnostics settings for the Community-Scripts API.
|
||||
#https://github.com/community-scripts/ProxmoxVE/discussions/1836
|
||||
#Your diagnostics will be sent to the Community-Scripts API for troubleshooting/statistical purposes.
|
||||
#You can review the data at https://community-scripts.github.io/ProxmoxVE/data
|
||||
#If you do not wish to send diagnostics, please set the variable 'DIAGNOSTICS' to "no" in /usr/local/community-scripts/diagnostics, or use the menue.
|
||||
#This will disable the diagnostics feature.
|
||||
#To send diagnostics, set the variable 'DIAGNOSTICS' to "yes" in /usr/local/community-scripts/diagnostics, or use the menue.
|
||||
#This will enable the diagnostics feature.
|
||||
#The following information will be sent:
|
||||
#"disk_size"
|
||||
#"core_count"
|
||||
#"ram_size"
|
||||
#"os_type"
|
||||
#"os_version"
|
||||
#"nsapp"
|
||||
#"method"
|
||||
#"pve_version"
|
||||
#"status"
|
||||
#If you have any concerns, please review the source code at /misc/build.func
|
||||
DIAGNOSTICS="${result:-no}"
|
||||
|
||||
cat <<EOF >"$config_file"
|
||||
DIAGNOSTICS=${DIAGNOSTICS}
|
||||
|
||||
# Community-Scripts Telemetry Configuration
|
||||
# https://telemetry.community-scripts.org
|
||||
#
|
||||
# This file stores your telemetry preference.
|
||||
# Set DIAGNOSTICS=yes to share anonymous installation data.
|
||||
# Set DIAGNOSTICS=no to disable telemetry.
|
||||
#
|
||||
# You can also change this via the Settings menu during installation.
|
||||
#
|
||||
# Data collected (when enabled):
|
||||
# disk_size, core_count, ram_size, os_type, os_version,
|
||||
# nsapp, method, pve_version, status, exit_code
|
||||
#
|
||||
# No personal data (IPs, hostnames, passwords) is ever collected.
|
||||
# Privacy: https://github.com/community-scripts/telemetry-service/blob/main/docs/PRIVACY.md
|
||||
EOF
|
||||
DIAGNOSTICS="yes"
|
||||
else
|
||||
cat <<EOF >/usr/local/community-scripts/diagnostics
|
||||
DIAGNOSTICS=no
|
||||
|
||||
#This file is used to store the diagnostics settings for the Community-Scripts API.
|
||||
#https://github.com/community-scripts/ProxmoxVE/discussions/1836
|
||||
#Your diagnostics will be sent to the Community-Scripts API for troubleshooting/statistical purposes.
|
||||
#You can review the data at https://community-scripts.github.io/ProxmoxVE/data
|
||||
#If you do not wish to send diagnostics, please set the variable 'DIAGNOSTICS' to "no" in /usr/local/community-scripts/diagnostics, or use the menue.
|
||||
#This will disable the diagnostics feature.
|
||||
#To send diagnostics, set the variable 'DIAGNOSTICS' to "yes" in /usr/local/community-scripts/diagnostics, or use the menue.
|
||||
#This will enable the diagnostics feature.
|
||||
#The following information will be sent:
|
||||
#"disk_size"
|
||||
#"core_count"
|
||||
#"ram_size"
|
||||
#"os_type"
|
||||
#"os_version"
|
||||
#"nsapp"
|
||||
#"method"
|
||||
#"pve_version"
|
||||
#"status"
|
||||
#If you have any concerns, please review the source code at /misc/build.func
|
||||
EOF
|
||||
DIAGNOSTICS="no"
|
||||
fi
|
||||
else
|
||||
DIAGNOSTICS=$(awk -F '=' '/^DIAGNOSTICS/ {print $2}' /usr/local/community-scripts/diagnostics)
|
||||
|
||||
fi
|
||||
}
|
||||
|
||||
diagnostics_menu() {
|
||||
if [ "${DIAGNOSTICS:-no}" = "yes" ]; then
|
||||
local current="${DIAGNOSTICS:-no}"
|
||||
local status_text="DISABLED"
|
||||
[[ "$current" == "yes" ]] && status_text="ENABLED"
|
||||
|
||||
local dialog_text=(
|
||||
"Telemetry is currently: ${status_text}\n\n"
|
||||
"Anonymous data helps us improve scripts and track issues.\n"
|
||||
"No personal data is ever collected.\n\n"
|
||||
"More info: https://telemetry.community-scripts.org\n\n"
|
||||
"Do you want to ${current:+change this setting}?"
|
||||
)
|
||||
|
||||
if [[ "$current" == "yes" ]]; then
|
||||
if whiptail --backtitle "Proxmox VE Helper Scripts" \
|
||||
--title "DIAGNOSTIC SETTINGS" \
|
||||
--yesno "Send Diagnostics?\n\nCurrent: ${DIAGNOSTICS}" 10 58 \
|
||||
--yes-button "No" --no-button "Back"; then
|
||||
--title "TELEMETRY SETTINGS" \
|
||||
--yesno "${dialog_text[*]}" 14 64 \
|
||||
--yes-button "Disable" --no-button "Keep enabled"; then
|
||||
DIAGNOSTICS="no"
|
||||
sed -i 's/^DIAGNOSTICS=.*/DIAGNOSTICS=no/' /usr/local/community-scripts/diagnostics
|
||||
whiptail --msgbox "Diagnostics set to ${DIAGNOSTICS}." 8 58
|
||||
whiptail --msgbox "Telemetry disabled.\n\nNote: Existing containers keep their current setting.\nNew containers will inherit this choice." 10 58
|
||||
fi
|
||||
else
|
||||
if whiptail --backtitle "Proxmox VE Helper Scripts" \
|
||||
--title "DIAGNOSTIC SETTINGS" \
|
||||
--yesno "Send Diagnostics?\n\nCurrent: ${DIAGNOSTICS}" 10 58 \
|
||||
--yes-button "Yes" --no-button "Back"; then
|
||||
--title "TELEMETRY SETTINGS" \
|
||||
--yesno "${dialog_text[*]}" 14 64 \
|
||||
--yes-button "Enable" --no-button "Keep disabled"; then
|
||||
DIAGNOSTICS="yes"
|
||||
sed -i 's/^DIAGNOSTICS=.*/DIAGNOSTICS=yes/' /usr/local/community-scripts/diagnostics
|
||||
whiptail --msgbox "Diagnostics set to ${DIAGNOSTICS}." 8 58
|
||||
whiptail --msgbox "Telemetry enabled.\n\nNote: Existing containers keep their current setting.\nNew containers will inherit this choice." 10 58
|
||||
fi
|
||||
fi
|
||||
}
|
||||
@@ -3561,6 +3554,7 @@ build_container() {
|
||||
# Core exports for install.func
|
||||
export DIAGNOSTICS="$DIAGNOSTICS"
|
||||
export RANDOM_UUID="$RANDOM_UUID"
|
||||
export EXECUTION_ID="$EXECUTION_ID"
|
||||
export SESSION_ID="$SESSION_ID"
|
||||
export CACHER="$APT_CACHER"
|
||||
export CACHER_IP="$APT_CACHER_IP"
|
||||
@@ -5552,6 +5546,8 @@ ensure_log_on_host() {
|
||||
# - Exit trap handler for reporting to API telemetry
|
||||
# - Captures exit code and reports to PocketBase using centralized error descriptions
|
||||
# - Uses explain_exit_code() from api.func for consistent error messages
|
||||
# - For signal exits (>128): sends telemetry FIRST before log collection
|
||||
# to prevent pct pull hangs from blocking status updates
|
||||
# - For non-zero exit codes: posts "failed" status
|
||||
# - For zero exit codes where post_update_to_api was never called:
|
||||
# catches orphaned "installing" records (e.g., script exited cleanly
|
||||
@@ -5560,8 +5556,15 @@ ensure_log_on_host() {
|
||||
api_exit_script() {
|
||||
local exit_code=$?
|
||||
if [ $exit_code -ne 0 ]; then
|
||||
ensure_log_on_host
|
||||
post_update_to_api "failed" "$exit_code"
|
||||
if [ $exit_code -gt 128 ]; then
|
||||
# Signal exit: send telemetry IMMEDIATELY (container may be dying)
|
||||
post_update_to_api "failed" "$exit_code" 2>/dev/null || true
|
||||
ensure_log_on_host 2>/dev/null || true
|
||||
else
|
||||
# Normal error: collect logs first for better error details
|
||||
ensure_log_on_host 2>/dev/null || true
|
||||
post_update_to_api "failed" "$exit_code"
|
||||
fi
|
||||
elif [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
|
||||
# Script exited with 0 but never sent a completion status
|
||||
# exit_code=0 is never an error — report as success
|
||||
@@ -5572,7 +5575,7 @@ api_exit_script() {
|
||||
if command -v pveversion >/dev/null 2>&1; then
|
||||
trap 'api_exit_script' EXIT
|
||||
fi
|
||||
trap 'local _ec=$?; if [[ $_ec -ne 0 ]]; then ensure_log_on_host; post_update_to_api "failed" "$_ec"; fi' ERR
|
||||
trap 'ensure_log_on_host; post_update_to_api "failed" "129"; exit 129' SIGHUP
|
||||
trap 'ensure_log_on_host; post_update_to_api "failed" "130"; exit 130' SIGINT
|
||||
trap 'ensure_log_on_host; post_update_to_api "failed" "143"; exit 143' SIGTERM
|
||||
trap 'local _ec=$?; if [[ $_ec -ne 0 ]]; then ensure_log_on_host 2>/dev/null || true; post_update_to_api "failed" "$_ec"; fi' ERR
|
||||
trap 'post_update_to_api "failed" "129" 2>/dev/null || true; ensure_log_on_host 2>/dev/null || true; exit 129' SIGHUP
|
||||
trap 'post_update_to_api "failed" "130" 2>/dev/null || true; ensure_log_on_host 2>/dev/null || true; exit 130' SIGINT
|
||||
trap 'post_update_to_api "failed" "143" 2>/dev/null || true; ensure_log_on_host 2>/dev/null || true; exit 143' SIGTERM
|
||||
|
||||
@@ -329,6 +329,8 @@ error_handler() {
|
||||
# - Cleans up lock files if lockfile variable is set
|
||||
# - Exits with captured exit code
|
||||
# - Always runs on script termination (success or failure)
|
||||
# - For signal exits (>128): sends telemetry FIRST before log collection
|
||||
# to prevent pct pull hangs from blocking status updates
|
||||
# ------------------------------------------------------------------------------
|
||||
on_exit() {
|
||||
local exit_code=$?
|
||||
@@ -337,14 +339,24 @@ on_exit() {
|
||||
# post_to_api was called ("installing" sent) but post_update_to_api was never called
|
||||
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
|
||||
if declare -f post_update_to_api >/dev/null 2>&1; then
|
||||
# Ensure log is accessible on host before reporting
|
||||
if declare -f ensure_log_on_host >/dev/null 2>&1; then
|
||||
ensure_log_on_host
|
||||
fi
|
||||
if [[ $exit_code -ne 0 ]]; then
|
||||
post_update_to_api "failed" "$exit_code"
|
||||
if [[ $exit_code -gt 128 ]]; then
|
||||
# Signal exit: send telemetry IMMEDIATELY (container may be dying, pct pull could hang)
|
||||
post_update_to_api "failed" "$exit_code" 2>/dev/null || true
|
||||
# Then try log collection (non-critical, best-effort)
|
||||
if declare -f ensure_log_on_host >/dev/null 2>&1; then
|
||||
ensure_log_on_host 2>/dev/null || true
|
||||
fi
|
||||
else
|
||||
post_update_to_api "failed" "1"
|
||||
# Normal exit: collect logs first for better error details
|
||||
if declare -f ensure_log_on_host >/dev/null 2>&1; then
|
||||
ensure_log_on_host 2>/dev/null || true
|
||||
fi
|
||||
if [[ $exit_code -ne 0 ]]; then
|
||||
post_update_to_api "failed" "$exit_code"
|
||||
else
|
||||
# exit_code=0 is never an error — report as success
|
||||
post_update_to_api "done" "0"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
@@ -356,22 +368,26 @@ on_exit() {
|
||||
# on_interrupt()
|
||||
#
|
||||
# - SIGINT (Ctrl+C) trap handler
|
||||
# - Reports to telemetry FIRST (time-critical: container may be dying)
|
||||
# - Displays "Interrupted by user" message
|
||||
# - Exits with code 130 (128 + SIGINT=2)
|
||||
# - Output redirected to /dev/null fallback to prevent SIGPIPE on closed terminals
|
||||
# ------------------------------------------------------------------------------
|
||||
on_interrupt() {
|
||||
# Ensure log is accessible on host before reporting
|
||||
if declare -f ensure_log_on_host >/dev/null 2>&1; then
|
||||
ensure_log_on_host
|
||||
fi
|
||||
# Report interruption to telemetry API (prevents stuck "installing" records)
|
||||
# CRITICAL: Send telemetry FIRST before any cleanup or output
|
||||
# If ensure_log_on_host hangs (e.g. pct pull on dying container),
|
||||
# the status update would never be sent, leaving records stuck in "installing"
|
||||
if declare -f post_update_to_api >/dev/null 2>&1; then
|
||||
post_update_to_api "failed" "130"
|
||||
post_update_to_api "failed" "130" 2>/dev/null || true
|
||||
fi
|
||||
# Best-effort log collection (non-critical after telemetry is sent)
|
||||
if declare -f ensure_log_on_host >/dev/null 2>&1; then
|
||||
ensure_log_on_host 2>/dev/null || true
|
||||
fi
|
||||
if declare -f msg_error >/dev/null 2>&1; then
|
||||
msg_error "Interrupted by user (SIGINT)"
|
||||
msg_error "Interrupted by user (SIGINT)" 2>/dev/null || true
|
||||
else
|
||||
echo -e "\n${RD}Interrupted by user (SIGINT)${CL}"
|
||||
echo -e "\n${RD}Interrupted by user (SIGINT)${CL}" 2>/dev/null || true
|
||||
fi
|
||||
exit 130
|
||||
}
|
||||
@@ -380,23 +396,27 @@ on_interrupt() {
|
||||
# on_terminate()
|
||||
#
|
||||
# - SIGTERM trap handler
|
||||
# - Reports to telemetry FIRST (time-critical: process being killed)
|
||||
# - Displays "Terminated by signal" message
|
||||
# - Exits with code 143 (128 + SIGTERM=15)
|
||||
# - Triggered by external process termination
|
||||
# - Output redirected to /dev/null fallback to prevent SIGPIPE on closed terminals
|
||||
# ------------------------------------------------------------------------------
|
||||
on_terminate() {
|
||||
# Ensure log is accessible on host before reporting
|
||||
if declare -f ensure_log_on_host >/dev/null 2>&1; then
|
||||
ensure_log_on_host
|
||||
fi
|
||||
# Report termination to telemetry API (prevents stuck "installing" records)
|
||||
# CRITICAL: Send telemetry FIRST before any cleanup or output
|
||||
# Same rationale as on_interrupt: ensure status gets reported even if
|
||||
# ensure_log_on_host hangs or terminal is already closed
|
||||
if declare -f post_update_to_api >/dev/null 2>&1; then
|
||||
post_update_to_api "failed" "143"
|
||||
post_update_to_api "failed" "143" 2>/dev/null || true
|
||||
fi
|
||||
# Best-effort log collection (non-critical after telemetry is sent)
|
||||
if declare -f ensure_log_on_host >/dev/null 2>&1; then
|
||||
ensure_log_on_host 2>/dev/null || true
|
||||
fi
|
||||
if declare -f msg_error >/dev/null 2>&1; then
|
||||
msg_error "Terminated by signal (SIGTERM)"
|
||||
msg_error "Terminated by signal (SIGTERM)" 2>/dev/null || true
|
||||
else
|
||||
echo -e "\n${RD}Terminated by signal (SIGTERM)${CL}"
|
||||
echo -e "\n${RD}Terminated by signal (SIGTERM)${CL}" 2>/dev/null || true
|
||||
fi
|
||||
exit 143
|
||||
}
|
||||
|
||||
@@ -37,6 +37,13 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
|
||||
load_functions
|
||||
catch_errors
|
||||
|
||||
# Persist diagnostics setting inside container (exported from build.func)
|
||||
# so addon scripts running later can find the user's choice
|
||||
if [[ ! -f /usr/local/community-scripts/diagnostics ]]; then
|
||||
mkdir -p /usr/local/community-scripts
|
||||
echo "DIAGNOSTICS=${DIAGNOSTICS:-no}" >/usr/local/community-scripts/diagnostics
|
||||
fi
|
||||
|
||||
# Get LXC IP address (must be called INSIDE container, after network is up)
|
||||
get_lxc_ip
|
||||
|
||||
@@ -56,7 +63,7 @@ post_progress_to_api() {
|
||||
|
||||
curl -fsS -m 5 -X POST "https://telemetry.community-scripts.org/telemetry" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"random_id\":\"${RANDOM_UUID}\",\"type\":\"lxc\",\"nsapp\":\"${app:-unknown}\",\"status\":\"configuring\"}" &>/dev/null || true
|
||||
-d "{\"random_id\":\"${RANDOM_UUID}\",\"execution_id\":\"${EXECUTION_ID:-${RANDOM_UUID}}\",\"type\":\"lxc\",\"nsapp\":\"${app:-unknown}\",\"status\":\"configuring\"}" &>/dev/null || true
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
|
||||
@@ -22,7 +22,7 @@ set -e
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "add-netbird-lxc" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "add-netbird-lxc" "addon"
|
||||
|
||||
while true; do
|
||||
read -p "This will add NetBird to an existing LXC Container ONLY. Proceed(y/n)?" yn
|
||||
|
||||
@@ -25,7 +25,7 @@ function msg_error() { echo -e " \e[1;31m✖\e[0m $1"; }
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "add-tailscale-lxc" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "add-tailscale-lxc" "addon"
|
||||
|
||||
header_info
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ function msg() {
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "all-templates" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "all-templates" "addon"
|
||||
|
||||
function validate_container_id() {
|
||||
local ctid="$1"
|
||||
|
||||
@@ -29,7 +29,7 @@ silent() { "$@" >/dev/null 2>&1; }
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "netdata" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "netdata" "addon"
|
||||
|
||||
set -e
|
||||
header_info
|
||||
|
||||
@@ -33,7 +33,7 @@ CROSS="${RD}✗${CL} "
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "add-iptag" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "add-iptag" "pve"
|
||||
|
||||
# Stop any running spinner
|
||||
stop_spinner() {
|
||||
|
||||
@@ -24,7 +24,7 @@ CL="\033[m"
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "clean-lxcs" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "clean-lxcs" "pve"
|
||||
|
||||
header_info
|
||||
echo "Loading..."
|
||||
|
||||
@@ -18,7 +18,7 @@ EOF
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "clean-orphaned-lvm" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "clean-orphaned-lvm" "pve"
|
||||
|
||||
# Function to check for orphaned LVM volumes
|
||||
function find_orphaned_lvm {
|
||||
|
||||
@@ -46,7 +46,7 @@ header_info
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "container-restore" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "container-restore" "pve"
|
||||
|
||||
function msg_info() {
|
||||
local msg="$1"
|
||||
|
||||
@@ -46,7 +46,7 @@ header_info
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "core-restore" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "core-restore" "pve"
|
||||
|
||||
function msg_info() {
|
||||
local msg="$1"
|
||||
|
||||
@@ -25,7 +25,7 @@ CL=$(echo "\033[m")
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "execute-lxcs" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "execute-lxcs" "pve"
|
||||
|
||||
header_info
|
||||
echo "Loading..."
|
||||
|
||||
@@ -18,7 +18,7 @@ EOF
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "frigate-support" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "frigate-support" "pve"
|
||||
|
||||
header_info
|
||||
while true; do
|
||||
|
||||
@@ -21,7 +21,7 @@ CL="\033[m"
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "fstrim" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "fstrim" "pve"
|
||||
|
||||
LOGFILE="/var/log/fstrim.log"
|
||||
touch "$LOGFILE"
|
||||
|
||||
@@ -18,7 +18,7 @@ EOF
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "host-backup" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "host-backup" "pve"
|
||||
|
||||
# Function to perform backup
|
||||
function perform_backup {
|
||||
|
||||
@@ -32,7 +32,7 @@ set -e
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "hw-acceleration" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "hw-acceleration" "pve"
|
||||
|
||||
header_info
|
||||
echo "Loading..."
|
||||
|
||||
@@ -24,7 +24,7 @@ CL="\033[m"
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "kernel-clean" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "kernel-clean" "pve"
|
||||
|
||||
# Detect current kernel
|
||||
current_kernel=$(uname -r)
|
||||
|
||||
@@ -28,7 +28,7 @@ available_kernels=$(dpkg --list | grep 'kernel-.*-pve' | awk '{print substr($2,
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "kernel-pin" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "kernel-pin" "pve"
|
||||
|
||||
header_info
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ CM="${TAB}✔️${TAB}${CL}"
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "lxc-delete" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "lxc-delete" "pve"
|
||||
|
||||
header_info
|
||||
echo "Loading..."
|
||||
|
||||
@@ -31,7 +31,7 @@ msg_error() { echo -e "${BFR} ${CROSS} ${RD}$1${CL}"; }
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "microcode" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "microcode" "pve"
|
||||
|
||||
header_info
|
||||
current_microcode=$(journalctl -k | grep -i 'microcode: Current revision:' | grep -oP 'Current revision: \K0x[0-9a-f]+')
|
||||
|
||||
@@ -17,7 +17,7 @@ EOF
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "monitor-all" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "monitor-all" "pve"
|
||||
|
||||
add() {
|
||||
echo -e "\n IMPORTANT: Tag-Based Monitoring Enabled"
|
||||
|
||||
@@ -35,7 +35,7 @@ EOF
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "nic-offloading-fix" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "nic-offloading-fix" "pve"
|
||||
|
||||
header_info
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ msg_error() {
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "pbs3-upgrade" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "pbs3-upgrade" "pve"
|
||||
|
||||
start_routines() {
|
||||
header_info
|
||||
|
||||
@@ -34,7 +34,7 @@ msg_error() { echo -e "${BFR} ${CROSS} ${RD}$1${CL}"; }
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "pbs4-upgrade" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "pbs4-upgrade" "pve"
|
||||
|
||||
start_routines() {
|
||||
header_info
|
||||
|
||||
@@ -31,7 +31,7 @@ msg_info() { echo -ne " ${HOLD} ${YW}$1..."; }
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "pbs-microcode" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "pbs-microcode" "pve"
|
||||
msg_ok() { echo -e "${BFR} ${CM} ${GN}$1${CL}"; }
|
||||
msg_error() { echo -e "${BFR} ${CROSS} ${RD}$1${CL}"; }
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ msg_error() { echo -e "${BFR} ${CROSS} ${RD}$1${CL}"; }
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "post-pbs-install" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "post-pbs-install" "pve"
|
||||
|
||||
# ---- helpers ----
|
||||
get_pbs_codename() {
|
||||
|
||||
@@ -45,7 +45,7 @@ msg_error() {
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "post-pmg-install" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "post-pmg-install" "pve"
|
||||
|
||||
if ! grep -q "Proxmox Mail Gateway" /etc/issue 2>/dev/null; then
|
||||
msg_error "This script is only intended for Proxmox Mail Gateway"
|
||||
|
||||
@@ -46,7 +46,7 @@ msg_error() {
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "post-pve-install" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "post-pve-install" "pve"
|
||||
|
||||
get_pve_version() {
|
||||
local pve_ver
|
||||
|
||||
@@ -13,7 +13,7 @@ fi
|
||||
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVE/raw/branch/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
load_functions
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "pve-privilege-converter" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "pve-privilege-converter" "pve"
|
||||
|
||||
set -euo pipefail
|
||||
shopt -s inherit_errexit nullglob
|
||||
|
||||
@@ -46,7 +46,7 @@ msg_error() {
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "pve8-upgrade" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "pve8-upgrade" "pve"
|
||||
|
||||
start_routines() {
|
||||
header_info
|
||||
|
||||
@@ -8,7 +8,7 @@ set -e
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "scaling-governor" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "scaling-governor" "pve"
|
||||
|
||||
header_info() {
|
||||
clear
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/refs/heads/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "update-apps" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "update-apps" "pve"
|
||||
|
||||
# =============================================================================
|
||||
# CONFIGURATION VARIABLES
|
||||
|
||||
@@ -27,7 +27,7 @@ CL=$(echo "\033[m")
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "update-lxcs" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "update-lxcs" "pve"
|
||||
|
||||
header_info
|
||||
echo "Loading..."
|
||||
|
||||
@@ -25,7 +25,7 @@ CL=$(echo "\033[m")
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "update-repo" "tool"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "update-repo" "pve"
|
||||
|
||||
header_info
|
||||
echo "Loading..."
|
||||
|
||||
Reference in New Issue
Block a user