forked from mirrors/nixpkgs
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:
parent
6341a12587
commit
dc61694d01
|
@ -2,12 +2,66 @@
|
||||||
|
|
||||||
with pkgs.lib;
|
with pkgs.lib;
|
||||||
|
|
||||||
let cfg = config.services.apcupsd;
|
let
|
||||||
configFile = pkgs.writeText "apcupsd.conf" ''
|
cfg = config.services.apcupsd;
|
||||||
## apcupsd.conf v1.1 ##
|
|
||||||
# apcupsd complains if the first line is not like above.
|
configFile = pkgs.writeText "apcupsd.conf" ''
|
||||||
${cfg.configText}
|
## 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
|
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 {
|
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
|
# Give users access to the "apcaccess" tool
|
||||||
environment.systemPackages = [ pkgs.apcupsd ];
|
environment.systemPackages = [ pkgs.apcupsd ];
|
||||||
|
|
||||||
|
@ -66,10 +147,6 @@ in
|
||||||
# not connected to a tty (it is connected to the journal):
|
# not connected to a tty (it is connected to the journal):
|
||||||
# wall: cannot get tty name: Inappropriate ioctl for device
|
# wall: cannot get tty name: Inappropriate ioctl for device
|
||||||
# The message still gets through.
|
# 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 = {
|
systemd.services.apcupsd = {
|
||||||
description = "UPS daemon";
|
description = "UPS daemon";
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
|
Loading…
Reference in a new issue