mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-02-18 00:17:39 +01:00
Improve temperature proxy control-plane flow
This commit is contained in:
@@ -90,15 +90,35 @@ update_allowed_nodes() {
|
||||
mkdir -p "$(dirname "$config_file")"
|
||||
touch "$config_file"
|
||||
|
||||
# Gather existing nodes (if any) to preserve manual edits
|
||||
local existing_nodes=()
|
||||
if command -v perl >/dev/null 2>&1; then
|
||||
mapfile -t existing_nodes < <(perl -0ne 'if (m/allowed_nodes:\n((?:[ \t]+-[^\n]*\n)+)/m) { @lines = split /\n/, $1; for (@lines) { s/^[ \t-]+//; s/\s+$//; next unless $_; print "$_\n"; } }' "$config_file" 2>/dev/null || true)
|
||||
fi
|
||||
|
||||
# Merge and de-duplicate nodes
|
||||
local merged_nodes=()
|
||||
declare -A seen_nodes=()
|
||||
for node in "${existing_nodes[@]}" "${nodes[@]}"; do
|
||||
node=$(echo "$node" | awk '{$1=$1;print}')
|
||||
if [[ -z "$node" ]]; then
|
||||
continue
|
||||
fi
|
||||
if [[ -z "${seen_nodes[$node]+set}" ]]; then
|
||||
merged_nodes+=("$node")
|
||||
seen_nodes["$node"]=1
|
||||
fi
|
||||
done
|
||||
|
||||
# Remove any existing allowed_nodes block (including descriptive comments) to prevent duplicates
|
||||
perl -0pi -e 's/\n(?:[ ]*#[^\n]*\n)*allowed_nodes:\n(?:(?:[ ]+-[^\n]*|[ ]*#[^\n]*)\n)*//g' "$config_file" 2>/dev/null || true
|
||||
perl -0pi -e 's/(?:^[ \t]*#[^\n]*\n)*allowed_nodes:\n(?:(?:[ \t]+-[^\n]*|[ \t]*#[^\n]*)\n)*//mg' "$config_file" 2>/dev/null || true
|
||||
|
||||
{
|
||||
echo ""
|
||||
echo "# ${comment_line}"
|
||||
echo "# These nodes are allowed to request temperature data when cluster IPC validation is unavailable"
|
||||
echo "allowed_nodes:"
|
||||
for node in "${nodes[@]}"; do
|
||||
for node in "${merged_nodes[@]}"; do
|
||||
echo " - $node"
|
||||
done
|
||||
} >> "$config_file"
|
||||
@@ -468,6 +488,9 @@ FALLBACK_BASE="${PULSE_SENSOR_PROXY_FALLBACK_URL:-}"
|
||||
SKIP_RESTART=false
|
||||
UNINSTALL=false
|
||||
PURGE=false
|
||||
CONTROL_PLANE_TOKEN=""
|
||||
CONTROL_PLANE_REFRESH=""
|
||||
SHORT_HOSTNAME=$(hostname -s 2>/dev/null || hostname | cut -d'.' -f1)
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
@@ -981,33 +1004,45 @@ register_with_pulse() {
|
||||
fi
|
||||
done
|
||||
|
||||
# Parse token from response
|
||||
local token
|
||||
token=$(echo "$response" | grep -o '"token":"[^"]*"' | cut -d'"' -f4)
|
||||
|
||||
if [[ -z "$token" ]]; then
|
||||
print_error "Registration succeeded but no token received"
|
||||
print_error "Response: $response"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Store token
|
||||
echo "$token" > /etc/pulse-sensor-proxy/.http-auth-token
|
||||
chmod 600 /etc/pulse-sensor-proxy/.http-auth-token
|
||||
chown pulse-sensor-proxy:pulse-sensor-proxy /etc/pulse-sensor-proxy/.http-auth-token
|
||||
|
||||
# Output to stderr so it doesn't interfere with command substitution
|
||||
print_success "Registered successfully - token received" >&2
|
||||
print_success "Registered successfully" >&2
|
||||
|
||||
# Parse instance name from response for logging
|
||||
local instance_name
|
||||
instance_name=$(echo "$response" | grep -o '"pve_instance":"[^"]*"' | cut -d'"' -f4)
|
||||
if [[ -n "$instance_name" ]]; then
|
||||
print_info "Linked to PVE instance: $instance_name" >&2
|
||||
# Return full response for caller parsing
|
||||
echo "$response"
|
||||
}
|
||||
|
||||
write_control_plane_token() {
|
||||
local token="$1"
|
||||
if [[ -z "$token" ]]; then
|
||||
return
|
||||
fi
|
||||
print_info "Writing control plane token..."
|
||||
echo "$token" > /etc/pulse-sensor-proxy/.pulse-control-token
|
||||
chmod 600 /etc/pulse-sensor-proxy/.pulse-control-token
|
||||
chown pulse-sensor-proxy:pulse-sensor-proxy /etc/pulse-sensor-proxy/.pulse-control-token
|
||||
}
|
||||
|
||||
ensure_control_plane_config() {
|
||||
local pulse_url="$1"
|
||||
local refresh="$2"
|
||||
if [[ -z "$pulse_url" ]]; then
|
||||
return
|
||||
fi
|
||||
if [[ -z "$refresh" ]]; then
|
||||
refresh=60
|
||||
fi
|
||||
if grep -q "^pulse_control_plane:" /etc/pulse-sensor-proxy/config.yaml 2>/dev/null; then
|
||||
return
|
||||
fi
|
||||
|
||||
# Return token for caller to use (stdout only)
|
||||
echo "$token"
|
||||
cat >> /etc/pulse-sensor-proxy/config.yaml << EOF
|
||||
|
||||
# Pulse control plane configuration (auto-generated)
|
||||
pulse_control_plane:
|
||||
url: "$pulse_url"
|
||||
token_file: "/etc/pulse-sensor-proxy/.pulse-control-token"
|
||||
refresh_interval: $refresh
|
||||
EOF
|
||||
}
|
||||
|
||||
# Create base config file if it doesn't exist
|
||||
@@ -1032,6 +1067,25 @@ EOF
|
||||
chmod 0644 /etc/pulse-sensor-proxy/config.yaml
|
||||
fi
|
||||
|
||||
# Register socket-mode proxy with Pulse if server provided
|
||||
if [[ "$HTTP_MODE" != true ]]; then
|
||||
if [[ -z "$PULSE_SERVER" ]]; then
|
||||
print_warn "PULSE_SERVER not provided; control plane sync disabled. Temperatures will only work on this host."
|
||||
else
|
||||
print_info "Registering socket proxy with Pulse server ${PULSE_SERVER}..."
|
||||
registration_response=$(register_with_pulse "$PULSE_SERVER" "$SHORT_HOSTNAME" "" "socket")
|
||||
if [[ $? -eq 0 && -n "$registration_response" ]]; then
|
||||
CONTROL_PLANE_TOKEN=$(echo "$registration_response" | grep -o '"control_token":"[^"]*"' | head -1 | cut -d'"' -f4)
|
||||
CONTROL_PLANE_REFRESH=$(echo "$registration_response" | grep -o '"refresh_interval":[0-9]*' | head -1 | awk -F: '{print $2}')
|
||||
if [[ -z "$CONTROL_PLANE_REFRESH" ]]; then
|
||||
CONTROL_PLANE_REFRESH="60"
|
||||
fi
|
||||
else
|
||||
print_warn "Failed to register socket proxy with Pulse; continuing without control plane sync"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# HTTP Mode Configuration
|
||||
if [[ "$HTTP_MODE" == true ]]; then
|
||||
echo ""
|
||||
@@ -1114,16 +1168,31 @@ if [[ "$HTTP_MODE" == true ]]; then
|
||||
PROXY_URL="https://${PRIMARY_IP}${HTTP_ADDR}"
|
||||
print_info "Proxy will be accessible at: $PROXY_URL"
|
||||
|
||||
# Register with Pulse and get auth token
|
||||
# Use short hostname for registration matching (PVE cluster endpoints use short names)
|
||||
SHORT_HOSTNAME=$(hostname -s 2>/dev/null || hostname | cut -d'.' -f1)
|
||||
HTTP_AUTH_TOKEN=$(register_with_pulse "$PULSE_SERVER" "$SHORT_HOSTNAME" "$PROXY_URL")
|
||||
if [[ $? -ne 0 || -z "$HTTP_AUTH_TOKEN" ]]; then
|
||||
# Register with Pulse and get auth/control tokens
|
||||
registration_response=$(register_with_pulse "$PULSE_SERVER" "$SHORT_HOSTNAME" "$PROXY_URL" "http")
|
||||
if [[ $? -ne 0 || -z "$registration_response" ]]; then
|
||||
print_error "Failed to register with Pulse - aborting installation"
|
||||
print_error "Fix the issue and re-run the installer"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
HTTP_AUTH_TOKEN=$(echo "$registration_response" | grep -o '"token":"[^"]*"' | head -1 | cut -d'"' -f4)
|
||||
CONTROL_PLANE_TOKEN=$(echo "$registration_response" | grep -o '"control_token":"[^"]*"' | head -1 | cut -d'"' -f4)
|
||||
CONTROL_PLANE_REFRESH=$(echo "$registration_response" | grep -o '"refresh_interval":[0-9]*' | head -1 | awk -F: '{print $2}')
|
||||
if [[ -z "$CONTROL_PLANE_REFRESH" ]]; then
|
||||
CONTROL_PLANE_REFRESH="60"
|
||||
fi
|
||||
|
||||
if [[ -z "$HTTP_AUTH_TOKEN" ]]; then
|
||||
print_error "Registration succeeded but Pulse did not return an auth token"
|
||||
print_error "Response: $registration_response"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "$HTTP_AUTH_TOKEN" > /etc/pulse-sensor-proxy/.http-auth-token
|
||||
chmod 600 /etc/pulse-sensor-proxy/.http-auth-token
|
||||
chown pulse-sensor-proxy:pulse-sensor-proxy /etc/pulse-sensor-proxy/.http-auth-token
|
||||
|
||||
# Backup config before modifying
|
||||
if [[ -f /etc/pulse-sensor-proxy/config.yaml ]]; then
|
||||
BACKUP_CONFIG="/etc/pulse-sensor-proxy/config.yaml.backup.$(date +%s)"
|
||||
@@ -1176,6 +1245,11 @@ EOF
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if [[ -n "$CONTROL_PLANE_TOKEN" && -n "$PULSE_SERVER" ]]; then
|
||||
write_control_plane_token "$CONTROL_PLANE_TOKEN"
|
||||
ensure_control_plane_config "$PULSE_SERVER" "$CONTROL_PLANE_REFRESH"
|
||||
fi
|
||||
|
||||
# Stop existing service if running (for upgrades)
|
||||
if systemctl is-active --quiet pulse-sensor-proxy 2>/dev/null; then
|
||||
print_info "Stopping existing service for upgrade..."
|
||||
|
||||
141
scripts/migrate-sensor-proxy-control-plane.sh
Normal file
141
scripts/migrate-sensor-proxy-control-plane.sh
Normal file
@@ -0,0 +1,141 @@
|
||||
#!/bin/bash
|
||||
|
||||
# migrate-sensor-proxy-control-plane.sh
|
||||
# Adds control-plane sync to existing pulse-sensor-proxy installations.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
PULSE_SERVER=""
|
||||
SKIP_RESTART=false
|
||||
|
||||
print_usage() {
|
||||
cat <<'EOF'
|
||||
Usage: migrate-sensor-proxy-control-plane.sh --pulse-server https://pulse.example.com:7655 [--skip-restart]
|
||||
|
||||
Adds the Pulse control-plane token/config to an existing proxy installation.
|
||||
EOF
|
||||
}
|
||||
|
||||
log() { echo "[INFO] $*"; }
|
||||
warn() { echo "[WARN] $*" >&2; }
|
||||
err() { echo "[ERROR] $*" >&2; }
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--pulse-server)
|
||||
PULSE_SERVER="$2"
|
||||
shift 2
|
||||
;;
|
||||
--skip-restart)
|
||||
SKIP_RESTART=true
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
print_usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
err "Unknown option: $1"
|
||||
print_usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
err "This script must be run as root"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "$PULSE_SERVER" ]]; then
|
||||
err "--pulse-server is required"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CONFIG_FILE="/etc/pulse-sensor-proxy/config.yaml"
|
||||
TOKEN_FILE="/etc/pulse-sensor-proxy/.pulse-control-token"
|
||||
|
||||
if [[ ! -f "$CONFIG_FILE" ]]; then
|
||||
err "Config file not found at $CONFIG_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SHORT_HOSTNAME=$(hostname -s 2>/dev/null || hostname | cut -d'.' -f1)
|
||||
register_proxy() {
|
||||
local mode="$1"
|
||||
local payload="{\"hostname\":\"${SHORT_HOSTNAME}\",\"proxy_url\":\"\",\"mode\":\"${mode}\"}"
|
||||
curl -fsSL -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$payload" \
|
||||
"${PULSE_SERVER%/}/api/temperature-proxy/register"
|
||||
}
|
||||
|
||||
log "Registering proxy with Pulse..."
|
||||
REGISTRATION_RESPONSE=$(register_proxy "socket") || {
|
||||
err "Registration failed"
|
||||
exit 1
|
||||
}
|
||||
|
||||
CONTROL_TOKEN=$(echo "$REGISTRATION_RESPONSE" | grep -o '"control_token":"[^"]*"' | head -1 | cut -d'"' -f4)
|
||||
REFRESH_INTERVAL=$(echo "$REGISTRATION_RESPONSE" | grep -o '"refresh_interval":[0-9]*' | head -1 | awk -F: '{print $2}')
|
||||
if [[ -z "$CONTROL_TOKEN" ]]; then
|
||||
err "Pulse did not return a control token. Response: $REGISTRATION_RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
if [[ -z "$REFRESH_INTERVAL" ]]; then
|
||||
REFRESH_INTERVAL=60
|
||||
fi
|
||||
|
||||
log "Writing control-plane token..."
|
||||
mkdir -p "$(dirname "$TOKEN_FILE")"
|
||||
echo "$CONTROL_TOKEN" > "$TOKEN_FILE"
|
||||
chmod 600 "$TOKEN_FILE"
|
||||
chown pulse-sensor-proxy:pulse-sensor-proxy "$TOKEN_FILE"
|
||||
|
||||
remove_control_block() {
|
||||
python3 - "$CONFIG_FILE" <<'PY'
|
||||
from pathlib import Path
|
||||
import sys
|
||||
path = Path(sys.argv[1])
|
||||
if not path.exists():
|
||||
sys.exit(0)
|
||||
lines = path.read_text().splitlines(keepends=True)
|
||||
result = []
|
||||
i = 0
|
||||
while i < len(lines):
|
||||
line = lines[i]
|
||||
if line.startswith("# Pulse control plane configuration"):
|
||||
i += 1
|
||||
while i < len(lines) and (lines[i].startswith(" ") or lines[i].startswith("\t") or lines[i].strip() == ""):
|
||||
i += 1
|
||||
continue
|
||||
if line.startswith("pulse_control_plane:"):
|
||||
i += 1
|
||||
while i < len(lines) and (lines[i].startswith(" ") or lines[i].startswith("\t") or lines[i].strip() == ""):
|
||||
i += 1
|
||||
continue
|
||||
result.append(line)
|
||||
i += 1
|
||||
path.write_text("".join(result))
|
||||
PY
|
||||
}
|
||||
|
||||
log "Updating config..."
|
||||
remove_control_block
|
||||
cat >> "$CONFIG_FILE" <<EOF
|
||||
|
||||
# Pulse control plane configuration (added by migrate-sensor-proxy-control-plane.sh)
|
||||
pulse_control_plane:
|
||||
url: "$PULSE_SERVER"
|
||||
token_file: "$TOKEN_FILE"
|
||||
refresh_interval: $REFRESH_INTERVAL
|
||||
EOF
|
||||
|
||||
if [[ "$SKIP_RESTART" == false ]]; then
|
||||
log "Restarting pulse-sensor-proxy..."
|
||||
systemctl restart pulse-sensor-proxy
|
||||
else
|
||||
warn "Skipping service restart; control-plane sync will start on next restart"
|
||||
fi
|
||||
|
||||
log "Migration complete."
|
||||
Reference in New Issue
Block a user