Skip to content

Commit

Permalink
apcupsd-service: add services.apcupsd.hooks option
Browse files Browse the repository at this point in the history
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'';
  };
  • Loading branch information
bjornfor committed Jul 22, 2013
1 parent 6341a12 commit dc61694
Showing 1 changed file with 87 additions and 10 deletions.
97 changes: 87 additions & 10 deletions modules/services/monitoring/apcupsd.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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

{
Expand Down Expand Up @@ -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.
'';
};

};

};
Expand All @@ -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 ];

Expand All @@ -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" ];
Expand Down

0 comments on commit dc61694

Please sign in to comment.