Uninterruptible power supply: Difference between revisions
init |
remove unnecessary portion under compatible hardware |
||
| (16 intermediate revisions by 2 users not shown) | |||
| Line 50: | Line 50: | ||
* upsd.conf, control access to upsd, power.ups.upsd option | * upsd.conf, control access to upsd, power.ups.upsd option | ||
* upsd.users, add user with access to upsd, power.ups.users option | * upsd.users, add user with access to upsd, power.ups.users option | ||
* upsmon.conf, connect to upsd, power.ups.upsmon.monitor section; | * upsmon.conf, connect upsmon to upsd, power.ups.upsmon.monitor section; | ||
* upsmon.conf, set how upsmon should react to status changes, | * upsmon.conf, set how upsmon should react to status changes, power.ups.upsmon.settings section | ||
* delayed UPS shutdown systemd unit, to make Restore Power on AC Return BIOS option functional, systemd.services.nut-delayed-ups-shutdown section | |||
* delayed UPS shutdown systemd unit, to make Restore Power on AC | |||
= Declare UPS units = | |||
systemd.services.nut-delayed-ups-shutdown | Corresponds to file ups.conf | ||
<syntaxhighlight lang="nix"> | |||
power.ups = { | |||
enable = true; | |||
mode = "standalone"; | |||
# section: The upsd UPS declarations: ups.conf | |||
# this UPS device is named UPS-1. | |||
ups."UPS-1" = { | |||
description = "Eaton Ellipse ECO 650 with 12V 7Ah lead-acid Batt"; | |||
# driver name from https://networkupstools.org/stable-hcl.html | |||
driver = "usbhid-ups"; | |||
# usbhid-ups driver always use value "auto" | |||
port = "auto"; | |||
directives = [ | |||
# "Restore power on AC" BIOS option needs power to be cut a few seconds to work; | |||
# this is achieved by the offdelay and ondelay directives. | |||
# in the last stages of system shutdown, "upsdrvctl shutdown" is called to tell UPS that | |||
# after offdelay seconds, the UPS power must be cut, even if | |||
# wall power returns. | |||
# There is a danger that the system will take longer than the default 20 seconds to shut down. | |||
# If that were to happen, the UPS shutdown would provoke a brutal system crash. | |||
# We adjust offdelay, to solve this issue. | |||
"offdelay = 60" | |||
# UPS power is now cut regardless of wall power. After (ondelay minus offdelay) seconds, | |||
# if wall power returns, turn on UPS power. The system has now been disconnected for a minimum of (ondelay minus offdelay) seconds, | |||
# "Restore power on AC" should now power on the system. | |||
# For reasons described above, ondelay value must be larger than offdelay value. | |||
# We adjust ondelay, to ensure Restore power on AC option returns to Power Disconnected state. | |||
"ondelay = 70" | |||
# set value for battery.charge.low, | |||
# upsmon initiate shutdown once this threshold is reached. | |||
"lowbatt = 40" | |||
# ignore it if the UPS reports a low battery condition | |||
# without this, system will shutdown only when ups reports lb, | |||
# not respecting lowbatt option | |||
"ignorelb" | |||
]; | |||
}; | |||
</syntaxhighlight> | |||
= Declare upsd listening ports = | |||
Corresponds to file upsd.conf. This file declares which ports the upsd daemon will listen to. | |||
<syntaxhighlight lang="nix"> | |||
power.ups = { | |||
# section: The upsd daemon access control; upsd.conf | |||
upsd = { | |||
listen = [ | |||
{ | |||
address = "127.0.0.1"; | |||
port = 3493; | |||
} | |||
{ | |||
address = "::1"; | |||
port = 3493; | |||
} | |||
]; | |||
}; | |||
}; | |||
</syntaxhighlight> | |||
= Declare users with access to UPS = | |||
Corresponds to file upsd.users. This file declares a virtual user (not related to /etc/passwd users) with write access to UPS. A password is also declared. | |||
<syntaxhighlight lang="nix"> | |||
power.ups = { | |||
# section: Users that can access upsd. The upsd daemon user | |||
# declarations. upsd.users | |||
users."nut-admin" = { | |||
passwordFile = "${../resources/ups-passwd.txt}"; | |||
upsmon = "primary"; | |||
}; | |||
}; | |||
</syntaxhighlight> | |||
= Connect upsmon to upsd = | |||
Corresponds to upsmon.conf. This file declares how upsmon should connect to upsd | |||
<syntaxhighlight lang="nix"> | |||
power.ups = { | |||
# section: The upsmon daemon configuration: upsmon.conf | |||
upsmon.monitor."UPS-1" = { | |||
system = "UPS-1@localhost"; | |||
powerValue = 1; | |||
user = "nut-admin"; | |||
passwordFile = "${../resources/ups-passwd.txt}"; | |||
type = "primary"; | |||
}; | |||
}; | |||
</syntaxhighlight> | |||
= Declare how upsmon should react to status changes = | |||
Corresponds to upsmon.conf. This file declares how upsmon is to handle NOTIFY events. | |||
<syntaxhighlight lang="nix"> | |||
power.ups = { | |||
upsmon.settings = { | |||
# This configuration file declares how upsmon is to handle | |||
# NOTIFY events. | |||
# POWERDOWNFLAG and SHUTDOWNCMD is provided by NixOS default | |||
# values | |||
# values provided by ConfigExamples 3.0 book | |||
NOTIFYMSG = [ | |||
[ "ONLINE" ''"UPS %s: On line power."'' ] | |||
[ "ONBATT" ''"UPS %s: On battery."'' ] | |||
[ "LOWBATT" ''"UPS %s: Battery is low."'' ] | |||
[ "REPLBATT" ''"UPS %s: Battery needs to be replaced."'' ] | |||
[ "FSD" ''"UPS %s: Forced shutdown in progress."'' ] | |||
[ "SHUTDOWN" ''"Auto logout and shutdown proceeding."'' ] | |||
[ "COMMOK" ''"UPS %s: Communications (re-)established."'' ] | |||
[ "COMMBAD" ''"UPS %s: Communications lost."'' ] | |||
[ "NOCOMM" ''"UPS %s: Not available."'' ] | |||
[ "NOPARENT" ''"upsmon parent dead, shutdown impossible."'' ] | |||
]; | |||
NOTIFYFLAG = [ | |||
[ "ONLINE" "SYSLOG+WALL" ] | |||
[ "ONBATT" "SYSLOG+WALL" ] | |||
[ "LOWBATT" "SYSLOG+WALL" ] | |||
[ "REPLBATT" "SYSLOG+WALL" ] | |||
[ "FSD" "SYSLOG+WALL" ] | |||
[ "SHUTDOWN" "SYSLOG+WALL" ] | |||
[ "COMMOK" "SYSLOG+WALL" ] | |||
[ "COMMBAD" "SYSLOG+WALL" ] | |||
[ "NOCOMM" "SYSLOG+WALL" ] | |||
[ "NOPARENT" "SYSLOG+WALL" ] | |||
]; | |||
# every RBWARNTIME seconds, upsmon will generate a replace | |||
# battery NOTIFY event | |||
RBWARNTIME = 216000; | |||
# every NOCOMMWARNTIME seconds, upsmon will generate a UPS | |||
# unreachable NOTIFY event | |||
NOCOMMWARNTIME = 300; | |||
# after sending SHUTDOWN NOTIFY event to warn users, upsmon | |||
# waits FINALDELAY seconds long before executing SHUTDOWNCMD | |||
# Some UPS's don't give much warning for low battery and will | |||
# require a value of 0 here for aq safe shutdown. | |||
FINALDELAY = 0; | |||
}; | |||
}; | |||
</syntaxhighlight> | |||
= Delay UPS Shutdown = | |||
As part of the system shutdown process, there needs to be an action to | |||
send a message to the UPS to tell it that some time later, it too will | |||
shut down. Note that the UPS does not shutdown at the same time as the | |||
system it protects. The UPS shutdown is delayed. By default the delay | |||
is 20 seconds. The absence of AC power to the protected system for a | |||
sufficient time has the effect of resetting the BIOS options, and in | |||
particular the option Restore power on AC return. This BIOS option | |||
will be needed to restart the box. | |||
During the system shutdown, systemd service unit runs the command | |||
<code>upsdrvctl shutdown</code>. This tells the UPS that it is to shut down | |||
offdelay seconds later. The system powers down before offdelay seconds | |||
have passed. Wall power returns before the UPS shuts down. Less than | |||
offdelay seconds have now passed. The UPS continues it's shutdown | |||
process. | |||
After offdelay seconds the UPS shuts down, disconnecting it's | |||
outlets. The beeping stops. With some UPS units, there is an audible | |||
clunk. An interval of ondelay minus offdelay seconds later: After ondelay | |||
seconds the UPS turns itself on, and repowers it's outlets. The system | |||
BIOS option Restore Power on AC return has hopefully been selected and | |||
the system powers up. | |||
There is a danger that the system will take longer | |||
than the default 20 seconds to shut down. If that were to happen, the UPS shutdown | |||
would provoke a brutal system crash. We have adjusted offdelay above, to solve this issue. | |||
<syntaxhighlight lang="nix"> | |||
# copied from ConfigExamples 3.0 book, Appendix B.2. | |||
systemd.services.nut-delayed-ups-shutdown = { | |||
enable = true; | |||
environment = config.systemd.services.upsmon.environment; | |||
description = "Initiate delayed UPS shutdown"; | |||
before = [ "umount.target" ]; | |||
wantedBy = [ "final.target" ]; | |||
serviceConfig = { | |||
Type = "oneshot"; | |||
# need to use '-u root', or else permission denied | |||
ExecStart = ''${pkgs.nut}/bin/upsdrvctl -u root shutdown''; | |||
# must not use slice: if used, upsdrvctl will not run as a late | |||
# shutdown service | |||
# Slice = ""; | |||
}; | |||
unitConfig = { | |||
ConditionPathExists = config.power.ups.upsmon.settings.POWERDOWNFLAG; | |||
DefaultDependencies = "no"; | |||
}; | |||
}; | |||
</syntaxhighlight> | |||
[[Category:Hardware]] | |||