diff options
author | Ismaël Bouya <ismael.bouya@normalesup.org> | 2023-10-04 01:35:06 +0200 |
---|---|---|
committer | Ismaël Bouya <ismael.bouya@normalesup.org> | 2023-10-04 02:11:48 +0200 |
commit | 1a64deeb894dc95e2645a75771732c6cc53a79ad (patch) | |
tree | 1b9df4838f894577a09b9b260151756272efeb53 /flakes/private/monitoring | |
parent | fa25ffd4583cc362075cd5e1b4130f33306103f0 (diff) | |
download | Nix-1a64deeb894dc95e2645a75771732c6cc53a79ad.tar.gz Nix-1a64deeb894dc95e2645a75771732c6cc53a79ad.tar.zst Nix-1a64deeb894dc95e2645a75771732c6cc53a79ad.zip |
Squash changes containing private information
There were a lot of changes since the previous commit, but a lot of them
contained personnal information about users. All thos changes got
stashed into a single commit (history is kept in a different place) and
private information was moved in a separate private repository
Diffstat (limited to 'flakes/private/monitoring')
28 files changed, 2542 insertions, 0 deletions
diff --git a/flakes/private/monitoring/flake.lock b/flakes/private/monitoring/flake.lock new file mode 100644 index 0000000..2e156fb --- /dev/null +++ b/flakes/private/monitoring/flake.lock | |||
@@ -0,0 +1,67 @@ | |||
1 | { | ||
2 | "nodes": { | ||
3 | "environment": { | ||
4 | "locked": { | ||
5 | "lastModified": 1, | ||
6 | "narHash": "sha256-rMKbM7fHqWQbI7y59BsPG8KwoDj2jyrvN2niPWB24uE=", | ||
7 | "path": "../environment", | ||
8 | "type": "path" | ||
9 | }, | ||
10 | "original": { | ||
11 | "path": "../environment", | ||
12 | "type": "path" | ||
13 | } | ||
14 | }, | ||
15 | "naemon": { | ||
16 | "locked": { | ||
17 | "lastModified": 1, | ||
18 | "narHash": "sha256-6le57WLKj1HXdhe4cgYO6N0Z9nJZC+plQY8HhOwzEIk=", | ||
19 | "path": "../../naemon", | ||
20 | "type": "path" | ||
21 | }, | ||
22 | "original": { | ||
23 | "path": "../../naemon", | ||
24 | "type": "path" | ||
25 | } | ||
26 | }, | ||
27 | "nixpkgs-lib": { | ||
28 | "locked": { | ||
29 | "dir": "lib", | ||
30 | "lastModified": 1691269286, | ||
31 | "narHash": "sha256-7cPTz1bPhwq8smt9rHDcFtJsd1tFDcBukzj5jOXqjfk=", | ||
32 | "owner": "NixOS", | ||
33 | "repo": "nixpkgs", | ||
34 | "rev": "85d4248a4f5aa6bc55dd2cea8131bb68b2d43804", | ||
35 | "type": "github" | ||
36 | }, | ||
37 | "original": { | ||
38 | "dir": "lib", | ||
39 | "owner": "NixOS", | ||
40 | "repo": "nixpkgs", | ||
41 | "type": "github" | ||
42 | } | ||
43 | }, | ||
44 | "root": { | ||
45 | "inputs": { | ||
46 | "environment": "environment", | ||
47 | "naemon": "naemon", | ||
48 | "nixpkgs-lib": "nixpkgs-lib", | ||
49 | "secrets": "secrets" | ||
50 | } | ||
51 | }, | ||
52 | "secrets": { | ||
53 | "locked": { | ||
54 | "lastModified": 1, | ||
55 | "narHash": "sha256-5AakznhrJFmwCD7lr4JEh55MtdAJL6WA/YuBks6ISSE=", | ||
56 | "path": "../../secrets", | ||
57 | "type": "path" | ||
58 | }, | ||
59 | "original": { | ||
60 | "path": "../../secrets", | ||
61 | "type": "path" | ||
62 | } | ||
63 | } | ||
64 | }, | ||
65 | "root": "root", | ||
66 | "version": 7 | ||
67 | } | ||
diff --git a/flakes/private/monitoring/flake.nix b/flakes/private/monitoring/flake.nix new file mode 100644 index 0000000..b7c3997 --- /dev/null +++ b/flakes/private/monitoring/flake.nix | |||
@@ -0,0 +1,267 @@ | |||
1 | { | ||
2 | inputs = { | ||
3 | environment.url = "path:../environment"; | ||
4 | secrets.url = "path:../../secrets"; | ||
5 | naemon.url = "path:../../naemon"; | ||
6 | nixpkgs-lib.url = "github:NixOS/nixpkgs?dir=lib"; | ||
7 | }; | ||
8 | outputs = { self, environment, nixpkgs-lib, secrets, naemon }: { | ||
9 | nagios-cli-config = ./nagios-cli.cfg; | ||
10 | lib = rec { | ||
11 | expandedObject = kind: object: objects: | ||
12 | if object ? "use" | ||
13 | then expandedObject kind objects.templates.${kind}.${object.use} objects // object | ||
14 | else object; | ||
15 | |||
16 | objectsCommon = import ./objects_common.nix; | ||
17 | toObjects = import ./to_objects.nix { inherit (nixpkgs-lib) lib; }; | ||
18 | |||
19 | toMasterPassiveObject = svcTemplate: freshnessThresholdMultiplier: objects: | ||
20 | { | ||
21 | service = with nixpkgs-lib.lib; map (s: | ||
22 | { | ||
23 | host_name = (expandedObject "service" s objects).host_name; | ||
24 | use = svcTemplate; | ||
25 | retry_interval = "1"; | ||
26 | freshness_threshold = let | ||
27 | fs = expandedObject "service" s objects; | ||
28 | in if builtins.isInt fs.check_interval | ||
29 | then builtins.ceil (freshnessThresholdMultiplier * 60 * fs.check_interval) | ||
30 | else fs.check_interval; | ||
31 | } | ||
32 | // filterAttrs (k: v: builtins.elem k ["service_description"] || builtins.substring 0 1 k == "_") s | ||
33 | // mapAttrs' | ||
34 | (n: nameValuePair (removePrefix "__passive_" n)) | ||
35 | (filterAttrs (k: _: hasPrefix "__passive_" k) s) | ||
36 | ) objects.service; | ||
37 | host = objects.host; | ||
38 | }; | ||
39 | |||
40 | emailCheck = allCfg: host: hostFQDN: let | ||
41 | cfg = allCfg."${host}"; | ||
42 | reverseTargets = builtins.attrNames (nixpkgs-lib.lib.filterAttrs (k: v: builtins.elem host v.targets) allCfg); | ||
43 | to_email = cfg': host': | ||
44 | let sep = if nixpkgs-lib.lib.hasInfix "+" cfg'.mail_address then "_" else "+"; | ||
45 | in "${cfg'.mail_address}${sep}${host'}@${cfg'.mail_domain}"; | ||
46 | mails_to_send = builtins.concatStringsSep "," (map (n: to_email allCfg."${n}" host) cfg.targets); | ||
47 | mails_to_receive = builtins.concatStringsSep "," (map (n: "${to_email cfg n}:${n}") reverseTargets); | ||
48 | command = if cfg.local | ||
49 | then | ||
50 | [ "check_emails_local" "/var/lib/naemon/checks/email" mails_to_send mails_to_receive ] | ||
51 | else | ||
52 | [ "check_emails" cfg.login cfg.port mails_to_send mails_to_receive ]; | ||
53 | in | ||
54 | { | ||
55 | service_description = "${hostFQDN} email service is active"; | ||
56 | use = "mail-service"; | ||
57 | host_name = hostFQDN; | ||
58 | servicegroups = "webstatus-email"; | ||
59 | check_command = command; | ||
60 | }; | ||
61 | }; | ||
62 | nixosModule = self.nixosModules.monitoring; | ||
63 | nixosModules.monitoring = { config, pkgs, lib, ... }: | ||
64 | let | ||
65 | cfg = config.myServices.monitoring; | ||
66 | allPluginsConfig = import ./myplugins.nix { | ||
67 | inherit pkgs lib config; | ||
68 | sudo = "/run/wrappers/bin/sudo"; | ||
69 | }; | ||
70 | mypluginsConfig = lib.mapAttrs (n: v: | ||
71 | if builtins.isFunction v | ||
72 | then v (cfg.pluginsArgs."${n}" or {}) | ||
73 | else v | ||
74 | ) (lib.getAttrs cfg.activatedPlugins allPluginsConfig); | ||
75 | myplugins = let | ||
76 | mypluginsChunk = builtins.concatStringsSep "\n" (lib.mapAttrsToList (k: v: v.chunk or "") mypluginsConfig); | ||
77 | in pkgs.runCommand "buildplugins" { | ||
78 | buildInputs = [ pkgs.makeWrapper pkgs.perl ]; | ||
79 | } '' | ||
80 | mkdir $out | ||
81 | ${mypluginsChunk} | ||
82 | ''; | ||
83 | objectsModule = with lib.types; submodule { | ||
84 | options = { | ||
85 | command = lib.mkOption { | ||
86 | type = attrsOf str; | ||
87 | default = {}; | ||
88 | description = "Command definitions"; | ||
89 | }; | ||
90 | |||
91 | host = lib.mkOption { | ||
92 | type = attrsOf (attrsOf str); | ||
93 | default = {}; | ||
94 | description = "Host definitions"; | ||
95 | }; | ||
96 | hostgroup = lib.mkOption { | ||
97 | type = attrsOf (attrsOf str); | ||
98 | default = {}; | ||
99 | description = "Host group definitions"; | ||
100 | }; | ||
101 | hostdependency = lib.mkOption { | ||
102 | type = listOf (attrsOf str); | ||
103 | default = []; | ||
104 | description = "Host dependency definitions"; | ||
105 | }; | ||
106 | |||
107 | service = lib.mkOption { | ||
108 | type = listOf (attrsOf (oneOf [ str (listOf str) int ])); | ||
109 | # str -> string | ||
110 | # listOf str -> list to be concatenated with "!" | ||
111 | # int -> toString | ||
112 | default = []; | ||
113 | description = "Service definitions"; | ||
114 | }; | ||
115 | servicegroup = lib.mkOption { | ||
116 | type = attrsOf (attrsOf str); | ||
117 | default = {}; | ||
118 | description = "Service group definitions"; | ||
119 | }; | ||
120 | servicedependency = lib.mkOption { | ||
121 | type = listOf (attrsOf str); | ||
122 | default = []; | ||
123 | description = "Service dependency definitions"; | ||
124 | }; | ||
125 | |||
126 | contact = lib.mkOption { | ||
127 | type = attrsOf (attrsOf str); | ||
128 | default = {}; | ||
129 | description = "Contact definitions"; | ||
130 | }; | ||
131 | contactgroup = lib.mkOption { | ||
132 | type = attrsOf (attrsOf str); | ||
133 | default = {}; | ||
134 | description = "Contact group definitions"; | ||
135 | }; | ||
136 | |||
137 | timeperiod = lib.mkOption { | ||
138 | type = attrsOf (attrsOf str); | ||
139 | default = {}; | ||
140 | description = "Time period definitions"; | ||
141 | }; | ||
142 | |||
143 | templates = lib.mkOption { | ||
144 | description = "Template definitions"; | ||
145 | default = {}; | ||
146 | type = submodule { | ||
147 | options = { | ||
148 | service = lib.mkOption { type = attrsOf (attrsOf (either str int)); default = {}; }; | ||
149 | contact = lib.mkOption { type = attrsOf (attrsOf str); default = {}; }; | ||
150 | host = lib.mkOption { type = attrsOf (attrsOf str); default = {}; }; | ||
151 | }; | ||
152 | }; | ||
153 | }; | ||
154 | }; | ||
155 | }; | ||
156 | in | ||
157 | { | ||
158 | options = { | ||
159 | myServices.monitoring = { | ||
160 | enable = lib.mkOption { | ||
161 | type = lib.types.bool; | ||
162 | default = false; | ||
163 | description = '' | ||
164 | Whether to enable monitoring. | ||
165 | ''; | ||
166 | }; | ||
167 | master = lib.mkOption { | ||
168 | type = lib.types.bool; | ||
169 | default = false; | ||
170 | description = '' | ||
171 | This instance is the master instance | ||
172 | ''; | ||
173 | }; | ||
174 | pluginsArgs = lib.mkOption { | ||
175 | default = {}; | ||
176 | description = "Arguments to pass to the naemon plugin configuration"; | ||
177 | type = lib.types.attrsOf (lib.types.attrsOf lib.types.unspecified); | ||
178 | }; | ||
179 | activatedPlugins = lib.mkOption { | ||
180 | default = []; | ||
181 | description = "List of naemon plugins to activate"; | ||
182 | type = lib.types.listOf (lib.types.enum (builtins.attrNames allPluginsConfig)); | ||
183 | }; | ||
184 | fromMasterActivatedPlugins = lib.mkOption { | ||
185 | default = []; | ||
186 | description = "List of naemon plugins to activate from master"; | ||
187 | type = lib.types.listOf (lib.types.str); | ||
188 | }; | ||
189 | resources = lib.mkOption { | ||
190 | default = {}; | ||
191 | description = "List of additionnal resources elements"; | ||
192 | type = lib.types.attrsOf (lib.types.str); | ||
193 | }; | ||
194 | objects = lib.mkOption { | ||
195 | default = {}; | ||
196 | description = "Object definitions"; | ||
197 | type = objectsModule; | ||
198 | }; | ||
199 | fromMasterObjects = lib.mkOption { | ||
200 | default = {}; | ||
201 | description = "Object definitions of checks that should be executed from master"; | ||
202 | type = objectsModule; | ||
203 | }; | ||
204 | }; | ||
205 | }; | ||
206 | |||
207 | imports = [ | ||
208 | environment.nixosModule | ||
209 | secrets.nixosModule | ||
210 | naemon.nixosModule | ||
211 | ]; | ||
212 | config = lib.mkIf cfg.enable { | ||
213 | myServices.monitoring.objects.command = | ||
214 | lib.foldr (v: o: o // (v.commands or {})) {} (builtins.attrValues mypluginsConfig); | ||
215 | |||
216 | security.sudo.extraRules = let | ||
217 | pluginsSudo = lib.lists.remove null (lib.mapAttrsToList (k: v: | ||
218 | if (v ? sudo) | ||
219 | then ({ users = [ "naemon" ]; } // (v.sudo myplugins)) | ||
220 | else null) mypluginsConfig); | ||
221 | in pluginsSudo; | ||
222 | |||
223 | environment.etc.cnagios.source = "${pkgs.cnagios}/share/doc/cnagios"; | ||
224 | environment.systemPackages = let | ||
225 | nagios-cli = pkgs.writeScriptBin "nagios-cli" '' | ||
226 | #!${pkgs.stdenv.shell} | ||
227 | sudo -u naemon ${pkgs.nagios-cli}/bin/nagios-cli -c ${self.nagios-cli-config} | ||
228 | ''; | ||
229 | in [ | ||
230 | pkgs.cnagios | ||
231 | nagios-cli | ||
232 | ]; | ||
233 | secrets.keys = { | ||
234 | "naemon/id_rsa" = { | ||
235 | user = "naemon"; | ||
236 | group = "naemon"; | ||
237 | permissions = "0400"; | ||
238 | text = config.myEnv.monitoring.ssh_secret_key; | ||
239 | }; | ||
240 | "naemon/resources.cfg".keyDependencies = [ myplugins ]; | ||
241 | }; | ||
242 | services.naemon = { | ||
243 | enable = true; | ||
244 | extraConfig = '' | ||
245 | use_syslog=1 | ||
246 | log_initial_states=1 | ||
247 | date_format=iso8601 | ||
248 | admin_email=${config.myEnv.monitoring.email} | ||
249 | '' + lib.optionalString (!cfg.master) '' | ||
250 | obsess_over_services=1 | ||
251 | ocsp_command=notify-master | ||
252 | ''; | ||
253 | extraResource = let | ||
254 | resources = [cfg.resources or {}] ++ (lib.mapAttrsToList (k: v: v.resources or {}) mypluginsConfig); | ||
255 | joined = lib.zipAttrsWith (n: v: if builtins.length (lib.unique v) == 1 then builtins.head v else abort "Non-unique resources names") resources; | ||
256 | joinedStr = builtins.concatStringsSep "\n" (lib.mapAttrsToList (k: v: "$" + "${k}$=${v}") joined); | ||
257 | in '' | ||
258 | $USER2$=${myplugins} | ||
259 | ${joinedStr} | ||
260 | ''; | ||
261 | objectDefs = | ||
262 | self.lib.toObjects cfg.objects; | ||
263 | }; | ||
264 | }; | ||
265 | }; | ||
266 | }; | ||
267 | } | ||
diff --git a/flakes/private/monitoring/myplugins.nix b/flakes/private/monitoring/myplugins.nix new file mode 100644 index 0000000..35730bb --- /dev/null +++ b/flakes/private/monitoring/myplugins.nix | |||
@@ -0,0 +1,400 @@ | |||
1 | { sudo, pkgs, lib, config }: | ||
2 | let | ||
3 | cfg = config.myServices.monitoring; | ||
4 | in | ||
5 | { | ||
6 | notify-secondary = { | ||
7 | resources = { | ||
8 | USER200 = config.myEnv.monitoring.status_url; | ||
9 | USER201 = config.myEnv.monitoring.status_token; | ||
10 | }; | ||
11 | commands = { | ||
12 | notify-master = "$USER2$/send_nrdp.sh -u \"$USER200$\" -t \"$USER201$\" -H \"$HOSTADDRESS$\" -s \"$SERVICEDESC$\" -S \"$SERVICESTATEID$\" -o \"$SERVICEOUTPUT$ | $SERVICEPERFDATA$\""; | ||
13 | }; | ||
14 | chunk = '' | ||
15 | cp ${./plugins}/send_nrdp.sh $out | ||
16 | patchShebangs $out/send_nrdp.sh | ||
17 | wrapProgram $out/send_nrdp.sh --prefix PATH : ${lib.makeBinPath [ | ||
18 | pkgs.curl pkgs.jq | ||
19 | ]} | ||
20 | ''; | ||
21 | }; | ||
22 | notify-primary = { | ||
23 | resources = { | ||
24 | USER210 = config.myEnv.monitoring.apprise_urls; | ||
25 | }; | ||
26 | commands = { | ||
27 | # $OVE is to force naemon to run via shell instead of execve which fails here | ||
28 | notify-host-by-email = "ADMINEMAIL=\"$ADMINEMAIL$\" SERVICENOTIFICATIONID=\"$SERVICENOTIFICATIONID$\" HOSTSTATE=\"$HOSTSTATE$\" HOSTOUTPUT=\"$HOSTOUTPUT$\" $USER2$/notify_by_email host \"$NOTIFICATIONTYPE$\" \"$HOSTALIAS$\" \"$LONGDATETIME$\" \"$CONTACTEMAIL$\" $OVE"; | ||
29 | # $OVE is to force naemon to run via shell instead of execve which fails here | ||
30 | notify-service-by-email = "ADMINEMAIL=\"$ADMINEMAIL$\" SERVICENOTIFICATIONID=\"$SERVICENOTIFICATIONID$\" SERVICEDESC=\"$SERVICEDESC$\" SERVICESTATE=\"$SERVICESTATE$\" SERVICEOUTPUT=\"$SERVICEOUTPUT$\" $USER2$/notify_by_email service \"$NOTIFICATIONTYPE$\" \"$HOSTALIAS$\" \"$LONGDATETIME$\" \"$CONTACTEMAIL$\" $OVE"; | ||
31 | notify-host-by-apprise = "HOST=\"$HOSTALIAS$\" NOTIFICATIONTYPE=\"$NOTIFICATIONTYPE$\" HOSTSTATE=\"$HOSTSTATE$\" HOSTOUTPUT=\"$HOSTOUTPUT$\" $USER2$/notify_by_apprise host \"$ARG1$\""; | ||
32 | notify-service-by-apprise = "HOST=\"$HOSTALIAS$\" NOTIFICATIONTYPE=\"$NOTIFICATIONTYPE$\" SERVICESTATE=\"$SERVICESTATE$\" SERVICEDESC=\"$SERVICEDESC$\" SERVICEOUTPUT=\"$SERVICEOUTPUT$\" $USER2$/notify_by_apprise service \"$ARG1$\""; | ||
33 | }; | ||
34 | chunk = '' | ||
35 | cp ${./plugins}/{notify_by_email,notify_by_apprise} $out | ||
36 | patchShebangs $out/{notify_by_email,notify_by_apprise} | ||
37 | wrapProgram $out/notify_by_email --prefix PATH : ${lib.makeBinPath [ | ||
38 | pkgs.mailutils | ||
39 | ]} | ||
40 | wrapProgram $out/notify_by_apprise --prefix PATH : ${lib.makeBinPath [ | ||
41 | pkgs.apprise | ||
42 | ]} | ||
43 | ''; | ||
44 | }; | ||
45 | bandwidth = { | ||
46 | commands = { | ||
47 | check_local_bandwidth = "$USER2$/check_bandwidth -i=$ARG1$ -w $ARG2$ -c $ARG3$"; | ||
48 | }; | ||
49 | chunk = '' | ||
50 | cp ${./plugins}/check_bandwidth $out/ | ||
51 | patchShebangs $out/check_bandwidth | ||
52 | wrapProgram $out/check_bandwidth --prefix PATH : ${lib.makeBinPath [ | ||
53 | pkgs.iproute pkgs.bc | ||
54 | ]} | ||
55 | ''; | ||
56 | }; | ||
57 | command = { | ||
58 | commands = { | ||
59 | check_command_match = "$USER2$/check_command -c \"$ARG1$\" -C \"$ARG2$\" $ARG3$"; | ||
60 | check_command_output = "$USER2$/check_command -c \"$ARG1$\" -s 0 -o \"$ARG2$\" $ARG3$"; | ||
61 | check_command_status = "$USER2$/check_command -c \"$ARG1$\" -s \"$ARG2$\" $ARG3$"; | ||
62 | }; | ||
63 | chunk = '' | ||
64 | cp ${./plugins}/check_command $out/ | ||
65 | patchShebangs $out/check_command | ||
66 | wrapProgram $out/check_command --prefix PATH : ${config.security.wrapperDir} | ||
67 | ''; | ||
68 | }; | ||
69 | dns = { | ||
70 | commands = { | ||
71 | check_dns = "$USER1$/check_dns -H $ARG1$ -s $HOSTADDRESS$ $ARG2$"; | ||
72 | check_external_dns = "$USER1$/check_dns -H $ARG2$ -s $ARG1$ $ARG3$"; | ||
73 | }; | ||
74 | }; | ||
75 | mdadm = { | ||
76 | commands = { | ||
77 | check_mdadm = "$USER2$/check_command -c \"${pkgs.mdadm}/bin/mdadm --monitor --scan -1\" -s 0 -o \"^$\" -r root"; | ||
78 | }; | ||
79 | sudo = _: { | ||
80 | commands = [ | ||
81 | { command = "${pkgs.mdadm}/bin/mdadm --monitor --scan -1"; options = [ "NOPASSWD" ]; } | ||
82 | ]; | ||
83 | runAs = "root"; | ||
84 | }; | ||
85 | }; | ||
86 | postfix = { | ||
87 | commands = { | ||
88 | check_mailq = "$USER1$/check_mailq -s -w 1 -c 2"; | ||
89 | }; | ||
90 | sudo = _: { | ||
91 | commands = [ | ||
92 | { command = "${pkgs.postfix}/bin/mailq"; options = [ "NOPASSWD" ]; } | ||
93 | ]; | ||
94 | runAs = "root"; | ||
95 | }; | ||
96 | }; | ||
97 | emails = { | ||
98 | resources = { | ||
99 | USER203 = config.secrets.fullPaths."naemon/id_rsa"; | ||
100 | }; | ||
101 | commands = { | ||
102 | check_emails = "$USER2$/check_emails -H $HOSTADDRESS$ -i $USER203$ -l $ARG1$ -p $ARG2$ -s $ARG3$ -f $ARG4$"; | ||
103 | check_emails_local = "$USER2$/check_emails -H $HOSTADDRESS$ -n $ARG1$ -r $ADMINEMAIL$ -s $ARG2$ -f $ARG3$"; | ||
104 | }; | ||
105 | chunk = let | ||
106 | send_mails = pkgs.runCommand "send_mails" { | ||
107 | buildInputs = [ pkgs.makeWrapper ]; | ||
108 | } '' | ||
109 | mkdir -p $out/bin | ||
110 | cp ${./send_mails} $out/bin/send_mails | ||
111 | patchShebangs $out | ||
112 | wrapProgram $out/bin/send_mails --prefix PATH : ${lib.makeBinPath [ | ||
113 | pkgs.mailutils | ||
114 | ]} | ||
115 | ''; | ||
116 | in '' | ||
117 | cp ${./plugins}/check_emails $out/ | ||
118 | patchShebangs $out/check_emails | ||
119 | wrapProgram $out/check_emails --prefix PATH : ${lib.makeBinPath [ | ||
120 | pkgs.openssh send_mails | ||
121 | ]} --prefix PERL5LIB : ${pkgs.perlPackages.makePerlPath [ | ||
122 | pkgs.perlPackages.TimeDate | ||
123 | ]} | ||
124 | ''; | ||
125 | }; | ||
126 | eriomem = { | ||
127 | resources = { | ||
128 | USER208 = builtins.concatStringsSep "," (map (builtins.concatStringsSep ":") config.myEnv.monitoring.eriomem_keys); | ||
129 | }; | ||
130 | commands = { | ||
131 | check_backup_eriomem = "$USER2$/check_eriomem $USER208$"; | ||
132 | check_backup_eriomem_age = "$USER2$/check_backup_eriomem_age $ARG1$"; | ||
133 | }; | ||
134 | chunk = '' | ||
135 | cp ${./plugins}/check_eriomem $out/ | ||
136 | patchShebangs $out/check_eriomem | ||
137 | wrapProgram $out/check_eriomem --prefix PATH : ${lib.makeBinPath [ | ||
138 | pkgs.s3cmd pkgs.python38 | ||
139 | ]} | ||
140 | cp ${./plugins}/check_backup_age $out/check_backup_eriomem_age | ||
141 | patchShebangs $out/check_backup_eriomem_age | ||
142 | wrapProgram $out/check_backup_eriomem_age --prefix PATH : ${lib.makeBinPath [ | ||
143 | pkgs.duplicity | ||
144 | ]} --set SECRETS_PATH ${lib.optionalString cfg.master config.secrets.fullPaths."eriomem_access_key"} | ||
145 | ''; | ||
146 | }; | ||
147 | file_date = { | ||
148 | commands = { | ||
149 | check_last_file_date = "${sudo} -u \"$ARG3$\" $USER2$/check_last_file_date \"$ARG1$\" \"$ARG2$\""; | ||
150 | }; | ||
151 | chunk = '' | ||
152 | cp ${./plugins}/check_last_file_date $out/ | ||
153 | patchShebangs $out/check_last_file_date | ||
154 | ''; | ||
155 | sudo = myplugins: { | ||
156 | commands = [ | ||
157 | { command = "${myplugins}/check_last_file_date /backup2/*"; options = [ "NOPASSWD" ]; } | ||
158 | ]; | ||
159 | runAs = "ALL"; | ||
160 | }; | ||
161 | }; | ||
162 | ftp = { | ||
163 | commands = { | ||
164 | check_ftp_database = "$USER2$/check_ftp_database"; | ||
165 | }; | ||
166 | chunk = '' | ||
167 | cp ${./plugins}/check_ftp_database $out/ | ||
168 | patchShebangs $out/check_ftp_database | ||
169 | wrapProgram $out/check_ftp_database --prefix PATH : ${lib.makeBinPath [ | ||
170 | pkgs.lftp | ||
171 | ]} | ||
172 | ''; | ||
173 | }; | ||
174 | git = { | ||
175 | resources = { | ||
176 | USER203 = config.secrets.fullPaths."naemon/id_rsa"; | ||
177 | }; | ||
178 | commands = { | ||
179 | check_git = "$USER2$/check_git $USER203$"; | ||
180 | }; | ||
181 | chunk = '' | ||
182 | cp ${./plugins}/check_git $out/ | ||
183 | patchShebangs $out/check_git | ||
184 | wrapProgram $out/check_git --prefix PATH : ${lib.makeBinPath [ | ||
185 | pkgs.git pkgs.openssh | ||
186 | ]} | ||
187 | ''; | ||
188 | }; | ||
189 | http = { | ||
190 | resources = { | ||
191 | USER202 = config.myEnv.monitoring.http_user_password; | ||
192 | }; | ||
193 | commands = { | ||
194 | check_http = "$USER1$/check_http --sni -f stickyport -H \"$ARG1$\" -u \"$ARG2$\" -r \"$ARG3$\""; | ||
195 | check_https = "$USER1$/check_http --sni --ssl -f stickyport -H \"$ARG1$\" -u \"$ARG2$\" -r \"$ARG3$\""; | ||
196 | check_https_4 = "$USER1$/check_http -4 --sni --ssl -f stickyport -H \"$ARG1$\" -u \"$ARG2$\" -r \"$ARG3$\""; | ||
197 | check_https_6 = "$USER1$/check_http -6 --sni --ssl -f stickyport -H \"$ARG1$\" -u \"$ARG2$\" -r \"$ARG3$\""; | ||
198 | check_https_auth = "$USER1$/check_http --sni --ssl -a \"$USER202$\" -f stickyport -H \"$ARG1$\" -u \"$ARG2$\" -r \"$ARG3$\""; | ||
199 | check_https_certificate = "$USER1$/check_http --sni --ssl -H \"$ARG1$\" -C 21,15"; | ||
200 | check_https_code = "$USER1$/check_http --sni --ssl -f stickyport -H \"$ARG1$\" -u \"$ARG2$\" -e \"$ARG3$\" -r \"$ARG4$\""; | ||
201 | }; | ||
202 | }; | ||
203 | imap = { | ||
204 | resources = { | ||
205 | USER204 = config.myEnv.monitoring.imap_login; | ||
206 | USER205 = config.myEnv.monitoring.imap_password; | ||
207 | }; | ||
208 | commands = { | ||
209 | check_imap_connection = "$USER2$/check_imap_connection -u \"$USER204$\" -p \"$USER205$\" -H \"imap.immae.eu:143\""; | ||
210 | }; | ||
211 | chunk = '' | ||
212 | cp ${./plugins}/check_imap_connection $out/ | ||
213 | patchShebangs $out/check_imap_connection | ||
214 | wrapProgram $out/check_imap_connection --prefix PATH : ${lib.makeBinPath [ | ||
215 | pkgs.openssl | ||
216 | ]} | ||
217 | ''; | ||
218 | }; | ||
219 | megaraid = let | ||
220 | megacli = pkgs.megacli.overrideAttrs(old: { meta = old.meta // { license = null; }; }); | ||
221 | in { | ||
222 | commands = { | ||
223 | check_megaraid = "$USER2$/check_megaraid_sas --sudo"; | ||
224 | }; | ||
225 | chunk = let | ||
226 | megaCliPlugin = pkgs.runCommand "megaCliPlugin" { | ||
227 | plugin = pkgs.fetchurl { | ||
228 | name = "check_megaraid_sas"; | ||
229 | url = "https://exchange.nagios.org/components/com_mtree/attachment.php?link_id=6381&cf_id=24"; | ||
230 | sha256 = "0yf60p4c0hb4q3fng9fc14qc89bqm0f1sijayzygadaqcl44jx4p"; | ||
231 | }; | ||
232 | } '' | ||
233 | mkdir $out | ||
234 | cp $plugin $out/check_megaraid_sas | ||
235 | chmod +x $out/check_megaraid_sas | ||
236 | patchShebangs $out | ||
237 | substituteInPlace $out/check_megaraid_sas --replace /usr/sbin/MegaCli ${megacli}/bin/MegaCli64 | ||
238 | substituteInPlace $out/check_megaraid_sas --replace 'sudo $megacli' '${sudo} $megacli' | ||
239 | sed -i -e "s/use utils qw(%ERRORS);/my %ERRORS = ('OK' => 0, 'WARNING' => 1, 'CRITICAL' => 2, 'UNKNOWN' => 3);/" $out/check_megaraid_sas | ||
240 | ''; | ||
241 | in '' | ||
242 | cp ${megaCliPlugin}/check_megaraid_sas $out/ | ||
243 | patchShebangs $out/check_megaraid_sas | ||
244 | ''; | ||
245 | sudo = _: { | ||
246 | commands = [ | ||
247 | { command = "${megacli}/bin/MegaCli64"; options = [ "NOPASSWD" ]; } | ||
248 | ]; | ||
249 | runAs = "root"; | ||
250 | }; | ||
251 | }; | ||
252 | memory = { | ||
253 | commands = { | ||
254 | check_memory = "$USER2$/check_mem.sh -w $ARG1$ -c $ARG2$"; | ||
255 | }; | ||
256 | chunk = '' | ||
257 | cp ${./plugins}/check_mem.sh $out/ | ||
258 | patchShebangs $out/check_mem.sh | ||
259 | wrapProgram $out/check_mem.sh --prefix PATH : ${lib.makeBinPath [ | ||
260 | pkgs.gnugrep pkgs.gawk pkgs.procps | ||
261 | ]} | ||
262 | ''; | ||
263 | }; | ||
264 | mysql = { | ||
265 | commands = { | ||
266 | check_mysql_replication = "${sudo} -u mysql $USER2$/check_mysql_replication \"$ARG1$\" \"$ARG2$\""; | ||
267 | }; | ||
268 | chunk = '' | ||
269 | cp ${./plugins}/check_mysql_replication $out/ | ||
270 | patchShebangs $out/check_mysql_replication | ||
271 | wrapProgram $out/check_mysql_replication --prefix PATH : ${lib.makeBinPath [ | ||
272 | pkgs.gnugrep pkgs.gnused pkgs.coreutils pkgs.mariadb | ||
273 | ]} | ||
274 | ''; | ||
275 | sudo = myplugins: { | ||
276 | commands = [ | ||
277 | { command = "${myplugins}/check_mysql_replication *"; options = [ "NOPASSWD" ]; } | ||
278 | ]; | ||
279 | runAs = "mysql"; | ||
280 | }; | ||
281 | }; | ||
282 | openldap = { | ||
283 | commands = { | ||
284 | check_openldap_replication = "${sudo} -u openldap $USER2$/check_openldap_replication \"$ARG1$\" \"$ARG2$\" \"$ARG3$\" \"$ARG4$\" \"$ARG5$\""; | ||
285 | }; | ||
286 | chunk = '' | ||
287 | cp ${./plugins}/check_openldap_replication $out/ | ||
288 | patchShebangs $out/check_openldap_replication | ||
289 | wrapProgram $out/check_openldap_replication --prefix PATH : ${lib.makeBinPath [ | ||
290 | pkgs.gnugrep pkgs.gnused pkgs.coreutils pkgs.openldap | ||
291 | ]} | ||
292 | ''; | ||
293 | sudo = myplugins: { | ||
294 | commands = [ | ||
295 | { command = "${myplugins}/check_openldap_replication *"; options = [ "NOPASSWD" ]; } | ||
296 | ]; | ||
297 | runAs = "openldap"; | ||
298 | }; | ||
299 | }; | ||
300 | ovh = { | ||
301 | resources = { | ||
302 | USER209 = builtins.concatStringsSep "," [ | ||
303 | config.myEnv.monitoring.ovh_sms.endpoint | ||
304 | config.myEnv.monitoring.ovh_sms.application_key | ||
305 | config.myEnv.monitoring.ovh_sms.application_secret | ||
306 | config.myEnv.monitoring.ovh_sms.consumer_key | ||
307 | config.myEnv.monitoring.ovh_sms.account | ||
308 | ]; | ||
309 | }; | ||
310 | commands = { | ||
311 | check_backup_ovh_age = "$USER2$/check_backup_ovh_age $ARG1$"; | ||
312 | check_ovh_sms = "$USER2$/check_ovh_sms \"$USER209$\""; | ||
313 | }; | ||
314 | chunk = '' | ||
315 | cp ${./plugins}/check_backup_age $out/check_backup_ovh_age | ||
316 | patchShebangs $out/check_backup_ovh_age | ||
317 | wrapProgram $out/check_backup_ovh_age --prefix PATH : ${lib.makeBinPath [ | ||
318 | pkgs.duplicity | ||
319 | ]} --set SECRETS_PATH ${lib.optionalString cfg.master config.secrets.fullPaths."ovh_access_key"} | ||
320 | cp ${./plugins}/check_ovh_sms $out/ | ||
321 | patchShebangs $out/check_ovh_sms | ||
322 | wrapProgram $out/check_ovh_sms --prefix PATH : ${lib.makeBinPath [ | ||
323 | (pkgs.python38.withPackages (ps: [ps.ovh])) | ||
324 | ]} | ||
325 | ''; | ||
326 | }; | ||
327 | postgresql = { package }: { | ||
328 | commands = { | ||
329 | check_postgresql_replication = "${sudo} -u postgres $USER2$/check_postgres_replication \"$ARG1$\" \"$ARG2$\" \"$ARG3$\""; | ||
330 | check_postgresql_database_count = "$USER2$/check_postgres_database_count \"$ARG1$\" \"$ARG2$\" \"$ARG3$\""; | ||
331 | }; | ||
332 | chunk = '' | ||
333 | cp ${./plugins}/check_postgres_replication $out/ | ||
334 | patchShebangs $out/check_postgres_replication | ||
335 | wrapProgram $out/check_postgres_replication --prefix PATH : ${lib.makeBinPath [ | ||
336 | package | ||
337 | ]} | ||
338 | cp ${./plugins}/check_postgres_database_count $out/ | ||
339 | patchShebangs $out/check_postgres_database_count | ||
340 | wrapProgram $out/check_postgres_database_count --prefix PATH : ${lib.makeBinPath [ | ||
341 | package | ||
342 | ]} | ||
343 | ''; | ||
344 | |||
345 | sudo = myplugins: { | ||
346 | commands = [ | ||
347 | { command = "${myplugins}/check_postgres_replication *"; options = [ "NOPASSWD" ]; } | ||
348 | ]; | ||
349 | runAs = "postgres"; | ||
350 | }; | ||
351 | }; | ||
352 | redis = { | ||
353 | commands = { | ||
354 | check_redis_replication = "${sudo} -u redis $USER2$/check_redis_replication \"$ARG1$\""; | ||
355 | }; | ||
356 | chunk = '' | ||
357 | cp ${./plugins}/check_redis_replication $out/ | ||
358 | patchShebangs $out/check_redis_replication | ||
359 | wrapProgram $out/check_redis_replication --prefix PATH : ${lib.makeBinPath [ | ||
360 | pkgs.gnugrep pkgs.coreutils pkgs.redis | ||
361 | ]} | ||
362 | ''; | ||
363 | sudo = myplugins: { | ||
364 | commands = [ | ||
365 | { command = "${myplugins}/check_redis_replication *"; options = [ "NOPASSWD" ]; } | ||
366 | ]; | ||
367 | runAs = "redis"; | ||
368 | }; | ||
369 | }; | ||
370 | tcp = { | ||
371 | commands = { | ||
372 | check_tcp = "$USER1$/check_tcp -H $HOSTADDRESS$ -p $ARG1$ -e \"$ARG2$\" -Mcrit"; | ||
373 | check_tcp_ssl = "$USER1$/check_tcp -H $HOSTADDRESS$ -p $ARG1$ -S -D 21,15"; | ||
374 | }; | ||
375 | }; | ||
376 | zfs = { | ||
377 | commands = { | ||
378 | check_zfs = "$USER2$/check_zpool.sh -p ALL -w 80 -c 90"; | ||
379 | check_zfs_snapshot = "$USER2$/check_zfs_snapshot -d $ARG1$ -c 18000 -w 14400"; | ||
380 | }; | ||
381 | chunk = let | ||
382 | zfsPlugin = pkgs.fetchurl { | ||
383 | url = "https://www.claudiokuenzler.com/monitoring-plugins/check_zpools.sh"; | ||
384 | sha256 = "0p9ms9340in80jkds4kfspw62xnzsv5s7ni9m28kxyd0bnzkbzhf"; | ||
385 | }; | ||
386 | in '' | ||
387 | cp ${zfsPlugin} $out/check_zpool.sh | ||
388 | chmod +x $out/check_zpool.sh | ||
389 | patchShebangs $out/check_zpool.sh | ||
390 | wrapProgram $out/check_zpool.sh --prefix PATH : ${lib.makeBinPath [ | ||
391 | pkgs.which pkgs.zfs pkgs.gawk | ||
392 | ]} | ||
393 | cp ${./plugins}/check_zfs_snapshot $out | ||
394 | patchShebangs $out/check_zfs_snapshot | ||
395 | wrapProgram $out/check_zfs_snapshot --prefix PATH : ${lib.makeBinPath [ | ||
396 | pkgs.zfs pkgs.coreutils pkgs.gawk pkgs.gnugrep | ||
397 | ]} | ||
398 | ''; | ||
399 | }; | ||
400 | } | ||
diff --git a/flakes/private/monitoring/nagios-cli.cfg b/flakes/private/monitoring/nagios-cli.cfg new file mode 100644 index 0000000..7bd30cb --- /dev/null +++ b/flakes/private/monitoring/nagios-cli.cfg | |||
@@ -0,0 +1,68 @@ | |||
1 | # -*- coding: utf-8; -*- | ||
2 | |||
3 | [cli] | ||
4 | history = /var/lib/naemon/nagios_cli_history | ||
5 | |||
6 | [ui] | ||
7 | color = 1 | ||
8 | prompt = naemon %s> | ||
9 | prompt_separator = " → " | ||
10 | |||
11 | [nagios] | ||
12 | log = /var/log/naemon | ||
13 | command_file = /run/naemon/naemon.cmd | ||
14 | log_file = %(log)s/naemon.log | ||
15 | object_cache_file = /var/lib/naemon/objects.cache | ||
16 | status_file = /var/lib/naemon/status.dat | ||
17 | |||
18 | [object] | ||
19 | host.status = | ||
20 | host_name | ||
21 | current_state | ||
22 | plugin_output | ||
23 | is_flapping | ||
24 | last_check | ||
25 | last_time_down | ||
26 | last_state_change | ||
27 | check_period | ||
28 | notification_period | ||
29 | current_attempt | ||
30 | max_attempts | ||
31 | service.status = | ||
32 | host_name | ||
33 | service_description | ||
34 | current_state | ||
35 | is_flapping | ||
36 | plugin_output | ||
37 | last_time_down | ||
38 | last_state_change | ||
39 | last_check | ||
40 | next_check | ||
41 | check_interval | ||
42 | check_latency | ||
43 | check_period | ||
44 | notification_period | ||
45 | current_attempt | ||
46 | max_attempts | ||
47 | |||
48 | [string] | ||
49 | level.ok = ↑ OK | ||
50 | level.warning = ! WARNING | ||
51 | level.critical = ↓ CRITICAL | ||
52 | level.unknown = ↕ UNKNOWN | ||
53 | |||
54 | [color] | ||
55 | error = bold_red | ||
56 | |||
57 | prompt = normal | ||
58 | prompt.object = bold | ||
59 | |||
60 | host.host_name = bold | ||
61 | host.plugin_output = bold | ||
62 | service.plugin_output = bold | ||
63 | |||
64 | level.ok = bold_green | ||
65 | level.warning = bold_yellow | ||
66 | level.critical = bold_red | ||
67 | level.unknown = bold_magenta | ||
68 | |||
diff --git a/flakes/private/monitoring/objects_common.nix b/flakes/private/monitoring/objects_common.nix new file mode 100644 index 0000000..1da7764 --- /dev/null +++ b/flakes/private/monitoring/objects_common.nix | |||
@@ -0,0 +1,227 @@ | |||
1 | { hostFQDN | ||
2 | , hostName | ||
3 | , interface ? "eth0" | ||
4 | , processWarn ? "250" | ||
5 | , processAlert ? "400" | ||
6 | , loadWarn ? "0.9" | ||
7 | , load5Warn ? loadWarn | ||
8 | , load15Warn ? load5Warn | ||
9 | , loadAlert ? "1.0" | ||
10 | , load5Alert ? loadAlert | ||
11 | , load15Alert ? load5Alert | ||
12 | , master | ||
13 | , ... | ||
14 | }: | ||
15 | { | ||
16 | host = { | ||
17 | "${hostFQDN}" = { | ||
18 | alias = hostFQDN; | ||
19 | address = hostFQDN; | ||
20 | use = "linux-server"; | ||
21 | hostgroups = "webstatus-hosts"; | ||
22 | _webstatus_name = hostName; | ||
23 | _webstatus_vhost = "status.immae.eu"; | ||
24 | }; | ||
25 | }; | ||
26 | service = [ | ||
27 | { | ||
28 | service_description = "Size on root partition"; | ||
29 | use = "local-service"; | ||
30 | check_command = ["check_local_disk" "20%" "10%" "/"]; | ||
31 | __passive_servicegroups = "webstatus-resources"; | ||
32 | } | ||
33 | { | ||
34 | service_description = "Total number of process"; | ||
35 | use = "local-service"; | ||
36 | check_command = [ | ||
37 | "check_local_procs" | ||
38 | processWarn | ||
39 | processAlert | ||
40 | "RSZDT" | ||
41 | ]; | ||
42 | __passive_servicegroups = "webstatus-resources"; | ||
43 | } | ||
44 | { | ||
45 | service_description = "Network bandwidth"; | ||
46 | use = "local-service"; | ||
47 | check_interval = 2; | ||
48 | max_check_attempts = "20"; | ||
49 | retry_interval = "2"; | ||
50 | check_command = [ | ||
51 | "check_local_bandwidth" | ||
52 | interface | ||
53 | "20480" # kb/s | ||
54 | "51200" # kb/s | ||
55 | ]; | ||
56 | __passive_servicegroups = "webstatus-resources"; | ||
57 | } | ||
58 | { | ||
59 | service_description = "Average load"; | ||
60 | use = "local-service"; | ||
61 | check_command = [ | ||
62 | "check_local_load" | ||
63 | "${loadWarn},${load5Warn},${load15Warn}" | ||
64 | "${loadAlert},${load5Alert},${load15Alert}" | ||
65 | ]; | ||
66 | __passive_servicegroups = "webstatus-resources"; | ||
67 | } | ||
68 | { | ||
69 | service_description = "Swap usage"; | ||
70 | use = "local-service"; | ||
71 | check_command = ["check_local_swap" "20" "10"]; | ||
72 | __passive_servicegroups = "webstatus-resources"; | ||
73 | } | ||
74 | { | ||
75 | service_description = "Memory usage"; | ||
76 | use = "local-service"; | ||
77 | check_command = ["check_memory" "80" "90"]; | ||
78 | __passive_servicegroups = "webstatus-resources"; | ||
79 | } | ||
80 | { | ||
81 | service_description = "NTP is activated and working"; | ||
82 | use = "local-service"; | ||
83 | check_command = ["check_ntp"]; | ||
84 | __passive_servicegroups = "webstatus-resources"; | ||
85 | } | ||
86 | ]; | ||
87 | command = { | ||
88 | check_local_disk = "$USER1$/check_disk -w $ARG1$ -c $ARG2$ -p $ARG3$"; | ||
89 | check_local_procs = "$USER1$/check_procs -w $ARG1$ -c $ARG2$ -s $ARG3$"; | ||
90 | check_local_load = "$USER1$/check_load -r -w $ARG1$ -c $ARG2$"; | ||
91 | check_local_swap = "$USER1$/check_swap -n ok -w $ARG1$ -c $ARG2$"; | ||
92 | check_ntp = "$USER1$/check_ntp_time -t 30 -q -H 0.arch.pool.ntp.org"; | ||
93 | check_smtp = "$USER1$/check_smtp -H $HOSTADDRESS$ -p 25 -S -D 21,15"; | ||
94 | |||
95 | check_host_alive = "$USER1$/check_ping -H $HOSTADDRESS$ -w 3000.0,80% -c 5000.0,100% -p 5"; | ||
96 | check_ok = "$USER1$/check_dummy 0 \"Dummy OK\""; | ||
97 | check_critical = "$USER1$/check_dummy 2 \"Dummy CRITICAL\""; | ||
98 | }; | ||
99 | timeperiod = { | ||
100 | "24x7" = { | ||
101 | alias = "24 Hours A Day, 7 Days A Week"; | ||
102 | monday = "00:00-24:00"; | ||
103 | tuesday = "00:00-24:00"; | ||
104 | wednesday = "00:00-24:00"; | ||
105 | thursday = "00:00-24:00"; | ||
106 | friday = "00:00-24:00"; | ||
107 | saturday = "00:00-24:00"; | ||
108 | sunday = "00:00-24:00"; | ||
109 | }; | ||
110 | }; | ||
111 | servicegroup = { | ||
112 | webstatus-webapps = { alias = "Web applications"; }; | ||
113 | webstatus-websites = { alias = "Personal websites"; }; | ||
114 | webstatus-ssl = { alias = "SSL certificates"; }; | ||
115 | webstatus-dns = { alias = "DNS resolution"; }; | ||
116 | webstatus-remote-services = { alias = "Other remote services"; }; | ||
117 | webstatus-local-services = { alias = "Other local services"; }; | ||
118 | webstatus-email = { alias = "E-mail services"; }; | ||
119 | webstatus-resources = { alias = "Local resources"; }; | ||
120 | webstatus-databases = { alias = "Databases resources"; }; | ||
121 | webstatus-backup = { alias = "Backup resources"; }; | ||
122 | }; | ||
123 | hostgroup = { | ||
124 | webstatus-hosts = { alias = "Hosts"; }; | ||
125 | }; | ||
126 | contactgroup = { | ||
127 | admins = { alias = "Naemon Administrators"; }; | ||
128 | }; | ||
129 | templates = { | ||
130 | service = { | ||
131 | generic-service = { | ||
132 | active_checks_enabled = "1"; | ||
133 | check_freshness = "0"; | ||
134 | check_interval = 10; | ||
135 | check_period = "24x7"; | ||
136 | contact_groups = "admins"; | ||
137 | event_handler_enabled = "1"; | ||
138 | flap_detection_enabled = "1"; | ||
139 | is_volatile = "0"; | ||
140 | max_check_attempts = "3"; | ||
141 | notification_interval = "60"; | ||
142 | notification_options = "w,u,c,r,f,s"; | ||
143 | notification_period = "24x7"; | ||
144 | notifications_enabled = if master then "1" else "0"; | ||
145 | obsess_over_service = "1"; | ||
146 | passive_checks_enabled = "1"; | ||
147 | process_perf_data = "1"; | ||
148 | retain_nonstatus_information = "1"; | ||
149 | retain_status_information = "1"; | ||
150 | retry_interval = "2"; | ||
151 | _webstatus_namespace = "immae"; | ||
152 | }; | ||
153 | local-service = { | ||
154 | use = "generic-service"; | ||
155 | host_name = hostFQDN; | ||
156 | check_interval = 5; | ||
157 | max_check_attempts = "4"; | ||
158 | retry_interval = "1"; | ||
159 | servicegroups = "webstatus-resources"; | ||
160 | }; | ||
161 | external-service = { | ||
162 | use = "generic-service"; | ||
163 | check_interval = 5; | ||
164 | max_check_attempts = "4"; | ||
165 | retry_interval = "1"; | ||
166 | }; | ||
167 | web-service = { | ||
168 | use = "generic-service"; | ||
169 | check_interval = 20; | ||
170 | max_check_attempts = "2"; | ||
171 | retry_interval = "1"; | ||
172 | }; | ||
173 | external-web-service = { | ||
174 | use = "generic-service"; | ||
175 | check_interval = 20; | ||
176 | max_check_attempts = "2"; | ||
177 | retry_interval = "1"; | ||
178 | }; | ||
179 | mail-service = { | ||
180 | use = "generic-service"; | ||
181 | check_interval = 15; | ||
182 | max_check_attempts = "1"; | ||
183 | retry_interval = "1"; | ||
184 | }; | ||
185 | dns-service = { | ||
186 | use = "generic-service"; | ||
187 | check_interval = 120; | ||
188 | notification_interval = "120"; | ||
189 | max_check_attempts = "5"; | ||
190 | retry_interval = "5"; | ||
191 | }; | ||
192 | }; | ||
193 | # No contact, we go through master | ||
194 | contact = { | ||
195 | generic-contact = { | ||
196 | host_notification_commands = "notify-host-by-email"; | ||
197 | host_notification_options = "d,u,r,f,s"; | ||
198 | host_notification_period = "24x7"; | ||
199 | service_notification_commands = "notify-service-by-email"; | ||
200 | service_notification_options = "w,u,c,r,f,s"; | ||
201 | service_notification_period = "24x7"; | ||
202 | }; | ||
203 | }; | ||
204 | host = { | ||
205 | generic-host = { | ||
206 | event_handler_enabled = "1"; | ||
207 | flap_detection_enabled = "1"; | ||
208 | notification_period = "24x7"; | ||
209 | notifications_enabled = "1"; | ||
210 | process_perf_data = "1"; | ||
211 | retain_nonstatus_information = "1"; | ||
212 | retain_status_information = "1"; | ||
213 | }; | ||
214 | linux-server = { | ||
215 | check_command = "check_host_alive"; | ||
216 | check_interval = "5"; | ||
217 | check_period = "24x7"; | ||
218 | contact_groups = "admins"; | ||
219 | max_check_attempts = "10"; | ||
220 | notification_interval = "120"; | ||
221 | notification_options = "d,u,r,f"; | ||
222 | retry_interval = "1"; | ||
223 | _webstatus_namespace = "immae"; | ||
224 | }; | ||
225 | }; | ||
226 | }; | ||
227 | } | ||
diff --git a/flakes/private/monitoring/plugins/check_backup_age b/flakes/private/monitoring/plugins/check_backup_age new file mode 100755 index 0000000..d873bdc --- /dev/null +++ b/flakes/private/monitoring/plugins/check_backup_age | |||
@@ -0,0 +1,66 @@ | |||
1 | #!/usr/bin/env bash | ||
2 | |||
3 | set -euo pipefail | ||
4 | |||
5 | source $SECRETS_PATH | ||
6 | export HOME=$(mktemp -d) | ||
7 | |||
8 | trap "rm -rf $HOME" EXIT | ||
9 | folder=$1 | ||
10 | |||
11 | parse_date() { | ||
12 | d=$1 | ||
13 | echo $d | sed -e "s/^\(....\)\(..\)\(..\)T\(..\)\(..\)\(..\)/\1-\2-\3T\4:\5:\6/" | ||
14 | } | ||
15 | |||
16 | output=$(duplicity collection-status --log-fd 2 "$BASE_URL$folder" 2>&1 > /dev/null) | ||
17 | |||
18 | output=$(echo "$output" | grep -v "^\.") | ||
19 | |||
20 | last_full=$(parse_date "$(echo "$output" | grep "^ full " | cut -d' ' -f3 | sort | tail -n1)") | ||
21 | last_bkp=$(parse_date "$(echo "$output" | grep -E "^ (full|inc) " | cut -d' ' -f3 | sort | tail -n1)") | ||
22 | orphaned_sets=$(echo "$output" | grep "^orphaned-sets-num" | cut -d' ' -f2) | ||
23 | incomplete_sets=$(echo "$output" | grep "^incomplete-sets-num" | cut -d' ' -f2) | ||
24 | |||
25 | if [[ -z "$last_full" || -z "$last_bkp" || -z "$orphaned_sets" || -z "$incomplete_sets" ]]; then | ||
26 | echo "duply-backup $folder UNKNOWN - impossible to parse result" | ||
27 | exit 3 | ||
28 | fi | ||
29 | |||
30 | last_full_age=$(( ($(date "+%s") - $(date -d "$last_full" "+%s")) / (60*60*24) )) | ||
31 | last_bkp_age=$(( ($(date "+%s") - $(date -d "$last_bkp" "+%s")) / (60*60) )) | ||
32 | |||
33 | PERFS="orphan=$orphaned_sets;1;;0; incomplete=$incomplete_sets;1;;0; age=${last_bkp_age}h;30;48;0; full_age=${last_full_age}d;35;45;0;" | ||
34 | |||
35 | |||
36 | WARNINGS="" | ||
37 | ERRORS="" | ||
38 | if [[ "$incomplete_sets" -gt 0 ]]; then | ||
39 | WARNINGS="$WARNINGS - Incomplete sets is $incomplete_sets" | ||
40 | fi | ||
41 | |||
42 | if [[ "$orphaned_sets" -gt 0 ]]; then | ||
43 | WARNINGS="$WARNINGS - Orphaned sets is $orphaned_sets" | ||
44 | fi | ||
45 | |||
46 | if [[ "$last_full_age" -gt 45 ]]; then | ||
47 | ERRORS="$ERRORS - Last full backup is too old $last_full" | ||
48 | elif [[ "$last_full_age" -gt 35 ]]; then | ||
49 | WARNINGS="$WARNINGS - Last full backup is getting old $last_full" | ||
50 | fi | ||
51 | |||
52 | if [[ "$last_bkp_age" -gt 48 ]]; then | ||
53 | ERRORS="$ERRORS - Last backup is too old $last_bkp" | ||
54 | elif [[ "$last_bkp_age" -gt 30 ]]; then | ||
55 | WARNINGS="$WARNINGS - Last backup is getting old $last_bkp" | ||
56 | fi | ||
57 | |||
58 | if [[ -n "$ERRORS" ]]; then | ||
59 | echo "duply-backup $folder CRITICAL$ERRORS$WARNINGS | $PERFS" | ||
60 | exit 2 | ||
61 | elif [[ -n "$WARNINGS" ]]; then | ||
62 | echo "duply-backup $folder WARNING$WARNINGS | $PERFS" | ||
63 | exit 1 | ||
64 | else | ||
65 | echo "duply-backup $folder OK | $PERFS" | ||
66 | fi | ||
diff --git a/flakes/private/monitoring/plugins/check_bandwidth b/flakes/private/monitoring/plugins/check_bandwidth new file mode 100755 index 0000000..21d01f5 --- /dev/null +++ b/flakes/private/monitoring/plugins/check_bandwidth | |||
@@ -0,0 +1,122 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | # ============================== SUMMARY ===================================== | ||
4 | #Author : Ken Roulamellah | ||
5 | #Date : 19/07/2018 | ||
6 | #Version : 1.0 | ||
7 | # Licence : GPL | ||
8 | # ===================== INFORMATION ABOUT THIS PLUGIN ======================== | ||
9 | # | ||
10 | # This plugin checks the average RX and TX bandwidth utilisation. It use | ||
11 | # kbytes as measure unite. | ||
12 | # | ||
13 | # ========================== START OF PROGRAM CODE =========================== | ||
14 | |||
15 | STATE_OK=0 | ||
16 | STATE_WARNING=1 | ||
17 | STATE_CRITICAL=2 | ||
18 | STATE_UNKNOWN=3 | ||
19 | |||
20 | interface=$( ip route | grep default | awk '{print $5}' | head -n1) | ||
21 | function print_usage() | ||
22 | { | ||
23 | echo "Usage :" | ||
24 | echo "$0 [ -i=INTERFACE] [ -ct=COUNT ] -w WARNING -c CRITICAL" | ||
25 | echo "This script calculate the average bandwith usage." | ||
26 | echo "Default values | interface: ${interface}, counter: 10" | ||
27 | } | ||
28 | |||
29 | counter=10 | ||
30 | warning=-1 | ||
31 | critical=-1 | ||
32 | |||
33 | sum_rx=0 | ||
34 | sum_tx=0 | ||
35 | avg_rx= | ||
36 | avg_tx= | ||
37 | i= | ||
38 | |||
39 | |||
40 | if [[ $# -lt 4 ]]; | ||
41 | then | ||
42 | echo "Error: Arguments are missing" | ||
43 | print_usage | ||
44 | exit $STATE_UNKNOWN | ||
45 | fi | ||
46 | |||
47 | while [[ $# -gt 0 ]]; do | ||
48 | case "$1" in | ||
49 | -i=*) | ||
50 | interface="$(cut -d'=' -f2 <<<"$1")" | ||
51 | shift | ||
52 | ;; | ||
53 | -ct=*) | ||
54 | counter="$(cut -d'=' -f2 <<<"$1")" | ||
55 | shift | ||
56 | ;; | ||
57 | -w) | ||
58 | warning=$2 | ||
59 | shift 2 | ||
60 | ;; | ||
61 | -c) | ||
62 | critical=$2 | ||
63 | shift 2 | ||
64 | ;; | ||
65 | *) | ||
66 | printf "\nError: Invalid option '$1'" | ||
67 | print_usage | ||
68 | exit $STATE_UNKNOWN | ||
69 | ;; | ||
70 | esac | ||
71 | done | ||
72 | |||
73 | if [ $warning -lt 0 ] || [ $critical -lt 0 ]; | ||
74 | then | ||
75 | echo "Error: You need to specify a warning and critical treshold" | ||
76 | print_usage | ||
77 | exit $STATE_UNKNOWN | ||
78 | fi | ||
79 | |||
80 | grep -q "up" /sys/class/net/$interface/operstate || exec echo "$interface: no such device or down" | ||
81 | |||
82 | read rx <"/sys/class/net/$interface/statistics/rx_bytes" | ||
83 | read tx <"/sys/class/net/$interface/statistics/tx_bytes" | ||
84 | |||
85 | i=$counter | ||
86 | while [ $i -gt 0 ]; do | ||
87 | sleep 1 | ||
88 | read newrx <"/sys/class/net/$interface/statistics/rx_bytes" | ||
89 | read newtx <"/sys/class/net/$interface/statistics/tx_bytes" | ||
90 | |||
91 | #echo "old rx :$rx" | ||
92 | #echo "new rx :$newrx" | ||
93 | rx_cal=$(bc <<< "scale=2; ($newrx-$rx) / 1000") | ||
94 | tx_cal=$(bc <<< "scale=2; ($newtx-$tx) / 1000") | ||
95 | |||
96 | sum_rx=$(bc <<< "scale=2;$sum_rx+$rx_cal") | ||
97 | sum_tx=$(bc <<< "scale=2;$sum_tx+$tx_cal") | ||
98 | |||
99 | #echo "$interface {rx: $rx_cal ko/s, tx: $tx_cal ko/s}" | ||
100 | rx=$newrx | ||
101 | tx=$newtx | ||
102 | ((i --)) | ||
103 | done | ||
104 | |||
105 | avg_rx=$(bc <<< "scale=2;$sum_rx/$counter") | ||
106 | avg_tx=$(bc <<< "scale=2;$sum_tx/$counter") | ||
107 | |||
108 | #echo "$avg_rx" | ||
109 | #echo "$avg_tx" | ||
110 | |||
111 | |||
112 | if [ $(bc <<< "$avg_rx > $critical || $avg_tx > $critical") -eq 1 ]; then | ||
113 | echo "$interface CRITICAL - AVG_RX: $avg_rx kb/s, AVG_TX: $avg_tx kb/s | RX="$avg_rx"kbps;0;0;0; TX="$avg_tx"kbps;0;0;0;" | ||
114 | exit $STATE_CRITICAL | ||
115 | elif [ $(bc <<< "$avg_rx > $warning || $avg_tx > $warning") -eq 1 ]; then | ||
116 | echo "$interface WARNING - AVG_RX: $avg_rx kb/s, AVG_TX: $avg_tx kb/s | RX="$avg_rx"kbps;0;0;0; TX="$avg_tx"kbps;0;0;0;" | ||
117 | exit $STATE_WARNING | ||
118 | else | ||
119 | echo "$interface - OK AVG_RX: $avg_rx kb/s, AVG_TX: $avg_tx kb/s | RX="$avg_rx"kbps;0;0;0; TX="$avg_tx"kbps;0;0;0;" | ||
120 | exit $STATE_OK | ||
121 | fi | ||
122 | exit 3 | ||
diff --git a/flakes/private/monitoring/plugins/check_command b/flakes/private/monitoring/plugins/check_command new file mode 100755 index 0000000..2b546c1 --- /dev/null +++ b/flakes/private/monitoring/plugins/check_command | |||
@@ -0,0 +1,113 @@ | |||
1 | #!/usr/bin/env perl | ||
2 | |||
3 | use strict; | ||
4 | use Getopt::Std; | ||
5 | $| = 1; | ||
6 | |||
7 | my %opts; | ||
8 | getopts('hr:C:c:s:o:', \%opts); | ||
9 | |||
10 | my $STATE_OK = 0; | ||
11 | my $STATE_WARNING = 1; | ||
12 | my $STATE_CRITICAL = 2; | ||
13 | my $STATE_UNKNOWN = 3; | ||
14 | |||
15 | if ($opts{'h'} || scalar(%opts) == 0) { | ||
16 | &print_help(); | ||
17 | exit($STATE_OK); | ||
18 | } | ||
19 | |||
20 | my $command = $opts{'c'}; | ||
21 | if ($command eq '') { | ||
22 | print "You must provide a command to check.\n"; | ||
23 | exit($STATE_UNKNOWN); | ||
24 | } | ||
25 | |||
26 | my $expected_output = $opts{'o'}; | ||
27 | my $expected_status = $opts{'s'}; | ||
28 | my $other_command = $opts{'C'}; | ||
29 | |||
30 | if ($other_command eq '' and $expected_status eq '' and $expected_output eq '') { | ||
31 | $expected_status = 0; | ||
32 | } | ||
33 | |||
34 | my $cmd = $command . ' 2>&1'; | ||
35 | my $other_cmd; | ||
36 | if ($other_command ne '') { | ||
37 | $other_cmd = $other_command . ' 2>&1'; | ||
38 | } | ||
39 | |||
40 | my $run_as; | ||
41 | if ($opts{'r'}) { | ||
42 | $run_as = $opts{'r'}; | ||
43 | $cmd = "sudo -u $run_as -n $cmd"; | ||
44 | |||
45 | if ($other_command ne '') { | ||
46 | $other_cmd = "sudo -u $run_as -n $other_cmd"; | ||
47 | } | ||
48 | |||
49 | } | ||
50 | |||
51 | my $cmd_result = `$cmd`; | ||
52 | my $other_cmd_result; | ||
53 | if ($other_command ne '') { | ||
54 | $other_cmd_result = `$other_cmd`; | ||
55 | chomp($other_cmd_result); | ||
56 | } | ||
57 | |||
58 | chomp($cmd_result); | ||
59 | if ($cmd_result =~ /sudo/i) { | ||
60 | print "$command CRITICAL - No sudo right to run the command | result=1;;;;\n"; | ||
61 | exit($STATE_UNKNOWN); | ||
62 | } elsif ($expected_status ne '') { | ||
63 | if ($? != $expected_status) { | ||
64 | print "$command CRITICAL - Response status $? | result=1;;;;\n"; | ||
65 | exit($STATE_CRITICAL); | ||
66 | } else { | ||
67 | print "$command OK - Response status $? | result=0;;;;\n"; | ||
68 | exit($STATE_OK); | ||
69 | } | ||
70 | } elsif ($other_command ne '') { | ||
71 | if ($cmd_result ne $other_cmd_result) { | ||
72 | print "$command CRITICAL - Expected output not matching other command output | result=1;;;;\n"; | ||
73 | exit($STATE_CRITICAL); | ||
74 | } else { | ||
75 | print "$command OK - Expected output matching other command output | result=0;;;;\n"; | ||
76 | exit($STATE_OK); | ||
77 | } | ||
78 | } else { | ||
79 | if ($cmd_result !~ /$expected_output/) { | ||
80 | print "$command CRITICAL - Expected output not matching | result=1;;;;\n"; | ||
81 | exit($STATE_CRITICAL); | ||
82 | } else { | ||
83 | print "$command OK - Expected output matching | result=0;;;;\n"; | ||
84 | exit($STATE_OK); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | sub print_help() { | ||
89 | print << "EOF"; | ||
90 | Check whether the given command responds as expected. One of -o -C or -s must be selected. | ||
91 | |||
92 | Options: | ||
93 | -h | ||
94 | Print detailed help screen | ||
95 | |||
96 | -c | ||
97 | command to run (required) | ||
98 | |||
99 | -C | ||
100 | other command to compare output | ||
101 | |||
102 | -r user | ||
103 | Run as user via sudo. | ||
104 | |||
105 | -s | ||
106 | status code to check | ||
107 | |||
108 | -o | ||
109 | output to check | ||
110 | |||
111 | EOF | ||
112 | } | ||
113 | |||
diff --git a/flakes/private/monitoring/plugins/check_emails b/flakes/private/monitoring/plugins/check_emails new file mode 100755 index 0000000..534e5a5 --- /dev/null +++ b/flakes/private/monitoring/plugins/check_emails | |||
@@ -0,0 +1,121 @@ | |||
1 | #!/usr/bin/env perl | ||
2 | |||
3 | use strict; | ||
4 | use Getopt::Std; | ||
5 | use File::Basename; | ||
6 | use Date::Parse; | ||
7 | use POSIX qw(strftime); | ||
8 | |||
9 | $| = 1; | ||
10 | |||
11 | my %opts; | ||
12 | getopts('hH:l:s:p:f:i:n:r:', \%opts); | ||
13 | |||
14 | my $STATE_OK = 0; | ||
15 | my $STATE_WARNING = 1; | ||
16 | my $STATE_CRITICAL = 2; | ||
17 | my $STATE_UNKNOWN = 3; | ||
18 | |||
19 | if ($opts{'h'} || scalar(%opts) == 0) { | ||
20 | &print_help(); | ||
21 | exit($STATE_OK); | ||
22 | } | ||
23 | |||
24 | my $port = $opts{'p'}; | ||
25 | my $host = $opts{'H'}; | ||
26 | my $login = $opts{'l'}; | ||
27 | if ($login ne '') { | ||
28 | $login = "$login@"; | ||
29 | } | ||
30 | |||
31 | my $identity = $opts{'i'}; | ||
32 | my $local_directory = $opts{'n'}; | ||
33 | my $return_path = $opts{'r'}; | ||
34 | |||
35 | my @emails_to_send = split(/,/, $opts{'s'}); | ||
36 | my @emails_to_expect = split(/,/, $opts{'f'}); | ||
37 | |||
38 | my $cmd_result; | ||
39 | if ($local_directory ne '') { | ||
40 | if (@emails_to_expect and ! -d $local_directory) { | ||
41 | print "Emails $host UNKNOWN - Could not find local directory"; | ||
42 | exit($STATE_UNKNOWN); | ||
43 | } | ||
44 | $cmd_result = `send_mails $local_directory $return_path @emails_to_send 2>&1`; | ||
45 | } else { | ||
46 | $cmd_result = `ssh -o BatchMode=yes -o UserKnownHostsFile=/dev/null -o CheckHostIP=no -o StrictHostKeyChecking=no -p $port -i $identity $login$host send_mails @emails_to_send 2>&1`; | ||
47 | |||
48 | if ($cmd_result =~ /Host key verification failed./) { | ||
49 | print "Emails $host UNKNOWN - Could not connect to host with ssh key\n"; | ||
50 | exit($STATE_UNKNOWN); | ||
51 | } | ||
52 | } | ||
53 | |||
54 | my @lines = split(/\n/, $cmd_result); | ||
55 | |||
56 | my %found_emails; | ||
57 | |||
58 | foreach my $line (@lines) { | ||
59 | my @split_line = split(/;/, $line, 2); | ||
60 | $found_emails{$split_line[0]} = $split_line[1]; | ||
61 | } | ||
62 | |||
63 | my $output = ""; | ||
64 | my $old = 0; | ||
65 | foreach my $email_from (@emails_to_expect) { | ||
66 | my @email_split = split(/:/, $email_from); | ||
67 | my $email = $email_split[0]; | ||
68 | my $from = $email_split[1]; | ||
69 | |||
70 | if ( exists $found_emails{$email} ) { | ||
71 | my $email_date = str2time($found_emails{$email}); | ||
72 | my $current_date = strftime "%s", localtime; | ||
73 | |||
74 | if ($current_date - $email_date > 60*30) { | ||
75 | $output = "$output$email ($found_emails{$email} from $from) "; | ||
76 | } | ||
77 | $old = ($current_date - $email_date) > $old ? ($current_date - $email_date) : $old; | ||
78 | } else { | ||
79 | $output = "$output$email (missing) " | ||
80 | } | ||
81 | } | ||
82 | |||
83 | if ($output ne '') { | ||
84 | print "Emails $host CRITICAL - expecting emails: $output | timestamp=${old}s;;;;\n"; | ||
85 | exit($STATE_CRITICAL); | ||
86 | } else { | ||
87 | print "Emails $host OK | timestamp=${old}s;;;;\n"; | ||
88 | exit($STATE_OK); | ||
89 | } | ||
90 | |||
91 | sub print_help() { | ||
92 | print << "EOF"; | ||
93 | Check sent emails | ||
94 | |||
95 | Options: | ||
96 | -h | ||
97 | Print detailed help screen | ||
98 | |||
99 | -H | ||
100 | Host to check | ||
101 | |||
102 | -l | ||
103 | Login | ||
104 | |||
105 | -i | ||
106 | Identity file | ||
107 | |||
108 | -n | ||
109 | Don’t use ssh, pass that directory to script | ||
110 | |||
111 | -r | ||
112 | Return path for local e-mails | ||
113 | |||
114 | -s | ||
115 | Comma separated list of emails to send from the host. | ||
116 | |||
117 | -f | ||
118 | Comma separated list of emails to expect on the host. | ||
119 | EOF | ||
120 | } | ||
121 | |||
diff --git a/flakes/private/monitoring/plugins/check_eriomem b/flakes/private/monitoring/plugins/check_eriomem new file mode 100755 index 0000000..880b88a --- /dev/null +++ b/flakes/private/monitoring/plugins/check_eriomem | |||
@@ -0,0 +1,83 @@ | |||
1 | #!/usr/bin/env python | ||
2 | import os | ||
3 | import sys | ||
4 | import getopt | ||
5 | import signal | ||
6 | from subprocess import Popen, PIPE | ||
7 | |||
8 | STATE_OK = 0 | ||
9 | STATE_WARNING = 1 | ||
10 | STATE_CRITICAL = 2 | ||
11 | STATE_UNKNOWN = 3 | ||
12 | |||
13 | keys = sys.argv[1].split(",") | ||
14 | |||
15 | def to_args(k): | ||
16 | access, secret = k.split(":", 1) | ||
17 | return [ | ||
18 | "s3cmd", | ||
19 | '-c=/dev/null', | ||
20 | '--no-check-certificate', | ||
21 | '--access_key={}'.format(access), | ||
22 | '--secret_key={}'.format(secret), | ||
23 | '--host=e.eriomem.net', | ||
24 | '--host-bucket=%(bucket)s.e.eriomem.net', | ||
25 | 'du' | ||
26 | ] | ||
27 | |||
28 | max_size = 1024*1024*1024*1024 | ||
29 | warning_percent = 99.75 | ||
30 | critical_percent = 99.95 | ||
31 | |||
32 | def output(code, msg): | ||
33 | print(msg) | ||
34 | sys.exit(code) | ||
35 | |||
36 | def main(): | ||
37 | def handler(signum, frame): | ||
38 | raise IOError | ||
39 | signal.signal(signal.SIGALRM, handler) | ||
40 | signal.alarm(60) | ||
41 | |||
42 | try: | ||
43 | ps = [Popen(to_args(a), stdout=PIPE, stderr=PIPE) for a in keys] | ||
44 | outs = [p.communicate() for p in ps] | ||
45 | rets = [p.wait() for p in ps] | ||
46 | except IOError: | ||
47 | for p in ps: | ||
48 | os.kill(p.pid, signal.SIGTERM) | ||
49 | output(STATE_UNKNOWN, | ||
50 | "Eriomem UNKNOWN - Command timeout after 60 seconds!") | ||
51 | |||
52 | signal.alarm(0) | ||
53 | |||
54 | if sum(rets) == 0: | ||
55 | usages = [int(out[0].decode().split("\n")[-2].split()[0]) for out in outs] | ||
56 | usage = sum(usages) | ||
57 | use_percent = 100 * usage / max_size | ||
58 | if use_percent > critical_percent: | ||
59 | output(STATE_CRITICAL, | ||
60 | "Eriomem CRITICAL - bucket usage: %s (%s%%);| size=%s;;;;" % | ||
61 | (sizeof_fmt(usage), use_percent, sizeof_fmt(usage))) | ||
62 | elif use_percent > warning_percent: | ||
63 | output(STATE_WARNING, | ||
64 | "Eriomem WARNING - bucket usage: %s (%s%%);| size=%s;;;;" % | ||
65 | (sizeof_fmt(usage), use_percent, sizeof_fmt(usage))) | ||
66 | else: | ||
67 | output(STATE_OK, | ||
68 | "Eriomem OK - bucket usage: %s (%d%%);| size=%s;;;;" % | ||
69 | (sizeof_fmt(usage), use_percent, sizeof_fmt(usage))) | ||
70 | else: | ||
71 | messages = "\n".join([out[0].decode() + out[1].decode() for out in outs]) | ||
72 | output(STATE_UNKNOWN, | ||
73 | "Eriomem UNKNOWN - Error in command") | ||
74 | |||
75 | def sizeof_fmt(num): | ||
76 | for unit in ['','ko','Mo','Go','To','Po','Eo','Zo']: | ||
77 | if abs(num) < 1024.0: | ||
78 | return "%3.1f%s" % (num, unit) | ||
79 | num /= 1024.0 | ||
80 | return "%.1f%s%s" % (num, 'Yo') | ||
81 | |||
82 | if __name__ == '__main__': | ||
83 | main() | ||
diff --git a/flakes/private/monitoring/plugins/check_ftp_database b/flakes/private/monitoring/plugins/check_ftp_database new file mode 100755 index 0000000..f9cf579 --- /dev/null +++ b/flakes/private/monitoring/plugins/check_ftp_database | |||
@@ -0,0 +1,11 @@ | |||
1 | #!/usr/bin/env bash | ||
2 | |||
3 | OUT=$(echo "ls" | lftp -u test_ftp,test_ftp eldiron.immae.eu | grep it_works | wc -l) | ||
4 | |||
5 | if [ "$OUT" -eq 1 ]; then | ||
6 | echo "ftp connection OK - access to ftp is working | ftp=1;;;;" | ||
7 | exit 0 | ||
8 | else | ||
9 | echo "ftp connection CRITICAL - no access to ftp | ftp=0;;;;" | ||
10 | exit 2 | ||
11 | fi | ||
diff --git a/flakes/private/monitoring/plugins/check_git b/flakes/private/monitoring/plugins/check_git new file mode 100755 index 0000000..e8fbb29 --- /dev/null +++ b/flakes/private/monitoring/plugins/check_git | |||
@@ -0,0 +1,81 @@ | |||
1 | #!/usr/bin/env bash | ||
2 | |||
3 | SSH_KEY="$1" | ||
4 | |||
5 | TMPDIR=$(mktemp -d) | ||
6 | |||
7 | if [ ! -d "$TMPDIR" ]; then | ||
8 | echo "gitolite UNKNOWN - impossible to create temp dir" | ||
9 | exit 3 | ||
10 | fi | ||
11 | |||
12 | trap "rm -rf $TMPDIR" EXIT | ||
13 | |||
14 | ERRORS="" | ||
15 | OUTPUT="" | ||
16 | PERFS="" | ||
17 | |||
18 | cd "$TMPDIR" | ||
19 | OUT=$(git clone -q git://git.immae.eu/perso/Immae/Projets/Ruby/Monitor.git 2>&1) | ||
20 | ERR=$? | ||
21 | if [ -n "$OUT" ]; then | ||
22 | OUTPUT="$OUTPUT | ||
23 | $OUT" | ||
24 | fi | ||
25 | if [ "$ERR" != 0 ]; then | ||
26 | PERFS="$PERFS git=0;;;;" | ||
27 | ERRORS="$ERRORS git://" | ||
28 | else | ||
29 | PERFS="$PERFS git=1;;;;" | ||
30 | fi | ||
31 | rm -rf Monitor | ||
32 | |||
33 | OUT=$(git clone -q http://git.immae.eu/perso/Immae/Projets/Ruby/Monitor.git 2>&1) | ||
34 | ERR=$? | ||
35 | if [ -n "$OUT" ]; then | ||
36 | OUTPUT="$OUTPUT | ||
37 | $OUT" | ||
38 | fi | ||
39 | if [ "$ERR" != 0 ]; then | ||
40 | ERRORS="$ERRORS http://" | ||
41 | PERFS="$PERFS http=0;;;;" | ||
42 | else | ||
43 | PERFS="$PERFS http=1;;;;" | ||
44 | fi | ||
45 | rm -rf Monitor | ||
46 | |||
47 | OUT=$(git clone -q https://git.immae.eu/perso/Immae/Projets/Ruby/Monitor.git 2>&1) | ||
48 | ERR=$? | ||
49 | if [ -n "$OUT" ]; then | ||
50 | OUTPUT="$OUTPUT | ||
51 | $OUT" | ||
52 | fi | ||
53 | if [ "$ERR" != 0 ]; then | ||
54 | ERRORS="$ERRORS https://" | ||
55 | PERFS="$PERFS https=0;;;;" | ||
56 | else | ||
57 | PERFS="$PERFS https=1;;;;" | ||
58 | fi | ||
59 | rm -rf Monitor | ||
60 | |||
61 | OUT=$(GIT_SSH_COMMAND="ssh -i $SSH_KEY -o BatchMode=yes -o UserKnownHostsFile=/dev/null -o CheckHostIP=no -o StrictHostKeyChecking=no" git clone -q gitolite@git.immae.eu:perso/Immae/Projets/Ruby/Monitor 2>&1) | ||
62 | ERR=$? | ||
63 | if [ -n "$OUT" ]; then | ||
64 | OUTPUT="$OUTPUT | ||
65 | $OUT" | ||
66 | fi | ||
67 | if [ "$ERR" != 0 ]; then | ||
68 | ERRORS="$ERRORS ssh" | ||
69 | PERFS="$PERFS ssh=0;;;;" | ||
70 | else | ||
71 | PERFS="$PERFS ssh=1;;;;" | ||
72 | fi | ||
73 | rm -rf Monitor | ||
74 | |||
75 | if [ -n "$ERRORS" ]; then | ||
76 | echo "gitolite CRITICAL - impossible to clone via$ERRORS | $PERFS" | ||
77 | exit 2 | ||
78 | else | ||
79 | echo "gitolite OK - ssh, git, http and https work | $PERFS" | ||
80 | exit 0 | ||
81 | fi | ||
diff --git a/flakes/private/monitoring/plugins/check_imap_connection b/flakes/private/monitoring/plugins/check_imap_connection new file mode 100755 index 0000000..c1ab0dd --- /dev/null +++ b/flakes/private/monitoring/plugins/check_imap_connection | |||
@@ -0,0 +1,52 @@ | |||
1 | #!/usr/bin/env perl | ||
2 | |||
3 | use strict; | ||
4 | use Getopt::Std; | ||
5 | $| = 1; | ||
6 | |||
7 | my %opts; | ||
8 | getopts('h:u:p:H:', \%opts); | ||
9 | |||
10 | my $STATE_OK = 0; | ||
11 | my $STATE_WARNING = 1; | ||
12 | my $STATE_CRITICAL = 2; | ||
13 | my $STATE_UNKNOWN = 3; | ||
14 | |||
15 | if ($opts{'h'} || !$opts{'u'} || !$opts{'p'} || !$opts{'H'}) { | ||
16 | &print_help(); | ||
17 | exit($STATE_UNKNOWN); | ||
18 | } | ||
19 | |||
20 | my $user = $opts{'u'}; | ||
21 | my $password = $opts{'p'}; | ||
22 | my $host = $opts{'H'}; | ||
23 | |||
24 | my $cmd_result = `(echo "a login $user $password"; echo "b logout") | openssl s_client -quiet -ign_eof -connect $host -starttls imap 2>&1`; | ||
25 | my $expected_result = "a OK Logged in"; | ||
26 | |||
27 | chomp($cmd_result); | ||
28 | if ($cmd_result !~ /$expected_result/) { | ||
29 | print "IMAP CRITICAL - Unable to connect via imaps | imap=0;;;;\n"; | ||
30 | exit($STATE_CRITICAL); | ||
31 | } else { | ||
32 | print "IMAP OK - imaps connected successfully | imap=1;;;;\n"; | ||
33 | exit($STATE_OK); | ||
34 | } | ||
35 | |||
36 | sub print_help() { | ||
37 | print << "EOF"; | ||
38 | Check whether imap works via ssl and is able to connect its database. | ||
39 | |||
40 | Options: | ||
41 | -h | ||
42 | Print detailed help screen | ||
43 | -u | ||
44 | User to log in as | ||
45 | -p | ||
46 | Password to log in | ||
47 | -H | ||
48 | Host to log in to | ||
49 | |||
50 | EOF | ||
51 | } | ||
52 | |||
diff --git a/flakes/private/monitoring/plugins/check_last_file_date b/flakes/private/monitoring/plugins/check_last_file_date new file mode 100755 index 0000000..f51a258 --- /dev/null +++ b/flakes/private/monitoring/plugins/check_last_file_date | |||
@@ -0,0 +1,28 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | STATE_OK=0 | ||
4 | STATE_WARNING=1 | ||
5 | STATE_CRITICAL=2 | ||
6 | STATE_UNKNOWN=3 | ||
7 | |||
8 | base_path=$1 | ||
9 | hours=$2 | ||
10 | |||
11 | last_date=$(find $base_path -mindepth 1 -maxdepth 1 -printf "%T@\n" 2>/dev/null | sort | tail -n 1) | ||
12 | |||
13 | if [ -z "$last_date" ]; then | ||
14 | echo "UNKNOWN: Could not read folder" | ||
15 | exit $STATE_UNKNOWN | ||
16 | else | ||
17 | LC_ALL=C last_date=$(printf "%.*f" 0 $last_date) | ||
18 | LC_ALL=C age=$(( $(date "+%s") - $last_date)) | ||
19 | max_age=$(( $hours * 60 * 60 )) | ||
20 | min_date=$(date -d "$hours hours ago" "+%s") | ||
21 | if [ "$min_date" -lt "$last_date" ]; then | ||
22 | echo "OK: Last file $(date -d @$last_date) | age=${age}s;;$max_age;;" | ||
23 | exit $STATE_OK | ||
24 | else | ||
25 | echo "CRITICAL: Last file $(date -d @$last_date) | age=${age}s;;$max_age;;" | ||
26 | exit $STATE_CRITICAL | ||
27 | fi | ||
28 | fi | ||
diff --git a/flakes/private/monitoring/plugins/check_mem.sh b/flakes/private/monitoring/plugins/check_mem.sh new file mode 100755 index 0000000..3a29040 --- /dev/null +++ b/flakes/private/monitoring/plugins/check_mem.sh | |||
@@ -0,0 +1,31 @@ | |||
1 | #!/usr/bin/env bash | ||
2 | |||
3 | if [ "$1" = "-w" ] && [ "$2" -gt "0" ] && [ "$3" = "-c" ] && [ "$4" -gt "0" ]; then | ||
4 | FreeM=`free -m -w` | ||
5 | memTotal_m=`echo "$FreeM" |grep Mem |awk '{print $2}'` | ||
6 | memUsed_m=`echo "$FreeM" |grep Mem |awk '{print $3}'` | ||
7 | memFree_m=`echo "$FreeM" |grep Mem |awk '{print $4}'` | ||
8 | memShared_m=`echo "$FreeM" |grep Mem |awk '{print $5}'` | ||
9 | memBuffer_m=`echo "$FreeM" |grep Mem |awk '{print $6}'` | ||
10 | memCache_m=`echo "$FreeM" |grep Mem |awk '{print $7}'` | ||
11 | memAvailable_m=`echo "$FreeM" |grep Mem |awk '{print $8}'` | ||
12 | memUsedPrc=`echo $((($memUsed_m-$memBuffer_m-$memCache_m)*100/$memTotal_m))||cut -d. -f1` | ||
13 | if [ "$memUsedPrc" -ge "$4" ]; then | ||
14 | echo "Memory: CRITICAL Total: $memTotal_m MB - Used/Buffer/Cache: $memUsed_m MB - $memUsedPrc% used!|TOTAL=$memTotal_m;;;; USED=$memUsed_m;;;; SHARED=$memShared_m;;;; CACHE=$memCache_m;;;; AVAILABLE=$memAvailable_m;;;; BUFFER=$memBuffer_m;;;;" | ||
15 | exit 2 | ||
16 | elif [ "$memUsedPrc" -ge "$2" ]; then | ||
17 | echo "Memory: WARNING Total: $memTotal_m MB - Used/Buffer/Cache: $memUsed_m MB - $memUsedPrc% used!|TOTAL=$memTotal_m;;;; USED=$memUsed_m;;;; SHARED=$memShared_m;;;; CACHE=$memCache_m;;;; AVAILABLE=$memAvailable_m;;;; BUFFER=$memBuffer_m;;;;" | ||
18 | exit 1 | ||
19 | else | ||
20 | echo "Memory: OK Total: $memTotal_m MB - Used/Buffer/Cache: $memUsed_m MB - $memUsedPrc% used|TOTAL=$memTotal_m;;;; USED=$memUsed_m;;;; SHARED=$memShared_m;;;; CACHE=$memCache_m;;;; AVAILABLE=$memAvailable_m;;;; BUFFER=$memBuffer_m;;;;" | ||
21 | exit 0 | ||
22 | fi | ||
23 | else # If inputs are not as expected, print help. | ||
24 | sName="`echo $0|awk -F '/' '{print $NF}'`" | ||
25 | echo -e "\n\n\t\t### $sName Version 2.0###\n" | ||
26 | echo -e "# Usage:\t$sName -w <warnlevel> -c <critlevel>" | ||
27 | echo -e "\t\t= warnlevel and critlevel is percentage value without %\n" | ||
28 | echo "# EXAMPLE:\t/usr/lib64/nagios/plugins/$sName -w 80 -c 90" | ||
29 | echo -e "\nCopyright (C) 2012 Lukasz Gogolin (lukasz.gogolin@gmail.com), improved by Nestor 2015\n\n" | ||
30 | exit | ||
31 | fi | ||
diff --git a/flakes/private/monitoring/plugins/check_mysql_replication b/flakes/private/monitoring/plugins/check_mysql_replication new file mode 100755 index 0000000..1ee5de1 --- /dev/null +++ b/flakes/private/monitoring/plugins/check_mysql_replication | |||
@@ -0,0 +1,41 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | STATE_OK=0 | ||
4 | STATE_WARNING=1 | ||
5 | STATE_CRITICAL=2 | ||
6 | STATE_UNKNOWN=3 | ||
7 | |||
8 | socket=$1 | ||
9 | config_file=$2 | ||
10 | info=$(mysql --defaults-file=${config_file} -S $socket -e "show slave status" --vertical) | ||
11 | exit_code=$? | ||
12 | |||
13 | lag=$(echo "$info" | grep "\bSeconds_Behind_Master\b" | cut -d':' -f2 | sed -e "s/\s//g") | ||
14 | |||
15 | IO_running=$(echo "$info" | grep "\bSlave_IO_Running\b" | cut -d':' -f2 | sed -e "s/\s//g") | ||
16 | SQL_running=$(echo "$info" | grep "\bSlave_SQL_Running\b" | cut -d':' -f2 | sed -e "s/\s//g") | ||
17 | |||
18 | if [[ $exit_code -ne 0 ]]; then | ||
19 | echo "UNKNOWN - Impossible to run mysql command" | ||
20 | exit $STATE_UNKNOWN | ||
21 | elif [[ -z "$lag" ]]; then | ||
22 | echo "UNKNOWN - No replication found for mysql" | ||
23 | exit $STATE_UNKNOWN | ||
24 | elif [[ "$IO_running" != "Yes" || "$SQL_running" != "Yes" ]]; then | ||
25 | echo "UNKNOWN - Replication is not running" | ||
26 | exit $STATE_UNKNOWN | ||
27 | else | ||
28 | output="Replication lag for mysql is ${lag}s" | ||
29 | LC_ALL=C lag=$(printf "%.*f" 0 $lag) | ||
30 | |||
31 | if [[ $lag -lt 5 ]]; then | ||
32 | echo "OK - $output | time=${lag}s;5;10;;" | ||
33 | exit $STATE_OK | ||
34 | elif [[ $lag -lt 10 ]]; then | ||
35 | echo "WARNING - $output | time=${lag}s;5;10;;" | ||
36 | exit $STATE_WARNING | ||
37 | else | ||
38 | echo "CRITICAL - $output | time=${lag}s;5;10;;" | ||
39 | exit $STATE_CRITICAL | ||
40 | fi | ||
41 | fi | ||
diff --git a/flakes/private/monitoring/plugins/check_openldap_replication b/flakes/private/monitoring/plugins/check_openldap_replication new file mode 100755 index 0000000..7136ad5 --- /dev/null +++ b/flakes/private/monitoring/plugins/check_openldap_replication | |||
@@ -0,0 +1,54 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | STATE_OK=0 | ||
4 | STATE_WARNING=1 | ||
5 | STATE_CRITICAL=2 | ||
6 | STATE_UNKNOWN=3 | ||
7 | |||
8 | distant_host="$1" | ||
9 | replication_dn="$2" | ||
10 | replication_pw="$3" | ||
11 | base="$4" | ||
12 | config="$5" | ||
13 | |||
14 | to_date() { | ||
15 | i="$1" | ||
16 | i=$(echo "$i" | grep contextCSN | cut -d":" -f2 | sed -e "s/\s//g") | ||
17 | i=$(echo "$i" | cut -d"#" -f1) | ||
18 | i=$(echo "$i" | cut -d"." -f1) | ||
19 | echo "$i" | ||
20 | } | ||
21 | |||
22 | # ldap | ||
23 | remote_ldap=$(ldapsearch -H $distant_host -D "$replication_dn" -y "$replication_pw" -b "$base" -s base -LLL contextCSN ) | ||
24 | exit_code_remote=$? | ||
25 | remote_ldap=$(to_date "$remote_ldap") | ||
26 | |||
27 | # slapcat | ||
28 | local_ldap=$(slapcat -b "$base" -f "$config" -a "(entryDN=$base)") | ||
29 | exit_code_local=$? | ||
30 | local_ldap=$(to_date "$local_ldap") | ||
31 | |||
32 | offset=$(($remote_ldap - $local_ldap)) | ||
33 | |||
34 | if [[ $exit_code_remote -ne 0 || $exit_code_local -ne 0 ]]; then | ||
35 | echo "UNKNOWN - Impossible to run ldap command" | ||
36 | exit $STATE_UNKNOWN | ||
37 | elif [[ -z "$offset" ]]; then | ||
38 | echo "UNKNOWN - No replication found" | ||
39 | exit $STATE_UNKNOWN | ||
40 | else | ||
41 | output="Replication lag for openldap is ${offset}s" | ||
42 | LC_ALL=C lag=$(printf "%.*f" 0 $lag) | ||
43 | |||
44 | if [[ $offset -lt 5 ]]; then | ||
45 | echo "OK - $output | time=${offset}s;5;10;;" | ||
46 | exit $STATE_OK | ||
47 | elif [[ $offset -lt 10 ]]; then | ||
48 | echo "WARNING - $output | time=${offset}s;5;10;;" | ||
49 | exit $STATE_WARNING | ||
50 | else | ||
51 | echo "CRITICAL - $output | time=${offset}s;5;10;;" | ||
52 | exit $STATE_CRITICAL | ||
53 | fi | ||
54 | fi | ||
diff --git a/flakes/private/monitoring/plugins/check_ovh_sms b/flakes/private/monitoring/plugins/check_ovh_sms new file mode 100755 index 0000000..caf279c --- /dev/null +++ b/flakes/private/monitoring/plugins/check_ovh_sms | |||
@@ -0,0 +1,25 @@ | |||
1 | #!/usr/bin/env python | ||
2 | |||
3 | import sys | ||
4 | try: | ||
5 | import ovh | ||
6 | |||
7 | [endpoint, application_key, application_secret, consumer_key, account] = sys.argv[1].split(",") | ||
8 | client = ovh.Client( | ||
9 | endpoint=endpoint, | ||
10 | application_key=application_key, | ||
11 | application_secret=application_secret, | ||
12 | consumer_key=consumer_key, | ||
13 | ) | ||
14 | |||
15 | result = client.get('/sms/{}'.format(account))["creditsLeft"] | ||
16 | |||
17 | if result < 20: | ||
18 | print("SMS OVH Critical - Not enough sms left ({})|SMS={};;;;".format(result, result)) | ||
19 | sys.exit(2) | ||
20 | else: | ||
21 | print("SMS OVH Ok - Enough sms left ({})|SMS={};;;;".format(result, result)) | ||
22 | sys.exit(0) | ||
23 | except Exception: | ||
24 | print("SMS OVH UNKNOWN - Error during script") | ||
25 | sys.exit(3) | ||
diff --git a/flakes/private/monitoring/plugins/check_postgres_database_count b/flakes/private/monitoring/plugins/check_postgres_database_count new file mode 100755 index 0000000..43bdd8c --- /dev/null +++ b/flakes/private/monitoring/plugins/check_postgres_database_count | |||
@@ -0,0 +1,32 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | STATE_OK=0 | ||
4 | STATE_WARNING=1 | ||
5 | STATE_CRITICAL=2 | ||
6 | STATE_UNKNOWN=3 | ||
7 | |||
8 | host=$1 | ||
9 | port=$2 | ||
10 | min=$3 | ||
11 | |||
12 | count=$(psql -h $host -p $port -A -q -c '\t' -c 'select count(datname) from pg_catalog.pg_database' postgres 2>&1) | ||
13 | exit_code=$? | ||
14 | |||
15 | if [[ $exit_code -ne 0 ]]; then | ||
16 | echo "UNKNOWN - Impossible to run psql command: $count" | ||
17 | exit $STATE_UNKNOWN | ||
18 | elif [[ -z "$count" ]]; then | ||
19 | echo "UNKNOWN - No database found" | ||
20 | exit $STATE_UNKNOWN | ||
21 | else | ||
22 | output="Database count is $count" | ||
23 | LC_ALL=C count=$(printf "%.*f" 0 $count) | ||
24 | |||
25 | if [[ $count -gt $min ]]; then | ||
26 | echo "OK - $output | count=${count};$min;$min;0;" | ||
27 | exit $STATE_OK | ||
28 | else | ||
29 | echo "CRITICAL - $output | count=${count};$min;$min;0;" | ||
30 | exit $STATE_CRITICAL | ||
31 | fi | ||
32 | fi | ||
diff --git a/flakes/private/monitoring/plugins/check_postgres_replication b/flakes/private/monitoring/plugins/check_postgres_replication new file mode 100755 index 0000000..ff257a3 --- /dev/null +++ b/flakes/private/monitoring/plugins/check_postgres_replication | |||
@@ -0,0 +1,35 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | STATE_OK=0 | ||
4 | STATE_WARNING=1 | ||
5 | STATE_CRITICAL=2 | ||
6 | STATE_UNKNOWN=3 | ||
7 | |||
8 | user=$1 | ||
9 | host=$2 | ||
10 | port=$3 | ||
11 | |||
12 | lag=$(psql -h $host -p $port -A -t -c "SELECT COALESCE(EXTRACT(EPOCH FROM replay_lag),0) FROM pg_stat_replication WHERE usename='$user'" 2>/dev/null) | ||
13 | exit_code=$? | ||
14 | |||
15 | if [[ $exit_code -ne 0 ]]; then | ||
16 | echo "UNKNOWN - Impossible to run psql command" | ||
17 | exit $STATE_UNKNOWN | ||
18 | elif [[ -z "$lag" ]]; then | ||
19 | echo "UNKNOWN - No replication found for $user" | ||
20 | exit $STATE_UNKNOWN | ||
21 | else | ||
22 | output="Replication lag for $user is ${lag}s" | ||
23 | LC_ALL=C lag=$(printf "%.*f" 0 $lag) | ||
24 | |||
25 | if [[ $lag -lt 5 ]]; then | ||
26 | echo "OK - $output | time=${lag}s;5;10;0;" | ||
27 | exit $STATE_OK | ||
28 | elif [[ $lag -lt 10 ]]; then | ||
29 | echo "WARNING - $output | time=${lag}s;5;10;0;" | ||
30 | exit $STATE_WARNING | ||
31 | else | ||
32 | echo "CRITICAL - $output | time=${lag}s;5;10;0;" | ||
33 | exit $STATE_CRITICAL | ||
34 | fi | ||
35 | fi | ||
diff --git a/flakes/private/monitoring/plugins/check_redis_replication b/flakes/private/monitoring/plugins/check_redis_replication new file mode 100755 index 0000000..6dbe4c4 --- /dev/null +++ b/flakes/private/monitoring/plugins/check_redis_replication | |||
@@ -0,0 +1,38 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | STATE_OK=0 | ||
4 | STATE_WARNING=1 | ||
5 | STATE_CRITICAL=2 | ||
6 | STATE_UNKNOWN=3 | ||
7 | |||
8 | socket=$1 | ||
9 | |||
10 | info=$(redis-cli -s $socket info replication) | ||
11 | lag=$(echo "$info" | grep master_last_io_seconds_ago | cut -d":" -f2 | sed -e "s/\s//g") | ||
12 | slave_offset=$(echo "$info" | grep slave_repl_offset | cut -d":" -f2 | sed -e "s/\s//g") | ||
13 | master_offset=$(echo "$info" | grep master_repl_offset | cut -d":" -f2 | sed -e "s/\s//g") | ||
14 | offset=$(($master_offset - $slave_offset)) | ||
15 | |||
16 | exit_code=$? | ||
17 | |||
18 | if [[ $exit_code -ne 0 ]]; then | ||
19 | echo "UNKNOWN - Impossible to run redis command" | ||
20 | exit $STATE_UNKNOWN | ||
21 | elif [[ -z "$lag" ]]; then | ||
22 | echo "UNKNOWN - No replication found" | ||
23 | exit $STATE_UNKNOWN | ||
24 | else | ||
25 | output="Replication lag for redis is ${lag}s and offset is ${offset}" | ||
26 | LC_ALL=C lag=$(printf "%.*f" 0 $lag) | ||
27 | |||
28 | if [[ $lag -lt 5 && $offset -lt 5 ]]; then | ||
29 | echo "OK - $output | time=${lag}s;5;10;0; offset=${offset};5;10;0;" | ||
30 | exit $STATE_OK | ||
31 | elif [[ $lag -lt 10 && $offset -lt 10 ]]; then | ||
32 | echo "WARNING - $output | time=${lag}s;5;10;0; offset=${offset};5;10;0;" | ||
33 | exit $STATE_WARNING | ||
34 | else | ||
35 | echo "CRITICAL - $output | time=${lag}s;5;10;0; offset=${offset};5;10;0;" | ||
36 | exit $STATE_CRITICAL | ||
37 | fi | ||
38 | fi | ||
diff --git a/flakes/private/monitoring/plugins/check_zfs_snapshot b/flakes/private/monitoring/plugins/check_zfs_snapshot new file mode 100755 index 0000000..56f8c4f --- /dev/null +++ b/flakes/private/monitoring/plugins/check_zfs_snapshot | |||
@@ -0,0 +1,325 @@ | |||
1 | #! /bin/sh | ||
2 | |||
3 | OS=$(uname) | ||
4 | |||
5 | # MIT License | ||
6 | # | ||
7 | # Copyright (c) 2016 Josef Friedrich <josef@friedrich.rocks> | ||
8 | # | ||
9 | # Permission is hereby granted, free of charge, to any person obtaining | ||
10 | # a copy of this software and associated documentation files (the | ||
11 | # "Software"), to deal in the Software without restriction, including | ||
12 | # without limitation the rights to use, copy, modify, merge, publish, | ||
13 | # distribute, sublicense, and/or sell copies of the Software, and to | ||
14 | # permit persons to whom the Software is furnished to do so, subject to | ||
15 | # the following conditions: | ||
16 | # | ||
17 | # The above copyright notice and this permission notice shall be | ||
18 | # included in all copies or substantial portions of the Software. | ||
19 | # | ||
20 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
21 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
22 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
23 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
24 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
25 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
26 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
27 | |||
28 | ######################################################################## | ||
29 | # Date functions | ||
30 | ######################################################################## | ||
31 | |||
32 | # This date function must be placed on the top of this file because | ||
33 | # they are used in some global variables. | ||
34 | |||
35 | # to_year ### | ||
36 | |||
37 | ## | ||
38 | # Get the four digit year integer from now. | ||
39 | # | ||
40 | # Return: | ||
41 | # The current 4 digit year. | ||
42 | ## | ||
43 | _now_to_year() { | ||
44 | date +%Y | ||
45 | } | ||
46 | |||
47 | ## | ||
48 | # Convert a date in the format YYYY-MM-DD to a four digit year integer. | ||
49 | # | ||
50 | # Parameters: | ||
51 | # a date in the format YYYY-MM-DD | ||
52 | # | ||
53 | # Return: | ||
54 | # four digit year integer | ||
55 | ## | ||
56 | _date_to_year() { | ||
57 | local OPTIONS | ||
58 | if [ "$OS" = 'Linux' ]; then | ||
59 | OPTIONS="--date $1" | ||
60 | # FreeBSD, Darwin | ||
61 | else | ||
62 | OPTIONS="-j -f %Y-%m-%d $1" | ||
63 | fi | ||
64 | date $OPTIONS +%Y | ||
65 | } | ||
66 | |||
67 | # to_datetime ### | ||
68 | |||
69 | ## | ||
70 | # Convert a UNIX timestamp to a datetime string. | ||
71 | # | ||
72 | # Parameters: | ||
73 | # UNIX timestamp | ||
74 | # | ||
75 | # Return: | ||
76 | # %Y-%m-%d.%H:%M:%S | ||
77 | ## | ||
78 | _timestamp_to_datetime() { | ||
79 | local OPTIONS | ||
80 | if [ "$OS" = 'Linux' ]; then | ||
81 | OPTIONS="--date @$1" | ||
82 | # FreeBSD, Darwin | ||
83 | else | ||
84 | OPTIONS="-j -f %s $1" | ||
85 | fi | ||
86 | date $OPTIONS +%Y-%m-%d.%H:%M:%S | ||
87 | } | ||
88 | |||
89 | # to_timestamp ### | ||
90 | |||
91 | ## | ||
92 | # Get the current UNIX timestamp. | ||
93 | # | ||
94 | # Return: | ||
95 | # %current UNIX timestamp | ||
96 | ## | ||
97 | _now_to_timestamp() { | ||
98 | date +%s | ||
99 | } | ||
100 | |||
101 | PROJECT_PAGES='https://github.com/Josef-Friedrich/check_zfs_snapshot | ||
102 | https://exchange.icinga.com/joseffriedrich/check_zfs_snapshot | ||
103 | https://exchange.nagios.org/directory/Plugins/System-Metrics/File-System/check_zfs_snapshot/details' | ||
104 | |||
105 | VERSION=1.2 | ||
106 | FIRST_RELEASE=2016-09-08 | ||
107 | SHORT_DESCRIPTION="Monitoring plugin to check how long ago the last \ | ||
108 | snapshot of a ZFS dataset was created." | ||
109 | USAGE="check_zfs_snapshot v$VERSION | ||
110 | Copyright (c) $(_date_to_year $FIRST_RELEASE)-$(_now_to_year) \ | ||
111 | Josef Friedrich <josef@friedrich.rocks> | ||
112 | |||
113 | $SHORT_DESCRIPTION | ||
114 | |||
115 | |||
116 | Usage: check_zfs_snapshot <options> | ||
117 | |||
118 | Options: | ||
119 | -c, --critical=OPT_CRITICAL | ||
120 | Interval in seconds for critical state. | ||
121 | -d, --dataset=OPT_DATASET | ||
122 | The ZFS dataset to check. | ||
123 | -h, --help | ||
124 | Show this help. | ||
125 | -s, --short-description | ||
126 | Show a short description of the command. | ||
127 | -v, --version | ||
128 | Show the version number. | ||
129 | -w, --warning=OPT_WARNING | ||
130 | Interval in seconds for warning state. Must be lower than -c | ||
131 | |||
132 | Performance data: | ||
133 | - last_ago | ||
134 | Time interval in seconds for last snapshot. | ||
135 | - warning | ||
136 | Interval in seconds. | ||
137 | - critical | ||
138 | Interval in seconds. | ||
139 | - snapshot_count | ||
140 | How many snapshot exists in the given dataset and all child | ||
141 | datasets exists. | ||
142 | " | ||
143 | |||
144 | # Exit codes | ||
145 | STATE_OK=0 | ||
146 | STATE_WARNING=1 | ||
147 | STATE_CRITICAL=2 | ||
148 | STATE_UNKNOWN=3 | ||
149 | |||
150 | _get_last_snapshot() { | ||
151 | zfs get creation -Hpr -t snapshot "$1" | \ | ||
152 | awk 'BEGIN {max = 0} {if ($3>max) max=$3} END {print max}' | ||
153 | } | ||
154 | |||
155 | _getopts() { | ||
156 | while getopts ':c:d:hsvw:-:' OPT ; do | ||
157 | case $OPT in | ||
158 | |||
159 | c) | ||
160 | OPT_CRITICAL=$OPTARG | ||
161 | ;; | ||
162 | |||
163 | d) | ||
164 | OPT_DATASET="$OPTARG" | ||
165 | ;; | ||
166 | |||
167 | h) | ||
168 | echo "$USAGE" | ||
169 | exit 0 | ||
170 | ;; | ||
171 | |||
172 | s) | ||
173 | echo "$SHORT_DESCRIPTION" | ||
174 | exit 0 | ||
175 | ;; | ||
176 | |||
177 | v) | ||
178 | echo "$VERSION" | ||
179 | exit 0 | ||
180 | ;; | ||
181 | |||
182 | w) | ||
183 | OPT_WARNING=$OPTARG | ||
184 | ;; | ||
185 | |||
186 | \?) | ||
187 | echo "Invalid option “-$OPTARG”!" >&2 | ||
188 | exit 2 | ||
189 | ;; | ||
190 | |||
191 | :) | ||
192 | echo "Option “-$OPTARG” requires an argument!" >&2 | ||
193 | exit 3 | ||
194 | ;; | ||
195 | |||
196 | -) | ||
197 | LONG_OPTARG="${OPTARG#*=}" | ||
198 | |||
199 | case $OPTARG in | ||
200 | |||
201 | critical=?*) | ||
202 | OPT_CRITICAL=$LONG_OPTARG | ||
203 | ;; | ||
204 | |||
205 | dataset=?*) | ||
206 | OPT_DATASET="$LONG_OPTARG" | ||
207 | ;; | ||
208 | |||
209 | help) | ||
210 | echo "$USAGE" | ||
211 | exit 0 | ||
212 | ;; | ||
213 | |||
214 | short-description) | ||
215 | echo "$SHORT_DESCRIPTION" | ||
216 | exit 0 | ||
217 | ;; | ||
218 | |||
219 | version) | ||
220 | echo "$VERSION" | ||
221 | exit 0 | ||
222 | ;; | ||
223 | |||
224 | warning=?*) | ||
225 | OPT_WARNING=$LONG_OPTARG | ||
226 | ;; | ||
227 | |||
228 | critical*|dataset*|warning*) | ||
229 | echo "Option “--$OPTARG” requires an argument!" >&2 | ||
230 | exit 3 | ||
231 | ;; | ||
232 | |||
233 | help*|short-description*|version*) | ||
234 | echo "No argument allowed for the option “--$OPTARG”!" >&2 | ||
235 | exit 4 | ||
236 | ;; | ||
237 | |||
238 | '') # "--" terminates argument processing | ||
239 | break | ||
240 | ;; | ||
241 | |||
242 | *) | ||
243 | echo "Invalid option “--$OPTARG”!" >&2 | ||
244 | exit 2 | ||
245 | ;; | ||
246 | |||
247 | esac | ||
248 | ;; | ||
249 | |||
250 | esac | ||
251 | done | ||
252 | } | ||
253 | |||
254 | _snapshot_count() { | ||
255 | # FreeBSD wc adds some whitespaces before the number! | ||
256 | # cat $HOME/debug | wc -l | ||
257 | # 7 | ||
258 | local COUNT | ||
259 | COUNT="$(zfs list -t snapshot | grep "$1" | wc -l)" | ||
260 | echo $COUNT | ||
261 | } | ||
262 | |||
263 | _performance_data() { | ||
264 | echo "| \ | ||
265 | last_ago=${DIFF}s;$OPT_WARNING;$OPT_CRITICAL;0 \ | ||
266 | count=$(_snapshot_count "$OPT_DATASET");;;0\ | ||
267 | " | ||
268 | } | ||
269 | |||
270 | ## This SEPARATOR is required for test purposes. Please don’t remove! ## | ||
271 | |||
272 | _getopts $@ | ||
273 | |||
274 | if [ -z "$OPT_WARNING" ]; then | ||
275 | # 1 day | ||
276 | OPT_WARNING=86400 | ||
277 | fi | ||
278 | |||
279 | if [ -z "$OPT_CRITICAL" ]; then | ||
280 | # 3 day | ||
281 | OPT_CRITICAL=259200 | ||
282 | fi | ||
283 | |||
284 | if [ -z "$OPT_DATASET" ]; then | ||
285 | echo "Dataset has to be set! Use option -d <dataset>" >&2 | ||
286 | echo "$USAGE" >&2 | ||
287 | exit $STATE_UNKNOWN | ||
288 | fi | ||
289 | |||
290 | if ! zfs list "$OPT_DATASET" > /dev/null 2>&1; then | ||
291 | echo "'$OPT_DATASET' is no ZFS dataset!" >&2 | ||
292 | echo "$USAGE" >&2 | ||
293 | exit $STATE_UNKNOWN | ||
294 | fi | ||
295 | |||
296 | NOW=$(_now_to_timestamp) | ||
297 | |||
298 | CREATION_DATE=$(_get_last_snapshot "$OPT_DATASET") | ||
299 | |||
300 | DIFF=$((NOW - CREATION_DATE)) | ||
301 | |||
302 | if [ "$OPT_WARNING" -gt "$OPT_CRITICAL" ]; then | ||
303 | echo '-w OPT_WARNING must be smaller than -c OPT_CRITICAL' | ||
304 | _usage >&2 | ||
305 | exit $STATE_UNKNOWN | ||
306 | fi | ||
307 | |||
308 | RETURN=STATE_UNKNOWN | ||
309 | |||
310 | if [ "$DIFF" -gt "$OPT_CRITICAL" ]; then | ||
311 | RETURN=$STATE_CRITICAL | ||
312 | MESSAGE="CRITICAL:" | ||
313 | elif [ "$DIFF" -gt "$OPT_WARNING" ]; then | ||
314 | RETURN=$STATE_WARNING | ||
315 | MESSAGE="WARNING:" | ||
316 | else | ||
317 | RETURN=$STATE_OK | ||
318 | MESSAGE="OK:" | ||
319 | fi | ||
320 | |||
321 | DATE="$(_timestamp_to_datetime "$CREATION_DATE")" | ||
322 | |||
323 | echo "$MESSAGE Last snapshot for dataset '$OPT_DATASET' was created on $DATE $(_performance_data)" | ||
324 | |||
325 | exit $RETURN | ||
diff --git a/flakes/private/monitoring/plugins/notify_by_apprise b/flakes/private/monitoring/plugins/notify_by_apprise new file mode 100755 index 0000000..82bc5a3 --- /dev/null +++ b/flakes/private/monitoring/plugins/notify_by_apprise | |||
@@ -0,0 +1,31 @@ | |||
1 | #!/usr/bin/env bash | ||
2 | |||
3 | APPRISE_USERNAME="Naemon" | ||
4 | APPRISE_USERICON="https://assets.immae.eu/monitoring.png" | ||
5 | APPRISE_URLS=$(echo "$2" | sed -e "s/{username}/$APPRISE_USERNAME/g" -e "s@{image_url}@$APPRISE_USERICON@g") | ||
6 | |||
7 | if [ "$SERVICESTATE" = "CRITICAL" ]; then | ||
8 | ICON="❗" | ||
9 | elif [ "$SERVICESTATE" = "WARNING" ]; then | ||
10 | ICON="⚠️:" | ||
11 | elif [ "$SERVICESTATE" = "OK" ]; then | ||
12 | ICON="✅" | ||
13 | elif [ "$SERVICESTATE" = "UNKNOWN" ]; then | ||
14 | ICON="❓" | ||
15 | elif [ "$HOSTSTATE" = "UP" ]; then | ||
16 | ICON="✅" | ||
17 | elif [ "$HOSTSTATE" = "DOWN" ]; then | ||
18 | ICON="❗" | ||
19 | elif [ "$HOSTSTATE" = "UNKNOWN" ]; then | ||
20 | ICON="❓" | ||
21 | elif [ "$HOSTSTATE" = "UNREACHABLE" ]; then | ||
22 | ICON="❓" | ||
23 | else | ||
24 | ICON="◻" | ||
25 | fi | ||
26 | |||
27 | if [ "$1" = "host" ]; then | ||
28 | apprise --title "${ICON} ${NOTIFICATIONTYPE} ${HOST} is ${HOSTSTATE}" --body "$HOSTOUTPUT" $APPRISE_URLS | ||
29 | else | ||
30 | apprise --title "${ICON} ${NOTIFICATIONTYPE} ${SERVICEDESC} on ${HOST} is ${SERVICESTATE}" --body "$SERVICEOUTPUT" $APPRISE_URLS | ||
31 | fi | ||
diff --git a/flakes/private/monitoring/plugins/notify_by_email b/flakes/private/monitoring/plugins/notify_by_email new file mode 100755 index 0000000..959db26 --- /dev/null +++ b/flakes/private/monitoring/plugins/notify_by_email | |||
@@ -0,0 +1,29 @@ | |||
1 | #!/usr/bin/env bash | ||
2 | |||
3 | # $1 = service/host | ||
4 | |||
5 | # $2 = type (PROBLEM RECOVERY ACKNOWLEDGEMENT FLAPPINGSTART FLAPPINGSTOP FLAPPINGDISABLED DOWNTIMESTART DOWNTIMESTOP DOWNTIMECANCELLED) | ||
6 | # http://www.naemon.org/documentation/usersguide/macrolist.html#notificationtype | ||
7 | |||
8 | # $3 = host alias | ||
9 | |||
10 | # $4 = date (YYYY-MM-DDTHH:MM:SS) | ||
11 | |||
12 | # $5 = E-mail | ||
13 | |||
14 | NOTIFICATION_TYPE="$2" | ||
15 | HOST_ALIAS="$3" | ||
16 | DATE="$4" | ||
17 | CONTACT="$5" | ||
18 | |||
19 | message="" | ||
20 | |||
21 | if [ "$1" = "host" ]; then | ||
22 | message=$(printf "%b" "***** Naemon *****\n\nNotification Type: $NOTIFICATION_TYPE\n\nHost: $HOST_ALIAS\nState: $HOSTSTATE\nInfo: $HOSTOUTPUT\n\nDate/Time: $DATE\n") | ||
23 | subject="** $NOTIFICATION_TYPE Host Alert: $HOST_ALIAS is $HOSTSTATE **" | ||
24 | else | ||
25 | message=$(printf "%b" "***** Naemon *****\n\nNotification Type: $NOTIFICATION_TYPE\n\nService: $SERVICEDESC\nHost: $HOST_ALIAS\nState: $SERVICESTATE\n\nDate/Time: $DATE\n\nAdditional Info:\n\n$SERVICEOUTPUT\n") | ||
26 | subject="** $NOTIFICATION_TYPE Service Alert: $HOST_ALIAS/$SERVICEDESC is $SERVICESTATE **" | ||
27 | fi | ||
28 | |||
29 | echo "$message" | MAILRC=/dev/null mail -r "$ADMINEMAIL" -n -s "$subject" "$CONTACT" | ||
diff --git a/flakes/private/monitoring/plugins/notify_by_slack b/flakes/private/monitoring/plugins/notify_by_slack new file mode 100755 index 0000000..1b16a0d --- /dev/null +++ b/flakes/private/monitoring/plugins/notify_by_slack | |||
@@ -0,0 +1,46 @@ | |||
1 | #!/usr/bin/env bash | ||
2 | |||
3 | SLACK_CHANNEL="$1" | ||
4 | SLACK_USERNAME="Naemon" | ||
5 | SLACK_URL="$2" | ||
6 | SLACK_USERICON="https://assets.immae.eu/monitoring.png" | ||
7 | |||
8 | if [ "$SERVICESTATE" = "CRITICAL" ]; then | ||
9 | ICON=":exclamation:" | ||
10 | COLOR="#DA0505" | ||
11 | elif [ "$SERVICESTATE" = "WARNING" ]; then | ||
12 | ICON=":warning:" | ||
13 | COLOR="#F1E903" | ||
14 | elif [ "$SERVICESTATE" = "OK" ]; then | ||
15 | ICON=":white_check_mark:" | ||
16 | COLOR="#36a64f" | ||
17 | elif [ "$SERVICESTATE" = "UNKNOWN" ]; then | ||
18 | ICON=":question:" | ||
19 | COLOR="#000000" | ||
20 | else | ||
21 | ICON=":white_medium_square:" | ||
22 | COLOR="#ffffff" | ||
23 | fi | ||
24 | |||
25 | payload=$(echo "{}" | jq -r \ | ||
26 | --arg "icon_url" "$SLACK_USERICON" \ | ||
27 | --arg "channel" "$SLACK_CHANNEL" \ | ||
28 | --arg "username" "$SLACK_USERNAME" \ | ||
29 | --arg "text" "${ICON} ${SERVICEDESC} on ${HOST} is ${SERVICESTATE}" \ | ||
30 | --arg "color" "$COLOR" \ | ||
31 | --arg "host" "$HOST" \ | ||
32 | --arg "desc" "$SERVICEDESC" \ | ||
33 | --arg "state" "$SERVICESTATE" \ | ||
34 | --arg "output" "$SERVICEOUTPUT" \ | ||
35 | '.icon_url = $icon_url | | ||
36 | .channel = $channel | | ||
37 | .username = $username | | ||
38 | .text = $text | | ||
39 | .attachments = [{fallback:"", color:$color,fields: [{},{},{},{}]}] | | ||
40 | .attachments[0].fields[0] = {title:"Host",value:$host,short:true} | | ||
41 | .attachments[0].fields[1] = {title:"Service description",value:$desc,short:true} | | ||
42 | .attachments[0].fields[2] = {title:"Status",value:$state,short:true} | | ||
43 | .attachments[0].fields[3] = {title:"Message",value:$output,short:false} | ||
44 | ') | ||
45 | |||
46 | curl -X POST --data "payload=$payload" $SLACK_URL | ||
diff --git a/flakes/private/monitoring/plugins/send_nrdp.sh b/flakes/private/monitoring/plugins/send_nrdp.sh new file mode 100755 index 0000000..c83c8cb --- /dev/null +++ b/flakes/private/monitoring/plugins/send_nrdp.sh | |||
@@ -0,0 +1,57 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | TEMPLATE='{ | ||
4 | "cmd": "submitcheck", | ||
5 | "token": $token, | ||
6 | "checkresult": [{ | ||
7 | "hostname": $hostname, | ||
8 | "state": $state, | ||
9 | "output": $output, | ||
10 | "type": $type, | ||
11 | "servicename": $servicename | ||
12 | }] | ||
13 | }' | ||
14 | |||
15 | while getopts "u:t:H:s:S:o:" option | ||
16 | do | ||
17 | case $option in | ||
18 | u) url=$OPTARG ;; | ||
19 | t) token=$OPTARG ;; | ||
20 | H) hostname=$OPTARG ;; | ||
21 | s) servicename=$OPTARG ;; | ||
22 | S) state=$OPTARG ;; | ||
23 | o) output=$OPTARG ;; | ||
24 | esac | ||
25 | done | ||
26 | |||
27 | if [ -n "$servicename" ]; then | ||
28 | checktype="service" | ||
29 | else | ||
30 | checktype="host" | ||
31 | fi | ||
32 | |||
33 | payload=$(jq -n \ | ||
34 | --arg type "$checktype" \ | ||
35 | --arg hostname "$hostname" \ | ||
36 | --arg servicename "$servicename" \ | ||
37 | --arg output "$output" \ | ||
38 | --arg token "$token" \ | ||
39 | --arg state "$state" \ | ||
40 | "$TEMPLATE") | ||
41 | |||
42 | rslt=$(curl -f --silent --insecure -d "$payload" -H "Content-Type: application/json" "$url") | ||
43 | ret=$? | ||
44 | |||
45 | if [ $ret != 0 ];then | ||
46 | echo "ERROR: could not connect to NRDP server at $url" | ||
47 | exit 1 | ||
48 | fi | ||
49 | |||
50 | status=$(echo "$rslt" | jq -r .status) | ||
51 | message=$(echo "$rslt" | jq -r .message) | ||
52 | |||
53 | if [ "$status" != "ok" ];then | ||
54 | echo "ERROR: The NRDP Server said $message" | ||
55 | exit 2 | ||
56 | fi | ||
57 | echo "Sent 1 checks to $url" | ||
diff --git a/flakes/private/monitoring/send_mails b/flakes/private/monitoring/send_mails new file mode 100755 index 0000000..105c505 --- /dev/null +++ b/flakes/private/monitoring/send_mails | |||
@@ -0,0 +1,15 @@ | |||
1 | #!/usr/bin/env bash | ||
2 | |||
3 | CHECK_DIR=$1 | ||
4 | shift | ||
5 | RETURN_PATH=$1 | ||
6 | shift | ||
7 | |||
8 | for mail in "$@"; do | ||
9 | echo "Test Mail" | MAILRC=/dev/null mail -n -r "$RETURN_PATH" -s "TestMailImmae " "$mail" | ||
10 | done | ||
11 | |||
12 | if [ -d "$CHECK_DIR" ]; then | ||
13 | cd $CHECK_DIR | ||
14 | stat -c '%n;%y' * | ||
15 | fi | ||
diff --git a/flakes/private/monitoring/to_objects.nix b/flakes/private/monitoring/to_objects.nix new file mode 100644 index 0000000..57a71ad --- /dev/null +++ b/flakes/private/monitoring/to_objects.nix | |||
@@ -0,0 +1,77 @@ | |||
1 | { lib }: | ||
2 | with lib.attrsets; | ||
3 | with lib.strings; | ||
4 | with lib.lists; | ||
5 | with lib.trivial; | ||
6 | let | ||
7 | pad = width: str: let | ||
8 | padWidth = width - stringLength str; | ||
9 | padding = concatStrings (genList (const " ") padWidth); | ||
10 | in str + optionalString (padWidth > 0) padding; | ||
11 | toStr = k: v: | ||
12 | if k == "check_command" && builtins.isList v | ||
13 | then builtins.concatStringsSep "!" v | ||
14 | else builtins.toString v; | ||
15 | |||
16 | toService = service: '' | ||
17 | define service { | ||
18 | ${builtins.concatStringsSep "\n" (mapAttrsToList (k: v: | ||
19 | " ${pad 30 k} ${toStr k v}" | ||
20 | ) (filterAttrs (k: v: ! hasPrefix "__passive_" k) service))} | ||
21 | } | ||
22 | ''; | ||
23 | toServices = services: builtins.concatStringsSep "\n" (map toService services); | ||
24 | |||
25 | toCommand = k: v: '' | ||
26 | define command { | ||
27 | ${pad 30 "command_name"} ${k} | ||
28 | ${pad 30 "command_line"} ${v} | ||
29 | } | ||
30 | ''; | ||
31 | toCommands = a: builtins.concatStringsSep "\n" (mapAttrsToList toCommand a); | ||
32 | |||
33 | toOther = keyname: k: v: '' | ||
34 | define ${keyname} { | ||
35 | ${pad 30 "${keyname}_name"} ${k} | ||
36 | ${builtins.concatStringsSep "\n" (mapAttrsToList (kk: vv: | ||
37 | " ${pad 30 kk} ${vv}" | ||
38 | ) v)} | ||
39 | } | ||
40 | ''; | ||
41 | toOtherNoName = keyname: v: '' | ||
42 | define ${keyname} { | ||
43 | ${builtins.concatStringsSep "\n" (mapAttrsToList (kk: vv: | ||
44 | " ${pad 30 kk} ${vv}" | ||
45 | ) v)} | ||
46 | } | ||
47 | ''; | ||
48 | toOthers = keyname: a: builtins.concatStringsSep "\n" (mapAttrsToList (toOther keyname) a); | ||
49 | toOthersArray = keyname: a: builtins.concatStringsSep "\n" (map (toOtherNoName keyname) a); | ||
50 | |||
51 | toTemplate = keyname: k: v: '' | ||
52 | define ${keyname} { | ||
53 | ${pad 30 "name"} ${k} | ||
54 | ${pad 30 "register"} 0 | ||
55 | ${builtins.concatStringsSep "\n" (mapAttrsToList (kk: vv: | ||
56 | " ${pad 30 kk} ${builtins.toString vv}" | ||
57 | ) v)} | ||
58 | } | ||
59 | ''; | ||
60 | toTemplates' = keyname: a: builtins.concatStringsSep "\n" (mapAttrsToList (toTemplate keyname) a); | ||
61 | toTemplates = v: builtins.concatStringsSep "\n" (mapAttrsToList toTemplates' v); | ||
62 | |||
63 | toObjects' = keyname: v: | ||
64 | if keyname == "service" | ||
65 | then toServices v | ||
66 | else if keyname == "command" | ||
67 | then toCommands v | ||
68 | else if keyname == "templates" | ||
69 | then toTemplates v | ||
70 | else if builtins.elem keyname ["hostgroup" "host" "contactgroup" "contact" "timeperiod" "servicegroup"] | ||
71 | then toOthers keyname v | ||
72 | else if builtins.elem keyname ["servicedependency" "hostdependency"] | ||
73 | then toOthersArray keyname v | ||
74 | else builtins.trace ("Warning: unknown object type " + keyname) ""; | ||
75 | toObjects = v: builtins.concatStringsSep "\n" (mapAttrsToList toObjects' v); | ||
76 | in | ||
77 | toObjects | ||