Unraid配置NUT连接UPS

Unraid配置NUT连接UPS

2021 from–https://forums.unraid.net/topic/93341-tutorial-networked-nut-for-cyberpower-ups/

I should start with the disclaimer that I have no particular expertise with NUT so this guide is not definitive.

I have a Cyberpower UPS (CP685AVR) powering a Raspberry Pi and my Unraid Server.

Initially I installed apcupsd on the Pi, connected it to the UPS (via USB) and setup Unraid as slave. Install was fairly straightforward and worked well except for automatic restart after shutdown – when power’s restored connected servers must be booted manually. (NOTE: If your CyberPower UPS is connected directly to your unRAID server, enabling Turn off UPS after shutdown in settings not only won’t work but may cause the UPS to cut power without warning, forcing a parity check.)

I settled on NUT running as master on the Pi (Debian-based) connected to the UPS via USB, with Unraid and all other clients as slaves.

Overview

We can trigger shutdown one of two ways – after a set amount of time on battery or at a set battery level.

The timer method is more robust because if, after a power outage and shutdown, power’s restored and the system boots but it’s lost again, unraid may pick up the battery-level shutdown signal before the startup process completes which seems risky. And that may happen several times.

Instead we’ll set NUT to shutdown clients after 20 minutes on battery (approximately 20% of my runtime capacity) so in theory it can handle a couple of these power’s restored/power’s lost cycles.

Low battery will still trigger shutdown but the goal’s to avoid a low battery condition.

Let’s get started:

On Raspberry Pi

sudo apt install nut
# Verify UPS is visible with

lsusb
# Configure

sudo emacs /etc/nut/ups.conf
# My configuration block in ups.conf

[cyberpower]
driver = usbhid-ups
port = auto
desc = "UPS CP685AVR"
offdelay = 20
ondelay = 0
ignorelb
override.battery.charge.low = 20
override.battery.charge.warning = 40
pollinterval = 15
A few notes about these settings:

offdelay says turn UPS off X seconds after master server shuts off, required for automatic restart
ondelay should be 30 (10s greater than off delay) but a cyberpower bug requires 0 to avoid unexpected power cuts (similar to apcupsd behavior)
a shorter pollinterval is required to prevent the Pi (and maybe other debian systems) from losing contact
ignorelb allows custom overrides for battery.charge

# Start

upsdrvctl start
# Configure nut upsd

sudo emacs /etc/nut/upsd.conf
# Add network request listener replacing with your Pi’s IP address

LISTEN 3493
# User setup

sudo emacs /etc/nut/upsd.users
# Add users for admin, monitoring, local and remote users replacing pwd with your preferred password

[admin]
password = pwd
actions = SET
instcmds = ALL
[local]
password = pwd
upsmon master
[remote]
password = pwd
upsmon slave
[monuser]
password = pwd
upsmon slave
# Configure monitoring

sudo emacs /etc/nut/upsmon.conf
# Change the following values:

# Increase slave shutdown wait period to 10 minutes (worst case)

HOSTSYNC 600
# Works with pollinterval setting to prevent USB disconnection

DEADTIME 25
# Alerting twice/day about a battery change is excessive, make it once

RBWARNTIME 86400
# To be safe give clients an additional 90 seconds to fully shutdown

FINALDELAY 90
# Add monitor replacing pwd with the password you specified for [local] above

MONITOR cyberpower@localhost 1 local pwd master
# Timed shutdown – see upssched.conf for details

NOTIFYCMD /sbin/upssched
NOTIFYFLAG ONBATT SYSLOG+WALL+EXEC
NOTIFYFLAG ONLINE SYSLOG+WALL+EXEC
NOTIFYFLAG REPLBATT SYSLOG+WALL+EXEC

# Set the schedules in upssched.conf:

sudo emacs /etc/nut/upssched.conf
# Verify it has the line

CMDSCRIPT /bin/upssched-cmd
# Add:

# Command pipe and lock-file
PIPEFN /var/run/nut/upssched.pipe
LOCKFN /var/run/nut/upssched.lock

# Send alerts immediately on change in line power
AT ONBATT EXECUTE onbatt
AT ONLINE
EXECUTE onpower

# (Optional) Silence the beeper after 2 minutes
AT ONBATT START-TIMER mute_beeper 120
AT ONLINE
CANCEL-TIMER mute_beeper

# Shutdown after 20 minutes on battery (20 60 = 1200)
AT ONBATT
START-TIMER onbatt_shutdown 1200

# Cancel timer if power’s restored
AT ONLINE * CANCEL-TIMER onbatt_shutdown

# Battery replacement indicated by cron’d quick test
AT REPLBATT * EXECUTE replace_batt

# Customize the executable called by upssched

sudo emacs /bin/upssched-cmd
# …by replacing existing code with the following (substituting the password you set for admin earlier for )

# START: User-specific settings
#
UPS_USERNAME="admin"
UPS_PASSWORD=""
UPS_LINK="cyberpower@localhost"
# END

case $1 in
onbatt)

make sure beeper is enabled

    upscmd -u ${UPS_USERNAME} -p ${UPS_PASSWORD} ${UPS_LINK} beeper.enable
    # alert
    message="Power outage, on battery"
    logger -t upssched-cmd "$message"
    ;;
onpower)
    message="Power restored"
    logger -t upssched-cmd "$message"
    ;;
