apcupsd-service: add services.apcupsd.hooks option

Each attribute in this option should name an apcupsd event and the
string value it contains will be executed in a shell in response to that
event. See "man apccontrol" for the list of events and what they
represent.

Now it is easy to hook into the apcupsd event system:

  services.apcupsd.hooks = {
    onbattery  = ''# shell commands to run when the onbattery event is emitted'';
    doshutdown = ''# shell commands to notify that the computer is shutting down'';
  };
This commit is contained in:
Bjørn Forsman 2013-07-21 17:21:06 +02:00
parent 6341a12587
commit dc61694d01

View File

@ -2,12 +2,66 @@
with pkgs.lib;
let cfg = config.services.apcupsd;
configFile = pkgs.writeText "apcupsd.conf" ''
## apcupsd.conf v1.1 ##
# apcupsd complains if the first line is not like above.
${cfg.configText}
'';
let
cfg = config.services.apcupsd;
configFile = pkgs.writeText "apcupsd.conf" ''
## apcupsd.conf v1.1 ##
# apcupsd complains if the first line is not like above.
${cfg.configText}
SCRIPTDIR ${toString scriptDir}
'';
# List of events from "man apccontrol"
eventList = [
"annoyme"
"battattach"
"battdetach"
"changeme"
"commfailure"
"commok"
"doreboot"
"doshutdown"
"emergency"
"failing"
"killpower"
"loadlimit"
"mainsback"
"onbattery"
"offbattery"
"powerout"
"remotedown"
"runlimit"
"timeout"
"startselftest"
"endselftest"
];
shellCmdsForEventScript = eventname: commands: ''
echo "#!${pkgs.stdenv.shell}" > "$out/${eventname}"
echo "${commands}" >> "$out/${eventname}"
chmod a+x "$out/${eventname}"
'';
eventToShellCmds = event: if builtins.hasAttr event cfg.hooks then (shellCmdsForEventScript event (builtins.getAttr event cfg.hooks)) else "";
scriptDir = pkgs.runCommand "apcupsd-scriptdir" {} (''
mkdir "$out"
# Copy SCRIPTDIR from apcupsd package
cp -r ${pkgs.apcupsd}/etc/apcupsd/* "$out"/
# Make the files writeable (nix will unset the write bits afterwards)
chmod u+w "$out"/*
# Remove the sample event notification scripts, because they don't work
# anyways (they try to send mail to "root" with the "mail" command)
(cd "$out" && rm changeme commok commfailure onbattery offbattery)
# Remove the sample apcupsd.conf file (we're generating our own)
rm "$out/apcupsd.conf"
# Set the SCRIPTDIR= line in apccontrol to the dir we're creating now
sed -i -e "s|^SCRIPTDIR=.*|SCRIPTDIR=$out|" "$out/apccontrol"
'' + concatStringsSep "\n" (map eventToShellCmds eventList)
);
in
{
@ -47,6 +101,24 @@ in
'';
};
hooks = mkOption {
default = {};
example = {
doshutdown = ''# shell commands to notify that the computer is shutting down'';
};
type = types.attrsOf types.string;
description = ''
Each attribute in this option names an apcupsd event and the string
value it contains will be executed in a shell, in response to that
event (prior to the default action). See "man apccontrol" for the
list of events and what they represent.
A hook script can stop apccontrol from doing its default action by
exiting with value 99. Do not do this unless you know what you're
doing.
'';
};
};
};
@ -56,6 +128,15 @@ in
config = mkIf cfg.enable {
assertions = [ {
assertion = let hooknames = builtins.attrNames cfg.hooks; in all (x: elem x eventList) hooknames;
message = ''
One (or more) attribute names in services.apcupsd.hooks are invalid.
Current attribute names: ${toString (builtins.attrNames cfg.hooks)}
Valid attribute names : ${toString eventList}
'';
} ];
# Give users access to the "apcaccess" tool
environment.systemPackages = [ pkgs.apcupsd ];
@ -66,10 +147,6 @@ in
# not connected to a tty (it is connected to the journal):
# wall: cannot get tty name: Inappropriate ioctl for device
# The message still gets through.
#
# TODO: apcupsd calls "mail" on powerfail etc. events, how should we
# handle that? A configurable mail package or let the event logic be
# configured from nix expressions?
systemd.services.apcupsd = {
description = "UPS daemon";
wantedBy = [ "multi-user.target" ];