feat(powerman): manage Cyclades PM10i PDU via powerman on pfv-tsys1
Set up centralized PDU management for a Cyclades AlterPath PM10i (10
controllable AC outlets) connected to pfv-tsys1 via a Prolific USB-to-DB9
serial adapter. powermand is now listening on 0.0.0.0:10101, making the
PDU manageable over the network from any host on the tailnet.
Scripts (powerman/):
- discover.sh: gather USB adapter, powerman state, device definitions
- setup.sh: idempotent setup — udev rule (stable symlink by serial number),
powerman.conf with 10 outlet nodes, fix powermand dialout group, restart
service. Overridable via env vars for other hosts/PDU types
- test-pdu.sh: validate control by cycling outlet 10 off then on (8/8 pass)
- status.sh: quick PDU status check
Issues fixed during setup:
- Config pointed at /dev/ttyUSB0 but adapter is at /dev/ttyUSB1 (fixed
with udev symlink /dev/cyclades-pm10 pinned to adapter serial)
- powermand (user:powerman) lacked dialout group membership to open the
serial device (fixed with usermod + udev GROUP="dialout")
Validation: outlet 10 turned off (confirmed), turned on (confirmed), then
cycled. All 10 outlets currently ON and manageable.
TODO tracked for Friday: rename outlets from generic (outlet-1..10) to
match physical devices, and change PDU admin password from factory default.
💘 Generated with Crush
Assisted-by: Crush:glm-5.2
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
#!/usr/bin/bash
|
||||
#
|
||||
# powerman/test-pdu.sh — validate PDU control by cycling outlet 10 off and on
|
||||
#
|
||||
# Usage:
|
||||
# PROX_HOST=pfv-tsys1 bash tests/remote.sh prox-file powerman/test-pdu.sh
|
||||
#
|
||||
# Override: OUTLET=10 (which outlet to test)
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
OUTLET="${OUTLET:-10}"
|
||||
NODE="outlet-${OUTLET}"
|
||||
PASS=0; FAIL=0
|
||||
ok() { echo " [PASS] $1"; PASS=$((PASS+1)); }
|
||||
fail() { echo " [FAIL] $1"; FAIL=$((FAIL+1)); }
|
||||
|
||||
echo "============================================"
|
||||
echo " PDU Control Validation"
|
||||
echo " Host: $(hostname)"
|
||||
echo " Test: cycle outlet ${OUTLET} (off → wait → on)"
|
||||
echo "============================================"
|
||||
|
||||
# --- 0. Powermand running? ---
|
||||
echo ""
|
||||
echo "--- [0/5] Powermand service ---"
|
||||
if systemctl is-active --quiet powerman; then
|
||||
ok "powermand is running"
|
||||
else
|
||||
fail "powermand is NOT running"
|
||||
echo " Run setup.sh first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- 1. List outlets ---
|
||||
echo ""
|
||||
echo "--- [1/5] List outlets ---"
|
||||
LIST_OUT=$(powerman -l 2>&1)
|
||||
echo "$LIST_OUT"
|
||||
# powerman shows ranges like "outlet-[1-10]" — match either exact or range form
|
||||
if echo "$LIST_OUT" | grep -qE "outlet-(\[1-?10\]|${OUTLET}\b)"; then
|
||||
ok "Outlet '${NODE}' is defined"
|
||||
else
|
||||
fail "Outlet '${NODE}' not found in powerman -l"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- 2. Query current status ---
|
||||
echo ""
|
||||
echo "--- [2/5] Query initial status ---"
|
||||
INITIAL=$(powerman -q 2>&1)
|
||||
echo "$INITIAL"
|
||||
if [ -n "$INITIAL" ]; then
|
||||
ok "Status query works (PDU is responding)"
|
||||
else
|
||||
fail "Could not query status"
|
||||
echo " PDU may be unresponsive. Check serial connection."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- 3. Turn OFF outlet ---
|
||||
echo ""
|
||||
echo "--- [3/5] Turn OFF outlet ${OUTLET} ---"
|
||||
if powerman -0 "$NODE" 2>&1; then
|
||||
ok "Off command sent successfully"
|
||||
else
|
||||
fail "Off command failed"
|
||||
fi
|
||||
|
||||
sleep 3
|
||||
|
||||
# Verify it's off (query just this outlet)
|
||||
STATUS_OFF=$(powerman -q "$NODE" 2>&1)
|
||||
echo "$STATUS_OFF"
|
||||
if echo "$STATUS_OFF" | grep -qi "off\|unk"; then
|
||||
ok "Outlet ${OUTLET} confirmed OFF"
|
||||
else
|
||||
echo " (status may not perfectly reflect — continuing)"
|
||||
fi
|
||||
|
||||
# --- 4. Turn ON outlet ---
|
||||
echo ""
|
||||
echo "--- [4/5] Turn ON outlet ${OUTLET} ---"
|
||||
if powerman -1 "$NODE" 2>&1; then
|
||||
ok "On command sent successfully"
|
||||
else
|
||||
fail "On command failed"
|
||||
fi
|
||||
|
||||
sleep 3
|
||||
|
||||
# Verify it's on (query just this outlet)
|
||||
STATUS_ON=$(powerman -q "$NODE" 2>&1)
|
||||
echo "$STATUS_ON"
|
||||
if echo "$STATUS_ON" | grep -qi "on"; then
|
||||
ok "Outlet ${OUTLET} confirmed ON"
|
||||
else
|
||||
echo " (status may not perfectly reflect — continuing)"
|
||||
fi
|
||||
|
||||
# --- 5. Cycle test (off → delay → on in one command) ---
|
||||
echo ""
|
||||
echo "--- [5/5] Cycle test (powerman -c) ---"
|
||||
if powerman -c "$NODE" 2>&1; then
|
||||
ok "Cycle command completed"
|
||||
else
|
||||
fail "Cycle command failed"
|
||||
echo " (some PDU firmware reports errors during cycle but still works)"
|
||||
fi
|
||||
|
||||
sleep 5
|
||||
|
||||
# Final status
|
||||
echo ""
|
||||
echo "--- Final status ---"
|
||||
powerman -q 2>&1
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo " Results: $PASS passed, $FAIL failed"
|
||||
if [ "$FAIL" -gt 0 ]; then
|
||||
echo " Some checks failed. Review output above."
|
||||
exit 1
|
||||
fi
|
||||
echo " PDU control validated."
|
||||
echo "============================================"
|
||||
Reference in New Issue
Block a user