--- /dev/null
+Track incoming connections on console
+Track CPU utilization on the hosts
--- /dev/null
+[postfix_mailqueue]
+user munin
+command sudo -u postfix -E %c
+
+[postfix_mailvolume]
+user munin
+command sudo -u munin -E %c
+
+env.logfile mail.log
+env.logdir /var/log
--- /dev/null
+xvm-munin-config (0.0.1) unstable; urgency=low
+
+ * Initial Release.
+
+ -- Evan Broder <broder@mit.edu> Sat, 22 Nov 2008 05:52:10 -0500
--- /dev/null
+Source: xvm-munin-config
+Section: servers
+Priority: extra
+Maintainer: SIPB XVM Project <xvm@mit.edu>
+Build-Depends: cdbs, debhelper (>= 5), config-package-dev, munin-node
+Standards-Version: 3.7.2
+
+Package: xvm-munin-host-config
+Architecture: all
+Pre-Depends: smartmontools
+Depends: ${shlibs:Depends}, ${misc:Depends}, munin-node, adduser
+Description: Configure Munin monitoring on XVM hosts
+ Configure the munin-node daemon on all XVM servers. Each server gets
+ a set of plugins configured based on its function.
+ .
+ This package configures Munin on the XVM hosts
+
+Package: xvm-munin-master-config
+Architecture: all
+Depends: ${shlibs:Depends}, ${misc:Depends}, munin-node, adduser, libdbd-pg-perl
+Description: Configure Munin monitoring on XVM master server
+ Configure the munin-node daemon on all XVM servers. Each server gets
+ a set of plugins configured based on its function.
+ .
+ This package configures Munin on the master (web and database)
+ server.
+
+Package: xvm-munin-remote-config
+Architecture: all
+Depends: ${shlibs:Depends}, ${misc:Depends}, munin-node, adduser
+Description: Configure Munin monitoring on XVM remote servers
+ Configure the munin-node daemon on all XVM servers. Each server gets
+ a set of plugins configured based on its function.
+ .
+ This package configures Munin on the remote (remctl) server.
+
+Package: xvm-munin-console-config
+Architecture: all
+Depends: ${shlibs:Depends}, ${misc:Depends}, munin-node, adduser
+Description: Configure Munin monitoring on XVM console server
+ Configure the munin-node daemon on all XVM servers. Each server gets
+ a set of plugins configured based on its function.
+ .
+ This package configures Munin on the console server.
--- /dev/null
+This software was written for the XVM project <xvm@mit.edu>
+of the MIT Student Information Processing Board.
+
+Copyright :
+
+ 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 2 of the License, or
+ (at your option) 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.
+
+On Debian systems, the complete text of the GNU General Public License
+can be found in the file /usr/share/common-licenses/GPL.
--- /dev/null
+#!/usr/bin/make -f
+
+DEB_DIVERT_EXTENSION = .xvm
+
+DEB_DIVERT_FILES_xvm-munin-host-config += \
+ /etc/munin/munin-node.conf.xvm
+DEB_DIVERT_FILES_xvm-munin-master-config += \
+ /etc/munin/munin-node.conf.xvm
+DEB_DIVERT_FILES_xvm-munin-remote-config += \
+ /etc/munin/munin-node.conf.xvm
+DEB_DIVERT_FILES_xvm-munin-console-config += \
+ /etc/munin/munin-node.conf.xvm
+
+include /usr/share/cdbs/1/rules/config-package.mk
+include /usr/share/cdbs/1/rules/debhelper.mk
+
+common-build-indep:: debian/munin-node.conf.xvm.mako
+
+binary-post-install/%::
+ mkdir -p $(DEB_DESTDIR)/etc/munin
+ touch $(DEB_DESTDIR)/etc/munin/munin-node.conf.xvm
+
+debian/munin-node.conf.xvm.mako: $(call debian_check_files,/etc/munin/munin-node.conf)
+ debian/transform_munin-node.conf.xvm.mako < $< > $@
--- /dev/null
+#!/usr/bin/perl -n
+BEGIN {
+ print <<'EOF';
+<%
+from invirt.config import structs as cfg
+%>
+EOF
+}
+
+s/^user root/user munin/m;
+s/^group root/group munin/m;
+s/^node.startup = manual/node.startup = automatic/m;
+# mako just generally doesn't deal well with lines that start with
+# hashes, so we'll strip them
+#
+# And empty lines too, just for cleanliness
+s/^#.*$//m;
+print unless /^$/;
+
+END {
+ print <<'EOF';
+% for host in cfg.monitoring:
+allow ^${host.ip.replace('.', '\.')}$
+% endfor
+EOF
+}
--- /dev/null
+#!/bin/bash
+### BEGIN INIT INFO
+# Provides: xvm-munin-console-config
+# Required-Start: $local_fs $remote_fs
+# Required-Stop: $local_fs $remote_fs
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: XVM Munin config
+# Description:
+### END INIT INFO
+
+PACKAGE=xvm-munin-console-config
+PARENTPACKAGE=munin-node
+GEN_FILES=/etc/munin/munin-node.conf.xvm
+
+dpkg -s "$PACKAGE" >/dev/null 2>/dev/null || exit 0
+
+. /lib/init/config-init.sh
+config_init "$1"
--- /dev/null
+common/* .
+debian/munin-node.conf.xvm.mako etc/munin
--- /dev/null
+#!/bin/sh
+# postinst script for #PACKAGE#
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * <postinst> `configure' <most-recently-configured-version>
+# * <old-postinst> `abort-upgrade' <new version>
+# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
+# <new-version>
+# * <postinst> `abort-remove'
+# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
+# <failed-install-package> <version> `removing'
+# <conflicting-package> <version>
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ configure)
+ # So munin can read the mail log
+ adduser munin adm
+
+ # So munin can sudo to get to postfix queue info
+ cat >>/etc/sudoers <<EOF
+### BEGIN xvm-munin-config
+munin ALL=(postfix) SETENV: NOPASSWD: /etc/munin/plugins/postfix_mailqueue
+munin ALL=(munin) SETENV: NOPASSWD: ALL
+### END xvm-munin-config
+EOF
+
+ # Install munin plugins that are now configured
+ munin-node-configure --suggest --shell | sh
+
+ invoke-rc.d munin-node restart
+ ;;
+
+ abort-upgrade|abort-remove|abort-deconfigure)
+ ;;
+
+ *)
+ echo "postinst called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
--- /dev/null
+#!/bin/sh
+# prerm script for #PACKAGE#
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * <prerm> `remove'
+# * <old-prerm> `upgrade' <new-version>
+# * <new-prerm> `failed-upgrade' <old-version>
+# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
+# * <deconfigured's-prerm> `deconfigure' `in-favour'
+# <package-being-installed> <version> `removing'
+# <conflicting-package> <version>
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ remove|upgrade|deconfigure)
+ perl -i.bak -ne 's%^### (BEGIN|END) xvm-munin-config\s*$%%m && ($skip = ($1 eq "BEGIN")); print unless $skip;' /etc/sudoers
+ ;;
+
+ failed-upgrade)
+ ;;
+
+ *)
+ echo "prerm called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
+
+
--- /dev/null
+#!/bin/bash
+### BEGIN INIT INFO
+# Provides: xvm-munin-host-config
+# Required-Start: $local_fs $remote_fs
+# Required-Stop: $local_fs $remote_fs
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: XVM Munin config
+# Description:
+### END INIT INFO
+
+PACKAGE=xvm-munin-host-config
+PARENTPACKAGE=munin-node
+GEN_FILES=/etc/munin/munin-node.conf.xvm
+
+dpkg -s "$PACKAGE" >/dev/null 2>/dev/null || exit 0
+
+. /lib/init/config-init.sh
+config_init "$1"
--- /dev/null
+common/* .
+host/* .
+debian/munin-node.conf.xvm.mako etc/munin
--- /dev/null
+#!/bin/sh
+# postinst script for #PACKAGE#
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * <postinst> `configure' <most-recently-configured-version>
+# * <old-postinst> `abort-upgrade' <new version>
+# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
+# <new-version>
+# * <postinst> `abort-remove'
+# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
+# <failed-install-package> <version> `removing'
+# <conflicting-package> <version>
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ configure)
+ # So munin can read the mail log
+ adduser munin adm
+
+ # So munin can sudo to get to postfix queue info
+ cat >>/etc/sudoers <<EOF
+### BEGIN xvm-munin-config
+munin ALL=(postfix) SETENV: NOPASSWD: /etc/munin/plugins/postfix_mailqueue
+munin ALL=(munin) SETENV: NOPASSWD: ALL
+munin ALL=(root) SETENV: NOPASSWD: /etc/munin/plugins/hddtemp_smartctl , /etc/munin/plugins/smart_*
+### END xvm-munin-config
+EOF
+
+ # Install munin plugins that are now configured
+ munin-node-configure --suggest --shell | sh
+
+ invoke-rc.d munin-node restart
+ ;;
+
+ abort-upgrade|abort-remove|abort-deconfigure)
+ ;;
+
+ *)
+ echo "postinst called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
--- /dev/null
+#!/bin/sh
+# prerm script for #PACKAGE#
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * <prerm> `remove'
+# * <old-prerm> `upgrade' <new-version>
+# * <new-prerm> `failed-upgrade' <old-version>
+# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
+# * <deconfigured's-prerm> `deconfigure' `in-favour'
+# <package-being-installed> <version> `removing'
+# <conflicting-package> <version>
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ remove|upgrade|deconfigure)
+ perl -i.bak -ne 's%^### (BEGIN|END) xvm-munin-config\s*$%%m && ($skip = ($1 eq "BEGIN")); print unless $skip;' /etc/sudoers
+ ;;
+
+ failed-upgrade)
+ ;;
+
+ *)
+ echo "prerm called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
+
+
--- /dev/null
+#!/bin/bash
+### BEGIN INIT INFO
+# Provides: xvm-munin-master-config
+# Required-Start: $local_fs $remote_fs
+# Required-Stop: $local_fs $remote_fs
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: XVM Munin config
+# Description:
+### END INIT INFO
+
+PACKAGE=xvm-munin-master-config
+PARENTPACKAGE=munin-node
+GEN_FILES=/etc/munin/munin-node.conf.xvm
+
+dpkg -s "$PACKAGE" >/dev/null 2>/dev/null || exit 0
+
+. /lib/init/config-init.sh
+config_init "$1"
--- /dev/null
+common/* .
+master/* .
+debian/munin-node.conf.xvm.mako etc/munin
--- /dev/null
+#!/bin/sh
+# postinst script for #PACKAGE#
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * <postinst> `configure' <most-recently-configured-version>
+# * <old-postinst> `abort-upgrade' <new version>
+# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
+# <new-version>
+# * <postinst> `abort-remove'
+# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
+# <failed-install-package> <version> `removing'
+# <conflicting-package> <version>
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ configure)
+ # So munin can read the mail log
+ adduser munin adm
+
+ # So munin can sudo to get to postfix queue info
+ cat >>/etc/sudoers <<EOF
+### BEGIN xvm-munin-config
+munin ALL=(postfix) SETENV: NOPASSWD: /etc/munin/plugins/postfix_mailqueue
+munin ALL=(munin) SETENV: NOPASSWD: ALL
+### END xvm-munin-config
+EOF
+
+ # So munin can read from the database
+ su postgres -c 'createuser -S -D -R munin' || true
+ su postgres -c 'psql invirt --quiet' <<EOF
+GRANT SELECT ON pg_class TO munin;
+GRANT SELECT ON pg_index TO munin;
+GRANT SELECT ON pg_statio_user_tables TO munin;
+GRANT SELECT ON pg_stat_activity TO munin;
+GRANT SELECT ON pg_locks TO munin;
+EOF
+
+ # Install munin plugins that are now configured
+ munin-node-configure --suggest --shell | sh
+
+ invoke-rc.d munin-node restart
+ ;;
+
+ abort-upgrade|abort-remove|abort-deconfigure)
+ ;;
+
+ *)
+ echo "postinst called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
--- /dev/null
+#!/bin/sh
+# prerm script for #PACKAGE#
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * <prerm> `remove'
+# * <old-prerm> `upgrade' <new-version>
+# * <new-prerm> `failed-upgrade' <old-version>
+# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
+# * <deconfigured's-prerm> `deconfigure' `in-favour'
+# <package-being-installed> <version> `removing'
+# <conflicting-package> <version>
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ remove|upgrade|deconfigure)
+ perl -i.bak -ne 's%^### (BEGIN|END) xvm-munin-config\s*$%%m && ($skip = ($1 eq "BEGIN")); print unless $skip;' /etc/sudoers
+ ;;
+
+ failed-upgrade)
+ ;;
+
+ *)
+ echo "prerm called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
+
+
--- /dev/null
+#!/bin/bash
+### BEGIN INIT INFO
+# Provides: xvm-munin-remote-config
+# Required-Start: $local_fs $remote_fs
+# Required-Stop: $local_fs $remote_fs
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: XVM Munin config
+# Description:
+### END INIT INFO
+
+PACKAGE=xvm-munin-remote-config
+PARENTPACKAGE=munin-node
+GEN_FILES=/etc/munin/munin-node.conf.xvm
+
+dpkg -s "$PACKAGE" >/dev/null 2>/dev/null || exit 0
+
+. /lib/init/gen-files.sh
+. /lib/init/std-init.sh
+
+do_start () {
+ gen_files
+
+ mako-render /usr/share/xvm-munin-remote-config/loggrep_remctl.mako >/etc/munin/plugin-conf.d/loggrep_remctl
+
+ for p in "${PARENTPACKAGE[@]}"; do
+ invoke-rc.d "$p" restart
+ done
+}
+
+do_reload() {
+ do_start
+}
+
+do_stop() {
+ for p in "${PARENTPACKAGE[@]}"; do
+ invoke-rc.d "$p" stop
+ done
+}
+
+std_init "$1"
--- /dev/null
+common/* .
+remote/* .
+debian/munin-node.conf.xvm.mako etc/munin
--- /dev/null
+#!/bin/sh
+# postinst script for #PACKAGE#
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * <postinst> `configure' <most-recently-configured-version>
+# * <old-postinst> `abort-upgrade' <new version>
+# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
+# <new-version>
+# * <postinst> `abort-remove'
+# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
+# <failed-install-package> <version> `removing'
+# <conflicting-package> <version>
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ configure)
+ # So munin can read the mail log
+ adduser munin adm
+
+ # So munin can sudo to get to postfix queue info
+ cat >>/etc/sudoers <<EOF
+### BEGIN xvm-munin-config
+munin ALL=(postfix) SETENV: NOPASSWD: /etc/munin/plugins/postfix_mailqueue
+munin ALL=(munin) SETENV: NOPASSWD: ALL
+### END xvm-munin-config
+EOF
+
+ # Install munin plugins that are now configured
+ munin-node-configure --suggest --shell | sh
+
+ invoke-rc.d munin-node restart
+ ;;
+
+ abort-upgrade|abort-remove|abort-deconfigure)
+ ;;
+
+ *)
+ echo "postinst called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
--- /dev/null
+#!/bin/sh
+# prerm script for #PACKAGE#
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * <prerm> `remove'
+# * <old-prerm> `upgrade' <new-version>
+# * <new-prerm> `failed-upgrade' <old-version>
+# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
+# * <deconfigured's-prerm> `deconfigure' `in-favour'
+# <package-being-installed> <version> `removing'
+# <conflicting-package> <version>
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ remove|upgrade|deconfigure)
+ perl -i.bak -ne 's%^### (BEGIN|END) xvm-munin-config\s*$%%m && ($skip = ($1 eq "BEGIN")); print unless $skip;' /etc/sudoers
+ ;;
+
+ failed-upgrade)
+ ;;
+
+ *)
+ echo "prerm called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
+
+
--- /dev/null
+[hddtemp_smartctl]
+user root
+env.drives sda sdb
+command sudo -E %c
--- /dev/null
+[smart_*]
+user root
+command sudo -E %c
--- /dev/null
+[postgres_*]
+env.dbuser munin
--- /dev/null
+/usr/share/xvm-munin-master-config/postgres_block_read_
\ No newline at end of file
--- /dev/null
+/usr/share/xvm-munin-master-config/postgres_connections
\ No newline at end of file
--- /dev/null
+/usr/share/xvm-munin-master-config/postgres_locks
\ No newline at end of file
--- /dev/null
+/usr/share/xvm-munin-master-config/postgres_space_
\ No newline at end of file
--- /dev/null
+#!/usr/bin/perl -w
+# -*- perl -*-
+
+# Plugin to monitor Postgresql memory usage; gives number of blocks
+# read from disk and from memory, showing how much of the database is
+# served from Postgresql's memory buffer.
+#
+# PLEASE NOTE: This plugin may not present the whole truth - the truth
+# may actually be even better than this plugin will show you! That is
+# because Postgresql statistics only considers memory block reads from
+# its own allocated memory. When Postgresql reads from disk, it may
+# actually still be read from memory, but from the _kernel_'s
+# memory. Summarily, your database server may run even better than
+# this plugin will indicate. See
+# http://www.postgresql.org/docs/7.4/interactive/monitoring-stats.html
+# for a (short) description.
+#
+# Copyright BjØrn Ruberg <bjorn@linpro.no> 2006
+#
+# Licenced under GPL v2.
+#
+# Usage:
+#
+# Symlink into /etc/munin/plugins/ and add the monitored
+# database to the filename. e.g.:
+#
+# ln -s /usr/share/munin/plugins/postgres_block_read_ \
+# /etc/munin/plugins/postgres_block_read_SomeDatabase
+# This should, however, be given through autoconf and suggest.
+#
+# If required, give username, password and/or Postgresql server
+# host through environment variables.
+#
+# You must also activate Postgresql statistics. See
+# http://www.postgresql.org/docs/7.4/interactive/monitoring-stats.html
+# for how to enable this. Specifically, the following lines must
+# exist in your postgresql.conf:
+#
+# stats_start_collector = true
+# stats_block_level = true
+#
+#
+# Parameters:
+#
+# config (required)
+#
+# Config variables:
+#
+# dbhost - Which database server to use. Defaults to
+# 'localhost'.
+# dbport - Which port on the database server to connect to.
+# Defaults to '5432'.
+# dbuser - A Postgresql user account with read permission to
+# the given database. Defaults to
+# 'postgres'. Anyway, Munin must be told which user
+# this plugin should be run as.
+# dbpass - The corresponding password, if
+# applicable. Default to undef. Remember that
+# pg_hba.conf must be configured accordingly.
+#
+# Magic markers
+#%# family=auto
+#%# capabilities=autoconf suggest
+
+use strict;
+use DBI;
+use Data::Dumper;
+use vars qw ( $debug $suggest $configure $dbh );
+
+# Need these variables at an early stage to enable
+# autoconf and suggest
+my $dbhost = $ENV{'dbhost'} || ''; # Connect to localhost by default
+my $dbport = $ENV{'dbport'} || '';
+my $dbuser = $ENV{'dbuser'} || 'postgres';
+my $dbpass = $ENV{'dbpass'} || '';
+
+if (exists $ARGV[0]) {
+ if ($ARGV[0] eq 'autoconf') {
+ my $dbname = $ENV{'dbname'} || 'template1';
+ # Check for DBD::Pg
+ if (! eval "require DBD::Pg;") {
+ print "no (DBD::Pg not found)";
+ exit 1;
+ }
+ # Then we try to detect Postgres presence by connecting to
+ # 'template1'.
+ my $dsn = "dbi:Pg:dbname=template1";
+ $dsn .= ";host=$dbhost" if $dbhost;
+ $dsn .= ";port=$dbport" if $dbport;
+ my $tempdbh = DBI->connect ($dsn, $dbuser, $dbpass);
+ if ($tempdbh) {
+ print "yes\n";
+ exit 0;
+ } else {
+ print "no (Can't connect to given host, please check environment settings)\n";
+ exit 1;
+ }
+ } elsif ($ARGV[0] eq 'debug') {
+ # Set debug flag
+ $debug = 1;
+ } elsif ($ARGV[0] eq 'config') {
+ # Set config flag
+ $configure = 1;
+ } elsif ($ARGV[0] eq 'suggest') {
+ # doesn't always work
+ my @datasources = DBI->data_sources ('Pg');
+ foreach my $dsn (grep !/\=template\d$/, @datasources) {
+ (my $db = $dsn) =~ s/^.*=//;
+ print "$db\n";
+ }
+ exit 0;
+ }
+}
+
+# Must do this here, after checking for autoconf/suggest/etc, because the
+# plugin must be able to run before it is linked to the databases.
+my (undef, undef, undef, $dbname) = split (/_/, $0, 4);
+die "No dbname configured (did you make the proper symlink?)" unless $dbname;
+
+my @datasources = DBI->data_sources ('Pg')
+ or die ("Can't read any possible data sources: $?");
+
+my $dsn = "DBI:Pg:dbname=$dbname";
+$dsn .= ";host=$dbhost" if $dbhost;
+$dsn .= ";port=$dbport" if $dbport;
+print "#$dsn\n" if $debug;
+my $dbh = DBI->connect ($dsn, $dbuser, $dbpass, {RaiseError =>1});
+unless($dbh) {
+ die("Database $dbname\@$dbhost (". $DBI::errstr .")\n");
+}
+
+if ($configure) {
+ print <<EOF;
+graph_title Postgres data reads from $dbname
+graph_args --base 1000
+graph_vlabel Blocks read per \${graph_period}
+graph_category Postgresql
+graph_info Shows number of blocks read from disk and from memory
+from_disk.label Read from disk
+from_disk.info Read from disk
+from_disk.type DERIVE
+from_disk.min 0
+from_disk.draw AREA
+from_memory.label Cached in memory
+from_memory.info Cached in memory
+from_memory.type DERIVE
+from_memory.min 0
+from_memory.draw STACK
+EOF
+} else {
+ my $sql = "SELECT (SUM (heap_blks_read) + SUM (idx_blks_read) + ";
+ $sql .= "SUM (toast_blks_read) + SUM (tidx_blks_read)) AS disk, ";
+ $sql .= "(SUM (heap_blks_hit) +SUM (idx_blks_hit) + ";
+ $sql .= "SUM (toast_blks_hit) + SUM (tidx_blks_hit)) AS mem ";
+ $sql .= "from pg_statio_user_tables ";
+ print "# $sql\n" if $debug;
+ my $sth = $dbh->prepare ($sql);
+ $sth->execute();
+ if ($sth->rows > 0) {
+ printf ("# Rows: %d\n", $sth->rows) if $debug;
+ my ($disk, $mem) = $sth->fetchrow_array();
+ print "from_disk.value $disk\n";
+ print "from_memory.value $mem\n";
+ }
+}
--- /dev/null
+#!/usr/bin/perl -w
+# -*- perl -*-
+#
+
+use strict;
+use DBI;
+
+my $dbhost = $ENV{'dbhost'} || '';
+my $dbport = $ENV{'dbport'} || '';
+my $dbname = $ENV{'dbname'} || 'template1';
+my $dbuser = $ENV{'dbuser'} || 'postgres';
+
+my $Con = "DBI:Pg:dbname=$dbname";
+$Con .= ";host=$dbhost" if $dbhost;
+$Con .= ";port=$dbport" if $dbport;
+my $Dbh = DBI->connect ($Con, $dbuser,'',{RaiseError =>1}) ||
+ die "Unable to access Database $dbname on host $dbhost as user $dbuser.\nError returned was: ". $DBI::errstr;
+
+if ($ARGV[0] && $ARGV[0] eq 'config') {
+ my $sql_max = "SHOW max_connections;";
+ my $sth_max = $Dbh->prepare($sql_max);
+ $sth_max->execute();
+ my ($max_conn) = $sth_max->fetchrow();
+ my $warning = int ($max_conn * 0.7);
+ my $critical = int ($max_conn * 0.8);
+ print <<EOF;
+graph_title Postgres active connections
+graph_args -l 0 --base 1000
+graph_vlabel Active connections
+graph_category Postgresql
+graph_info Shows active Postgresql connections
+connections.label Active connections
+connections.info Active connections
+connections.type GAUGE
+connections.warning $warning
+connections.critical $critical
+EOF
+} else {
+ my $sql_curr = "SELECT COUNT (*) FROM pg_stat_activity;";
+ my $sth_curr = $Dbh->prepare($sql_curr);
+ $sth_curr->execute();
+ my ($curr_conn) = $sth_curr->fetchrow();
+ print "connections.value $curr_conn\n";
+}
--- /dev/null
+#!/usr/bin/perl -w
+# -*- perl -*-
+#
+# Show postgres lock statistics
+#
+# Parameters:
+#
+# config (required)
+#
+# Config variables:
+#
+# dbhost - Which database server to use. Defaults to
+# 'localhost'.
+# dbport - Which port on the database server to connect to.
+# Defaults to '5432'.
+# dbuser - A Postgresql user account with read permission to
+# the given database. Defaults to
+# 'postgres'. Anyway, Munin must be told which user
+# this plugin should be run as.
+# dbpass - The corresponding password, if
+# applicable. Default to undef. Remember that
+# pg_hba.conf must be configured accordingly.
+#
+# Magic markers
+#%# family=auto
+#%# capabilities=suggest
+
+use strict;
+use DBI;
+
+# See postgress_block_read_ for docs
+
+my $dbhost = $ENV{'dbhost'} || '';
+my $dbport = $ENV{'dbport'} || '';
+my $dbname = $ENV{'dbname'} || 'template1';
+my $dbuser = $ENV{'dbuser'} || 'postgres';
+
+if ($ARGV[0] && $ARGV[0] eq "config") {
+ print <<EOF;
+graph_title Postgres locks
+graph_args --base 1000
+graph_vlabel Locks
+graph_category Postgresql
+graph_info Shows Postgresql locks
+locks.label Locks
+locks.info Locks (more info here, please... :)
+locks.type GAUGE
+locks.warning 5
+locks.critical 10
+exlocks.label Exclusive locks
+exlocks.info Exclusive locks (here too, please... :)
+exlocks.type GAUGE
+exlocks.warning 5
+exlocks.critical 10
+EOF
+} else {
+ my $Con = "DBI:Pg:dbname=$dbname";
+ $Con .= ";host=$dbhost" if $dbhost;
+ $Con .= ";port=$dbport" if $dbport;
+ my $Dbh = DBI->connect ($Con, $dbuser,
+ '',
+ {RaiseError =>1}) || die "Unable to access Database $dbname on host $dbhost as user $dbuser.\nError returned was: ". $DBI::errstr;
+
+ my $sql="SELECT mode,COUNT(mode) FROM pg_locks GROUP BY mode ORDER BY mode;";
+ my $sth = $Dbh->prepare ($sql);
+ $sth->execute ();
+ my $locks = 0;
+ my $exlocks = 0;
+ while (my ($mode, $count) = $sth->fetchrow ()) {
+ if ($mode =~ /exclusive/i) {
+ $exlocks = $exlocks + $count;
+ }
+ $locks = $locks+$count;
+ }
+ print "locks.value $locks\n";
+ print "exlocks.value $exlocks\n";
+}
--- /dev/null
+#!/usr/bin/perl -w
+# -*- perl -*-
+
+# Written by Bjrn Ruberg (bjorn@linpro.no) 2006
+# Rewritten by Moses Moore 2006-04-08 moc.iazom@sesom
+# Licenced under GPL
+
+# Magic markers
+#%# family=auto
+#%# capabilities=autoconf suggest
+
+use strict;
+use DBI;
+use vars qw ( $debug $suggest $configure $dbh );
+
+# Package maintainers should provide an environment
+# file for the /etc/munin/plugin-conf.d/ directory
+# to override these values if necessary.
+# NOTE: The plugin (also when auto configured) should
+# be run by the postgresql user account.
+
+# Need these variables at an early stage to enable
+# autoconf and suggest
+my $dbhost = $ENV{'dbhost'} || ''; # Connect to localhost by default
+my $dbport = $ENV{'dbport'} || '';
+my $dbuser = $ENV{'dbuser'} || 'postgres';
+my $dbpass = $ENV{'dbpass'} || '';
+
+if (exists $ARGV[0]) {
+ if ($ARGV[0] eq 'autoconf') {
+ # Check for DBD::Pg
+ if (! eval "require DBD::Pg;") {
+ print "no (DBD::Pg not found)";
+ exit 1;
+ }
+ # Then we try to detect Postgres presence by connecting to
+ # 'template1'.
+ my $dsn = "dbi:Pg:dbname=template1";
+ $dsn .= ";host=$dbhost" if $dbhost;
+ $dsn .= ";port=$dbport" if $dbport;
+ my $tempdbh = DBI->connect ($dsn, $dbuser, $dbpass);
+ if ($tempdbh) {
+ print "yes\n";
+ exit 0;
+ } else {
+ print "no (Can't connect to given host, please check environment settings)\n";
+ exit 1;
+ }
+ } elsif ($ARGV[0] and $ARGV[0] eq 'debug') {
+ # Set config flag
+ $debug = 1;
+ } elsif ($ARGV[0] and $ARGV[0] eq 'config') {
+ # Set config flag
+ $configure = 1;
+ } elsif ($ARGV[0] eq 'suggest') {
+ # doesn't always work
+ my @datasources = DBI->data_sources ('Pg');
+ foreach my $dsn (grep !/\=template\d$/, @datasources) {
+ (my $db = $dsn) =~ s/^.*=//;
+ print "$db\n";
+ }
+ exit 0;
+ }
+}
+
+# Must do this here, after checking for autoconf/suggest/etc, because the
+# plugin must be able to run before it is linked to the databases.
+my (undef, undef, $dbname) = split (/_/, $0, 3);
+die "No dbname configured (did you make the proper symlink?)" unless $dbname;
+
+my @datasources = DBI->data_sources ('Pg')
+ or die ("Can't read any possible data sources: $?");
+
+my $dsn = "DBI:Pg:dbname=$dbname";
+$dsn .= ";host=$dbhost" if $dbhost;
+$dsn .= ";port=$dbport" if $dbport;
+print "#$dsn\n" if $debug;
+my $dbh = DBI->connect ($dsn, $dbuser, $dbpass, {RaiseError =>1});
+unless($dbh) {
+ die("Database $dbname\@$dbhost (". $DBI::errstr .")\n");
+}
+
+if ($configure) {
+ print <<_EOM;
+graph_title Postgres database $dbname
+graph_args -l 0 --base 1024
+graph_vlabel bytes
+graph_category Postgresql
+graph_info Size
+size.label Database size (bytes)
+size.info Database size
+size.type GAUGE
+size.draw AREA
+indexsize.label Index size (bytes)
+indexsize.info Index size
+indexsize.type GAUGE
+indexsize.draw STACK
+metasize.label Meta database size (bytes)
+metasize.info Meta database size
+metasize.type GAUGE
+metasize.draw STACK
+metaindexsize.label Meta index size (bytes)
+metaindexsize.info Meta index size
+metaindexsize.type GAUGE
+metaindexsize.draw STACK
+_EOM
+} else {
+ my $database_pages = 0;
+ my $database_indexes = 0;
+ my $metadatabase_pages = 0;
+ my $metadatabase_indexes = 0;
+ my @names = $dbh->tables;
+
+ # Find relfilenode and relpages from the given table
+ my $q_ind = "SELECT relkind, relfilenode, relpages FROM pg_class
+ WHERE relname = ?
+ UNION
+ SELECT relkind, relfilenode, relpages FROM pg_class
+ WHERE relfilenode IN (SELECT indexrelid FROM pg_index
+ WHERE indrelid IN (SELECT relfilenode FROM pg_class
+ WHERE relname = ?))";
+ my $sth = $dbh->prepare ($q_ind) or die $dbh->errstr;
+
+ # Iterate over the tables in the database
+ foreach my $table (@names) {
+ my $meta = 1;
+ print "#TABLE: $table\n" if $debug;
+ my $table_pages = 0;
+ my $table_indexes = 0;
+ my $metatable_pages = 0;
+ my $metatable_indexes = 0;
+ # "public" tables are the user data
+ $meta = 0 if $table =~ /^public\./;
+ $table =~ s/^.*\.//;
+
+ # Call the query with $table twice for each side of the UNION
+ $sth->execute ($table, $table) or die $dbh->errstr;
+ while (my ($relkind, $relfilenode, $relpages) = $sth->fetchrow_array) {
+ if ($relkind eq 'r') {
+ $table_pages += $relpages if $meta == 0;
+ $metatable_pages += $relpages if $meta == 1;
+ } elsif ($relkind eq 'i') {
+ $table_indexes += $relpages if $meta == 0;
+ $metatable_indexes += $relpages if $meta == 1;
+ }
+ # Define the query
+ my $q2 = "SELECT SUM(relpages)
+ FROM pg_class
+ WHERE relname IN (?, ?)";
+ my $sth2 = $dbh->prepare ($q2);
+ $sth2->execute ("pg_toast_${relfilenode}",
+ "pg_toast_${relfilenode}_index");
+ my $relpages = $sth2->fetchrow_array;
+ if ($relpages) {
+ if ($relkind eq 'r') {
+ $table_pages += $relpages if $meta == 0;
+ $metatable_pages += $relpages if $meta == 1;
+ } elsif ($relkind eq 'i') {
+ $table_indexes += $relpages if $meta == 0;
+ $metatable_indexes += $relpages if $meta == 1;
+ }
+ }
+ print "#\tR:$relfilenode\tP:$table_pages\tI:$table_indexes\n" if $debug;
+ }
+ $database_pages += $table_pages;
+ $database_indexes += $table_indexes;
+ $metadatabase_pages += $metatable_pages;
+ $metadatabase_indexes += $metatable_indexes;
+ }
+ $sth->finish;
+ $dbh->disconnect;
+ print "size\.value " . $database_pages * 8192 . "\n";
+ print "indexsize\.value " . $database_indexes * 8192 . "\n";
+ print "metasize\.value " . $metadatabase_pages * 8192 . "\n";
+ print "metaindexsize\.value " . $metadatabase_indexes * 8192 . "\n";
+}
--- /dev/null
+/usr/share/munin/plugins/loggrep
\ No newline at end of file
--- /dev/null
+[loggrep_remctl]
+user munin
+command sudo -u munin -E %c
+
+env.title remctls
+env.logfile /var/log/syslog
+
+% for n, r in enumerate(('listvms', 'vnccert', 'lvcreate', 'lvremove', 'lvrename', 'lvresize')):
+env.regex_web_${n} \w{3} [ :0-9]{11} [._[:alnum:]-]+ remctld\[[0-9]+\]: COMMAND from .*.MIT.EDU: web ${r}
+env.label_web_${n} web ${r}
+% endfor
+
+% for n, r in enumerate(('help', 'create', 'install', 'list-host', 'listhost', 'list', 'vcpu-list', 'uptime', 'destroy', 'shutdown', 'reboot', 'list-long', 'vnctoken')):
+env.regex_control_${n} \w{3} [ :0-9]{11} [._[:alnum:]-]+ remctld\[[0-9]+\]: COMMAND from .*.MIT.EDU: control \S+ ${r}
+env.label_control_${n} control ${r}
+% endfor