#!/bin/sh # # Revision 1.1 2012/02/26 03:43:27 # Improved labels # # Revision 1.0 2012/02/25 21:31:16 # Initial release # : <<=cut =head1 NAME imap_bandwidth - Munin plugin to measure the current bandwidth of one or more remote IMAP servers. =head1 APPLICABLE SYSTEMS Any Linux system with the package "isync" (or "mbsync") installed. =head1 CONFIGURATION This configuration section shows a usable example for two imap servers: [imap_bandwidth] env.imap_servers internal=imap-internal.example.org external=imap.example.org env.cert_file /etc/munin-imap-cert.pem env.username foo_user env.password secret env.transfer_volume_kbyte 100 env.use_ssl yes Both "use_ssl" and "transfer_volume_kbyte" are optional and default to the above values. All other parameters are required. Generate the certificate file by running "mbsync-get-cert imap.example.org". "imap_servers" is a space-separated list of key=value combinations. "key" is used as a label in munin graphs. "value" is the full hostname or IP of the IMAP server. All IMAP servers need to share the same authentication database (i.e. accept the same username/password). Reduce the "transfer_volume_kbyte" parameter if you need to minimize traffic. Maybe you need to specify the "timeout" setting for this plugin if it takes longer than munin's default timeout. =head1 INTERPRETATION The plugin simply shows the average bandwidth during one IMAP upload and one IMAP download of a file containing random bytes. You need to be aware that this measurement obviously increases the load on your IMAP servers for the duration of the measurement. You also need to be aware of the safety implications imposed by storing sensitive information (username and password combinations) on your monitoring server in plaintext. =head1 VERSION Version 1.0 =head1 BUGS None known Set the environment variable DEBUG=1 if you need to investigate problems. =head1 AUTHOR Lars Kruse =head1 LICENSE GPLv3 or higher =cut set -eu #%# family=auto #%# capabilities=autoconf TRANSFER_SIZE=${transfer_volume_kbyte:-100} USE_SSL=${use_ssl:-yes} IMAP_USERNAME=${username} IMAP_PASSWORD=${password} CERT_FILE=${cert_file} # example value: # internal=imap-internal.example.org external=imap.example.org SERVERS="$imap_servers" if test -n "${DEBUG:-}"; then TRANSFER_SIZE=20 set -x fi . $MUNIN_LIBDIR/plugins/plugin.sh if [ "$1" = "autoconf" ]; then if ( which mbsync >/dev/null 2>&1 ); then echo yes exit 0 else echo "no (could not run \"mbsync\")" exit 0 fi fi if [ "$1" = "config" ]; then echo 'graph_title IMAP bandwidth' echo 'graph_vlabel to (+) / from (-) server [bit/s]' echo 'graph_category mail' for item in $SERVERS; do key="$(echo "$item" | cut -f 1 -d =)" clean_name="$(clean_fieldname "$key")" echo "download_${clean_name}.graph no" echo "download_${clean_name}.label download" echo "upload_${clean_name}.label $key" echo "upload_${clean_name}.negative download_${clean_name}" done exit 0 fi create_dummy_file() { dd if=/dev/urandom "of=$DUMMY_FILENAME" bs=1K count=${TRANSFER_SIZE} 2>/dev/null } is_dummy_file_missing() { test ! -e "$DUMMY_FILENAME" } remove_mail_files() { get_mail_files | while read fname; do rm "$fname"; done } get_mail_files() { find "$MAILDIR" -type f | grep -v "/\." } # run the synchronization run_sync() { if test -n "${DEBUG:-}"; then echo yes | mbsync --config "$SYNCRC" sync || true else echo yes | mbsync --config "$SYNCRC" sync >/dev/null 2>/dev/null || true fi } # run the synchronization and determine the duration of this operation speed_sync() { start=$(date +%s%N) run_sync end=$(date +%s%N) # did we wrap a minute? test "$end" -lt "$start" && end=$((end + 60 * 1000000000)) delay=$((end - start)) # use "bit" multiplier echo "$((8 * TRANSFER_SIZE * 1024 * 1000000000 / delay))" } for item in $SERVERS; do key="$(echo "$item" | cut -f 1 -d =)" host="$(echo "$item" | cut -f 2- -d =)" clean_name="$(clean_fieldname "$key")" MAILDIR="$(mktemp -d)" # this file needs to include a dot at the beginning - otherwise it gets cleaned up ... SYNCRC="$MAILDIR/.mbsyncrc" SYNC_STATE_FILE_PREFIX="$MAILDIR/.syncstate-" cat - >"$SYNCRC" <<- EOF SyncState $SYNC_STATE_FILE_PREFIX Expunge Both MaildirStore local Path $MAILDIR Inbox $MAILDIR IMAPStore remote Host $host UseIMAPS $USE_SSL User $IMAP_USERNAME Pass $IMAP_PASSWORD CertificateFile $CERT_FILE Channel sync Master :local: Slave :remote: EOF mkdir "$MAILDIR/new" "$MAILDIR/tmp" "$MAILDIR/cur" DUMMY_FILENAME="$MAILDIR/new/$(date +%N)" # download all existing files run_sync # remove all local files -> to be purged remotely later remove_mail_files # create dummy file for upload create_dummy_file "$MAILDIR" output="upload_${clean_name}.value $(speed_sync)" is_dummy_file_missing && echo "$output" || echo >&2 "upload failed" # remove local file remove_mail_files "$MAILDIR" # persuade mbsync that we have never seen the dummy file ... rm "$SYNC_STATE_FILE_PREFIX"* output="download_${clean_name}.value $(speed_sync)" get_mail_files | grep -q . && echo "$output" || echo >&2 "download failed" # remove the new file from the imap server remove_mail_files run_sync # clean up rm -r "$MAILDIR" done