大量更新

This commit is contained in:
zeaslity
2026-05-19 14:28:44 +08:00
parent a8f6bda703
commit 9fc3372fa3
5299 changed files with 423176 additions and 426690 deletions

View File

@@ -0,0 +1,319 @@
#!/usr/bin/env bash
set -euo pipefail
###############################################################################
# Configuration
###############################################################################
# Space separated host IPs. Include the master IP if the master node also needs
# rmdc-watchdog-node installed.
INSTALL_HOSTS="192.168.3.31 192.168.3.32 192.168.3.33"
# Absolute binary path on the master node. Remote nodes will receive the binary
# at the same absolute path.
RMDC_WATCHDOG_NODE_BIN="/root/wdd/rmdc-watchdog-node"
# Replace WDD_BOOTSTRAP_PSK in the systemd service.
WDD_BOOTSTRAP_PSK="hO8dKlh9hSXZ25Bv9xsySxDe2rh7XikV"
# Main NIC name. The script reads each node's IPv4 address on this NIC and uses
# it as WDD_LISTEN_IP.
MAIN_NIC="eno3"
# Master node private IP. This replaces WDD_BOOTSTRAP_ALLOW_IPS.
MASTER_IP="192.168.3.31"
# Systemd service install path on every node.
SERVICE_PATH="/usr/lib/systemd/system/rmdc-watchdog-node.service"
# SSH settings for remote nodes.
SSH_PORT="22"
SSH_CONNECT_TIMEOUT_SEC="10"
SSH_CONTROL_PERSIST="10m"
###############################################################################
# Implementation
###############################################################################
SERVICE_NAME="$(basename "$SERVICE_PATH")"
REMOTE_TMP_DIR="/tmp/rmdc-watchdog-node-deploy"
REMOTE_SERVICE_TMP="${REMOTE_TMP_DIR}/${SERVICE_NAME}"
SSH_CONTROL_DIR=""
SSH_CONTROL_PATH=""
log() {
printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*"
}
die() {
printf 'error: %s\n' "$*" >&2
exit 1
}
shell_quote() {
printf "'"
printf '%s' "${1-}" | sed "s/'/'\\\\''/g"
printf "'"
}
require_command() {
command -v "$1" >/dev/null 2>&1 || die "required command not found: $1"
}
validate_config() {
[[ "$(id -u)" == "0" ]] || die "this script must run as root"
[[ "$#" == "0" ]] || die "this script does not accept command line arguments; edit the configuration section instead"
[[ -n "$INSTALL_HOSTS" ]] || die "INSTALL_HOSTS is empty"
[[ -f "$RMDC_WATCHDOG_NODE_BIN" ]] || die "binary not found: $RMDC_WATCHDOG_NODE_BIN"
[[ -n "$WDD_BOOTSTRAP_PSK" && "$WDD_BOOTSTRAP_PSK" != "change-me" ]] || die "WDD_BOOTSTRAP_PSK must be configured"
[[ -n "$MAIN_NIC" ]] || die "MAIN_NIC must be configured"
[[ -n "$MASTER_IP" ]] || die "MASTER_IP must be configured"
[[ "$SERVICE_PATH" = /* ]] || die "SERVICE_PATH must be an absolute path"
[[ "$RMDC_WATCHDOG_NODE_BIN" = /* ]] || die "RMDC_WATCHDOG_NODE_BIN must be an absolute path"
require_command awk
require_command basename
require_command dirname
require_command install
require_command ip
require_command mktemp
require_command sed
require_command systemctl
}
get_local_ipv4s() {
{
hostname -I 2>/dev/null | tr ' ' '\n' || true
ip -o -4 addr show 2>/dev/null | awk '{split($4, a, "/"); print a[1]}' || true
} | awk 'NF' | sort -u
}
is_local_host() {
local host="$1"
case "$host" in
localhost|127.0.0.1|::1)
return 0
;;
esac
get_local_ipv4s | awk -v host="$host" '$0 == host {found = 1} END {exit found ? 0 : 1}'
}
local_nic_ip() {
ip -o -4 addr show dev "$MAIN_NIC" scope global |
awk '{split($4, a, "/"); print a[1]; exit}'
}
remote_sh() {
local host="$1"
local command="$2"
ssh \
-p "$SSH_PORT" \
-o ConnectTimeout="$SSH_CONNECT_TIMEOUT_SEC" \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
-o LogLevel=ERROR \
-o ControlMaster=auto \
-o ControlPersist="$SSH_CONTROL_PERSIST" \
-o ControlPath="$SSH_CONTROL_PATH" \
"root@${host}" \
"bash -lc $(shell_quote "$command")"
}
remote_scp() {
local source_path="$1"
local host="$2"
local target_path="$3"
scp \
-P "$SSH_PORT" \
-o ConnectTimeout="$SSH_CONNECT_TIMEOUT_SEC" \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
-o LogLevel=ERROR \
-o ControlMaster=auto \
-o ControlPersist="$SSH_CONTROL_PERSIST" \
-o ControlPath="$SSH_CONTROL_PATH" \
"$source_path" \
"root@${host}:${target_path}"
}
cleanup_ssh_control() {
local host
if [[ -n "${SSH_CONTROL_DIR:-}" && -d "$SSH_CONTROL_DIR" ]]; then
for host in $INSTALL_HOSTS; do
if ! is_local_host "$host"; then
ssh \
-p "$SSH_PORT" \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
-o LogLevel=ERROR \
-o ControlPath="$SSH_CONTROL_PATH" \
-O exit \
"root@${host}" >/dev/null 2>&1 || true
fi
done
rm -rf "$SSH_CONTROL_DIR"
fi
}
remote_nic_ip() {
local host="$1"
remote_sh "$host" "ip -o -4 addr show dev $(shell_quote "$MAIN_NIC") scope global | awk '{split(\$4, a, \"/\"); print a[1]; exit}'"
}
render_service() {
local listen_ip="$1"
local output_path="$2"
local working_dir
working_dir="$(dirname "$RMDC_WATCHDOG_NODE_BIN")"
cat > "$output_path" <<EOF
[Unit]
Description=RMDC Watchdog Node Daemon
After=network.target
[Service]
Type=simple
User=root
Group=root
WorkingDirectory=${working_dir}
ExecStart=${RMDC_WATCHDOG_NODE_BIN}
Restart=on-failure
RestartSec=3
Environment="WDD_LISTEN_IP=${listen_ip}"
Environment="WDD_BOOTSTRAP_TIMEOUT_SEC=300"
Environment="WDD_BOOTSTRAP_ALLOW_IPS=${MASTER_IP}"
Environment="WDD_BOOTSTRAP_RE_ALLOW=false"
Environment="WDD_RUNTIME_MAX_CONCURRENT=4"
Environment="WDD_RUNTIME_QUEUE_CAPACITY=128"
Environment="WDD_RUNTIME_TASK_TIMEOUT_SEC=1800"
Environment="WDD_SECURITY_REQUIRE_ROOT=true"
Environment="WDD_SECURITY_TOTP_WINDOW=1"
Environment="WDD_BOOTSTRAP_PSK=${WDD_BOOTSTRAP_PSK}"
[Install]
WantedBy=multi-user.target
EOF
}
install_local() {
local host="$1"
local listen_ip
local rendered_service
listen_ip="$(local_nic_ip)"
[[ -n "$listen_ip" ]] || die "failed to get local IPv4 address from NIC ${MAIN_NIC}"
rendered_service="$(mktemp)"
render_service "$listen_ip" "$rendered_service"
log "${host}: installing local service with WDD_LISTEN_IP=${listen_ip}"
chmod 0755 "$RMDC_WATCHDOG_NODE_BIN"
chown root:root "$RMDC_WATCHDOG_NODE_BIN"
install -d -m 0755 "$(dirname "$SERVICE_PATH")"
install -m 0644 -o root -g root "$rendered_service" "$SERVICE_PATH"
rm -f "$rendered_service"
systemctl daemon-reload
systemctl enable "$SERVICE_NAME"
systemctl restart "$SERVICE_NAME"
systemctl is-active --quiet "$SERVICE_NAME"
}
install_remote() {
local host="$1"
local listen_ip
local rendered_service
local binary_dir
local service_dir
listen_ip="$(remote_nic_ip "$host")"
[[ -n "$listen_ip" ]] || die "${host}: failed to get IPv4 address from NIC ${MAIN_NIC}"
rendered_service="$(mktemp)"
render_service "$listen_ip" "$rendered_service"
binary_dir="$(dirname "$RMDC_WATCHDOG_NODE_BIN")"
service_dir="$(dirname "$SERVICE_PATH")"
log "${host}: preparing remote directories"
remote_sh "$host" "mkdir -p $(shell_quote "$binary_dir") $(shell_quote "$service_dir") $(shell_quote "$REMOTE_TMP_DIR")"
log "${host}: uploading binary to ${RMDC_WATCHDOG_NODE_BIN}"
remote_scp "$RMDC_WATCHDOG_NODE_BIN" "$host" "$RMDC_WATCHDOG_NODE_BIN"
log "${host}: uploading service with WDD_LISTEN_IP=${listen_ip}"
remote_scp "$rendered_service" "$host" "$REMOTE_SERVICE_TMP"
rm -f "$rendered_service"
log "${host}: reloading and restarting ${SERVICE_NAME}"
remote_sh "$host" "set -euo pipefail
chmod 0755 $(shell_quote "$RMDC_WATCHDOG_NODE_BIN")
chown root:root $(shell_quote "$RMDC_WATCHDOG_NODE_BIN")
install -m 0644 -o root -g root $(shell_quote "$REMOTE_SERVICE_TMP") $(shell_quote "$SERVICE_PATH")
systemctl daemon-reload
systemctl enable $(shell_quote "$SERVICE_NAME")
systemctl restart $(shell_quote "$SERVICE_NAME")
systemctl is-active --quiet $(shell_quote "$SERVICE_NAME")
rm -f $(shell_quote "$REMOTE_SERVICE_TMP")"
}
print_failure_diagnostics() {
local host="$1"
if is_local_host "$host"; then
systemctl --no-pager --full status "$SERVICE_NAME" || true
journalctl -u "$SERVICE_NAME" -n 80 --no-pager || true
else
remote_sh "$host" "systemctl --no-pager --full status $(shell_quote "$SERVICE_NAME") || true; journalctl -u $(shell_quote "$SERVICE_NAME") -n 80 --no-pager || true" || true
fi
}
main() {
validate_config "$@"
local has_remote="false"
local host
for host in $INSTALL_HOSTS; do
if ! is_local_host "$host"; then
has_remote="true"
break
fi
done
if [[ "$has_remote" == "true" ]]; then
require_command ssh
require_command scp
SSH_CONTROL_DIR="$(mktemp -d -t rmdc-watchdog-node-ssh.XXXXXX)"
SSH_CONTROL_PATH="${SSH_CONTROL_DIR}/%r@%h:%p"
trap cleanup_ssh_control EXIT
fi
for host in $INSTALL_HOSTS; do
log "${host}: deployment started"
if is_local_host "$host"; then
if ! install_local "$host"; then
print_failure_diagnostics "$host"
die "${host}: deployment failed"
fi
else
if ! install_remote "$host"; then
print_failure_diagnostics "$host"
die "${host}: deployment failed"
fi
fi
log "${host}: deployment finished"
done
log "all deployments finished"
}
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
main "$@"
fi