#!/usr/bin/bash # # powerman/setup.sh — idempotent powerman setup for Cyclades PM10i PDU # # Creates a stable udev symlink for the USB-DB9 adapter, writes powerman.conf # with 10 outlet nodes, and enables + starts powermand. # # This script is designed to be run ON the target host (pfv-tsys1) as root. # It is idempotent: safe to run multiple times. # # Usage: # PROX_HOST=pfv-tsys1 bash tests/remote.sh prox-file powerman/setup.sh # # Override defaults via environment variables: # PDU_SERIAL — USB adapter serial (default: BJAAb144J07) # PDU_VENDOR — USB vendor ID (default: 067b) # PDU_DEV_NAME — udev symlink name (default: cyclades-pm10) # PDU_BAUD — serial baud rate (default: 9600,8n1) # PDU_TYPE — powerman spec type (default: pm10) # PDU_OUTLETS — number of outlets (default: 10) # PDU_LISTEN — powermand listen (default: 0.0.0.0:10101) # set -euo pipefail # --- Config (overridable via env) --- PDU_SERIAL="${PDU_SERIAL:-BJAAb144J07}" PDU_VENDOR="${PDU_VENDOR:-067b}" PDU_DEV_NAME="${PDU_DEV_NAME:-cyclades-pm10}" PDU_BAUD="${PDU_BAUD:-9600,8n1}" PDU_TYPE="${PDU_TYPE:-pm10}" PDU_OUTLETS="${PDU_OUTLETS:-10}" PDU_LISTEN="${PDU_LISTEN:-}" # Auto-detect Tailscale IP if empty UDEV_RULE="/etc/udev/rules.d/99-cyclades-pdu.rules" POWERMAN_CONF="/etc/powerman/powerman.conf" DEV_FILE="/etc/powerman/cyclades-pm10.dev" # --- Auto-detect Tailscale IP for listen address --- if [ -z "$PDU_LISTEN" ]; then TS_IP=$(tailscale ip -4 2>/dev/null || true) if [ -n "$TS_IP" ]; then PDU_LISTEN="${TS_IP}:10101" echo " Auto-detected Tailscale IP: $TS_IP" else PDU_LISTEN="127.0.0.1:10101" echo " WARNING: No Tailscale IP detected. Defaulting to localhost." fi fi echo "============================================" echo " Powerman PDU Setup" echo " Host: $(hostname)" echo " PDU: Cyclades PM${PDU_OUTLETS}i" echo " Adapter serial: $PDU_SERIAL" echo " Device symlink: /dev/$PDU_DEV_NAME" echo " Listen: $PDU_LISTEN (Tailscale only)" echo "============================================" # --- 1. Ensure powerman is installed --- echo "" echo "--- [1/5] Checking powerman installation ---" if ! dpkg -l powerman 2>/dev/null | grep -q '^ii'; then echo " Installing powerman from Debian repo..." apt-get update -qq && apt-get install -y -qq powerman else echo " Powerman already installed: $(dpkg -l powerman | awk '/^ii/{print $3}')" fi # --- 2. Create udev rule for stable device name --- echo "" echo "--- [2/5] Creating udev rule for USB-DB9 adapter ---" cat > "$UDEV_RULE" </dev/null || true udevadm trigger --subsystem-match=tty 2>/dev/null || true sleep 1 if [ -e "/dev/${PDU_DEV_NAME}" ]; then echo " Device symlink active: /dev/${PDU_DEV_NAME} -> $(readlink -f "/dev/${PDU_DEV_NAME}")" else echo " WARNING: /dev/${PDU_DEV_NAME} not found yet. Adapter may be unplugged." echo " Falling back to /dev/ttyUSB* discovery..." # Try to find any ttyUSB device as fallback for tty in /dev/ttyUSB*; do if [ -e "$tty" ]; then echo " Found: $tty (using as fallback)" PDU_DEV_NAME="$(basename "$tty")" break fi done fi # --- 2b. Ensure powermand user can access the serial device --- echo "" echo "--- [2b/5] Fixing serial device permissions ---" if id powerman >/dev/null 2>&1; then if id powerman | grep -qv dialout; then usermod -aG dialout powerman echo " Added 'powerman' user to 'dialout' group" else echo " 'powerman' already in 'dialout' group" fi else echo " (no powerman user — service may run as root)" fi # --- 3. Write powerman.conf --- echo "" echo "--- [3/5] Writing powerman.conf ---" # Build node definitions NODES="" for i in $(seq 1 "$PDU_OUTLETS"); do NODES+="node \"outlet-${i}\" \"${PDU_DEV_NAME}\" \"${i}\"\n" done cat > "$POWERMAN_CONF" </dev/null || true systemctl restart powerman 2>/dev/null || true sleep 2 if systemctl is-active --quiet powerman; then echo " powermand is running." else echo " WARNING: powermand failed to start. Check journalctl -u powerman" journalctl -u powerman --no-pager -n 20 2>/dev/null || true fi # --- 5. Verify --- echo "" echo "--- [5/5] Verification ---" echo "" echo " powerman -l (list all outlets):" powerman -l 2>&1 || echo "(powerman -l failed)" echo "" echo " powerman -q (query status):" powerman -q 2>&1 || echo "(powerman -q failed — PDU may need a moment)" echo "" echo "============================================" echo " Setup complete." echo "" echo " Outlet names are generic (outlet-1 ... outlet-${PDU_OUTLETS})." echo " Rename them in ${POWERMAN_CONF} when onsite to match attached devices." echo "" echo " Test: powerman -0 outlet-10 (off)" echo " powerman -1 outlet-10 (on)" echo " powerman -c outlet-10 (cycle)" echo " powerman -q (status)" echo "============================================"