#!/bin/bash : << =cut =head1 NAME zpool_capacity - Munin plugin to monitor ZFS capacity These functions are implemented: capacity : to monitor zpool capacity % allocated : to monitor zpool allocated bytes dedup : to monitor zpool dedup and compress ratio Tested with Solaris 10 and 11, OpenIndiana Hipster, FreeBSD 11, CentOS 7 =head1 CONFIGURATION Make symlink: cd /path/to/munin/etc/plugins ln -s /path/to/munin/lib/plugins/zpool_capacity . For FreeBSD, it should be necessary to change shebang /bin/bash -> /usr/local/bin/bash For Linux, root privilege is necessary to run zpool command. [zpool_capacity] user root =head1 ENVIRONMENT VARIABLES critical : default 90 warning : default 80 =head1 AUTHOR K.Cima https://github.com/shakemid =head1 LICENSE GPLv2 =head1 Magic markers #%# family=contrib #%# capabilities=autoconf =cut # Include plugin.sh . "${MUNIN_LIBDIR:-}/plugins/plugin.sh" is_multigraph "$@" # Shell options set -o nounset # Global variables plugin_name=zpool_capacity functions='capacity allocated dedup' zpool_cmd=/sbin/zpool zfs_cmd=/sbin/zfs # Environment variables : "${warning:=80}" : "${critical:=90}" # Note: The performance of ZFS may significantly degrade when zpool capacity > 90% # See also: https://docs.oracle.com/cd/E53394_01/html/E54801/zfspools-4.html # Functions preconfig() { local func="$1" local p c # data_attr format: field type draw label # label can contain white-spaces. data_attr= case $func in capacity) global_attr=" graph_title ZFS storage pool - Capacity graph_category fs graph_args --base 1000 --lower-limit 0 --upper-limit 100 graph_vlabel % allocated graph_info ZFS storage pool - Capacity warning ${warning} critical ${critical} " for p in $pool_list do data_attr="${data_attr} ${p} GAUGE LINE2 ${p}" done ;; allocated) global_attr=" graph_title ZFS storage pool - Allocated bytes graph_category fs graph_args --base 1024 --lower-limit 0 graph_vlabel Bytes graph_info ZFS storage pool - Allocated bytes " c=0 for p in $pool_list do data_attr="${data_attr} ${p}_size GAUGE LINE ${p} size ${p}_allocated GAUGE LINE2 ${p} allocated" global_attr="${global_attr} ${p}_size.colour COLOUR${c} ${p}_allocated.colour COLOUR${c}" c=$(( c + 1 )) done ;; dedup) global_attr=" graph_title ZFS storage pool - Dedup and compress ratio graph_category fs graph_args --base 1000 --lower-limit 1 graph_vlabel Ratio graph_info ZFS storage pool - Dedup and compress ratio " for p in $pool_list do data_attr="${data_attr} ${p}_dedup GAUGE LINE ${p} dedup ${p}_compress GAUGE LINE ${p} compress" done ;; esac } do_config() { local func="$1" local label_max_length=45 local field type draw label preconfig "$func" echo "multigraph ${plugin_name}_${func}" # print global attributes echo "$global_attr" | sed -e 's/^ *//' -e '/^$/d' # print data source attributes echo "$data_attr" | while read -r field type draw label do [ -z "$field" ] && continue field=$( clean_fieldname "$field" ) echo "${field}.type ${type}" echo "${field}.draw ${draw}" echo "${field}.label ${label:0:${label_max_length}}" if [ "$type" = 'DERIVE' ]; then echo "${field}.min 0" fi if [ "$label" = 'dummy' ]; then echo "${field}.graph no" fi done echo } get_stats() { local func="$1" case $func in capacity) "$zpool_cmd" list -H -o name,capacity | sed 's/%$//' ;; allocated) ( "$zpool_cmd" list -H -o name,allocated \ | awk '{ print $1"_allocated", $2 }' "$zpool_cmd" list -H -o name,size \ | awk '{ print $1"_size", $2 }' ) \ | perl -ane ' @unit{ qw/ K M G T P E / } = ( 1 .. 6 ); $name = $F[0]; $byteu = $F[1]; ( $n, $u ) = $byteu =~ /^([\d.]+)([KMGTPE]?)$/; $byte = int( $n * 1024 ** ( $u ? $unit{ $u } : 0 ) ); print "$name $byte\n"; ' # Note: ZFS supports up to 16EB. ;; dedup) "$zpool_cmd" list -H -o name,dedup \ | sed 's/x$//' \ | awk '{ print $1"_dedup", $2 }' # example output: # $ zpool list -H -o name,dedup # rpool 1.00x # ... "$zpool_cmd" list -H -o name \ | xargs "$zfs_cmd" get -H -o name,value compressratio \ | sed 's/x$//' \ | awk '{ print $1"_compress", $2 }' # example output: # $ zfs get -H -o name,value compressratio rpool # rpool 1.00x ;; esac } do_fetch() { local func="$1" local zpool_stats field value # zpool_stats contains 'key value\n' zpool_stats=$( get_stats "$func" ) echo "multigraph ${plugin_name}_${func}" echo "$zpool_stats" | while read -r field value do field=$( clean_fieldname "$field" ) echo "${field}.value ${value}" done echo } autoconf() { if [ -x "$zpool_cmd" ]; then echo yes else echo "no (failed to find executable 'zpool')" fi } config() { local func pool_list=$( "$zpool_cmd" list -H -o name ) for func in $functions do do_config "$func" done } fetch() { local func for func in $functions do do_fetch "$func" done } # Main case ${1:-} in autoconf) autoconf ;; config) config if [ "${MUNIN_CAP_DIRTYCONFIG:-0}" = "1" ]; then fetch; fi ;; *) fetch ;; esac exit 0