feat(monitor): implement monitor role #29

Merged
ochenstarik-ui merged 1 commit from feat/monitor-role into main 2026-08-10 08:04:29 +00:00
2 changed files with 159 additions and 0 deletions

View file

@ -1225,6 +1225,105 @@ uninstall_agent() {
log "Agent removed${purge:+ ($purge)}."
}
install_monitor() {
local public_key="$1"
require_root
validate_platform
local metrics_script="/usr/local/libexec/ochenstarik-smm-metrics"
local monitor_user="ochenstarik-monitor"
local monitor_home="/var/lib/ochenstarik-monitor"
if ! id -u "$monitor_user" >/dev/null 2>&1; then
useradd -r -s /usr/sbin/nologin -d "$monitor_home" -M "$monitor_user"
fi
install -d -m 0755 -o "$monitor_user" -g "$monitor_user" "$monitor_home"
install -d -m 0755 "/usr/local/libexec"
cat >"$metrics_script" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
# ochenstarik-smm-metrics
MESH_STATUS=""
if [[ -x /usr/bin/wg && -f /etc/wireguard/smm0.conf ]]; then
MESH_STATUS=$(wg show smm0 2>/dev/null || true)
fi
echo "PROTOCOL=1"
echo "HOSTNAME=$(hostname)"
UPTIME=$(awk '{print int($1)}' /proc/uptime 2>/dev/null || echo "0")
echo "UPTIME_SECONDS=${UPTIME}"
LOAD1=$(awk '{print $1}' /proc/loadavg 2>/dev/null || echo "0.00")
echo "LOAD1=${LOAD1}"
CPU_COUNT=$(nproc 2>/dev/null || echo "1")
echo "CPU_COUNT=${CPU_COUNT}"
MEM_TOTAL=$(awk '/^MemTotal:/ {print $2}' /proc/meminfo 2>/dev/null || echo "0")
echo "MEM_TOTAL_KB=${MEM_TOTAL}"
MEM_AVAIL=$(awk '/^MemAvailable:/ {print $2}' /proc/meminfo 2>/dev/null || echo "0")
if [ "$MEM_AVAIL" = "0" ] || [ -z "$MEM_AVAIL" ]; then
MEM_FREE=$(awk '/^MemFree:/ {print $2}' /proc/meminfo 2>/dev/null || echo "0")
MEM_CACHED=$(awk '/^Cached:/ {print $2}' /proc/meminfo 2>/dev/null || echo "0")
MEM_AVAIL=$((MEM_FREE + MEM_CACHED))
fi
echo "MEM_AVAILABLE_KB=${MEM_AVAIL}"
SWAP_TOTAL=$(awk '/^SwapTotal:/ {print $2}' /proc/meminfo 2>/dev/null || echo "0")
echo "SWAP_TOTAL_KB=${SWAP_TOTAL}"
SWAP_FREE=$(awk '/^SwapFree:/ {print $2}' /proc/meminfo 2>/dev/null || echo "0")
echo "SWAP_FREE_KB=${SWAP_FREE}"
DF_OUT=$(df -k / 2>/dev/null | awk 'NR==2 {print $2, $4}' || echo "0 0")
DISK_TOTAL=$(echo "$DF_OUT" | awk '{print $1}')
DISK_AVAIL=$(echo "$DF_OUT" | awk '{print $2}')
echo "DISK_TOTAL_KB=${DISK_TOTAL}"
echo "DISK_AVAILABLE_KB=${DISK_AVAIL}"
DF_INODES=$(df -i / 2>/dev/null | awk 'NR==2 {print $2, $4}' || echo "0 0")
INODES_TOTAL=$(echo "$DF_INODES" | awk '{print $1}')
INODES_FREE=$(echo "$DF_INODES" | awk '{print $2}')
echo "DISK_INODES_TOTAL=${INODES_TOTAL}"
echo "DISK_INODES_FREE=${INODES_FREE}"
NET_RX=$(awk 'NR>2 {rx+=$1} END {print rx}' /proc/net/dev 2>/dev/null || echo "0")
NET_TX=$(awk 'NR>2 {tx+=$9} END {print tx}' /proc/net/dev 2>/dev/null || echo "0")
echo "NETWORK_RX_BYTES=${NET_RX}"
echo "NETWORK_TX_BYTES=${NET_TX}"
KERNEL=$(uname -r 2>/dev/null || echo "unknown")
echo "KERNEL=${KERNEL}"
if [ -n "$MESH_STATUS" ]; then
echo "--- MESH STATUS ---"
echo "$MESH_STATUS"
fi
EOF
chown root:root "$metrics_script"
chmod 0755 "$metrics_script"
install -d -m 0700 -o "$monitor_user" -g "$monitor_user" "$monitor_home/.ssh"
local auth_keys="$monitor_home/.ssh/authorized_keys"
# We idempotently add the key
local key_entry="command=\"$metrics_script\",restrict,no-pty,no-agent-forwarding,no-port-forwarding,no-X11-forwarding $public_key"
if [[ -f "$auth_keys" ]] && grep -qF "$public_key" "$auth_keys"; then
log "Monitor key already installed."
else
echo "$key_entry" >> "$auth_keys"
chown "$monitor_user:$monitor_user" "$auth_keys"
chmod 0600 "$auth_keys"
log "Monitor key installed."
fi
}
uninstall_monitor() {
require_root
local monitor_user="ochenstarik-monitor"
local monitor_home="/var/lib/ochenstarik-monitor"
local metrics_script="/usr/local/libexec/ochenstarik-smm-metrics"
if id -u "$monitor_user" >/dev/null 2>&1; then
userdel -f "$monitor_user" || true
fi
rm -rf -- "$monitor_home"
rm -f -- "$metrics_script"
log "Monitor removed."
}
uninstall_control() {
[[ "${1:-}" == "--confirm-destroy-control" ]] || fail "Control removal requires --confirm-destroy-control"
require_root
@ -1260,6 +1359,8 @@ main() {
install-control) [[ $# -ge 2 && $# -le 3 ]] || fail "install-control requires ARCHIVE PUBLIC_HOST [HTTPS_PORT]"; install_control "$@" ;;
install-agent) [[ $# -eq 4 ]] || fail "install-agent requires ARCHIVE NODE_ID CONTROL_URL CA_CERT"; install_agent "$@" ;;
install-node) [[ $# -eq 1 ]] || fail "install-node requires ARCHIVE"; install_node_from_code "$1" ;;
install-monitor) [[ $# -eq 1 ]] || fail "install-monitor requires PUBLIC_KEY"; install_monitor "$1" ;;
uninstall-monitor) [[ $# -eq 0 ]] || fail "uninstall-monitor takes no arguments"; uninstall_monitor ;;
mesh-init) [[ $# -ge 1 && $# -le 2 ]] || fail "mesh-init requires PUBLIC_ENDPOINT [WG_PORT]"; mesh_init "$@" ;;
peer-add) [[ $# -eq 1 ]] || fail "peer-add requires SMMPEER1_CODE"; add_mesh_peer "$1" ;;
mesh-status) [[ $# -eq 0 ]] || fail "mesh-status takes no arguments"; show_mesh_status ;;

View file

@ -0,0 +1,58 @@
#!/usr/bin/env bash
set -euo pipefail
# test_monitor_snapshot.sh
# Acceptance test for Monitor role installation and metrics format
cd "$(dirname "$0")/../.."
BOOTSTRAP="./deploy/ochenstarik-server-monitor-manager.sh"
DUMMY_KEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDummyTestKeyForAcceptanceTest dummy@test"
echo "=== Testing install-monitor ==="
sudo "$BOOTSTRAP" install-monitor "$DUMMY_KEY"
# 1. Verify user exists and has nologin
getent passwd ochenstarik-monitor | grep -q "/usr/sbin/nologin" || {
echo "ERROR: User ochenstarik-monitor does not exist or does not have nologin"
exit 1
}
# 2. Verify authorized_keys
AUTH_KEYS="/var/lib/ochenstarik-monitor/.ssh/authorized_keys"
if ! sudo test -f "$AUTH_KEYS"; then
echo "ERROR: authorized_keys not found"
exit 1
fi
sudo grep -q "command=\"/usr/local/libexec/ochenstarik-smm-metrics\",restrict" "$AUTH_KEYS" || {
echo "ERROR: Forced command not found in authorized_keys"
exit 1
}
# 3. Verify metrics script output format
echo "=== Testing metrics output ==="
METRICS_OUT=$(sudo /usr/local/libexec/ochenstarik-smm-metrics)
echo "$METRICS_OUT"
for FIELD in PROTOCOL HOSTNAME UPTIME_SECONDS LOAD1 CPU_COUNT MEM_TOTAL_KB MEM_AVAILABLE_KB SWAP_TOTAL_KB SWAP_FREE_KB DISK_TOTAL_KB DISK_AVAILABLE_KB DISK_INODES_TOTAL DISK_INODES_FREE NETWORK_RX_BYTES NETWORK_TX_BYTES KERNEL; do
if ! echo "$METRICS_OUT" | grep -q "^${FIELD}="; then
echo "ERROR: Missing field ${FIELD} in metrics output"
exit 1
fi
done
# 4. Verify uninstall
echo "=== Testing uninstall-monitor ==="
sudo "$BOOTSTRAP" uninstall-monitor
if getent passwd ochenstarik-monitor >/dev/null 2>&1; then
echo "ERROR: User ochenstarik-monitor was not removed"
exit 1
fi
if sudo test -f "$AUTH_KEYS" || sudo test -f "/usr/local/libexec/ochenstarik-smm-metrics"; then
echo "ERROR: Leftover files found after uninstall"
exit 1
fi
echo "=== PASS: Monitor role acceptance test ==="