about summary refs log tree commit diff
path: root/nixos/modules/services/monitoring/watchdogd.nix
blob: e8d104651c6ad03a984d137bfc9e169dac44b14d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
{ config, lib, pkgs, ... }:
with lib;
let
  cfg = config.services.watchdogd;

  mkPluginOpts = plugin: defWarn: defCrit: {
    enabled = mkEnableOption "watchdogd plugin ${plugin}";
    interval = mkOption {
      type = types.ints.unsigned;
      default = 300;
      description = ''
        Amount of seconds between every poll.
      '';
    };
    logmark = mkOption {
      type = types.bool;
      default = false;
      description = ''
        Whether to log current stats every poll interval.
      '';
    };
    warning = mkOption {
      type = types.numbers.nonnegative;
      default = defWarn;
      description = ''
        The high watermark level. Alert sent to log.
      '';
    };
    critical = mkOption {
      type = types.numbers.nonnegative;
      default = defCrit;
      description = ''
        The critical watermark level. Alert sent to log, followed by reboot or script action.
      '';
    };
  };
in {
  options.services.watchdogd = {
    enable = mkEnableOption "watchdogd, an advanced system & process supervisor";
    package = mkPackageOption pkgs "watchdogd" { };

    settings = mkOption {
      type = with types; submodule {
        freeformType = let
          valueType = oneOf [
            bool
            int
            float
            str
          ];
        in attrsOf (either valueType (attrsOf valueType));

        options = {
          timeout = mkOption {
            type = types.ints.unsigned;
            default = 15;
            description = ''
              The WDT timeout before reset.
            '';
          };
          interval = mkOption {
            type = types.ints.unsigned;
            default = 5;
            description = ''
              The kick interval, i.e. how often {manpage}`watchdogd(8)` should reset the WDT timer.
            '';
          };

          safe-exit = mkOption {
            type = types.bool;
            default = true;
            description = ''
              With {var}`safeExit` enabled, the daemon will ask the driver to disable the WDT before exiting.
              However, some WDT drivers (or hardware) may not support this.
            '';
          };

          filenr = mkPluginOpts "filenr" 0.9 1.0;

          loadavg = mkPluginOpts "loadavg" 1.0 2.0;

          meminfo = mkPluginOpts "meminfo" 0.9 0.95;
        };
      };
      default = { };
      description = ''
        Configuration to put in {file}`watchdogd.conf`.
        See {manpage}`watchdogd.conf(5)` for more details.
      '';
    };
  };

  config = let
    toConfig = attrs: concatStringsSep "\n" (mapAttrsToList toValue attrs);

    toValue = name: value:
      if isAttrs value
        then pipe value [
          (mapAttrsToList toValue)
          (map (s: "  ${s}"))
          (concatStringsSep "\n")
          (s: "${name} {\n${s}\n}")
        ]
      else if isBool value
        then "${name} = ${boolToString value}"
      else if any (f: f value) [isString isInt isFloat]
        then "${name} = ${toString value}"
      else throw ''
        Found invalid type in `services.watchdogd.settings`: '${typeOf value}'
      '';

    watchdogdConf = pkgs.writeText "watchdogd.conf" (toConfig cfg.settings);
  in mkIf cfg.enable {
    environment.systemPackages = [ cfg.package ];

    systemd.services.watchdogd = {
      documentation = [
        "man:watchdogd(8)"
        "man:watchdogd.conf(5)"
      ];
      wantedBy = [ "multi-user.target" ];
      description = "Advanced system & process supervisor";
      serviceConfig = {
        Type = "simple";
        ExecStart = "${cfg.package}/bin/watchdogd -n -f ${watchdogdConf}";
      };
    };
  };

  meta.maintainers = with maintainers; [ vifino ];
}