update
This commit is contained in:
+4
-1
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
action="${1:-}"
|
action="${1:-}"
|
||||||
FOLDER='/opt/idssys/ta-proxmenu'
|
FOLDER='/opt/idssys/ta-proxmenu'
|
||||||
VERS='2026.7.25-45'
|
VERS='2026.7.25-46'
|
||||||
|
|
||||||
noupdate=' '
|
noupdate=' '
|
||||||
|
|
||||||
@@ -16,6 +16,9 @@ fi
|
|||||||
|
|
||||||
VIRTIO_STABLE_URL="https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso"
|
VIRTIO_STABLE_URL="https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso"
|
||||||
|
|
||||||
|
PULSE_RELEASE='v6.1.1'
|
||||||
|
PULSE_PORT='7655'
|
||||||
|
|
||||||
TAPM_BROKER_URL='https://tapm.scity.us'
|
TAPM_BROKER_URL='https://tapm.scity.us'
|
||||||
S1_BROKER_PACKAGE='sentinelone-linux'
|
S1_BROKER_PACKAGE='sentinelone-linux'
|
||||||
S1_PACKAGE='tapm-sentinelone.deb'
|
S1_PACKAGE='tapm-sentinelone.deb'
|
||||||
|
|||||||
@@ -0,0 +1,411 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# TA-managed Pulse LXC deployment for Proxmox VE.
|
||||||
|
#
|
||||||
|
# TA-ProxMenu owns the LXC provisioning and pins an exact Pulse release. The
|
||||||
|
# matching upstream installer and archive are both downloaded from that release
|
||||||
|
# and verified with Pulse's published SSH signing key before use. There is no
|
||||||
|
# "latest" URL lookup or HEAD request in this workflow.
|
||||||
|
|
||||||
|
TAPM_PULSE_SIGNING_IDENTITY='pulse-installer'
|
||||||
|
TAPM_PULSE_SIGNING_NAMESPACE='pulse-install'
|
||||||
|
TAPM_PULSE_SIGNING_KEY='ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMZd/DaH+BldzOkq1A8KVTcFk73nAyrE8aJOyf7i00jm'
|
||||||
|
|
||||||
|
TAPM_PULSE_VALID_RELEASE() {
|
||||||
|
[[ "${1:-}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([.-][A-Za-z0-9.-]+)?$ ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
TAPM_PULSE_VALID_CTID() {
|
||||||
|
[[ "${1:-}" =~ ^[1-9][0-9]{2,8}$ ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
TAPM_PULSE_VALID_HOSTNAME() {
|
||||||
|
[[ "${1:-}" =~ ^[A-Za-z0-9][A-Za-z0-9.-]{0,62}$ ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
TAPM_PULSE_VALID_IPV4_CIDR() {
|
||||||
|
local value="${1:-}"
|
||||||
|
local address prefix octet
|
||||||
|
local -a octets
|
||||||
|
|
||||||
|
[[ "$value" == */* ]] || return 1
|
||||||
|
address="${value%/*}"
|
||||||
|
prefix="${value#*/}"
|
||||||
|
[[ "$prefix" =~ ^[0-9]+$ ]] && (( prefix <= 32 )) || return 1
|
||||||
|
IFS=. read -r -a octets <<<"$address"
|
||||||
|
(( ${#octets[@]} == 4 )) || return 1
|
||||||
|
for octet in "${octets[@]}"; do
|
||||||
|
[[ "$octet" =~ ^[0-9]+$ ]] && (( 10#$octet <= 255 )) || return 1
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
TAPM_PULSE_ARCH() {
|
||||||
|
case "${1:-}" in
|
||||||
|
x86_64|amd64) printf 'amd64\n';;
|
||||||
|
aarch64|arm64) printf 'arm64\n';;
|
||||||
|
*) return 1;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
TAPM_PULSE_RESOURCE_INSTALLED() {
|
||||||
|
local resources_json="${1:-[]}"
|
||||||
|
|
||||||
|
RESOURCES_JSON="$resources_json" python3 -c '
|
||||||
|
import json, os
|
||||||
|
try:
|
||||||
|
resources = json.loads(os.environ["RESOURCES_JSON"])
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
raise SystemExit(1)
|
||||||
|
for item in resources:
|
||||||
|
tags = str(item.get("tags", "")).split(";")
|
||||||
|
if item.get("type") == "lxc" and (
|
||||||
|
"pulse" in tags or str(item.get("name", "")).lower() == "pulse"
|
||||||
|
):
|
||||||
|
raise SystemExit(0)
|
||||||
|
raise SystemExit(1)
|
||||||
|
' 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
TAPM_PULSE_PROMPT() {
|
||||||
|
local variable="$1"
|
||||||
|
local label="$2"
|
||||||
|
local default_value="${3:-}"
|
||||||
|
local value
|
||||||
|
|
||||||
|
if [[ -n "$default_value" ]]; then
|
||||||
|
read -r -p " ${label} [${default_value}]: " value
|
||||||
|
printf -v "$variable" '%s' "${value:-$default_value}"
|
||||||
|
else
|
||||||
|
read -r -p " ${label}: " value
|
||||||
|
printf -v "$variable" '%s' "$value"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
TAPM_PULSE_FAIL() {
|
||||||
|
echo -e "\n${idsCL[LightRed]}$1${idsCL[Default]}"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
TAPM_PULSE_SELECT_BRIDGE() {
|
||||||
|
local variable="$1"
|
||||||
|
local bridge default_bridge="${2:-vmbr0}"
|
||||||
|
local default_found=0
|
||||||
|
local -a bridges=()
|
||||||
|
local -a labels=()
|
||||||
|
local -a values=()
|
||||||
|
|
||||||
|
while IFS= read -r bridge; do
|
||||||
|
[[ -n "$bridge" ]] || continue
|
||||||
|
bridges+=("$bridge")
|
||||||
|
[[ "$bridge" == "$default_bridge" ]] && default_found=1
|
||||||
|
done < <(
|
||||||
|
for bridge_path in /sys/class/net/*/bridge; do
|
||||||
|
[[ -d "$bridge_path" ]] && basename "$(dirname "$bridge_path")"
|
||||||
|
done | sort -V
|
||||||
|
)
|
||||||
|
|
||||||
|
(( ${#bridges[@]} > 0 )) ||
|
||||||
|
{ TAPM_PULSE_FAIL "No Linux bridges were found on this host."; return 1; }
|
||||||
|
|
||||||
|
if (( default_found == 1 )); then
|
||||||
|
labels+=("${default_bridge} — default")
|
||||||
|
values+=("bridge:${default_bridge}")
|
||||||
|
fi
|
||||||
|
for bridge in "${bridges[@]}"; do
|
||||||
|
[[ $default_found == 1 && "$bridge" == "$default_bridge" ]] && continue
|
||||||
|
labels+=("$bridge")
|
||||||
|
values+=("bridge:${bridge}")
|
||||||
|
done
|
||||||
|
|
||||||
|
SELECT_MENU "Pulse network bridge" labels values
|
||||||
|
case "$MENU_SELECTION" in
|
||||||
|
bridge:*) printf -v "$variable" '%s' "${MENU_SELECTION#bridge:}";;
|
||||||
|
quit) EXIT1; exit 0;;
|
||||||
|
*) return 1;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
TAPM_PULSE_STORAGE_IS_SHARED() {
|
||||||
|
local storage="$1"
|
||||||
|
|
||||||
|
pvesh get "/storage/${storage}" --output-format json 2>/dev/null |
|
||||||
|
python3 -c '
|
||||||
|
import json, sys
|
||||||
|
try:
|
||||||
|
value = json.load(sys.stdin).get("shared", 0)
|
||||||
|
except (AttributeError, TypeError, ValueError):
|
||||||
|
raise SystemExit(1)
|
||||||
|
raise SystemExit(0 if str(value).lower() in {"1", "true", "yes"} else 1)
|
||||||
|
'
|
||||||
|
}
|
||||||
|
|
||||||
|
TAPM_PULSE_VERIFY_SIGNATURE() {
|
||||||
|
local target_path="$1"
|
||||||
|
local signature_path="$2"
|
||||||
|
local label="${3:-Pulse release asset}"
|
||||||
|
local allowed_signers
|
||||||
|
|
||||||
|
command -v ssh-keygen >/dev/null 2>&1 ||
|
||||||
|
{ TAPM_PULSE_FAIL "OpenSSH is required to verify ${label}."; return 1; }
|
||||||
|
[[ -s "$target_path" && -s "$signature_path" ]] ||
|
||||||
|
{ TAPM_PULSE_FAIL "${label} or its signature is missing."; return 1; }
|
||||||
|
|
||||||
|
allowed_signers="$(mktemp /tmp/tapm-pulse-signers.XXXXXX)" ||
|
||||||
|
{ TAPM_PULSE_FAIL "Could not create the Pulse signature verifier file."; return 1; }
|
||||||
|
printf '%s %s\n' "$TAPM_PULSE_SIGNING_IDENTITY" \
|
||||||
|
"$TAPM_PULSE_SIGNING_KEY" >"$allowed_signers"
|
||||||
|
|
||||||
|
if ! ssh-keygen -Y verify \
|
||||||
|
-f "$allowed_signers" \
|
||||||
|
-I "$TAPM_PULSE_SIGNING_IDENTITY" \
|
||||||
|
-n "$TAPM_PULSE_SIGNING_NAMESPACE" \
|
||||||
|
-s "$signature_path" <"$target_path" >/dev/null 2>&1; then
|
||||||
|
rm -f -- "$allowed_signers"
|
||||||
|
TAPM_PULSE_FAIL "Signature verification failed for ${label}; nothing was installed."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
rm -f -- "$allowed_signers"
|
||||||
|
}
|
||||||
|
|
||||||
|
TAPM_PULSE_REMOVE_PARTIAL_LXC() {
|
||||||
|
local ctid="$1"
|
||||||
|
|
||||||
|
echo -e "${idsCL[LightYellow]}Removing incomplete LXC ${ctid} created by this deployment...${idsCL[Default]}"
|
||||||
|
pct stop "$ctid" --skiplock 1 >/dev/null 2>&1 || true
|
||||||
|
pct destroy "$ctid" --purge 1 >/dev/null 2>&1 || true
|
||||||
|
}
|
||||||
|
|
||||||
|
TAPM_DEPLOY_PULSE_LXC() {
|
||||||
|
local release="${PULSE_RELEASE:-v6.1.1}"
|
||||||
|
local pulse_port="${PULSE_PORT:-7655}"
|
||||||
|
local ctid default_ctid hostname bridge address_cidr gateway vlan_id
|
||||||
|
local root_storage default_root_storage template_storage template_name template_path
|
||||||
|
local arch archive_name base_url installer archive signature installer_signature
|
||||||
|
local network_config choice add_ha='no' container_ip timezone temp_dir
|
||||||
|
local container_created=0
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo -e "${idsCL[LightCyan]}Deploy Pulse monitoring in a dedicated LXC${idsCL[Default]}"
|
||||||
|
echo
|
||||||
|
echo " This TA-managed workflow creates the container and installs a pinned,"
|
||||||
|
echo " cryptographically verified Pulse release. It does not query a latest"
|
||||||
|
echo " release URL before installation."
|
||||||
|
echo
|
||||||
|
|
||||||
|
[[ $EUID -eq 0 ]] ||
|
||||||
|
{ TAPM_PULSE_FAIL "Run this action as root on a Proxmox VE host."; return 1; }
|
||||||
|
for command in pct pvesm pveam pvesh ssh-keygen python3; do
|
||||||
|
command -v "$command" >/dev/null 2>&1 ||
|
||||||
|
{ TAPM_PULSE_FAIL "Required command '${command}' was not found."; return 1; }
|
||||||
|
done
|
||||||
|
TAPM_PULSE_VALID_RELEASE "$release" ||
|
||||||
|
{ TAPM_PULSE_FAIL "Configured Pulse release '${release}' is invalid."; return 1; }
|
||||||
|
|
||||||
|
default_ctid="$(pvesh get /cluster/nextid 2>/dev/null || true)"
|
||||||
|
TAPM_PULSE_PROMPT ctid "Container ID" "$default_ctid"
|
||||||
|
TAPM_PULSE_VALID_CTID "$ctid" ||
|
||||||
|
{ TAPM_PULSE_FAIL "The container ID is invalid."; return 1; }
|
||||||
|
if pct status "$ctid" >/dev/null 2>&1; then
|
||||||
|
TAPM_PULSE_FAIL "Container ${ctid} already exists; no changes were made."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
TAPM_PULSE_PROMPT hostname "Container hostname" "pulse"
|
||||||
|
TAPM_PULSE_VALID_HOSTNAME "$hostname" ||
|
||||||
|
{ TAPM_PULSE_FAIL "The hostname is invalid."; return 1; }
|
||||||
|
TAPM_PULSE_SELECT_BRIDGE bridge vmbr0 || return 1
|
||||||
|
TAPM_PULSE_PROMPT address_cidr \
|
||||||
|
"Static IPv4 address with prefix (leave blank for DHCP)"
|
||||||
|
if [[ -n "$address_cidr" ]]; then
|
||||||
|
TAPM_PULSE_VALID_IPV4_CIDR "$address_cidr" ||
|
||||||
|
{ TAPM_PULSE_FAIL "The static IPv4 address is invalid."; return 1; }
|
||||||
|
TAPM_PULSE_PROMPT gateway "IPv4 gateway"
|
||||||
|
TAPM_PULSE_VALID_IPV4_CIDR "${gateway}/32" ||
|
||||||
|
{ TAPM_PULSE_FAIL "The IPv4 gateway is invalid."; return 1; }
|
||||||
|
fi
|
||||||
|
TAPM_PULSE_PROMPT vlan_id "VLAN ID (leave blank for untagged)"
|
||||||
|
if [[ -n "$vlan_id" ]] &&
|
||||||
|
{ [[ ! "$vlan_id" =~ ^[0-9]+$ ]] || (( vlan_id < 1 || vlan_id > 4094 )); }; then
|
||||||
|
TAPM_PULSE_FAIL "The VLAN ID must be between 1 and 4094."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
default_root_storage="$(
|
||||||
|
pvesm status --content rootdir 2>/dev/null |
|
||||||
|
awk 'NR > 1 && $3 == "active" { print $1; exit }'
|
||||||
|
)"
|
||||||
|
[[ -n "$default_root_storage" ]] ||
|
||||||
|
{ TAPM_PULSE_FAIL "No active storage supports LXC volumes."; return 1; }
|
||||||
|
TAPM_ISO_NFS_SELECT_STORAGE root_storage \
|
||||||
|
"Pulse root filesystem storage" "$default_root_storage" || return 1
|
||||||
|
|
||||||
|
default_root_storage="$(
|
||||||
|
pvesm status --content vztmpl 2>/dev/null |
|
||||||
|
awk 'NR > 1 && $3 == "active" { print $1; exit }'
|
||||||
|
)"
|
||||||
|
[[ -n "$default_root_storage" ]] ||
|
||||||
|
{ TAPM_PULSE_FAIL "No active storage supports container templates."; return 1; }
|
||||||
|
template_storage="$default_root_storage"
|
||||||
|
|
||||||
|
if TAPM_PULSE_STORAGE_IS_SHARED "$root_storage" &&
|
||||||
|
command -v ha-manager >/dev/null 2>&1; then
|
||||||
|
read -r -p " Add the Pulse LXC to Proxmox HA after installation? [Y/n] " choice
|
||||||
|
[[ ! "$choice" =~ ^[Nn]$ ]] && add_ha='yes'
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo " Deployment summary"
|
||||||
|
echo " Pulse release: ${release}"
|
||||||
|
echo " LXC: ${ctid} (${hostname}), unprivileged"
|
||||||
|
if [[ -n "$address_cidr" ]]; then
|
||||||
|
echo " Network: ${address_cidr} via ${gateway} on ${bridge}"
|
||||||
|
else
|
||||||
|
echo " Network: DHCP on ${bridge}"
|
||||||
|
fi
|
||||||
|
[[ -n "$vlan_id" ]] && echo " VLAN: ${vlan_id}"
|
||||||
|
echo " Resources: 2 vCPU, 2048 MiB RAM, 512 MiB swap, 100 CPU units"
|
||||||
|
echo " Root volume: ${root_storage}:8 GiB"
|
||||||
|
echo " Pulse port: ${pulse_port}"
|
||||||
|
echo " Start at boot: yes"
|
||||||
|
echo " Automatic update: enabled"
|
||||||
|
echo " Proxmox HA: ${add_ha}"
|
||||||
|
echo
|
||||||
|
read -r -p " Create this Pulse container (type yes to continue)? " choice
|
||||||
|
[[ "$choice" =~ ^[Yy][Ee][Ss]$ ]] || {
|
||||||
|
echo " Cancelled; no changes were made."
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
arch="$(TAPM_PULSE_ARCH "$(uname -m)")" ||
|
||||||
|
{ TAPM_PULSE_FAIL "Pulse does not support this host architecture."; return 1; }
|
||||||
|
archive_name="pulse-${release}-linux-${arch}.tar.gz"
|
||||||
|
base_url="https://github.com/rcourtman/Pulse/releases/download/${release}"
|
||||||
|
|
||||||
|
if ! TAPM_CREATE_TEMP_DIR pulse; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
temp_dir="$TAPM_TEMP_DIR"
|
||||||
|
installer="${temp_dir}/install.sh"
|
||||||
|
installer_signature="${installer}.sshsig"
|
||||||
|
archive="${temp_dir}/${archive_name}"
|
||||||
|
signature="${archive}.sshsig"
|
||||||
|
|
||||||
|
echo -e "\n${idsCL[LightCyan]}Downloading and verifying Pulse ${release}...${idsCL[Default]}"
|
||||||
|
if ! TAPM_DOWNLOAD_HTTPS "${base_url}/install.sh" "$installer" "Pulse installer" ||
|
||||||
|
! TAPM_DOWNLOAD_HTTPS "${base_url}/install.sh.sshsig" \
|
||||||
|
"$installer_signature" "Pulse installer signature" ||
|
||||||
|
! TAPM_PULSE_VERIFY_SIGNATURE "$installer" "$installer_signature" "Pulse installer" ||
|
||||||
|
! TAPM_DOWNLOAD_HTTPS "${base_url}/${archive_name}" "$archive" "Pulse archive" ||
|
||||||
|
! TAPM_DOWNLOAD_HTTPS "${base_url}/${archive_name}.sshsig" \
|
||||||
|
"$signature" "Pulse archive signature" ||
|
||||||
|
! TAPM_PULSE_VERIFY_SIGNATURE "$archive" "$signature" "Pulse archive"; then
|
||||||
|
TAPM_CLEAN_TEMP_DIR "$temp_dir"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "\n${idsCL[LightCyan]}Locating a Debian container template...${idsCL[Default]}"
|
||||||
|
if ! pveam update; then
|
||||||
|
TAPM_CLEAN_TEMP_DIR "$temp_dir"
|
||||||
|
TAPM_PULSE_FAIL "Could not refresh the container template catalog."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
template_name="$(
|
||||||
|
pveam available --section system |
|
||||||
|
awk '$2 ~ /^debian-(13|12)-standard_/ { print $2 }' |
|
||||||
|
sort -V |
|
||||||
|
tail -1
|
||||||
|
)"
|
||||||
|
if [[ -z "$template_name" ]]; then
|
||||||
|
TAPM_CLEAN_TEMP_DIR "$temp_dir"
|
||||||
|
TAPM_PULSE_FAIL "No supported Debian 12/13 standard template was found."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
template_path="${template_storage}:vztmpl/${template_name}"
|
||||||
|
if ! pveam list "$template_storage" 2>/dev/null |
|
||||||
|
awk 'NR > 1 { print $1 }' |
|
||||||
|
grep -Fxq -- "$template_path"; then
|
||||||
|
if ! pveam download "$template_storage" "$template_name"; then
|
||||||
|
TAPM_CLEAN_TEMP_DIR "$temp_dir"
|
||||||
|
TAPM_PULSE_FAIL "The Debian template download failed."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$address_cidr" ]]; then
|
||||||
|
network_config="name=eth0,bridge=${bridge},ip=${address_cidr},gw=${gateway},firewall=1,type=veth"
|
||||||
|
else
|
||||||
|
network_config="name=eth0,bridge=${bridge},ip=dhcp,firewall=1,type=veth"
|
||||||
|
fi
|
||||||
|
[[ -n "$vlan_id" ]] && network_config+=",tag=${vlan_id}"
|
||||||
|
|
||||||
|
echo -e "\n${idsCL[LightCyan]}Creating and starting LXC ${ctid}...${idsCL[Default]}"
|
||||||
|
if ! pct create "$ctid" "$template_path" \
|
||||||
|
--hostname "$hostname" \
|
||||||
|
--ostype debian \
|
||||||
|
--unprivileged 1 \
|
||||||
|
--features nesting=1 \
|
||||||
|
--cores 2 \
|
||||||
|
--cpunits 100 \
|
||||||
|
--memory 2048 \
|
||||||
|
--swap 512 \
|
||||||
|
--rootfs "${root_storage}:8" \
|
||||||
|
--net0 "$network_config" \
|
||||||
|
--onboot 1 \
|
||||||
|
--startup order=10 \
|
||||||
|
--tags 'tapm;pulse'; then
|
||||||
|
TAPM_CLEAN_TEMP_DIR "$temp_dir"
|
||||||
|
TAPM_PULSE_FAIL "Container creation failed."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
container_created=1
|
||||||
|
if ! pct start "$ctid" ||
|
||||||
|
! timeout 90 bash -c \
|
||||||
|
"until pct exec '$ctid' -- test -d /run/systemd/system >/dev/null 2>&1; do sleep 2; done"; then
|
||||||
|
TAPM_PULSE_REMOVE_PARTIAL_LXC "$ctid"
|
||||||
|
TAPM_CLEAN_TEMP_DIR "$temp_dir"
|
||||||
|
TAPM_PULSE_FAIL "The new Pulse container did not become ready."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
timezone="$(timedatectl show --property=Timezone --value 2>/dev/null || true)"
|
||||||
|
[[ -n "$timezone" ]] || timezone='America/Chicago'
|
||||||
|
pct exec "$ctid" -- ln -snf "/usr/share/zoneinfo/${timezone}" /etc/localtime || true
|
||||||
|
|
||||||
|
echo -e "\n${idsCL[LightCyan]}Installing verified Pulse release inside LXC ${ctid}...${idsCL[Default]}"
|
||||||
|
if ! pct push "$ctid" "$installer" /tmp/install.sh ||
|
||||||
|
! pct push "$ctid" "$archive" "/tmp/${archive_name}" ||
|
||||||
|
! pct push "$ctid" "$signature" "/tmp/${archive_name}.sshsig" ||
|
||||||
|
! timeout 600 pct exec "$ctid" -- env "FRONTEND_PORT=${pulse_port}" \
|
||||||
|
bash /tmp/install.sh \
|
||||||
|
--in-container \
|
||||||
|
--version "$release" \
|
||||||
|
--archive "/tmp/${archive_name}" \
|
||||||
|
--enable-auto-updates ||
|
||||||
|
! pct exec "$ctid" -- systemctl is-active --quiet pulse; then
|
||||||
|
(( container_created == 1 )) && TAPM_PULSE_REMOVE_PARTIAL_LXC "$ctid"
|
||||||
|
TAPM_CLEAN_TEMP_DIR "$temp_dir"
|
||||||
|
TAPM_PULSE_FAIL "Pulse could not be installed or verified."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
container_ip="$(
|
||||||
|
pct exec "$ctid" -- hostname -I 2>/dev/null |
|
||||||
|
awk '{ print $1; exit }'
|
||||||
|
)"
|
||||||
|
if [[ "$add_ha" == 'yes' ]] &&
|
||||||
|
! ha-manager add "ct:${ctid}" --state started; then
|
||||||
|
echo -e "${idsCL[LightYellow]}Pulse is running, but it could not be added to HA.${idsCL[Default]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
pct exec "$ctid" -- rm -f \
|
||||||
|
/tmp/install.sh "/tmp/${archive_name}" "/tmp/${archive_name}.sshsig" || true
|
||||||
|
TAPM_CLEAN_TEMP_DIR "$temp_dir"
|
||||||
|
container_created=0
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo -e "${idsCL[Green]}Pulse ${release} was installed and its service is active.${idsCL[Default]}"
|
||||||
|
if [[ -n "$container_ip" ]]; then
|
||||||
|
echo -e " Open ${idsCL[LightCyan]}http://${container_ip}:${pulse_port}${idsCL[Default]} to finish setup."
|
||||||
|
else
|
||||||
|
echo " Open the Pulse LXC address on port ${pulse_port} to finish setup."
|
||||||
|
fi
|
||||||
|
}
|
||||||
+5
-22
@@ -7,6 +7,7 @@ source /opt/idssys/defaults/default.inc
|
|||||||
source /opt/idssys/ta-proxmenu/defaults.inc
|
source /opt/idssys/ta-proxmenu/defaults.inc
|
||||||
source /opt/idssys/ta-proxmenu/inc/git-update.inc
|
source /opt/idssys/ta-proxmenu/inc/git-update.inc
|
||||||
source /opt/idssys/ta-proxmenu/inc/deploy-iso-nfs-lxc.sh
|
source /opt/idssys/ta-proxmenu/inc/deploy-iso-nfs-lxc.sh
|
||||||
|
source /opt/idssys/ta-proxmenu/inc/deploy-pulse-lxc.sh
|
||||||
source /opt/idssys/ta-proxmenu/inc/virtio-helpers.inc
|
source /opt/idssys/ta-proxmenu/inc/virtio-helpers.inc
|
||||||
|
|
||||||
ACTION_REQUESTED=0
|
ACTION_REQUESTED=0
|
||||||
@@ -234,30 +235,12 @@ print(package.get("version", "") if package else "")
|
|||||||
}
|
}
|
||||||
|
|
||||||
INSTALL_PULSE() {
|
INSTALL_PULSE() {
|
||||||
local installer
|
if ! TAPM_DEPLOY_PULSE_LXC; then
|
||||||
local temp_dir
|
echo -e "${idsCL[LightRed]}Pulse deployment failed.${idsCL[Default]}"
|
||||||
|
|
||||||
echo
|
|
||||||
if ! TAPM_CREATE_TEMP_DIR pulse; then
|
|
||||||
FINISH_FAILED_ACTION
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
temp_dir="$TAPM_TEMP_DIR"
|
|
||||||
installer="${temp_dir}/install.sh"
|
|
||||||
|
|
||||||
if ! TAPM_DOWNLOAD_HTTPS \
|
|
||||||
'https://github.com/rcourtman/Pulse/releases/latest/download/install.sh' \
|
|
||||||
"$installer" 'Pulse installer' ||
|
|
||||||
! bash "$installer"; then
|
|
||||||
TAPM_CLEAN_TEMP_DIR "$temp_dir"
|
|
||||||
echo -e "${idsCL[LightRed]}Pulse installation failed.${idsCL[Default]}"
|
|
||||||
FINISH_FAILED_ACTION
|
FINISH_FAILED_ACTION
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
TAPM_CLEAN_TEMP_DIR "$temp_dir"
|
|
||||||
echo
|
|
||||||
echo -e "\n${idsCL[Green]}Pulse installer completed successfully.${idsCL[Default]}"
|
|
||||||
FINISH_ACTION
|
FINISH_ACTION
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1874,8 +1857,8 @@ MONITORING_MENU() {
|
|||||||
local cluster_resources
|
local cluster_resources
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
cluster_resources="$(pvesh get /cluster/resources 2>/dev/null)"
|
cluster_resources="$(pvesh get /cluster/resources --type vm --output-format json 2>/dev/null)"
|
||||||
grep -qi pulse <<< "$cluster_resources" &&
|
TAPM_PULSE_RESOURCE_INSTALLED "$cluster_resources" &&
|
||||||
labels=("Pulse monitoring (installed)") ||
|
labels=("Pulse monitoring (installed)") ||
|
||||||
labels=("Install Pulse monitoring")
|
labels=("Install Pulse monitoring")
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -u -o pipefail
|
||||||
|
|
||||||
|
TEST_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
source "${TEST_ROOT}/tests/testlib.sh"
|
||||||
|
source "${TEST_ROOT}/inc/deploy-pulse-lxc.sh"
|
||||||
|
|
||||||
|
assert_success "stable Pulse release" TAPM_PULSE_VALID_RELEASE v6.1.1
|
||||||
|
assert_success "prerelease Pulse release" TAPM_PULSE_VALID_RELEASE v6.2.0-rc.1
|
||||||
|
assert_failure "Pulse release requires v prefix" TAPM_PULSE_VALID_RELEASE 6.1.1
|
||||||
|
assert_failure "Pulse release rejects URL content" \
|
||||||
|
TAPM_PULSE_VALID_RELEASE 'v6.1.1/../../latest'
|
||||||
|
|
||||||
|
assert_equal amd64 "$(TAPM_PULSE_ARCH x86_64)" "x86 architecture mapping"
|
||||||
|
assert_equal arm64 "$(TAPM_PULSE_ARCH aarch64)" "ARM architecture mapping"
|
||||||
|
assert_failure "unsupported Pulse architecture" TAPM_PULSE_ARCH riscv64
|
||||||
|
|
||||||
|
assert_success "valid Pulse CTID" TAPM_PULSE_VALID_CTID 210
|
||||||
|
assert_failure "invalid Pulse CTID" TAPM_PULSE_VALID_CTID 99
|
||||||
|
assert_success "valid Pulse hostname" TAPM_PULSE_VALID_HOSTNAME pulse-monitor
|
||||||
|
assert_failure "invalid Pulse hostname" TAPM_PULSE_VALID_HOSTNAME 'pulse monitor'
|
||||||
|
assert_success "valid Pulse IPv4 CIDR" TAPM_PULSE_VALID_IPV4_CIDR 10.10.1.50/24
|
||||||
|
assert_failure "invalid Pulse IPv4 CIDR" TAPM_PULSE_VALID_IPV4_CIDR 10.10.1.500/24
|
||||||
|
|
||||||
|
resources='[
|
||||||
|
{"type":"lxc","name":"pulse-a","tags":"tapm;pulse"},
|
||||||
|
{"type":"qemu","name":"unrelated"}
|
||||||
|
]'
|
||||||
|
assert_success "tagged Pulse LXC detected" TAPM_PULSE_RESOURCE_INSTALLED "$resources"
|
||||||
|
assert_success "legacy Pulse hostname detected" \
|
||||||
|
TAPM_PULSE_RESOURCE_INSTALLED '[{"type":"lxc","name":"Pulse"}]'
|
||||||
|
assert_failure "unrelated resource not detected" \
|
||||||
|
TAPM_PULSE_RESOURCE_INSTALLED '[{"type":"qemu","name":"pulse"}]'
|
||||||
|
|
||||||
|
finish_tests
|
||||||
Reference in New Issue
Block a user