Uninterruptible power supply: Difference between revisions

Tie-ling (talk | contribs)
init
 
Wo2wz (talk | contribs)
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
  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
 
   Return BIOS option functional,
= Declare UPS units =
   systemd.services.nut-delayed-ups-shutdown section
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]]