From bf9c3caae930e466c603d9ed97024c36ef5d652a Mon Sep 17 00:00:00 2001 From: Artem Sheremet Date: Fri, 15 Nov 2013 23:46:37 +0300 Subject: [PATCH 01/33] Add open_files capability to ejabberd_resources_ It appears that erlang port is not bound to an OS file very often. Thus "ulimit -n" is moved to a separate graph and lsof/fstat is used as a backend to count the number of files open. --- .../ejabberd_resources_/ejabberd_resources_ | 63 ++++++++++++++----- 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/plugins/ejabberd/ejabberd_resources_/ejabberd_resources_ b/plugins/ejabberd/ejabberd_resources_/ejabberd_resources_ index 43d6ed27..f725183d 100755 --- a/plugins/ejabberd/ejabberd_resources_/ejabberd_resources_ +++ b/plugins/ejabberd/ejabberd_resources_/ejabberd_resources_ @@ -14,6 +14,7 @@ # - connect to a running ejabberd node # # OS: *NIX +# Requires lsof/fstat for open_files. # # Author: Artem Sheremet # @@ -120,7 +121,7 @@ code.info The total amount of memory currently allocated for Erlang code. This m ets.info The total amount of memory currently allocated for ets tables. This memory is part of the memory presented as system memory. INFO_FROM_DOC else - pid=$(<$EJABBERD_PID_PATH) + local pid=$(<$EJABBERD_PID_PATH) for memory_type in rss vsz; do memory_value=$(ps -p $pid -o $memory_type=) let memory_value=$memory_value*1024 @@ -140,42 +141,69 @@ function ejabberd_report_ports() { local limit=$(ejabberd_exec 'os:getenv("ERL_MAX_PORTS").' | tr '"' ' ') # string "false" indicates that this variable is not defined, thus a default of 1024 [ $limit = false ] && limit=1024 - local os_limit=$(ejabberd_exec 'os:cmd("ulimit -n").' | tr '"\\n' ' ') - if [ $limit -gt $os_limit ]; then - local real_limit=$os_limit - else - local real_limit=$limit - fi if [ "$1" = "config" ]; then cat </dev/null; then + echo lsof + return 0 + elif hash fstat &>/dev/null; then + echo fstat + return 0 + fi + return 1 +} + +function open_files_number() { + echo $[$($(open_files_counter_util) -np $(<$EJABBERD_PID_PATH) | wc -l)-1] +} + +function ejabberd_report_open_files() { + # this spawns a child process, but in most cases the open files limit is inherited + local limit=$(ejabberd_exec 'os:cmd("ulimit -n").' | tr '"\\n' ' ') + if [ "$1" = "config" ]; then + cat </dev/null && echo open_files exit 0 ;; config) From 1bf1090901895324bc0974a2ef50eabd46752275 Mon Sep 17 00:00:00 2001 From: Tuxis Internet Engineering Date: Mon, 16 Dec 2013 10:55:35 +0100 Subject: [PATCH 02/33] Add support for ZFS On Linux --- plugins/zfs/zfs_cache_efficiency | 52 +++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/plugins/zfs/zfs_cache_efficiency b/plugins/zfs/zfs_cache_efficiency index 7ea7a7a7..7f364dc5 100755 --- a/plugins/zfs/zfs_cache_efficiency +++ b/plugins/zfs/zfs_cache_efficiency @@ -6,10 +6,12 @@ #%# capabilities=autoconf sysctl='/sbin/sysctl' +ostype=`uname -s` +procfile='/proc/spl/kstat/zfs/arcstats' case $1 in config) - cat < Date: Fri, 20 Dec 2013 10:18:46 -0800 Subject: [PATCH 03/33] Removed deprecated hadoop command for hdfs Made hdfs user configurable (FIXME: user plugin.conf) --- plugins/hadoop/hadoop-dfs-plugin | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/hadoop/hadoop-dfs-plugin b/plugins/hadoop/hadoop-dfs-plugin index c99288e1..f89a165d 100755 --- a/plugins/hadoop/hadoop-dfs-plugin +++ b/plugins/hadoop/hadoop-dfs-plugin @@ -15,11 +15,12 @@ use strict; use File::Basename qw(basename); -my $type = &getType($0); +my $hdfs_user = "hdfs"; # # main # +my $type = &getType($0); if ($ARGV[0]) { if ($ARGV[0] eq "autoconf") { print "yes\n"; @@ -95,7 +96,7 @@ sub getCapacity { } sub getStatistics { - open(DFSADMIN, "hadoop dfsadmin -report|") || die("Cannot open dfsadmin: $!"); + open(DFSADMIN, "su $hdfs_user -c 'hdfs dfsadmin -report'|") || die("Cannot open dfsadmin: $!"); while(defined(my $line = )) { chomp($line); From 4682e4fee493b2589795a9fbfa05054fa1c2d086 Mon Sep 17 00:00:00 2001 From: tsaavik Date: Fri, 20 Dec 2013 10:26:40 -0800 Subject: [PATCH 04/33] better way to do it --- plugins/hadoop/hadoop-dfs-plugin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/hadoop/hadoop-dfs-plugin b/plugins/hadoop/hadoop-dfs-plugin index f89a165d..52075e59 100755 --- a/plugins/hadoop/hadoop-dfs-plugin +++ b/plugins/hadoop/hadoop-dfs-plugin @@ -96,7 +96,7 @@ sub getCapacity { } sub getStatistics { - open(DFSADMIN, "su $hdfs_user -c 'hdfs dfsadmin -report'|") || die("Cannot open dfsadmin: $!"); + open(DFSADMIN, "sudo -u $hdfs_user hdfs dfsadmin -report|") || die("Cannot open dfsadmin: $!"); while(defined(my $line = )) { chomp($line); From 10dc32cd07d6913431410ecdf68fc89dec9abe8e Mon Sep 17 00:00:00 2001 From: tsaavik Date: Fri, 20 Dec 2013 11:03:42 -0800 Subject: [PATCH 05/33] updated to user the perl munin module and user config from plugin-conf --- plugins/hadoop/hadoop-dfs-plugin | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/plugins/hadoop/hadoop-dfs-plugin b/plugins/hadoop/hadoop-dfs-plugin index 52075e59..4d1a4c7c 100755 --- a/plugins/hadoop/hadoop-dfs-plugin +++ b/plugins/hadoop/hadoop-dfs-plugin @@ -9,13 +9,21 @@ # Symlink this file to hadoop_hdfs_block or hadoop_hdfs_capacity to get block # or capacity informations about the DFS. # +# +# Needs following minimal configuration in plugin-conf.d/munin-node: +# [hadoop_hdfs_block] +# user hdfs +# +# [hadoop_hdfs_capacity] +# user hdfs +# # Author: KARASZI Istvan # use strict; use File::Basename qw(basename); +use Munin::Plugin; -my $hdfs_user = "hdfs"; # # main @@ -96,7 +104,7 @@ sub getCapacity { } sub getStatistics { - open(DFSADMIN, "sudo -u $hdfs_user hdfs dfsadmin -report|") || die("Cannot open dfsadmin: $!"); + open(DFSADMIN, "hdfs dfsadmin -report|") || die("Cannot open dfsadmin: $!"); while(defined(my $line = )) { chomp($line); From 08eefc25879742fd2c7b1e6d719aa8b4afe62772 Mon Sep 17 00:00:00 2001 From: tsaavik Date: Fri, 20 Dec 2013 13:06:41 -0800 Subject: [PATCH 06/33] don't collect/send redundant data to munin --- plugins/hadoop/hadoop-dfs-plugin | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/hadoop/hadoop-dfs-plugin b/plugins/hadoop/hadoop-dfs-plugin index 4d1a4c7c..5918f5a5 100755 --- a/plugins/hadoop/hadoop-dfs-plugin +++ b/plugins/hadoop/hadoop-dfs-plugin @@ -107,6 +107,9 @@ sub getStatistics { open(DFSADMIN, "hdfs dfsadmin -report|") || die("Cannot open dfsadmin: $!"); while(defined(my $line = )) { chomp($line); + if ($line =~ /-------------------------------------------------/) { + last + } if ($type eq "block") { &getBlock($line); From aec5ca142b5bdc12b3da4f7e1fc3a414a9fbd0ed Mon Sep 17 00:00:00 2001 From: Otavio Fernandes Date: Thu, 2 Jan 2014 09:56:19 +0100 Subject: [PATCH 07/33] Adding simple Bash script plugin to read information also from Netatalk v3. --- plugins/network/netatalk3 | 144 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100755 plugins/network/netatalk3 diff --git a/plugins/network/netatalk3 b/plugins/network/netatalk3 new file mode 100755 index 00000000..db05183b --- /dev/null +++ b/plugins/network/netatalk3 @@ -0,0 +1,144 @@ +#!/bin/bash - +# +#### Abstract ################################################################ +# +# Munin contributed plugin to measure open, locked and files being hold by +# Netatalk version 3.*; +# +#### Author ################################################################## +# +# Otavio Fernandes +# Wednesday, 01/01/2014 +# + +#### Functions ############################################################### +# + +function afpd_full_path () { + echo $(which afpd |head -n 1) +} + +function afp_related_file_exists () { + local afp_file_path=$1 + if [ -z "$afp_file_path" -o ! -f "$afp_file_path" ]; then + echo "ERROR: AFP related file not found: \"${afpd_bin_path}\";" >&2 + exit 1 + fi +} + +function is_netatalk_version_3 () { + local afpd_bin_path=$1 + version_string="$(${afpd_bin_path} -version |head -n1 |grep '^afpd' |cut -d' ' -f2)" + if [[ $version_string != 3\.* ]]; then + cat <&2 +ERROR: Netatalk is not version 3. + Binary: ${afpd_bin_path}; + Version: ${version_string}; +EOM + exit 1 + fi +} + +function count_running_procs () { + local afpd_bin_path=$1 + echo $(ps ax --no-headers -o command |grep "^${afpd_bin_path}" |wc -l) +} + +function count_connected_users () { + local afpd_bin_path=$1 + afpd_procs=$(ps anx --no-headers -o uid,command |grep -E "\w+\d+*\s${afpd_bin_path}" |wc -l) + # one of those processess will be always from root user, so it's not being + # used to externaly connect volumes, therefor being disconsider. + echo $(echo "${afpd_procs} - 1" |bc) +} + +function base_lsof () { + local afpd_bin_path=$1 + process_name="$(basename ${afpd_bin_path})" + excluded_fds="^DEL,^err,^jld,^ltx,^Mxx,^m86,^mem,^mmap,^pd,^rtd,^tr,^txt,^v86" + echo "lsof -a -c ${process_name} -d ${excluded_fds}" +} + +function count_locked_files () { + local afpd_bin_path=$1 + cmd_suffix="$(base_lsof "${afpd_bin_path}")" + echo "$(${cmd_suffix} -F -l |grep '^l[rRwWu]' |wc -l)" +} + +function probe_afp_conf_file () { + local afpd_bin_path=$1 + echo "$(${afpd_bin_path} -version 2>&1 |grep -E '^\s+afp.conf\:' |awk '{print $2}')" +} + +function count_open_shares () { + local afpd_bin_path=$1 + local afp_conf_path=$2 + + mounted=0 + declare -a shares=($(grep '^path.*\=' ${afp_conf_path} |awk -F '=' '{print $2}' |sed -E 's/^\s+//g')) + if [ ! -z "$shares" ]; then + # narrowing lsof results to only list configured mount directories + cmd_lookup_prefix=$(echo ${shares[@]} |tr " " "|") + cmd_suffix="$(base_lsof "${afpd_bin_path}")" + mounted=$(${cmd_suffix} -F n |grep '^n' |egrep "(${cmd_lookup_prefix})" |wc -l) + fi + echo $mounted +} + + +#### Main #################################################################### +# For all routines, holds the entry points dealing with the informed parameter +# or lack of it, meaning just print out collected data. +# + +case "$1" in + config) + # printing configuration for this plugin's produced data + cat < Date: Thu, 2 Jan 2014 17:42:28 -0500 Subject: [PATCH 08/33] fork the mysql_connections plugin to add per-user support --- plugins/mysql/mysql_connections_per_user | 192 +++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100755 plugins/mysql/mysql_connections_per_user diff --git a/plugins/mysql/mysql_connections_per_user b/plugins/mysql/mysql_connections_per_user new file mode 100755 index 00000000..e1da7130 --- /dev/null +++ b/plugins/mysql/mysql_connections_per_user @@ -0,0 +1,192 @@ +#!/usr/bin/perl +# +# Copyright (C) 2008 Rackspace US, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; version 2 dated June, +# 1991. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see http://www.gnu.org/licenses/gpl.txt +# +# +# This plugin is based off of the Connection Usage +# section of the MySQL Connection Health Page +# +# http://dev.mysql.com/doc/administrator/en/mysql-administrator-health-connection-health.html +# +# To enable, link mysql_connections to this file. E.g. +# +# ln -s /usr/share/node/node/plugins/mysql_connections /etc/munin/plugins/mysql_connections +# +# Revision 1.0 2007/08/03 +# Created by Justin Shepherd +# +# Revision 2.0 2013/01/02 +# Per user support by anarcat@koumbit.org +# +# Parameters: +# +# config +# autoconf +# +# Configuration variables +# +# mysqlopts - Options to pass to mysql +# mysqladmin - Override location of mysqladmin +# warning - Override default warning limit +# critical - Override default critical limit +# +#%# family=auto +#%# capabilities=autoconf + +use strict; + +# Define the mysqladmin paths, and commands +my $MYSQLADMIN = $ENV{mysqladmin} || "mysqladmin"; +my $TEST_COMMAND = "$MYSQLADMIN $ENV{mysqlopts} processlist"; +my $MYSQL_VARIABLES = "$MYSQLADMIN $ENV{mysqlopts} extended-status variables"; +my $warning = $ENV{warning} || "80"; +my $critical = $ENV{critical} || "90"; + +# Pull in any arguments +my $arg = shift(); + +# Check to see how the script was called +if ($arg eq 'config') { + print_graph_information(); + exit(); +} elsif ($arg eq 'autoconf') { + if (test_service()) { print "yes\n"; } + else { print "no\n"; } + exit; +} else { + # Define the values that are returned to munin + my ($current, $upper_limit) = (0,0,0); + + # Gather the values from mysqladmin + $current = poll_variables($MYSQL_VARIABLES,"Threads_connected"); + $upper_limit = poll_variables($MYSQL_VARIABLES,"max_connections"); + + # Return the values to Munin + print "current.value $current\n"; + print "limit.value $upper_limit\n"; + + my $threads = get_thread_list(); + my %counts = (); + my ($thread, $user, $count); + while (($thread, $user) = each %$threads) { + $counts{$user} = 0 unless defined($counts{$user}); + $counts{$user} += 1; + } + while (($user, $count) = each %counts) { + print "$user.value $count\n"; + } +} + + +sub poll_variables { + my $command = shift; + my $expression = shift; + my $ret = 0; + open(SERVICE, "$command |") + or die("Coult not execute '$command': $!"); + while () { + my ($field, $value) = (m/(\w+).*?(\d+(?:\.\d+)?)/); + next unless ($field); + if ($field eq $expression ) { + $ret = "$value"; + } + } + close(SERVICE); + return $ret; +} + + +sub print_graph_information { +print <) { + my ($threadid, $user) = split "\t"; + next unless ($threadid); + $threads{$threadid} = $user; + } + return \%threads; +} + + +sub test_service { + my $return = 1; + system ("$MYSQLADMIN --version >/dev/null 2>/dev/null"); + if ($? == 0) + { + system ("$TEST_COMMAND >/dev/null 2>/dev/null"); + if ($? == 0) + { + print "yes\n"; + $return = 0; + } + else + { + print "no (could not connect to mysql)\n"; + } + } + else + { + print "no (mysqladmin not found)\n"; + } + exit $return; +} From c2214999c390777fd3a3533e8c9d09bc1e7838dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoine=20Beaupr=C3=A9?= Date: Thu, 2 Jan 2014 18:47:44 -0500 Subject: [PATCH 09/33] limit to ten the number of users by default --- plugins/mysql/mysql_connections_per_user | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/plugins/mysql/mysql_connections_per_user b/plugins/mysql/mysql_connections_per_user index e1da7130..ee000707 100755 --- a/plugins/mysql/mysql_connections_per_user +++ b/plugins/mysql/mysql_connections_per_user @@ -40,6 +40,7 @@ # # mysqlopts - Options to pass to mysql # mysqladmin - Override location of mysqladmin +# numusers - Override maximum number of users to display # warning - Override default warning limit # critical - Override default critical limit # @@ -54,6 +55,7 @@ my $TEST_COMMAND = "$MYSQLADMIN $ENV{mysqlopts} processlist"; my $MYSQL_VARIABLES = "$MYSQLADMIN $ENV{mysqlopts} extended-status variables"; my $warning = $ENV{warning} || "80"; my $critical = $ENV{critical} || "90"; +my $numusers = $ENV{numusers} || 10; # Pull in any arguments my $arg = shift(); @@ -67,6 +69,11 @@ if ($arg eq 'config') { else { print "no\n"; } exit; } else { + print_graph_data(); + exit; +} + +sub print_graph_data() { # Define the values that are returned to munin my ($current, $upper_limit) = (0,0,0); @@ -85,8 +92,14 @@ if ($arg eq 'config') { $counts{$user} = 0 unless defined($counts{$user}); $counts{$user} += 1; } - while (($user, $count) = each %counts) { - print "$user.value $count\n"; + + sub valsort { + return $$threads{$a} <=> $$threads{$b}; + } + my $i = 0; + foreach my $user (sort valsort keys(%counts)) { + last if $i++ >= $numusers; + print "$user.value $counts{$user}\n"; } } From ade148171755f0029313f3ed35333a80173e6c74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoine=20Beaupr=C3=A9?= Date: Thu, 2 Jan 2014 18:47:52 -0500 Subject: [PATCH 10/33] cosmetic fixes --- plugins/mysql/mysql_connections_per_user | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/mysql/mysql_connections_per_user b/plugins/mysql/mysql_connections_per_user index ee000707..a3ac5374 100755 --- a/plugins/mysql/mysql_connections_per_user +++ b/plugins/mysql/mysql_connections_per_user @@ -88,9 +88,10 @@ sub print_graph_data() { my $threads = get_thread_list(); my %counts = (); my ($thread, $user, $count); + while (($thread, $user) = each %$threads) { $counts{$user} = 0 unless defined($counts{$user}); - $counts{$user} += 1; + $counts{$user}++; } sub valsort { @@ -103,7 +104,6 @@ sub print_graph_data() { } } - sub poll_variables { my $command = shift; my $expression = shift; From 88ba6e86bea88873841605295d04b2eba233e801 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoine=20Beaupr=C3=A9?= Date: Thu, 2 Jan 2014 18:52:58 -0500 Subject: [PATCH 11/33] reorder graph to, hopefully, fix stacking --- plugins/mysql/mysql_connections_per_user | 26 ++++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/plugins/mysql/mysql_connections_per_user b/plugins/mysql/mysql_connections_per_user index a3ac5374..9ec479da 100755 --- a/plugins/mysql/mysql_connections_per_user +++ b/plugins/mysql/mysql_connections_per_user @@ -82,9 +82,6 @@ sub print_graph_data() { $upper_limit = poll_variables($MYSQL_VARIABLES,"max_connections"); # Return the values to Munin - print "current.value $current\n"; - print "limit.value $upper_limit\n"; - my $threads = get_thread_list(); my %counts = (); my ($thread, $user, $count); @@ -102,6 +99,8 @@ sub print_graph_data() { last if $i++ >= $numusers; print "$user.value $counts{$user}\n"; } + print "current.value $current\n"; + print "limit.value $upper_limit\n"; } sub poll_variables { @@ -130,14 +129,6 @@ graph_vlabel Connections graph_info The number of current connexions per user. graph_category mysql graph_total Total -current.label In Use -current.draw LINE1 -current.info The number of current threads connected -current.warning $warning -current.critical $critical -limit.label Maximum -limit.draw LINE1 -limit.info The current value of the "max_connections" variable EOM my $threads = get_thread_list(); my %seen = (); @@ -148,7 +139,6 @@ while (($thread, $user) = each %$threads) { next; } else { - $seen{$user} = 1; print < Date: Thu, 2 Jan 2014 19:08:10 -0500 Subject: [PATCH 12/33] limit and sort the config entries the same way as we sort values, based on values --- plugins/mysql/mysql_connections_per_user | 62 +++++++++++------------- 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/plugins/mysql/mysql_connections_per_user b/plugins/mysql/mysql_connections_per_user index 9ec479da..d0c8f98e 100755 --- a/plugins/mysql/mysql_connections_per_user +++ b/plugins/mysql/mysql_connections_per_user @@ -82,17 +82,11 @@ sub print_graph_data() { $upper_limit = poll_variables($MYSQL_VARIABLES,"max_connections"); # Return the values to Munin - my $threads = get_thread_list(); - my %counts = (); - my ($thread, $user, $count); - - while (($thread, $user) = each %$threads) { - $counts{$user} = 0 unless defined($counts{$user}); - $counts{$user}++; - } + my $counts = count_thread_users(); + my %counts = %{$counts}; sub valsort { - return $$threads{$a} <=> $$threads{$b}; + return $counts{$a} <=> $counts{$b}; } my $i = 0; foreach my $user (sort valsort keys(%counts)) { @@ -130,31 +124,31 @@ graph_info The number of current connexions per user. graph_category mysql graph_total Total EOM -my $threads = get_thread_list(); -my %seen = (); -my ($thread, $user); -while (($thread, $user) = each %$threads) { - # display user only once - if (defined($seen{$user})) { - next; - } - else { - print < $counts{$b}; +} +my $i = 0; +foreach my $user (sort valsort keys(%counts)) { + last if $i++ >= $numusers; + print < 1) { + print "STACK\n"; + } + else { + print "AREA\n"; } - } + print <) { my ($threadid, $user) = split "\t"; next unless ($threadid); - $threads{$threadid} = $user; + $counts{$user} = 0 unless defined($counts{$user}); + $counts{$user}++; } - return \%threads; + return \%counts; } - sub test_service { my $return = 1; system ("$MYSQLADMIN --version >/dev/null 2>/dev/null"); From 6002cb63ebc8111b2d2fe4885cc82dbb1986c5d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoine=20Beaupr=C3=A9?= Date: Thu, 2 Jan 2014 19:17:09 -0500 Subject: [PATCH 13/33] overhaul graph display: remove total, make "current" the "limit" i did this because I can't figure out how to *not* stack the lines after the areas. furthermore, removing the limit is essential to have a proper resolution in the display. --- plugins/mysql/mysql_connections_per_user | 26 ++++++++---------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/plugins/mysql/mysql_connections_per_user b/plugins/mysql/mysql_connections_per_user index d0c8f98e..cc7bfbd0 100755 --- a/plugins/mysql/mysql_connections_per_user +++ b/plugins/mysql/mysql_connections_per_user @@ -75,11 +75,6 @@ if ($arg eq 'config') { sub print_graph_data() { # Define the values that are returned to munin - my ($current, $upper_limit) = (0,0,0); - - # Gather the values from mysqladmin - $current = poll_variables($MYSQL_VARIABLES,"Threads_connected"); - $upper_limit = poll_variables($MYSQL_VARIABLES,"max_connections"); # Return the values to Munin my $counts = count_thread_users(); @@ -89,12 +84,14 @@ sub print_graph_data() { return $counts{$a} <=> $counts{$b}; } my $i = 0; + my $total = 0; foreach my $user (sort valsort keys(%counts)) { last if $i++ >= $numusers; + $total += $counts{$user}; print "$user.value $counts{$user}\n"; } - print "current.value $current\n"; - print "limit.value $upper_limit\n"; + my $other = poll_variables($MYSQL_VARIABLES,"Threads_connected") - $total; + print "other.value $other\n"; } sub poll_variables { @@ -117,7 +114,7 @@ sub poll_variables { sub print_graph_information { print <= $numusers; print < Date: Thu, 2 Jan 2014 19:30:41 -0500 Subject: [PATCH 14/33] cosmetic --- plugins/mysql/mysql_connections_per_user | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/mysql/mysql_connections_per_user b/plugins/mysql/mysql_connections_per_user index cc7bfbd0..334fe04f 100755 --- a/plugins/mysql/mysql_connections_per_user +++ b/plugins/mysql/mysql_connections_per_user @@ -63,15 +63,13 @@ my $arg = shift(); # Check to see how the script was called if ($arg eq 'config') { print_graph_information(); - exit(); } elsif ($arg eq 'autoconf') { if (test_service()) { print "yes\n"; } else { print "no\n"; } - exit; } else { print_graph_data(); - exit; } +exit; sub print_graph_data() { # Define the values that are returned to munin From c255203d9a92181ef687792d53f52371c907dbc5 Mon Sep 17 00:00:00 2001 From: Johann Schmitz Date: Fri, 3 Jan 2014 06:55:00 +0100 Subject: [PATCH 15/33] Stub for juniper plugin --- plugins/snmp/snmp__juniper | 102 +++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 plugins/snmp/snmp__juniper diff --git a/plugins/snmp/snmp__juniper b/plugins/snmp/snmp__juniper new file mode 100644 index 00000000..0b5c21c7 --- /dev/null +++ b/plugins/snmp/snmp__juniper @@ -0,0 +1,102 @@ +#!/usr/bin/python + +# Copyright (C) 2014 Johann Schmitz +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; version 2 only +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +""" +=head1 NAME + +snmp__juniper - Health monitoring plugin for Juniper firewalls. + +=head1 CONFIGURATION + +Make sure your Juniper device is accessible via SNMP (e.g. via snmpwalk) and the munin-node +has been configured correctly + +=head1 MAGIC MARKERS + + #%# family=contrib + #%# capabilities= + +=head1 VERSION + +0.0.1 + +=head1 BUGS + +Open a ticket at https://github.com/ercpe/contrib if you find one. + +=head1 AUTHOR + +Johann Schmitz + +=head1 LICENSE + +GPLv2 + +=cut +""" + +import re +import sys +import os + +host = None +port = 161 +community = os.getenv('community', None) + +try: + match = re.search("^(?:|.*\/)snmp_([^_]+)_juniper$", sys.argv[0]) + host = match.group(1) + request = match.group(2) + match = re.search("^([^:]+):(\d+)$", host) + if match is not None: + host = match.group(1) + port = match.group(2) +except: + pass + +if not (host and port and community): + print "# Bad configuration. Cannot run with Host=%s, port=%s and community=%s" % (host, port, community) + sys.exit(1) + +def get_devices(): + pass + +def print_config(): + juntemp_tpl = """multigraph juniper_temperature%s +graph_title $host/%s system temperature +graph_vlabel °C +graph_category system +graph_info This graph shows the system temperature on $host + +temp.info System temperature in °C +temp.label temp +temp.type GAUGE +temp.min 0 +""" + +def print_data(): + pass + +if "config" in sys.argv[1:]: + print_config() +elif "snmpconf" in sys.argv[1:]: + #print "require 1.3.6.1.4.1.18928.1.2.2.1.8.1.1" + sys.exit(0) +else: + print_data() + sys.exit(0) \ No newline at end of file From 2eb7552c5d7154ead67697e04ec04a7008b9ef4d Mon Sep 17 00:00:00 2001 From: Igor Borodikhin Date: Fri, 3 Jan 2014 19:47:37 +0600 Subject: [PATCH 16/33] Fixed wrong path to munin-node config file in doc --- plugins/nginx/nginx_upstream_multi_ | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/nginx/nginx_upstream_multi_ b/plugins/nginx/nginx_upstream_multi_ index cf401594..07780041 100755 --- a/plugins/nginx/nginx_upstream_multi_ +++ b/plugins/nginx/nginx_upstream_multi_ @@ -25,7 +25,7 @@ # Use it in your site configuration (/etc/nginx/sites-enabled/anything.conf): # access_log /var/log/nginx/upstream.log upstream; # -# And specify some options in munin-node.conf: +# And specify some options in /etc/munin/plugin-conf.d/munin-node: # # [nginx_upstream_multi_upstream] # env.graphs cache http time request From 7ca5814ce75b6d0a075d2c4770a77c536b658e46 Mon Sep 17 00:00:00 2001 From: Lars Windolf Date: Tue, 7 Jan 2014 15:27:16 +0100 Subject: [PATCH 17/33] Avoid negative connection count on Sphinx restart Difference calculation can go negative when Sphinx is restarted. This makes ugly spikes in the graph. --- plugins/sphinx/sphinx_connections | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/sphinx/sphinx_connections b/plugins/sphinx/sphinx_connections index da389a0a..029a6db2 100755 --- a/plugins/sphinx/sphinx_connections +++ b/plugins/sphinx/sphinx_connections @@ -54,6 +54,9 @@ if (!file_exists($sTmpFilePath)) { fclose($fp); $toShow = (int) ($iCurrent - (int) $iOldCount); + if ($toShow < 0) { + $toShow = 0; + } } echo "current.value $toShow\n"; From b32ff11c61b145dd22cd09ed909e27675ed6cb14 Mon Sep 17 00:00:00 2001 From: Lars Windolf Date: Tue, 7 Jan 2014 15:28:01 +0100 Subject: [PATCH 18/33] Avoid negative queries count on Sphinx restart Difference calculation can go negative when Sphinx is restarted. This makes ugly spikes in the graph. --- plugins/sphinx/sphinx_queries | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/sphinx/sphinx_queries b/plugins/sphinx/sphinx_queries index 0862b7c3..7a9d9527 100755 --- a/plugins/sphinx/sphinx_queries +++ b/plugins/sphinx/sphinx_queries @@ -54,6 +54,9 @@ if (!file_exists($sTmpFilePath)) { fclose($fp); $toShow = (int) ($iCurrent - (int) $iOldCount); + if ($toShow < 0) { + $toShow = 0; + } } echo "current.value $toShow\n"; From 3e5627a223ecbf8e568059715f40de330bce6017 Mon Sep 17 00:00:00 2001 From: Luc Didry Date: Tue, 7 Jan 2014 16:54:13 +0100 Subject: [PATCH 19/33] [plugins/disk/du-2] Doc and autoconf updates --- plugins/disk/du-2 | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/plugins/disk/du-2 b/plugins/disk/du-2 index 39787e50..db991fb8 100755 --- a/plugins/disk/du-2 +++ b/plugins/disk/du-2 @@ -7,12 +7,15 @@ =head1 AUTHOR AND COPYRIGHT - Copyright 2011-2012 Luc Didry + Copyright 2011-2013 Luc Didry =head1 HOWTO CONFIGURE AND USE : =over +=item - /etc/munin/plugins/du + cp du /etc/munin/plugins/ + =item - /etc/munin/plugin-conf.d/du_ [du] @@ -22,14 +25,9 @@ env.suppr /home/ # PLEASE USE \# INSTEAD OF # timeout 900 # 15 MINUTES IN SECONDS -=item - /etc/munin/plugins-enabled - - ln -svf ../plugins-available/site/du - - =item - restart Munin node - sudo killall -TERM munin-node + /etc/init.d/munin-node restart =back @@ -73,7 +71,7 @@ my $TIMEFILE="$Munin::Plugin::pluginstatedir/du.time"; ##### autoconf if( (defined $ARGV[0]) && ($ARGV[0] eq "autoconf") ) { - print "yes\n"; + print "no\n"; ## Done ! munin_exit_done(); } From 89b632233c1752fb9d4e18d0da96717cd2d85a3a Mon Sep 17 00:00:00 2001 From: Luc Didry Date: Tue, 7 Jan 2014 17:02:08 +0100 Subject: [PATCH 20/33] Add new plugin : du_pattern --- plugins/disk/du_pattern | 78 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100755 plugins/disk/du_pattern diff --git a/plugins/disk/du_pattern b/plugins/disk/du_pattern new file mode 100755 index 00000000..b7d0df02 --- /dev/null +++ b/plugins/disk/du_pattern @@ -0,0 +1,78 @@ +#!/bin/sh +# -*- sh -*- +# vim: ft=sh + +: << =cut + +=head1 NAME + + du_pattern - plugin to monitor files size selected and grouped by a pattern + +=head1 CONFIGURATION + + [du_pattern] + env.DIR /var/log/apache/ + env.PATTERN www.example.com www.sample.com + + In PATTERN, all items will be expanded like this : www.example.com* + In this example, you will monitor the size of : + /var/log/apache/www.example.com* + /var/log/apache/www.sample.com* + + It's useful if you want to graph the size of your sites' log archives for example, + one graph per site. + +=head1 AUTHOR AND COPYRIGHT + + Copyright 2013 Luc Didry + +=head1 LICENSE + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +=cut + +NAME=${0##*/du_pattern_} + +if [ "$1" = "config" ]; then + echo "multigraph du_pattern_${NAME}" + echo "graph_title Files size in ${DIR}" + echo "graph_vlabel size of files" + echo "graph_category disk" + echo "graph_total Total" + echo "graph_info This graph shows the size of files grouped by a pattern." + FIRST=1 + for i in ${PATTERN} + do + CLEAN=${i//\./_} + echo "$CLEAN.label $CLEAN" + if [[ $FIRST -eq 1 ]] + then + echo "$CLEAN.draw AREA" + FIRST=0 + else + echo "$CLEAN.draw STACK" + fi + done + exit 0 +fi + +for i in ${PATTERN} +do + CLEAN=${i//\./_} + FILES="${DIR}/${i}*" + echo -n "$CLEAN.value " + echo $(du -cbs ${FILES} | grep total | cut -f 1) +done +exit 0 From 29e732d7ee389a3a96c4181fb46565a2b9ae795c Mon Sep 17 00:00:00 2001 From: Luc Didry Date: Tue, 7 Jan 2014 17:13:40 +0100 Subject: [PATCH 21/33] Add new plugin : postfwd2 --- plugins/mail/postfwd2 | 269 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 269 insertions(+) create mode 100755 plugins/mail/postfwd2 diff --git a/plugins/mail/postfwd2 b/plugins/mail/postfwd2 new file mode 100755 index 00000000..e1967d71 --- /dev/null +++ b/plugins/mail/postfwd2 @@ -0,0 +1,269 @@ +#!/usr/bin/perl +# vim: set filetype=perl sw=4 tabstop=4 expandtab smartindent: # + +=head1 NAME + + postfwd2 - plugin to get stats from postfwd2 + +=head1 AUTHOR AND COPYRIGHT + + Copyright 2013 Luc Didry + +=head1 HOWTO CONFIGURE AND USE : + +=over + +=item - /etc/munin/plugin-conf.d/postfwd2 + + [postfwd2] + user root + env.path /usr/local/sbin/postfwd2 # OPTIONAL : looks for postfwd2 in /bin, /sbin, /usr/bin, /usr/sbin, /usr/local/bin, /usr/local/sbin + env.include .*ISBAD #OPTIONAL + env.exclude .*ISGOOD #OPTIONAL + +=item - env.include and env.exclude + + This are perl regexp. + If env.include is set and env.exclude is not, only the policy which name + matchs will be used. + If env.exclude is set and env.include is not, only the policy which name NOT + matchs will be used. + If both are set, a policy which name matchs the both regex will be used, a + policy which matchs only the exclude regexp will NOT be used and a policy + which match not the exclude regex will be used, even if it not matchs the + include regexp. + if none are set, all the policy will be used. + + +=item - /etc/munin/plugins + + cp postfwd2 /etc/munin/plugins + + +=item - restart Munin node + + service munin-node restart + +=back + +=head1 LICENSE + + This program is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + this program. If not, see . + +=cut + +use warnings; +use strict; +use Munin::Plugin; + +need_multigraph(); + +my @keys =qw/cache_queries cache_stats policy_requests policy_timeout policy_matchs/; +my %graphs = ( + cache_queries => { + title => 'Cache queries', + vlabel => 'Nb of cache queries', + series => { + cache_queries => { + label => 'Cache queries', + type => 'COUNTER' + } + }, + }, + cache_stats => { + title => 'Cache stats', + vlabel => 'percent', + series => { + cache_requests => { + label => 'Requests hitrate', + type => 'GAUGE' + }, + cache_dns => { + label => 'Dns hitrate', + type => 'GAUGE' + }, + cache_rates => { + label => 'Rates hitrate', + type => 'GAUGE' + } + }, + }, + policy_requests => { + title => 'Policy requests', + vlabel => 'Nb of policy requests', + series => { + policy_requests => { + label => 'Policy requests', + type => 'COUNTER' + } + }, + }, + policy_timeout => { + title => 'Policy timeout', + vlabel => 'Nb of policy timeout', + series => { + policy_timeout => { + label => 'Policy timeout', + type => 'COUNTER' + } + } + }, + policy_matchs => { + title => 'Policy matchs', + vlabel => 'Matchs percentage' + } +); + +my $PLUGIN_NAME = 'postfwd2'; +my $CACHEFILE="$Munin::Plugin::pluginstatedir/postfwd2.cache"; + +my ($include, $exclude) = ($ENV{include}, $ENV{exclude}); +if (defined($include) && (!defined($exclude))) { + $exclude = '.*'; +} + +##### Cache file, to continue to graph old policies which doesn't exist anymore +if (!(-f $CACHEFILE) || !(-e $CACHEFILE)) { + open (FILE, ">", $CACHEFILE) or munin_exit_fail(); + close(FILE); +} +open (FILE, "<", $CACHEFILE) or munin_exit_fail(); +my @policies = ; +close(FILE); +my %policies = map { $_, 1 } @policies; +foreach my $policy (keys %policies) { + chomp $policy; + $graphs{policy_matchs}->{series}->{$policy}->{type} = 'GAUGE'; + $graphs{policy_matchs}->{series}->{$policy}->{label} = $policy; + $graphs{policy_matchs}->{series}->{$policy}->{value} = 0; +} + +##### Check postfwd2 path +if (!defined($ENV{path}) || !(-x $ENV{path})) { + foreach my $path (qw{/bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin}) { + $ENV{path} = $path.'/postfwd2' if (!defined($ENV{path}) && -x $path.'/postfwd2'); + last if (defined($ENV{path})); + } +} +munin_exit_fail() unless (defined($ENV{path}) && -x $ENV{path}); + +##### I have to parse the output BEFORE config, since policy matchs are dependant of the postfwd --dumpstats output +open(DATA, $ENV{path}.' --dumpstats |') or munin_exit_fail(); +my $total_requests; +while(defined (my $data = )) { + if ($data =~ m/^\[STATS\] postfwd2::cache .*: (\d+) queries since/) { + $graphs{cache_queries}->{series}->{cache_queries}->{value} = $1; + } + if ($data =~ m/^\[STATS\] Hitrates: ([\.\d]+)% requests, ([\.\d]+)% dns, ([\.\d]+)% rates$/) { + $graphs{cache_stats}->{series}->{cache_requests}->{value} = $1; + $graphs{cache_stats}->{series}->{cache_dns}->{value} = $2; + $graphs{cache_stats}->{series}->{cache_rates}->{value} = $3; + } + if ($data =~ m/^\[STATS\] postfwd2::policy .*: (\d+) requests since/) { + $graphs{policy_requests}->{series}->{policy_requests}->{value} = $1; + $total_requests = $1; + } + if ($data =~ m/^\[STATS\] Timeouts: .*% \((\d+) of \d+ dns queries\)$/) { + $graphs{policy_timeout}->{series}->{policy_timeout}->{value} = $1; + } + if ($data =~ m/^\[STATS\] +(\d+) matches for id: (.*)$/) { + my ($value, $label) = ($1, $2); + if ( ( !defined($exclude) ) || ( $label !~ m/$exclude/ || ( defined($include) && $label =~ m/$include/ ) ) ) { + if (!defined($policies{$label})) { + open (FILE, ">>", $CACHEFILE) or munin_exit_fail(); + print FILE $label, "\n"; + close(FILE); + $graphs{policy_matchs}->{series}->{$label}->{type} = 'GAUGE'; + $graphs{policy_matchs}->{series}->{$label}->{label} = $label; + } + $graphs{policy_matchs}->{series}->{$label}->{value} = sprintf("%.2f", 100*$value/$total_requests); + } + } +} +close(DATA); + +##### config +if( (defined $ARGV[0]) && ($ARGV[0] eq 'config') ) { + foreach my $key (@keys) { + print 'multigraph postfwd2_', $key, "\n"; + print 'graph_title Postfwd2 ', $graphs{$key}->{title}, "\n"; + print 'graph_vlabel ', $graphs{$key}->{vlabel}, "\n"; + my $args = ($key eq 'cache_stats') ? ' --upper-limit 100 --rigid' : ''; + print 'graph_args --lower-limit 0', $args, "\n"; + print 'graph_category mail', "\n"; + if ($key eq 'policy_matchs') { + print 'graph_width 600', "\n"; + my @pol_keys = sort { $graphs{$key}->{series}->{$b}->{value} <=> $graphs{$key}->{series}->{$a}->{value} } keys %{$graphs{$key}->{series}}; + foreach my $label (@pol_keys) { + print $label, '.label ', $graphs{$key}->{series}->{$label}->{label}, "\n"; + print $label, '.draw LINE', "\n"; + print $label, '.type ', $graphs{$key}->{series}->{$label}->{type}, "\n"; + } + foreach my $label (@pol_keys) { + print 'multigraph postfwd2_', $key, '.', $label, "\n"; + print 'graph_title Postfwd2 ', $label, "\n"; + print 'graph_vlabel ', $graphs{$key}->{vlabel}, "\n"; + print 'graph_width 600', "\n"; + print 'graph_args --lower-limit 0 ', $args, "\n"; + print 'graph_category others', "\n"; + print $label, '.label ', $graphs{$key}->{series}->{$label}->{label}, "\n"; + print $label, '.draw LINE', "\n"; + print $label, '.type GAUGE', "\n"; + } + } else { + foreach my $label (keys %{$graphs{$key}->{series}}) { + print $label, '.label ', $graphs{$key}->{series}->{$label}->{label}, "\n"; + print $label, '.draw AREASTACK', "\n"; + print $label, '.type ', $graphs{$key}->{series}->{$label}->{type}, "\n"; + } + } + } + munin_exit_done(); +} + +##### fetch +foreach my $key (@keys) { + print 'multigraph postfwd2_', $key, "\n"; + if ($key eq 'policy_matchs') { + my @pol_keys = sort { $graphs{$key}->{series}->{$b}->{value} <=> $graphs{$key}->{series}->{$a}->{value} } keys %{$graphs{$key}->{series}}; + foreach my $label (@pol_keys) { + print $label, '.value ', $graphs{$key}->{series}->{$label}->{value}, "\n"; + } + foreach my $label (@pol_keys) { + print 'multigraph postfwd2_', $key, '.', $label, "\n"; + print $label, '.value ', $graphs{$key}->{series}->{$label}->{value}, "\n"; + } + } else { + foreach my $label (keys %{$graphs{$key}->{series}}) { + print $label, '.value ', $graphs{$key}->{series}->{$label}->{value}, "\n"; + } + } +} +munin_exit_done(); + +# +## +### INTERNALS FONCTIONS +############################################################################### +sub munin_exit_done { + munin_exit(0); +} ## sub munin_exit_done + +sub munin_exit_fail { + munin_exit(1); +} ## sub munin_exit_fail + +sub munin_exit { + my $exitcode = shift; + exit($exitcode) if(defined $exitcode); + exit(1); +} ## sub munin_exit From 3f253ebec9a3558e41c84ba3c54221d2ad24d6ca Mon Sep 17 00:00:00 2001 From: Luc Didry Date: Tue, 7 Jan 2014 17:17:50 +0100 Subject: [PATCH 22/33] Copyright year update --- plugins/disk/du-2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/disk/du-2 b/plugins/disk/du-2 index db991fb8..41e4adc1 100755 --- a/plugins/disk/du-2 +++ b/plugins/disk/du-2 @@ -7,7 +7,7 @@ =head1 AUTHOR AND COPYRIGHT - Copyright 2011-2013 Luc Didry + Copyright 2011-2014 Luc Didry =head1 HOWTO CONFIGURE AND USE : From 54560ad5ed08527a56092c100bb9cdbc15fa7681 Mon Sep 17 00:00:00 2001 From: Luc Didry Date: Tue, 7 Jan 2014 17:21:06 +0100 Subject: [PATCH 23/33] Copyright year update --- plugins/disk/du_pattern | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/disk/du_pattern b/plugins/disk/du_pattern index b7d0df02..221cda77 100755 --- a/plugins/disk/du_pattern +++ b/plugins/disk/du_pattern @@ -24,7 +24,7 @@ =head1 AUTHOR AND COPYRIGHT - Copyright 2013 Luc Didry + Copyright 2013-2014 Luc Didry =head1 LICENSE From e838e28ee030a730653ca8721daea3533201b732 Mon Sep 17 00:00:00 2001 From: Luc Didry Date: Tue, 7 Jan 2014 17:22:21 +0100 Subject: [PATCH 24/33] Copyright year update --- plugins/mail/postfwd2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/mail/postfwd2 b/plugins/mail/postfwd2 index e1967d71..de9844aa 100755 --- a/plugins/mail/postfwd2 +++ b/plugins/mail/postfwd2 @@ -7,7 +7,7 @@ =head1 AUTHOR AND COPYRIGHT - Copyright 2013 Luc Didry + Copyright 2013-2014 Luc Didry =head1 HOWTO CONFIGURE AND USE : From 2fff9d6bac682c3802ada1797cdd3a53ad0e7f3a Mon Sep 17 00:00:00 2001 From: Johann Schmitz Date: Fri, 10 Jan 2014 14:17:05 +0100 Subject: [PATCH 25/33] First version of the juniper SNMP plugin --- plugins/snmp/snmp__juniper | 163 +++++++++++++++++++++++++++++++++---- 1 file changed, 145 insertions(+), 18 deletions(-) mode change 100644 => 100755 plugins/snmp/snmp__juniper diff --git a/plugins/snmp/snmp__juniper b/plugins/snmp/snmp__juniper old mode 100644 new mode 100755 index 0b5c21c7..f7b7523f --- a/plugins/snmp/snmp__juniper +++ b/plugins/snmp/snmp__juniper @@ -53,6 +53,9 @@ GPLv2 import re import sys import os +import logging + +from pysnmp.entity.rfc3413.oneliner import cmdgen host = None port = 161 @@ -73,30 +76,154 @@ if not (host and port and community): print "# Bad configuration. Cannot run with Host=%s, port=%s and community=%s" % (host, port, community) sys.exit(1) -def get_devices(): - pass +jnxOperatingTable = '1.3.6.1.4.1.2636.3.1.13.1.5' -def print_config(): - juntemp_tpl = """multigraph juniper_temperature%s -graph_title $host/%s system temperature -graph_vlabel °C +jnxOperatingTemp = '1.3.6.1.4.1.2636.3.1.13.1.7' +jnxOperatingCPU = '1.3.6.1.4.1.2636.3.1.13.1.8' +jnxOperatingBuffer = '1.3.6.1.4.1.2636.3.1.13.1.11' + +class JunOSSnmpClient(object): + def __init__(self, host, port, community): + self.transport = cmdgen.UdpTransportTarget((host, int(port))) + self.auth = cmdgen.CommunityData('test-agent', community) + self.gen = cmdgen.CommandGenerator() + + def get_devices(self): + errorIndication, errorStatus, errorIndex, varBindTable = self.gen.bulkCmd( + self.auth, + self.transport, + 0, 20, + jnxOperatingTable, + ignoreNonIncreasingOids=True) + + if errorIndication: + logging.error("SNMP bulkCmd for devices failed: %s, %s, %s" % (errorIndication, errorStatus, errorIndex)) + return {} + + devices = {} + for row in varBindTable: + for name, value in row: + if not str(name).startswith(jnxOperatingTable): + continue + + if str(value).endswith(' Routing Engine'): + devices[str(name)[len(jnxOperatingTable):]] = re.sub("[^\w]", '_', str(value).replace(' Routing Engine', '')) + return devices + + def get_one(self, prefix_oid, suffix): + oid = prefix_oid + suffix + errorIndication, errorStatus, errorIndex, varBindTable = self.gen.getCmd( + self.auth, + self.transport, + oid) + + if errorIndication: + logging.error("SNMP getCmd for %s failed: %s, %s, %s" % (oid, errorIndication, errorStatus, errorIndex)) + return None + + return int(varBindTable[0][1]) + + + + def get_data(self): + devs = self.get_devices() + + return { + 'temp': dict([(name, self.get_one(jnxOperatingTemp, suffix)) for suffix, name in devs.iteritems()]), + 'cpu': dict([(name, self.get_one(jnxOperatingCPU, suffix)) for suffix, name in devs.iteritems()]), + 'buffer': dict([(name, self.get_one(jnxOperatingBuffer, suffix)) for suffix, name in devs.iteritems()]), + } + + def print_config(self): + devices = self.get_devices() + + tpl = """multigraph juniper_temperature +graph_title $host system temperature +graph_vlabel System temperature in C per ${graph_period} graph_category system -graph_info This graph shows the system temperature on $host +graph_info System temperature for ${host} + +%s""" + + s = "" + for suffix, node in devices.iteritems(): + ident = "%s_temp" % node + s += """{label}.info System temperature on {node} +{label}.label {label} +{label}.type GAUGE32 +{label}.min 0 + +""".format(label=ident, node=node) + + print tpl % s + + + + + tpl = """multigraph juniper_cpu +graph_title $host CPU usage +graph_vlabel CPU usage in %% per ${graph_period} +graph_category system +graph_info CPU usage for ${host} + +%s""" + + s = "" + for suffix, node in devices.iteritems(): + ident = "cpu_%s" % node + s += """{label}.info CPU usage on {node} +{label}.label {label} +{label}.type GAUGE32 +{label}.min 0 +{label}.max 100 + +""".format(label=ident, node=node) + + print tpl % s + + + + tpl = """multigraph juniper_buffer +graph_title $host Buffer usage +graph_vlabel Buffer usage in %% per ${graph_period} +graph_category system +graph_info Buffer usage for ${host} + +%s""" + + s = "" + for suffix, node in devices.iteritems(): + ident = "buffer_%s" % node + s += """{label}.info Buffer usage on {node} +{label}.label {label} +{label}.type GAUGE32 +{label}.min 0 +{label}.max 100 + +""".format(label=ident, node=node) + + print tpl % s + + + + def execute(self): + data = self.get_data() +# import pprint +# pprint.pprint(data) + + for pre, values in data.iteritems(): + for node, value in values.iteritems(): + print "%s_%s.value %s" % (pre, node, value) -temp.info System temperature in °C -temp.label temp -temp.type GAUGE -temp.min 0 -""" def print_data(): pass +c = JunOSSnmpClient(host, port, community) if "config" in sys.argv[1:]: - print_config() -elif "snmpconf" in sys.argv[1:]: - #print "require 1.3.6.1.4.1.18928.1.2.2.1.8.1.1" - sys.exit(0) + c.print_config() +#elif "snmpconf" in sys.argv[1:]: +# #print "require 1.3.6.1.4.1.18928.1.2.2.1.8.1.1" +# sys.exit(0) else: - print_data() - sys.exit(0) \ No newline at end of file + c.execute() From ee0d7b38264b3dfd34b118ee755ccd8c22d95a69 Mon Sep 17 00:00:00 2001 From: Johann Schmitz Date: Fri, 10 Jan 2014 14:53:47 +0100 Subject: [PATCH 26/33] Some fixes --- plugins/snmp/snmp__juniper | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/snmp/snmp__juniper b/plugins/snmp/snmp__juniper index f7b7523f..8f332f22 100755 --- a/plugins/snmp/snmp__juniper +++ b/plugins/snmp/snmp__juniper @@ -93,8 +93,8 @@ class JunOSSnmpClient(object): self.auth, self.transport, 0, 20, - jnxOperatingTable, - ignoreNonIncreasingOids=True) + jnxOperatingTable) +# ignoreNonIncreasingOids=True) if errorIndication: logging.error("SNMP bulkCmd for devices failed: %s, %s, %s" % (errorIndication, errorStatus, errorIndex)) @@ -147,10 +147,10 @@ graph_info System temperature for ${host} s = "" for suffix, node in devices.iteritems(): - ident = "%s_temp" % node + ident = "temp_%s" % node s += """{label}.info System temperature on {node} {label}.label {label} -{label}.type GAUGE32 +{label}.type GAUGE {label}.min 0 """.format(label=ident, node=node) @@ -173,7 +173,7 @@ graph_info CPU usage for ${host} ident = "cpu_%s" % node s += """{label}.info CPU usage on {node} {label}.label {label} -{label}.type GAUGE32 +{label}.type GAUGE {label}.min 0 {label}.max 100 @@ -196,7 +196,7 @@ graph_info Buffer usage for ${host} ident = "buffer_%s" % node s += """{label}.info Buffer usage on {node} {label}.label {label} -{label}.type GAUGE32 +{label}.type GAUGE {label}.min 0 {label}.max 100 From acfd3e4e08cecabf2a9368fd12d088081579711a Mon Sep 17 00:00:00 2001 From: Johann Schmitz Date: Fri, 10 Jan 2014 15:03:13 +0100 Subject: [PATCH 27/33] Fixing trailing whitespaces --- plugins/snmp/snmp__juniper | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/snmp/snmp__juniper b/plugins/snmp/snmp__juniper index 8f332f22..e52d368d 100755 --- a/plugins/snmp/snmp__juniper +++ b/plugins/snmp/snmp__juniper @@ -183,7 +183,7 @@ graph_info CPU usage for ${host} - tpl = """multigraph juniper_buffer + tpl = """multigraph juniper_buffer graph_title $host Buffer usage graph_vlabel Buffer usage in %% per ${graph_period} graph_category system From f78847fbaeafe6e0e1cd90530239c8cea05e9110 Mon Sep 17 00:00:00 2001 From: Johann Schmitz Date: Sat, 11 Jan 2014 10:14:17 +0100 Subject: [PATCH 28/33] Fixed the plugin --- plugins/snmp/snmp__juniper | 130 +++++++++++++------------------------ 1 file changed, 44 insertions(+), 86 deletions(-) diff --git a/plugins/snmp/snmp__juniper b/plugins/snmp/snmp__juniper index e52d368d..44ee5ae3 100755 --- a/plugins/snmp/snmp__juniper +++ b/plugins/snmp/snmp__juniper @@ -1,4 +1,5 @@ #!/usr/bin/python +# -*- coding: utf-8 -*- # Copyright (C) 2014 Johann Schmitz # @@ -24,12 +25,12 @@ snmp__juniper - Health monitoring plugin for Juniper firewalls. =head1 CONFIGURATION Make sure your Juniper device is accessible via SNMP (e.g. via snmpwalk) and the munin-node -has been configured correctly +has been configured correctly. =head1 MAGIC MARKERS - #%# family=contrib - #%# capabilities= + #%# family=snmpauto + #%# capabilities=snmpconf =head1 VERSION @@ -58,9 +59,14 @@ import logging from pysnmp.entity.rfc3413.oneliner import cmdgen host = None -port = 161 +port = os.getenv('port', 161) community = os.getenv('community', None) +debug = bool(os.getenv('MUNIN_DEBUG', os.getenv('DEBUG', 0))) + +if debug: + logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)-7s %(message)s') + try: match = re.search("^(?:|.*\/)snmp_([^_]+)_juniper$", sys.argv[0]) host = match.group(1) @@ -72,10 +78,6 @@ try: except: pass -if not (host and port and community): - print "# Bad configuration. Cannot run with Host=%s, port=%s and community=%s" % (host, port, community) - sys.exit(1) - jnxOperatingTable = '1.3.6.1.4.1.2636.3.1.13.1.5' jnxOperatingTemp = '1.3.6.1.4.1.2636.3.1.13.1.7' @@ -84,6 +86,7 @@ jnxOperatingBuffer = '1.3.6.1.4.1.2636.3.1.13.1.11' class JunOSSnmpClient(object): def __init__(self, host, port, community): + self.hostname = host self.transport = cmdgen.UdpTransportTarget((host, int(port))) self.auth = cmdgen.CommunityData('test-agent', community) self.gen = cmdgen.CommandGenerator() @@ -94,7 +97,7 @@ class JunOSSnmpClient(object): self.transport, 0, 20, jnxOperatingTable) -# ignoreNonIncreasingOids=True) +# ignoreNonIncreasingOids=True) # only available with pysnmp >= 4.2.4 (?) if errorIndication: logging.error("SNMP bulkCmd for devices failed: %s, %s, %s" % (errorIndication, errorStatus, errorIndex)) @@ -106,6 +109,7 @@ class JunOSSnmpClient(object): if not str(name).startswith(jnxOperatingTable): continue + # TODO: Find a better way to get the routing engines in a cluster if str(value).endswith(' Routing Engine'): devices[str(name)[len(jnxOperatingTable):]] = re.sub("[^\w]", '_', str(value).replace(' Routing Engine', '')) return devices @@ -137,93 +141,47 @@ class JunOSSnmpClient(object): def print_config(self): devices = self.get_devices() - tpl = """multigraph juniper_temperature -graph_title $host system temperature -graph_vlabel System temperature in C per ${graph_period} -graph_category system -graph_info System temperature for ${host} + data_def = [ + ('temp', self.hostname, 'System temperature', '--base 1000', 'System temperature in C', 'system'), + ('cpu', self.hostname, 'CPU usage', '--base 1000 -l 0 --upper-limit 100', 'CPU usage in %', 'system'), + ('buffer', self.hostname, 'Buffer usage', '--base 1000 -l 0 --upper-limit 100', 'Buffer usage in %', 'system'), + ] -%s""" + for datarow, hostname, title, args, vlabel, category in data_def: + print """multigraph juniper_{datarow} +host_name {hostname} +graph_title {title} +graph_vlabel {vlabel} +graph_args {args} +graph_category {category} +graph_info {title}""".format(datarow=datarow, hostname=hostname, title=title, args=args, vlabel=vlabel, category=category) - s = "" - for suffix, node in devices.iteritems(): - ident = "temp_%s" % node - s += """{label}.info System temperature on {node} -{label}.label {label} + for suffix, node in devices.iteritems(): + ident = "%s_%s" % (datarow, node) + print """{label}.info {title} on {node} +{label}.label {node} {label}.type GAUGE -{label}.min 0 - -""".format(label=ident, node=node) - - print tpl % s - - - - - tpl = """multigraph juniper_cpu -graph_title $host CPU usage -graph_vlabel CPU usage in %% per ${graph_period} -graph_category system -graph_info CPU usage for ${host} - -%s""" - - s = "" - for suffix, node in devices.iteritems(): - ident = "cpu_%s" % node - s += """{label}.info CPU usage on {node} -{label}.label {label} -{label}.type GAUGE -{label}.min 0 -{label}.max 100 - -""".format(label=ident, node=node) - - print tpl % s - - - - tpl = """multigraph juniper_buffer -graph_title $host Buffer usage -graph_vlabel Buffer usage in %% per ${graph_period} -graph_category system -graph_info Buffer usage for ${host} - -%s""" - - s = "" - for suffix, node in devices.iteritems(): - ident = "buffer_%s" % node - s += """{label}.info Buffer usage on {node} -{label}.label {label} -{label}.type GAUGE -{label}.min 0 -{label}.max 100 - -""".format(label=ident, node=node) - - print tpl % s - - +{label}.min 0""".format(title=title, label=ident, node=node) def execute(self): data = self.get_data() -# import pprint -# pprint.pprint(data) for pre, values in data.iteritems(): + print "multigraph juniper_%s" % pre for node, value in values.iteritems(): print "%s_%s.value %s" % (pre, node, value) - -def print_data(): - pass - c = JunOSSnmpClient(host, port, community) -if "config" in sys.argv[1:]: - c.print_config() -#elif "snmpconf" in sys.argv[1:]: -# #print "require 1.3.6.1.4.1.18928.1.2.2.1.8.1.1" -# sys.exit(0) + +if "snmpconf" in sys.argv[1:]: + print "require 1.3.6.1.4.1.2636.3.1.13.1.5" + sys.exit(0) else: - c.execute() + if not (host and port and community): + print "# Bad configuration. Cannot run with Host=%s, port=%s and community=%s" % (host, port, community) + sys.exit(1) + + if "config" in sys.argv[1:]: + c.print_config() + else: + c.execute() From f52a7ea9a76d867877e5534c83d3ad3591b60121 Mon Sep 17 00:00:00 2001 From: Johann Schmitz Date: Sat, 11 Jan 2014 19:24:42 +0100 Subject: [PATCH 29/33] New plugin to monitor flow and cp sessions of Juniper firewalls via SNMP. --- plugins/snmp/snmp__juniper_spu | 228 +++++++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100755 plugins/snmp/snmp__juniper_spu diff --git a/plugins/snmp/snmp__juniper_spu b/plugins/snmp/snmp__juniper_spu new file mode 100755 index 00000000..ac84c3ab --- /dev/null +++ b/plugins/snmp/snmp__juniper_spu @@ -0,0 +1,228 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (C) 2014 Johann Schmitz +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; version 2 only +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +""" +=head1 NAME + +snmp__juniper_spu - Network monitoring plugin for the SPU's in Juniper firewalls. + +=head1 CONFIGURATION + +Make sure your Juniper device is accessible via SNMP (e.g. via snmpwalk) and the munin-node +has been configured correctly. + +=head1 MAGIC MARKERS + + #%# family=snmpauto + #%# capabilities=snmpconf + +=head1 VERSION + +0.0.1 + +=head1 BUGS + +Open a ticket at https://github.com/ercpe/contrib if you find one. + +=head1 AUTHOR + +Johann Schmitz + +=head1 LICENSE + +GPLv2 + +=cut +""" + +import re +import sys +import os +import logging + +from pysnmp.entity.rfc3413.oneliner import cmdgen + +host = None +port = os.getenv('port', 161) +community = os.getenv('community', "public") + +debug = bool(os.getenv('MUNIN_DEBUG', os.getenv('DEBUG', 0))) + +if debug: + logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)-7s %(message)s') + +try: + match = re.search("^(?:|.*\/)snmp_([^_]+)_juniper_spu$", sys.argv[0]) + host = match.group(1) + request = match.group(2) + match = re.search("^([^:]+):(\d+)$", host) + if match is not None: + host = match.group(1) + port = match.group(2) +except: + pass + +jnxJsSPUMonitoringObjectsTable = '1.3.6.1.4.1.2636.3.39.1.12.1.1' +#jnxJsSPUMonitoringIndex = jnxJsSPUMonitoringObjectsTable + '.1.1' +#jnxJsSPUMonitoringFPCIndex = jnxJsSPUMonitoringObjectsTable + '.1.2' +#jnxJsSPUMonitoringSPUIndex = jnxJsSPUMonitoringObjectsTable + '.1.3' +#jnxJsSPUMonitoringCPUUsage = jnxJsSPUMonitoringObjectsTable + '.1.4' +#jnxJsSPUMonitoringMemoryUsage = jnxJsSPUMonitoringObjectsTable + '.1.5' +jnxJsSPUMonitoringCurrentFlowSession = jnxJsSPUMonitoringObjectsTable + '.1.6' +jnxJsSPUMonitoringMaxFlowSession = jnxJsSPUMonitoringObjectsTable + '.1.7' +jnxJsSPUMonitoringCurrentCPSession = jnxJsSPUMonitoringObjectsTable + '.1.8' +jnxJsSPUMonitoringMaxCPSession = jnxJsSPUMonitoringObjectsTable + '.1.9' +#jnxJsSPUMonitoringNodeIndex = jnxJsSPUMonitoringObjectsTable + '.1.10' +jnxJsSPUMonitoringNodeDescr = jnxJsSPUMonitoringObjectsTable + '.1.11' +jnxJsSPUMonitoringFlowSessIPv4 = jnxJsSPUMonitoringObjectsTable + '.1.12' +jnxJsSPUMonitoringFlowSessIPv6 = jnxJsSPUMonitoringObjectsTable + '.1.13' +jnxJsSPUMonitoringCPSessIPv4 = jnxJsSPUMonitoringObjectsTable + '.1.14' +jnxJsSPUMonitoringCPSessIPv6 = jnxJsSPUMonitoringObjectsTable + '.1.15' + +class JunOSSnmpClient(object): + + def __init__(self, host, port, community): + self.hostname = host + self.transport = cmdgen.UdpTransportTarget((host, int(port))) + self.auth = cmdgen.CommunityData('test-agent', community) + self.gen = cmdgen.CommandGenerator() + + def get_data(self): + errorIndication, errorStatus, errorIndex, varBindTable = self.gen.bulkCmd( + self.auth, + self.transport, + 0, 10, + jnxJsSPUMonitoringObjectsTable) +# ignoreNonIncreasingOids=True) # only available with pysnmp >= 4.2.4 (?) and broken anyway + + if errorIndication: + logging.error("SNMP bulkCmd for devices failed: %s, %s, %s" % (errorIndication, errorStatus, errorIndex)) + return {} + + devices = {} + values = {} + for row in varBindTable: + for name, value in row: + if not str(name).startswith(jnxJsSPUMonitoringObjectsTable): + continue + + oid = str(name) + + nodeid = oid[oid.rindex('.'):] + + idx = oid[len(jnxJsSPUMonitoringObjectsTable)+3:] + idx = idx[:idx.index('.')] + + if oid.startswith(jnxJsSPUMonitoringNodeDescr): + devices[nodeid] = str(value) + continue + + values[oid] = int(value) + return devices, values + + def print_config(self): + devices, data = self.get_data() + + data_def = [ + ('flow', self.hostname, 'Flow sessions', '--base 1000', '# of sessions', jnxJsSPUMonitoringMaxFlowSession), + ('cp', self.hostname, 'Central point sessions', '--base 1000', '# of sessions', jnxJsSPUMonitoringMaxCPSession), + ] + + for datarow, hostname, title, args, vlabel, max_prefix in data_def: + print """multigraph juniper_{datarow} +host_name {hostname} +graph_title {title} +graph_vlabel {vlabel} +graph_args {args} +graph_category network +graph_info {title}""".format(datarow=datarow, hostname=hostname, title=title, args=args, vlabel=vlabel) + + for suffix, node in devices.iteritems(): + ident = "%s_%s" % (datarow, node) + print """{label}.info {title} on {node} +{label}.label {node} +{label}.type GAUGE +{label}.min 0 +{label}.max {max}""".format(title=title, label=ident, node=node, max=data.get(max_prefix + suffix)) + + for suffix, node in devices.iteritems(): + print """ +multigraph juniper_{datarow}.{node} +host_name {hostname} +graph_title {title} +graph_vlabel {vlabel} +graph_args {args} +graph_category network +graph_info {title} +{datarow}V4.info Current IPv4 {datarow} sessions +{datarow}V4.label IPv4 +{datarow}V4.draw AREASTACK +{datarow}V4.type GAUGE +{datarow}V6.info Current IPv6 {datarow} sessions +{datarow}V6.label IPv6 +{datarow}V6.draw AREASTACK +{datarow}V6.type GAUGE +{datarow}Current.info Current total {datarow} sessions +{datarow}Current.label Total +{datarow}Current.draw LINE1 +{datarow}Current.type GAUGE +{datarow}Current.colour 000000 +{datarow}Max.info Max. {datarow} sessions supported by the device(s) +{datarow}Max.label Max +{datarow}Max.draw LINE0 +{datarow}Max.type GAUGE +""".format(datarow=datarow, hostname=hostname, title=title, args=args, vlabel=vlabel, node=node) + + def execute(self): + devices, data = self.get_data() + + print "multigraph juniper_flow" + for suffix, node in devices.iteritems(): + print "flow_%s.value %s" % (node, data.get(jnxJsSPUMonitoringCurrentFlowSession + suffix, 0)) + + print "multigraph juniper_flow.%s" % node + print "flowV4.value %s" % data.get(jnxJsSPUMonitoringFlowSessIPv4 + suffix, 0) + print "flowV6.value %s" % data.get(jnxJsSPUMonitoringFlowSessIPv6 + suffix, 0) + print "flowCurrent.value %s" % data.get(jnxJsSPUMonitoringCurrentFlowSession + suffix, 0) + print "flowMax.value %s" % data.get(jnxJsSPUMonitoringMaxFlowSession + suffix, 0) + + print "multigraph juniper_cp" + for suffix, node in devices.iteritems(): + print "cp_%s.value %s" % (node, data.get(jnxJsSPUMonitoringCurrentCPSession + suffix, 0)) + + print "multigraph juniper_cp.%s" % node + print "cpV4.value %s" % data.get(jnxJsSPUMonitoringCPSessIPv4 + suffix, 0) + print "cpV6.value %s" % data.get(jnxJsSPUMonitoringCPSessIPv6 + suffix, 0) + print "cpCurrent.value %s" % data.get(jnxJsSPUMonitoringCurrentCPSession + suffix, 0) + print "cpMax.value %s" % data.get(jnxJsSPUMonitoringMaxCPSession + suffix, 0) + +c = JunOSSnmpClient(host, port, community) + +if "snmpconf" in sys.argv[1:]: + print "require %s" % (jnxJsSPUMonitoringObjectsTable, ) + sys.exit(0) +else: + if not (host and port and community): + print "# Bad configuration. Cannot run with Host=%s, port=%s and community=%s" % (host, port, community) + sys.exit(1) + + if "config" in sys.argv[1:]: + c.print_config() + else: + c.execute() From ae30c5979c63f114e4b19bedcfcbc482dfbcde27 Mon Sep 17 00:00:00 2001 From: Johann Schmitz Date: Sat, 11 Jan 2014 19:50:44 +0100 Subject: [PATCH 30/33] Finished the plugin --- plugins/snmp/snmp__juniper_spu | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/snmp/snmp__juniper_spu b/plugins/snmp/snmp__juniper_spu index ac84c3ab..c810d34a 100755 --- a/plugins/snmp/snmp__juniper_spu +++ b/plugins/snmp/snmp__juniper_spu @@ -158,7 +158,6 @@ graph_info {title}""".format(datarow=datarow, hostname=hostname, title=title, ar print """{label}.info {title} on {node} {label}.label {node} {label}.type GAUGE -{label}.min 0 {label}.max {max}""".format(title=title, label=ident, node=node, max=data.get(max_prefix + suffix)) for suffix, node in devices.iteritems(): @@ -196,6 +195,7 @@ graph_info {title} for suffix, node in devices.iteritems(): print "flow_%s.value %s" % (node, data.get(jnxJsSPUMonitoringCurrentFlowSession + suffix, 0)) + for suffix, node in devices.iteritems(): print "multigraph juniper_flow.%s" % node print "flowV4.value %s" % data.get(jnxJsSPUMonitoringFlowSessIPv4 + suffix, 0) print "flowV6.value %s" % data.get(jnxJsSPUMonitoringFlowSessIPv6 + suffix, 0) @@ -206,6 +206,7 @@ graph_info {title} for suffix, node in devices.iteritems(): print "cp_%s.value %s" % (node, data.get(jnxJsSPUMonitoringCurrentCPSession + suffix, 0)) + for suffix, node in devices.iteritems(): print "multigraph juniper_cp.%s" % node print "cpV4.value %s" % data.get(jnxJsSPUMonitoringCPSessIPv4 + suffix, 0) print "cpV6.value %s" % data.get(jnxJsSPUMonitoringCPSessIPv6 + suffix, 0) From 785dab37064b249fd1ca3300fc844ca27ef7a068 Mon Sep 17 00:00:00 2001 From: Johann Schmitz Date: Sun, 12 Jan 2014 08:18:21 +0100 Subject: [PATCH 31/33] Finished the juniper_spu plugin --- plugins/snmp/snmp__juniper_spu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/snmp/snmp__juniper_spu b/plugins/snmp/snmp__juniper_spu index c810d34a..920f0b83 100755 --- a/plugins/snmp/snmp__juniper_spu +++ b/plugins/snmp/snmp__juniper_spu @@ -164,7 +164,7 @@ graph_info {title}""".format(datarow=datarow, hostname=hostname, title=title, ar print """ multigraph juniper_{datarow}.{node} host_name {hostname} -graph_title {title} +graph_title {title} on {node} graph_vlabel {vlabel} graph_args {args} graph_category network From 59ecf3f15e63f1ebd80005696597daddc11b7f9b Mon Sep 17 00:00:00 2001 From: thefinn93 Date: Wed, 15 Jan 2014 19:07:28 -0800 Subject: [PATCH 32/33] Moved mailman-queue-check to the mailman folder --- plugins/{other => mail}/mailman-queue-check | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename plugins/{other => mail}/mailman-queue-check (100%) diff --git a/plugins/other/mailman-queue-check b/plugins/mail/mailman-queue-check similarity index 100% rename from plugins/other/mailman-queue-check rename to plugins/mail/mailman-queue-check From faca733fd6ab7168c1bbd03aae2b92814914dd2d Mon Sep 17 00:00:00 2001 From: thefinn93 Date: Wed, 15 Jan 2014 19:09:31 -0800 Subject: [PATCH 33/33] Added a category to mailman-queue-check --- plugins/mail/mailman-queue-check | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/mail/mailman-queue-check b/plugins/mail/mailman-queue-check index 8240a71c..4c75c792 100755 --- a/plugins/mail/mailman-queue-check +++ b/plugins/mail/mailman-queue-check @@ -17,6 +17,7 @@ if [ "$1" = "config" ]; then echo "graph_title Mailman Queue" + echo "graph_category mailman" echo "graph_args --base 1000 -l 0" echo "archive.label Archive" echo "archive.draw LINE2"