mute_beeper)
     message="(2) minute limit exceeded, muting beeper"
     upscmd -u ${UPS_USERNAME} -p ${UPS_PASSWORD} ${UPS_LINK} beeper.mute
     ;;
onbatt_shutdown)
    message="Triggering shutdown after (20) minutes on battery"
    logger -t upssched-cmd "$message"
    /sbin/upsmon -c fsd
    ;;
replace_batt)
    message="Quick self-test indicates battery requires replacement"
    logger -t upssched-cmd "$message"
    ;;
*)
    logger -t upssched-cmd "Unrecognized command: $1"
    ;;

esac
# Verify it’s executable by all:

ls -l /bin/upssched-cmd

# Schedule the (weekly) quick test mentioned earlier

sudo crontab -e
# Add

# Weekly UPS self-test
0 2 MON /bin/upscmd -u admin -p cyberpower@localhost test.battery.start.quick

# Configure nut as netserver

sudo emacs /etc/nut/nut.conf
# Change MODE

MODE=netserver

Now reboot the Pi to verify the NUT services launch on startup

# Confirm services are running

sudo service nut-server status
sudo service nut-client status
# Confirm communication with UPS – this should return a bunch of info

upsc cyberpower

On Unraid

# Install NUT from CA

# Configure as follows using the Pi IP, monuser password and remote password specified earlier

# NOTE: Whether in the case of a timed shutdown or an emergency low battery shutdown

# we’re relying on the Pi (NUT server) to send the signal. Ideally the shutdown triggers here

# won’t be used.

1208822292_ScreenShot2021-01-23at5_33_32AM.thumb.png.3bb0b7cbf27e6b7b8330e729573cfe3a.png

Miscellaneous

# Test shutdown.

# NOTE: This will shutdown your system so it’s safest if you stop the array first.

# But stopping is most of the required shutdown time, so after you confirm

# this works you might want to test again without stopping the array.

sudo upsmon -c fsd

Optional

# Cyberpower uses status codes not recognized by the NUT plugin which as far as I can tell only affect display but I want my dashboard to be pretty so let’s customize the display script (NOTE: this will get overwritten, and possibly cause conflicts, on plugin update)

mkdir /boot/extras/nut
cp /usr/local/emhttp/plugins/nut/include/nut_status.php /boot/extras/nut/nut_status.php
vi /boot/extras/nut/nut_status.php
# Replace the state array with the following

$state = [
‘OL’ => ‘Online’,
‘OL CHRG’ => ‘Online: charging‘,
‘OL CHRG LB’ => ‘Online: charging‘,
‘OL DISCHRG’ => ‘Online: discharging‘,
‘OL DISCHRG LB’ => ‘Online: discharging‘,
‘OL BOOST’ => ‘Online: low voltage‘,
‘OB DISCHRG’ => ‘Offline: On battery’,
‘OB LB’ => ‘Offline: Low battery’
];

# If you prefer the look of the built-in UPS dashboard, the next two sections (presented in diff form) mimic it

# diff /usr/local/emhttp/plugins/nut/include/nut_status.php.orig /usr/local/emhttp/plugins/nut/include/nut_status.php
44,45c48,49
<       $runtime   = gmdate("H:i:s", $val);
<       $status[2] = strtok($val/60,' ')<=5 && !in_array('ups.status: OL', $rows) ? "<td $red>$runtime</td>" : "<td $green>$runtime</td>";
---
>       $runtime   = strtok($val/60,' ');
>       $status[2] = strtok($val/60,' ')<=5 && !in_array('ups.status: OL', $rows) ? "<td $red>".intval($runtime)."m</td>" : "<td $green>".intval($runtime)."m</td>";
49a54,56
>     case 'input.voltage':
>       $voltage   = intval(strtok($val,' '));
>       break;
64c71
<   $status[3] = $power==0 ? "<td $red>${power}w</td>" : "<td $green>${power}w</td>";
---
>   $status[3] = $voltage<114 ? "<td $orange>${voltage}V</td>" : "<td $green>${voltage}V</td>";
# diff /usr/local/emhttp/plugins/nut/nutFooter.page.orig /usr/local/emhttp/plugins/nut/nutFooter.page
151a152
> <span class='ups'>Input voltage:</span><span class='nut_nompower'></span><br>
154d154
< <span class='ups'>Nominal power:</span><span class='nut_nompower'></span><br>

# Set your go file to overwrite the default files with the customized version on boot

vi /boot/config/go
# Add to the end:

# Customize nut (UPS) display
cp /usr/local/emhttp/plugins/nut/include/nut_status.php /usr/local/emhttp/plugins/nut/include/nut_status.php.orig
cp /boot/extras/nut/nut_status.php /usr/local/emhttp/plugins/nut/include/nut_status.php
# display voltage instead of max power
cp /usr/local/emhttp/plugins/nut/nutFooter.page /usr/local/emhttp/plugins/nut/nutFooter.page.orig
cp /boot/extras/nut/nutFooter.page /usr/local/emhttp/plugins/nut/nutFooter.page

All done. Automatic shutdown of the servers and UPS work and (assuming proper BIOS settings) they’ll all restart when power’s restored.

Edit 7/6/2020: Increase offdelay to account for slow unraid shutdown

Edit 1/23/2020: Misc reliability tweaks, shift from battery level-based shutdown to timer-based shutdown

上一篇
下一篇