lol

munin: refactor package and add nixos service

+358 -9
+1
nixos/modules/module-list.nix
··· 128 128 ./services/monitoring/dd-agent.nix 129 129 ./services/monitoring/graphite.nix 130 130 ./services/monitoring/monit.nix 131 + ./services/monitoring/munin.nix 131 132 ./services/monitoring/nagios/default.nix 132 133 ./services/monitoring/smartd.nix 133 134 ./services/monitoring/statsd.nix
+216
nixos/modules/services/monitoring/munin.nix
··· 1 + { config, pkgs, ... }: 2 + 3 + # TODO: support munin-async 4 + # TODO: LWP/Pg perl libs aren't recognized 5 + 6 + # TODO: support fastcgi 7 + # http://munin-monitoring.org/wiki/CgiHowto2 8 + # spawn-fcgi -s /var/run/munin/fastcgi-graph.sock -U www-data -u munin -g munin /usr/lib/munin/cgi/munin-cgi-graph 9 + # spawn-fcgi -s /var/run/munin/fastcgi-html.sock -U www-data -u munin -g munin /usr/lib/munin/cgi/munin-cgi-html 10 + # https://paste.sh/vofcctHP#-KbDSXVeWoifYncZmLfZzgum 11 + # nginx http://munin.readthedocs.org/en/latest/example/webserver/nginx.html 12 + 13 + 14 + with pkgs.lib; 15 + 16 + let 17 + nodeCfg = config.services.munin-node; 18 + cronCfg = config.services.munin-cron; 19 + 20 + muninPlugins = pkgs.stdenv.mkDerivation { 21 + name = "munin-available-plugins"; 22 + buildCommand = '' 23 + mkdir -p $out 24 + 25 + cp --preserve=mode ${pkgs.munin}/lib/plugins/* $out/ 26 + 27 + for file in $out/*; do 28 + case "$file" in 29 + plugin.sh) continue;; 30 + esac 31 + 32 + # read magic makers from the file 33 + family=$(sed -nr 's/.*#%#\s+family\s*=\s*(\S+)\s*/\1/p' $file) 34 + cap=$(sed -nr 's/.*#%#\s+capabilities\s*=\s*(.+)/\1/p' $file) 35 + 36 + wrapProgram $file \ 37 + --set PATH "/run/current-system/sw/bin:/run/current-system/sw/sbin" \ 38 + --set MUNIN_LIBDIR "${pkgs.munin}/lib" \ 39 + --set MUNIN_PLUGSTATE "/var/run/munin" 40 + 41 + # munin uses markers to tell munin-node-configure what a plugin can do 42 + echo "#%# family=$family" >> $file 43 + echo "#%# capabilities=$cap" >> $file 44 + done 45 + 46 + # NOTE: we disable disktstats because plugin seems to fail and it hangs html generation (100% CPU + memory leak) 47 + rm -f $out/diskstats 48 + ''; 49 + buildInputs = [ pkgs.makeWrapper ]; 50 + }; 51 + 52 + muninConf = pkgs.writeText "munin.conf" 53 + '' 54 + dbdir /var/lib/munin 55 + htmldir /var/www/munin 56 + logdir /var/log/munin 57 + rundir /var/run/munin 58 + 59 + ${cronCfg.extraGlobalConfig} 60 + 61 + ${cronCfg.hosts} 62 + ''; 63 + 64 + nodeConf = pkgs.writeText "munin-node.conf" 65 + '' 66 + log_level 3 67 + log_file Sys::Syslog 68 + port 4949 69 + host * 70 + background 0 71 + user root 72 + group root 73 + host_name ${config.networking.hostName} 74 + setsid 0 75 + 76 + # wrapped plugins by makeWrapper being with dots 77 + ignore_file ^\. 78 + 79 + allow ^127\.0\.0\.1$ 80 + 81 + ${nodeCfg.extraConfig} 82 + ''; 83 + in 84 + 85 + { 86 + 87 + options = { 88 + 89 + services.munin-node = { 90 + 91 + enable = mkOption { 92 + default = false; 93 + description = '' 94 + Enable Munin Node agent. Munin node listens on 0.0.0.0 and 95 + by default accepts connections only from 127.0.0.1 for security reasons. 96 + 97 + See <link xlink:href='http://munin-monitoring.org/wiki/munin-node' />. 98 + ''; 99 + }; 100 + 101 + extraConfig = mkOption { 102 + default = ""; 103 + description = '' 104 + <filename>munin-node.conf</filename> extra configuration. See 105 + <link xlink:href='http://munin-monitoring.org/wiki/munin-node.conf' /> 106 + ''; 107 + }; 108 + 109 + # TODO: add option to add additional plugins 110 + 111 + }; 112 + 113 + services.munin-cron = { 114 + 115 + enable = mkOption { 116 + default = false; 117 + description = '' 118 + Enable munin-cron. Takes care of all heavy lifting to collect data from 119 + nodes and draws graphs to html. Runs munin-update, munin-limits, 120 + munin-graphs and munin-html in that order. 121 + 122 + HTML output is in <filename>/var/www/munin/</filename>, configure your 123 + favourite webserver to serve static files. 124 + ''; 125 + example = literalExample '' 126 + services = { 127 + munin-node.enable = true; 128 + munin-cron = { 129 + enable = true; 130 + hosts = ''' 131 + [''${config.networking.hostName}] 132 + address localhost 133 + '''; 134 + extraGlobalConfig = ''' 135 + contact.email.command mail -s "Munin notification for ''${var:host}" someone@example.com 136 + '''; 137 + }; 138 + }; 139 + ''; 140 + }; 141 + 142 + extraGlobalConfig = mkOption { 143 + default = ""; 144 + description = '' 145 + <filename>munin.conf</filename> extra global configuration. 146 + See <link xlink:href='http://munin-monitoring.org/wiki/munin-node' />. 147 + Useful to setup notifications, see 148 + <link xlink:href='http://munin-monitoring.org/wiki/HowToContact' /> 149 + ''; 150 + }; 151 + 152 + hosts = mkOption { 153 + example = '' 154 + [''${config.networking.hostName}] 155 + address localhost 156 + ''; 157 + description = '' 158 + Definitions of hosts of nodes to collect data from. Needs at least one 159 + hosts for cron to succeed. See 160 + <link xlink:href='http://munin-monitoring.org/wiki/munin.conf' /> 161 + ''; 162 + }; 163 + 164 + }; 165 + 166 + }; 167 + 168 + config = mkMerge [ (mkIf (nodeCfg.enable || cronCfg.enable) { 169 + 170 + environment.systemPackages = [ pkgs.munin ]; 171 + 172 + users.extraUsers = [{ 173 + name = "munin"; 174 + description = "Munin monitoring user"; 175 + group = "munin"; 176 + }]; 177 + 178 + users.extraGroups = [{ 179 + name = "munin"; 180 + }]; 181 + 182 + }) (mkIf nodeCfg.enable { 183 + 184 + systemd.services.munin-node = { 185 + description = "Munin node, the agent process"; 186 + after = [ "network.target" ]; 187 + wantedBy = [ "multi-user.target" ]; 188 + path = [ pkgs.munin ]; 189 + environment.MUNIN_PLUGSTATE = "/var/run/munin"; 190 + serviceConfig = { 191 + ExecStart = "${pkgs.munin}/sbin/munin-node --config ${nodeConf} --servicedir /etc/munin/plugins/"; 192 + }; 193 + }; 194 + 195 + system.activationScripts.munin-node = '' 196 + echo "updating munin plugins..." 197 + 198 + export PATH="/run/current-system/sw/bin:/run/current-system/sw/sbin"; 199 + mkdir -p /etc/munin/plugins 200 + rm -rf /etc/munin/plugins/* 201 + ${pkgs.munin}/sbin/munin-node-configure --shell --families contrib,auto,manual --config ${nodeConf} --libdir=${muninPlugins} --servicedir=/etc/munin/plugins 2>/dev/null | ${pkgs.bash}/bin/bash 202 + ''; 203 + 204 + }) (mkIf cronCfg.enable { 205 + 206 + services.cron.systemCronJobs = [ 207 + "*/5 * * * * munin ${pkgs.munin}/bin/munin-cron --config ${muninConf}" 208 + ]; 209 + 210 + system.activationScripts.munin-cron = stringAfter [ "users" "groups" ] '' 211 + mkdir -p /var/{run,log,www,lib}/munin 212 + chown -R munin:munin /var/{run,log,www,lib}/munin 213 + ''; 214 + 215 + })]; 216 + }
+84
pkgs/servers/monitoring/munin/adding_servicedir_munin-node.patch
··· 1 + From 75a3ec48814e7b9a9b22259a04009076363be3f1 Mon Sep 17 00:00:00 2001 2 + From: Igor Kolar <igor.kolar@gmail.com> 3 + Date: Thu, 17 Oct 2013 00:48:23 +0200 4 + Subject: [PATCH 1/2] node: added --servicedir switch to munin-node 5 + 6 + This code is copied over from munin-node-config, that already does the same 7 + --- 8 + node/sbin/munin-node | 7 ++++++- 9 + 1 file changed, 6 insertions(+), 1 deletion(-) 10 + 11 + diff --git a/node/sbin/munin-node b/node/sbin/munin-node 12 + index 7b2e180..0a93450 100755 13 + --- a/node/sbin/munin-node 14 + +++ b/node/sbin/munin-node 15 + @@ -35,7 +35,7 @@ use Munin::Node::OS; 16 + use Munin::Node::Service; 17 + use Munin::Node::Server; 18 + 19 + -my $servicedir; 20 + +my $servicedir = "$Munin::Common::Defaults::MUNIN_CONFDIR/plugins"; 21 + my $sconfdir = "$Munin::Common::Defaults::MUNIN_CONFDIR/plugin-conf.d"; 22 + my $conffile = "$Munin::Common::Defaults::MUNIN_CONFDIR/munin-node.conf"; 23 + my $DEBUG = 0; 24 + @@ -101,6 +101,7 @@ sub parse_args 25 + 26 + print_usage_and_exit() unless GetOptions( 27 + "config=s" => \$conffile, 28 + + "servicedir=s" => \$servicedir, 29 + "debug!" => \$DEBUG, 30 + "pidebug!" => \$PIDEBUG, 31 + "paranoia!" => \$paranoia, 32 + @@ -166,6 +167,10 @@ and returning the output they produce. 33 + 34 + Use E<lt>fileE<gt> as configuration file. [@@CONFDIR@@/munin-node.conf] 35 + 36 + +=item B<< --servicedir <dir> >> 37 + + 38 + +Override plugin directory [@@CONFDIR@@/plugins/] 39 + + 40 + =item B< --[no]paranoia > 41 + 42 + Only run plugins owned by root. Check permissions as well. [--noparanoia] 43 + -- 44 + 1.8.4 45 + 46 + 47 + From b8e17cbe73ae4c71b93ff5687ba86db1d0c1f5bd Mon Sep 17 00:00:00 2001 48 + From: Steve Schnepp <steve.schnepp@pwkf.org> 49 + Date: Thu, 17 Oct 2013 11:52:10 +0200 50 + Subject: [PATCH 2/2] node: untaint the service-dir args 51 + 52 + --- 53 + node/sbin/munin-node | 6 +++++- 54 + 1 file changed, 5 insertions(+), 1 deletion(-) 55 + 56 + diff --git a/node/sbin/munin-node b/node/sbin/munin-node 57 + index 0a93450..909c8c4 100755 58 + --- a/node/sbin/munin-node 59 + +++ b/node/sbin/munin-node 60 + @@ -99,9 +99,10 @@ sub parse_args 61 + { 62 + my @ORIG_ARGV = @ARGV; 63 + 64 + + my $servicedir_cmdline; 65 + print_usage_and_exit() unless GetOptions( 66 + "config=s" => \$conffile, 67 + - "servicedir=s" => \$servicedir, 68 + + "servicedir=s" => \$servicedir_cmdline, 69 + "debug!" => \$DEBUG, 70 + "pidebug!" => \$PIDEBUG, 71 + "paranoia!" => \$paranoia, 72 + @@ -109,6 +110,9 @@ sub parse_args 73 + "help" => \&print_usage_and_exit, 74 + ); 75 + 76 + + # We untaint the args brutally, since the sysadm should know what he does 77 + + $servicedir = $1 if defined $servicedir_cmdline && $servicedir_cmdline =~ m/(.*)/; 78 + + 79 + # Reset ARGV (for HUPing) 80 + @ARGV = @ORIG_ARGV; 81 + 82 + -- 83 + 1.8.4 84 +
+39 -9
pkgs/servers/monitoring/munin/default.nix
··· 1 1 { stdenv, fetchurl, makeWrapper, which, coreutils, rrdtool, perl, perlPackages 2 - , python, ruby, openjdk }: 3 - 4 - # TODO: split into server/node derivations 5 - 6 - # FIXME: munin tries to write log files and web graphs to its installation path. 2 + , python, ruby, openjdk, nettools }: 7 3 8 4 stdenv.mkDerivation rec { 9 5 version = "2.0.17"; ··· 19 15 which 20 16 coreutils 21 17 rrdtool 18 + nettools 22 19 perl 23 20 perlPackages.ModuleBuild 24 21 perlPackages.HTMLTemplate ··· 36 33 perlPackages.NetServer 37 34 perlPackages.ListMoreUtils 38 35 perlPackages.TimeHiRes 36 + perlPackages.LWPUserAgent 37 + perlPackages.DBDPg 39 38 python 40 39 ruby 41 40 openjdk 41 + # tests 42 + perlPackages.TestLongString 43 + perlPackages.TestDifferences 44 + perlPackages.TestDeep 45 + perlPackages.TestMockModule 46 + perlPackages.TestMockObject 47 + perlPackages.FileSlurp 48 + perlPackages.IOStringy 49 + ]; 50 + 51 + # TODO: tests are failing http://munin-monitoring.org/ticket/1390#comment:1 52 + # NOTE: important, test command always exits with 0, think of a way to abort the build once tests pass 53 + doCheck = false; 54 + 55 + checkPhase = '' 56 + export PERL5LIB="$PERL5LIB:${rrdtool}/lib/perl" 57 + LC_ALL=C make -j1 test 58 + ''; 59 + 60 + patches = [ 61 + # https://rt.cpan.org/Public/Bug/Display.html?id=75112 62 + ./dont_preserve_source_dir_permissions.patch 63 + 64 + # https://github.com/munin-monitoring/munin/pull/134 65 + ./adding_servicedir_munin-node.patch 42 66 ]; 43 67 44 68 preBuild = '' 69 + substituteInPlace "Makefile" \ 70 + --replace "/bin/pwd" "pwd" 71 + 72 + # munin checks at build time if user/group exists, unpure 45 73 sed -i '/CHECKUSER/d' Makefile 46 74 sed -i '/CHOWN/d' Makefile 47 75 sed -i '/CHECKGROUP/d' Makefile 48 - substituteInPlace "Makefile" \ 49 - --replace "/usr/pwd" "pwd" 76 + 77 + # munin hardcodes PATH, we need it to obey $PATH 78 + sed -i '/ENV{PATH}/d' node/lib/Munin/Node/Service.pm 50 79 ''; 51 80 52 81 # DESTDIR shouldn't be needed (and shouldn't have worked), but munin ··· 60 89 PYTHON=${python}/bin/python 61 90 RUBY=${ruby}/bin/ruby 62 91 JAVARUN=${openjdk}/bin/java 63 - HOSTNAME=default 92 + PLUGINUSER=munin 64 93 ''; 65 94 66 95 postFixup = '' ··· 78 107 case "$file" in 79 108 *.jar) continue;; 80 109 esac 81 - wrapProgram "$file" --set PERL5LIB $out/lib/perl5/site_perl:${perlPackages.Log4Perl}/lib/perl5/site_perl:${perlPackages.IOSocketInet6}/lib/perl5/site_perl:${perlPackages.Socket6}/lib/perl5/site_perl:${perlPackages.URI}/lib/perl5/site_perl:${perlPackages.DBFile}/lib/perl5/site_perl:${perlPackages.DateManip}/lib/perl5/site_perl:${perlPackages.HTMLTemplate}/lib/perl5/site_perl:${perlPackages.FileCopyRecursive}/lib/perl5/site_perl:${perlPackages.FCGI}/lib/perl5/site_perl:${perlPackages.NetSNMP}/lib/perl5/site_perl:${perlPackages.NetServer}/lib/perl5/site_perl:${perlPackages.ListMoreUtils}/lib/perl5/site_perl:${perlPackages.TimeHiRes}/lib/perl5/site_perl:${rrdtool}/lib/perl 110 + wrapProgram "$file" \ 111 + --set PERL5LIB "$out/lib/perl5/site_perl:${perlPackages.Log4Perl}/lib/perl5/site_perl:${perlPackages.IOSocketInet6}/lib/perl5/site_perl:${perlPackages.Socket6}/lib/perl5/site_perl:${perlPackages.URI}/lib/perl5/site_perl:${perlPackages.DBFile}/lib/perl5/site_perl:${perlPackages.DateManip}/lib/perl5/site_perl:${perlPackages.HTMLTemplate}/lib/perl5/site_perl:${perlPackages.FileCopyRecursive}/lib/perl5/site_perl:${perlPackages.FCGI}/lib/perl5/site_perl:${perlPackages.NetSNMP}/lib/perl5/site_perl:${perlPackages.NetServer}/lib/perl5/site_perl:${perlPackages.ListMoreUtils}/lib/perl5/site_perl:${perlPackages.TimeHiRes}/lib/perl5/site_perl:${rrdtool}/lib/perl:${perlPackages.DBDPg}/lib/perl5/site_perl:${perlPackages.LWPUserAgent}/lib/perl5/site_perl" 82 112 done 83 113 ''; 84 114
+18
pkgs/servers/monitoring/munin/dont_preserve_source_dir_permissions.patch
··· 1 + # https://rt.cpan.org/Public/Bug/Display.html?id=75112 2 + diff --git a/master/lib/Munin/Master/HTMLOld.pm b/master/lib/Munin/Master/HTMLOld.pm 3 + index 2b6e71f..c0aa2c0 100644 4 + --- a/master/lib/Munin/Master/HTMLOld.pm 5 + +++ b/master/lib/Munin/Master/HTMLOld.pm 6 + @@ -711,10 +711,12 @@ sub emit_main_index { 7 + 8 + sub copy_web_resources { 9 + my ($staticdir, $htmldir) = @_; 10 + + local $File::Copy::Recursive::KeepMode = 0; 11 + unless(dircopy($staticdir, "$htmldir/static")){ 12 + ERROR "[ERROR] Could not copy contents from $staticdir to $htmldir"; 13 + die "[ERROR] Could not copy contents from $staticdir to $htmldir"; 14 + } 15 + + local $File::Copy::Recursive::KeepMode = 1; 16 + } 17 + 18 + sub instanciate_comparison_templates {