nut-notify: Initial import

This is the `nut-notify` script as it existed on the original UPS server
(*serial0.pyrocufflink.blue*).
main
Dustin 2024-01-19 17:29:51 -06:00
parent 9798d402ba
commit 77b701ffc0
1 changed files with 222 additions and 0 deletions

222
nut-notify.sh Executable file
View File

@ -0,0 +1,222 @@
#!/bin/sh
# vim: set ts=4 sts=4 sw=4 et :
CRITICAL_VMS='
cloud0
dc0
dc2
file0
k8s-amd64-n0
k8s-ctrl0
logs0
matrix0
smtp1
web0
'
VM_HOSTS='
vmhost0.pyrocufflink.blue
vmhost1.pyrocufflink.blue
'
MESSAGE="$1"
consolidate_vms() {
count=0
for h in ${VM_HOSTS}; do
[ -n "${h}" ] || continue
uri=qemu+ssh://root@${h}/system
c=$(($(virsh -c ${uri} list --name | wc -l) - 1))
printf 'VM host %s has %d running VMs\n' "${h}" "${c}" \
| log -p daemon.debug
if [ ${c} -gt ${count} ]; then
target=${h}
count=${c}
fi
done
[ -n "${target}" ] || return 1
printf 'Consolidating VMs onto host %s\n' "${target}" \
| log -p daemon.warning
for h in ${VM_HOSTS}; do
[ -n "${h}" ] || continue
[ "${h}" != "${target}" ] || continue
migrate_vms ${h} ${target}
remote_shutdown ${h}
done
}
handle_online() {
notify_ntfy high white_check_mark,electric_plug
}
handle_onbatt() {
notify_ntfy high warning,battery
}
handle_lowbatt() {
notify_ntfy max warning,battery
if is_only_ups; then
shut_down_all
else
low_power_mode
fi
}
handle_commok() {
notify_ntfy high white_check_mark
}
handle_commbad() {
notify_ntfy high warning
}
handle_replbatt() {
notify_ntfy default warning,battery
}
handle_nocomm() {
notify_ntfy high warning
}
handle_unknown() {
printf 'Unknown notification type %s for UPS %s: %s' \
"${NOTIFYTYPE}" \
"${UPSNAME}" \
"${MESSAGE}" \
| log -p daemon.notice
}
is_only_ups() {
for ups in $(upsc -l); do
bat_chg=$(upsc "${ups}" battery.charge)
bat_low=$(upsc "${ups}" battery.charge.low)
if [ "${bat_chg}" -gt "${bat_low}" ]; then
return 1
fi
done
return 0
}
log() {
logger --id=$$ -t "${0##*/}" "$@"
}
low_power_mode() {
echo 'UPS battery low, going to low power mode' \
| log -p daemon.warning
remote_shutdown host-dca632474c83.pyrocufflink.red
remote_shutdown burp1.pyrocufflink.blue
stop_noncritical_vms
consolidate_vms
}
migrate_vms() {
srcuri=qemu+ssh://root@${1}/system
tgturi=qemu+ssh://root@${2}/system
for vm in $(virsh -c ${srcuri} list --name); do
[ -n "${vm}" ] || continue
printf 'Migrating %s from %s to %s\n' "${vm}" "${1}" "${2}" \
| log -p daemon.info
virsh -c ${srcuri} migrate ${vm} ${tgturi} \
--live \
--persistent \
--undefinesource
done
}
notify_ntfy() {
priority="${1:-default}"
tags="${2}"
curl -fsSL https://ntfy.pyrocufflink.blue/pixel5 \
-o /dev/null \
-H 'Content-Type: text/plain' \
-H "Priority: ${priority}" \
-H "Tags: ${tags}" \
-d "${MESSAGE}"
}
remote_shutdown() {
printf 'Shutting down %s\n' "${1}" \
| log -p daemon.warning
# XXX Should probably create a nut user on remote machines
ssh \
-o BatchMode=yes \
-o StrictHostKeyChecking=no \
-o ConnectTimeout=5 \
-l root \
"${1}" \
systemctl poweroff
}
shut_down_all() {
echo 'Battery low on last UPS, shutting down' \
| log -p daemon.alert
for h in ${VM_HOSTS}; do
remote_shutdown ${h}
done
}
stop_noncritical_vms() {
echo 'Stopping all non-critical virtual machines' \
| log -p daemon.warning
t_running=$(mktemp)
t_critical=$(mktemp)
for name in ${CRITICAL_VMS}; do
[ -n "${name}" ] || continue
echo "${name}"
done | sort > "${t_critical}"
for h in ${VM_HOSTS}; do
[ -n "${h}" ] || continue
ssh -o BatchMode=yes -o StrictHostKeyChecking=no -l root ${h} :
uri=qemu+ssh://root@${h}/system
virsh -c ${uri} list --name | sort > "${t_running}"
for name in $(comm -23 "${t_running}" "${t_critical}"); do
[ -n "${name}" ] || continue
printf 'Stopping virtual machine: %s\n' "${name}" \
| log -p daemon.info
#virsh -c ${uri} shutdown ${name}
done
done
rm -f "${t_running}" "${t_critical}"
}
printf '%s running as %d %s\n' "${0##*/}" "$(id -u)" "$(whoami)" \
| log -p daemon.info
printf '%s %s %s\n' "${UPSNAME}" "${NOTIFYTYPE}" "${MESSAGE}" \
| log -p daemon.info
PATH=/usr/bin:/bin:/usr/sbin:/sbin
export PATH
case "${NOTIFYTYPE}" in
ONLINE)
handle_online
;;
ONBATT)
handle_onbatt
;;
LOWBATT)
handle_lowbatt
;;
COMMOK)
handle_commok
;;
COMMBAD)
handle_commbad
;;
REPLBATT)
handle_replbatt
;;
NOCOMM)
handle_nocomm
;;
*)
handle_unknown
;;
esac