summary refs log tree commit diff
path: root/modules/services/monitoring/apcupsd.nix
diff options
context:
space:
mode:
authorBjørn Forsman <bjorn.forsman@gmail.com>2013-07-21 17:21:06 +0200
committerBjørn Forsman <bjorn.forsman@gmail.com>2013-07-22 14:19:21 +0200
commitdc61694d013cc7bc65006770b0a5278cd56440a7 (patch)
tree8400b608540e6e62d0a81f8a5e47f4c2883db832 /modules/services/monitoring/apcupsd.nix
parent6341a1258750fd19647f1a2bcebe7f011f7acae7 (diff)
downloadnixpkgs-dc61694d013cc7bc65006770b0a5278cd56440a7.tar
nixpkgs-dc61694d013cc7bc65006770b0a5278cd56440a7.tar.gz
nixpkgs-dc61694d013cc7bc65006770b0a5278cd56440a7.tar.bz2
nixpkgs-dc61694d013cc7bc65006770b0a5278cd56440a7.tar.lz
nixpkgs-dc61694d013cc7bc65006770b0a5278cd56440a7.tar.xz
nixpkgs-dc61694d013cc7bc65006770b0a5278cd56440a7.tar.zst
nixpkgs-dc61694d013cc7bc65006770b0a5278cd56440a7.zip
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'';
  };
Diffstat (limited to 'modules/services/monitoring/apcupsd.nix')
-rw-r--r--modules/services/monitoring/apcupsd.nix97
1 files changed, 87 insertions, 10 deletions
diff --git a/modules/services/monitoring/apcupsd.nix b/modules/services/monitoring/apcupsd.nix
index 5541fb92fe1..053851be398 100644
--- a/modules/services/monitoring/apcupsd.nix
+++ b/modules/services/monitoring/apcupsd.nix
@@ -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" ];