diff --git a/defaults.inc b/defaults.inc index 83b56fd..e39ee32 100755 --- a/defaults.inc +++ b/defaults.inc @@ -3,7 +3,7 @@ action="${1:-}" FOLDER='/opt/idssys/ta-proxmenu' -VERS='2026.7.25-61' +VERS='2026.7.25-63' noupdate=' ' diff --git a/inc/deploy-pulse-lxc.sh b/inc/deploy-pulse-lxc.sh index 1d6bc3e..842c227 100644 --- a/inc/deploy-pulse-lxc.sh +++ b/inc/deploy-pulse-lxc.sh @@ -202,6 +202,31 @@ raise SystemExit(1) ' 2>/dev/null } +TAPM_PULSE_RESOURCE_INSTALLED_FROM_CONFIGS() { + local nodes_directory="${1:-/etc/pve/nodes}" + local config hostname tags + local -a configs + + [[ -d "$nodes_directory" ]] || return 2 + configs=("$nodes_directory"/*/lxc/*.conf) + for config in "${configs[@]}"; do + [[ -f "$config" ]] || continue + hostname="$( + awk -F':[[:space:]]*' '$1 == "hostname" { print $2; exit }' "$config" + )" + tags="$( + awk -F':[[:space:]]*' '$1 == "tags" { print $2; exit }' "$config" + )" + case "$hostname" in + [Pp][Uu][Ll][Ss][Ee]|[Pp][Uu][Ll][Ss][Ee]-[Mm][Oo][Nn][Ii][Tt][Oo][Rr]) + return 0 + ;; + esac + [[ ";${tags};" == *";pulse;"* ]] && return 0 + done + return 1 +} + TAPM_PULSE_PROMPT() { local variable="$1" local label="$2" diff --git a/proxmenu-scripts.sh b/proxmenu-scripts.sh index 3777f0a..f2ba36a 100755 --- a/proxmenu-scripts.sh +++ b/proxmenu-scripts.sh @@ -1219,11 +1219,30 @@ for guest in json.load(sys.stdin): TAPM_QEMU_CPU_MODEL() { local vmid="$1" local node="$2" + local config_file local config_output local cpu_model [[ "$vmid" =~ ^[1-9][0-9]{2,8}$ ]] || return 1 [[ "$node" =~ ^[A-Za-z0-9][A-Za-z0-9._-]{0,62}$ ]] || return 1 + config_file="/etc/pve/nodes/${node}/qemu-server/${vmid}.conf" + if [[ -r "$config_file" ]]; then + cpu_model="$( + awk ' +$1 == "cpu:" { + sub(/^[^:]*:[[:space:]]*/, "") + print + exit +} +' "$config_file" + )" || return 1 + [[ -n "$cpu_model" ]] || cpu_model='kvm64' + printf '%s\n' "$cpu_model" + return 0 + fi + + # Fall back to the node-aware API if the shared pmxcfs entry is briefly + # unavailable, such as while cluster membership is changing. config_output="$( pvesh get "/nodes/${node}/qemu/${vmid}/config" \ --output-format json 2>/dev/null @@ -1696,7 +1715,11 @@ FORCE_UPDATE_CHECK() { MENU_HEADER() { local version_display - LOAD_UPDATE_STATUS + # Reuse a settled update result instead of running Git checks on every + # arrow-key redraw. Continue refreshing only while the worker is pending. + if [[ "$UPDATE_STATUS" == 'unknown' || "$UPDATE_STATUS" == 'checking' ]]; then + LOAD_UPDATE_STATUS + fi case "$UPDATE_STATUS" in behind) version_display="${idsCL[LightYellow]}${VERS} ** UPDATE AVAILABLE **${idsCL[Default]}" @@ -1844,12 +1867,8 @@ HOST_SETUP_MENU() { labels+=("Detect CPU model for live migrations") values+=("cpu") - TAPM_REFRESH_ISO_STORAGES >/dev/null 2>&1 || true - if TAPM_ANY_LOCAL_VIRTIO_ISOS; then - labels+=("VirtIO driver downloads (local ISOs available)") - else - labels+=("VirtIO driver downloads") - fi + # Discover ISO storage only after the VirtIO submenu is selected. + labels+=("VirtIO driver downloads") values+=("virtio") command -v glances >/dev/null 2>&1 && @@ -1881,10 +1900,19 @@ MONITORING_MENU() { local -a labels local -a values=("pulse" "rmm" "acronis" "sentinelone" "screenconnect") local cluster_resources + local pulse_status while true; do - cluster_resources="$(pvesh get /cluster/resources --type vm --output-format json 2>/dev/null)" - TAPM_PULSE_RESOURCE_INSTALLED "$cluster_resources" && + TAPM_PULSE_RESOURCE_INSTALLED_FROM_CONFIGS + pulse_status=$? + if (( pulse_status == 2 )); then + cluster_resources="$( + pvesh get /cluster/resources --type vm --output-format json 2>/dev/null + )" + TAPM_PULSE_RESOURCE_INSTALLED "$cluster_resources" + pulse_status=$? + fi + (( pulse_status == 0 )) && labels=("Pulse monitoring (installed)") || labels=("Install Pulse monitoring") diff --git a/tests/test-pulse.sh b/tests/test-pulse.sh index 68705d4..9be6d75 100644 --- a/tests/test-pulse.sh +++ b/tests/test-pulse.sh @@ -185,6 +185,26 @@ assert_success "untagged default Pulse hostname detected" \ assert_failure "unrelated resource not detected" \ TAPM_PULSE_RESOURCE_INSTALLED '[{"type":"qemu","name":"pulse"}]' +test_pulse_config_detection() { + local fixture_root status + + fixture_root="$(mktemp -d /tmp/tapm-pulse-configs.XXXXXX)" || return 1 + mkdir -p "${fixture_root}/pve1/lxc" || return 1 + printf '%s\n' \ + 'arch: amd64' \ + 'hostname: Pulse-Monitor' \ + 'memory: 2048' >"${fixture_root}/pve1/lxc/200.conf" + TAPM_PULSE_RESOURCE_INSTALLED_FROM_CONFIGS "$fixture_root" + status=$? + rm -rf -- "$fixture_root" + return "$status" +} + +assert_success "Pulse LXC detected from shared Proxmox configuration" \ + test_pulse_config_detection +assert_failure "missing Pulse configuration directory is not installed" \ + TAPM_PULSE_RESOURCE_INSTALLED_FROM_CONFIGS /does/not/exist + ha_status=$'quorum OK\nmaster pve1 (active, Sat Jul 25 12:00:00 2026)\nlrm pve1 (active, Sat Jul 25 12:00:00 2026)' assert_success "active Proxmox HA detected" TAPM_PULSE_HA_STATUS_ENABLED "$ha_status" assert_failure "inactive Proxmox HA rejected" \