-
Notifications
You must be signed in to change notification settings - Fork 43
Expand file tree
/
Copy pathapi.func
More file actions
322 lines (287 loc) · 11 KB
/
api.func
File metadata and controls
322 lines (287 loc) · 11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
# Copyright (c) 2021-2026 community-scripts ORG
# Author: michelroegl-brunner
# License: MIT | https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/LICENSE
# ==============================================================================
# API.FUNC - TELEMETRY & DIAGNOSTICS API
# ==============================================================================
#
# Provides functions for sending anonymous telemetry data to Community-Scripts
# API for analytics and diagnostics purposes.
#
# Features:
# - Container/VM creation statistics
# - Installation success/failure tracking
# - Error code mapping and reporting
# - Privacy-respecting anonymous telemetry
#
# Usage:
# source <(curl -fsSL .../api.func)
# post_to_api # Report container creation
# post_update_to_api # Report installation status
#
# Privacy:
# - Only anonymous statistics (no personal data)
# - User can opt-out via diagnostics settings
# - Random UUID for session tracking only
#
# ==============================================================================
# ==============================================================================
# SECTION 1: ERROR CODE DESCRIPTIONS
# ==============================================================================
# ------------------------------------------------------------------------------
# explain_exit_code()
#
# - Maps numeric exit codes to human-readable error descriptions
# - Supports:
# * Generic/Shell errors (1, 2, 126, 127, 128, 130, 137, 139, 143)
# * Package manager errors (APT, DPKG: 100, 101, 255)
# * Node.js/npm errors (243-249, 254)
# * Python/pip/uv errors (210-212)
# * PostgreSQL errors (231-234)
# * MySQL/MariaDB errors (241-244)
# * MongoDB errors (251-254)
# * Proxmox custom codes (200-231)
# - Returns description string for given exit code
# - Shared function with error_handler.func for consistency
# ------------------------------------------------------------------------------
explain_exit_code() {
local code="$1"
case "$code" in
# --- Generic / Shell ---
1) echo "General error / Operation not permitted" ;;
2) echo "Misuse of shell builtins (e.g. syntax error)" ;;
126) echo "Command invoked cannot execute (permission problem?)" ;;
127) echo "Command not found" ;;
128) echo "Invalid argument to exit" ;;
130) echo "Terminated by Ctrl+C (SIGINT)" ;;
137) echo "Killed (SIGKILL / Out of memory?)" ;;
139) echo "Segmentation fault (core dumped)" ;;
143) echo "Terminated (SIGTERM)" ;;
# --- Package manager / APT / DPKG ---
100) echo "APT: Package manager error (broken packages / dependency problems)" ;;
101) echo "APT: Configuration error (bad sources.list, malformed config)" ;;
255) echo "DPKG: Fatal internal error" ;;
# --- Node.js / npm / pnpm / yarn ---
243) echo "Node.js: Out of memory (JavaScript heap out of memory)" ;;
245) echo "Node.js: Invalid command-line option" ;;
246) echo "Node.js: Internal JavaScript Parse Error" ;;
247) echo "Node.js: Fatal internal error" ;;
248) echo "Node.js: Invalid C++ addon / N-API failure" ;;
249) echo "Node.js: Inspector error" ;;
254) echo "npm/pnpm/yarn: Unknown fatal error" ;;
# --- Python / pip / uv ---
210) echo "Python: Virtualenv / uv environment missing or broken" ;;
211) echo "Python: Dependency resolution failed" ;;
212) echo "Python: Installation aborted (permissions or EXTERNALLY-MANAGED)" ;;
# --- PostgreSQL ---
231) echo "PostgreSQL: Connection failed (server not running / wrong socket)" ;;
232) echo "PostgreSQL: Authentication failed (bad user/password)" ;;
233) echo "PostgreSQL: Database does not exist" ;;
234) echo "PostgreSQL: Fatal error in query / syntax" ;;
# --- MySQL / MariaDB ---
241) echo "MySQL/MariaDB: Connection failed (server not running / wrong socket)" ;;
242) echo "MySQL/MariaDB: Authentication failed (bad user/password)" ;;
243) echo "MySQL/MariaDB: Database does not exist" ;;
244) echo "MySQL/MariaDB: Fatal error in query / syntax" ;;
# --- MongoDB ---
251) echo "MongoDB: Connection failed (server not running)" ;;
252) echo "MongoDB: Authentication failed (bad user/password)" ;;
253) echo "MongoDB: Database not found" ;;
254) echo "MongoDB: Fatal query error" ;;
# --- Proxmox Custom Codes ---
200) echo "Custom: Failed to create lock file" ;;
203) echo "Custom: Missing CTID variable" ;;
204) echo "Custom: Missing PCT_OSTYPE variable" ;;
205) echo "Custom: Invalid CTID (<100)" ;;
206) echo "Custom: CTID already in use (check 'pct list' and /etc/pve/lxc/)" ;;
207) echo "Custom: Password contains unescaped special characters (-, /, \\, *, etc.)" ;;
208) echo "Custom: Invalid configuration (DNS/MAC/Network format error)" ;;
209) echo "Custom: Container creation failed (check logs for pct create output)" ;;
210) echo "Custom: Cluster not quorate" ;;
211) echo "Custom: Timeout waiting for template lock (concurrent download in progress)" ;;
214) echo "Custom: Not enough storage space" ;;
215) echo "Custom: Container created but not listed (ghost state - check /etc/pve/lxc/)" ;;
216) echo "Custom: RootFS entry missing in config (incomplete creation)" ;;
217) echo "Custom: Storage does not support rootdir (check storage capabilities)" ;;
218) echo "Custom: Template file corrupted or incomplete download (size <1MB or invalid archive)" ;;
220) echo "Custom: Unable to resolve template path" ;;
221) echo "Custom: Template file exists but not readable (check file permissions)" ;;
222) echo "Custom: Template download failed after 3 attempts (network/storage issue)" ;;
223) echo "Custom: Template not available after download (storage sync issue)" ;;
225) echo "Custom: No template available for OS/Version (check 'pveam available')" ;;
231) echo "Custom: LXC stack upgrade/retry failed (outdated pve-container - check https://github.com/community-scripts/ProxmoxVE/discussions/8126)" ;;
# --- Default ---
*) echo "Unknown error" ;;
esac
}
# ==============================================================================
# SECTION 2: TELEMETRY FUNCTIONS
# ==============================================================================
# ------------------------------------------------------------------------------
# post_to_api()
#
# - Sends LXC container creation statistics to Community-Scripts API
# - Only executes if:
# * curl is available
# * DIAGNOSTICS=yes
# * RANDOM_UUID is set
# - Payload includes:
# * Container type, disk size, CPU cores, RAM
# * OS type and version
# * IPv6 disable status
# * Application name (NSAPP)
# * Installation method
# * PVE version
# * Status: "installing"
# * Random UUID for session tracking
# - Anonymous telemetry (no personal data)
# ------------------------------------------------------------------------------
post_to_api() {
if ! command -v curl &>/dev/null; then
return
fi
if [ "$DIAGNOSTICS" = "no" ]; then
return
fi
if [ -z "$RANDOM_UUID" ]; then
return
fi
local API_URL="http://api.community-scripts.org/upload"
local pve_version="not found"
pve_version=$(pveversion | awk -F'[/ ]' '{print $2}')
JSON_PAYLOAD=$(
cat <<EOF
{
"ct_type": $CT_TYPE,
"type":"lxc",
"disk_size": $DISK_SIZE,
"core_count": $CORE_COUNT,
"ram_size": $RAM_SIZE,
"os_type": "$var_os",
"os_version": "$var_version",
"nsapp": "$NSAPP",
"method": "$METHOD(PVE-Local)",
"pve_version": "$pve_version",
"status": "installing",
"random_id": "$RANDOM_UUID"
}
EOF
)
if [[ "$DIAGNOSTICS" == "yes" ]]; then
RESPONSE=$(curl -s -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD") || true
fi
}
# ------------------------------------------------------------------------------
# post_to_api_vm()
#
# - Sends VM creation statistics to Community-Scripts API
# - Similar to post_to_api() but for virtual machines (not containers)
# - Reads DIAGNOSTICS from /usr/local/community-scripts/diagnostics file
# - Payload differences:
# * ct_type=2 (VM instead of LXC)
# * type="vm"
# * Disk size without 'G' suffix (parsed from DISK_SIZE variable)
# - Only executes if DIAGNOSTICS=yes and RANDOM_UUID is set
# ------------------------------------------------------------------------------
post_to_api_vm() {
if [[ ! -f /usr/local/community-scripts/diagnostics ]]; then
return
fi
DIAGNOSTICS=$(grep -i "^DIAGNOSTICS=" /usr/local/community-scripts/diagnostics | awk -F'=' '{print $2}')
if ! command -v curl &>/dev/null; then
return
fi
if [ "$DIAGNOSTICS" = "no" ]; then
return
fi
if [ -z "$RANDOM_UUID" ]; then
return
fi
local API_URL="http://api.community-scripts.org/upload"
local pve_version="not found"
pve_version=$(pveversion | awk -F'[/ ]' '{print $2}')
DISK_SIZE_API=${DISK_SIZE%G}
JSON_PAYLOAD=$(
cat <<EOF
{
"ct_type": 2,
"type":"vm",
"disk_size": $DISK_SIZE_API,
"core_count": $CORE_COUNT,
"ram_size": $RAM_SIZE,
"os_type": "$var_os",
"os_version": "$var_version",
"nsapp": "$NSAPP",
"method": "$METHOD(PVE-Local)",
"pve_version": "$pve_version",
"status": "installing",
"random_id": "$RANDOM_UUID"
}
EOF
)
if [[ "$DIAGNOSTICS" == "yes" ]]; then
RESPONSE=$(curl -s -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD") || true
fi
}
# ------------------------------------------------------------------------------
# post_update_to_api()
#
# - Reports installation completion status to API
# - Prevents duplicate submissions via POST_UPDATE_DONE flag
# - Arguments:
# * $1: status ("success" or "failed")
# * $2: exit_code (default: 1 for failed, 0 for success)
# - Payload includes:
# * Final status (success/failed)
# * Error description via get_error_description()
# * Random UUID for session correlation
# - Only executes once per session
# - Silently returns if:
# * curl not available
# * Already reported (POST_UPDATE_DONE=true)
# * DIAGNOSTICS=no
# ------------------------------------------------------------------------------
post_update_to_api() {
if ! command -v curl &>/dev/null; then
return
fi
# Initialize flag if not set (prevents 'unbound variable' error with set -u)
POST_UPDATE_DONE=${POST_UPDATE_DONE:-false}
if [ "$POST_UPDATE_DONE" = true ]; then
return 0
fi
exit_code=${2:-1}
local API_URL="http://api.community-scripts.org/upload/updatestatus"
local status="${1:-failed}"
if [[ "$status" == "failed" ]]; then
local exit_code="${2:-1}"
elif [[ "$status" == "success" ]]; then
local exit_code="${2:-0}"
fi
if [[ -z "$exit_code" ]]; then
exit_code=1
fi
error=$(explain_exit_code "$exit_code")
if [ -z "$error" ]; then
error="Unknown error"
fi
JSON_PAYLOAD=$(
cat <<EOF
{
"status": "$status",
"error": "$error",
"random_id": "$RANDOM_UUID"
}
EOF
)
if [[ "$DIAGNOSTICS" == "yes" ]]; then
RESPONSE=$(curl -s -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD") || true
fi
POST_UPDATE_DONE=true
}