2017-05-08 01:22:46 +02:00
|
|
|
#!/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
|
2018-08-02 02:03:42 +02:00
|
|
|
|
2017-05-08 01:22:46 +02:00
|
|
|
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() {
|
2017-08-14 05:04:00 +02:00
|
|
|
local func="$1"
|
2017-05-08 01:22:46 +02:00
|
|
|
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() {
|
2017-08-14 05:04:00 +02:00
|
|
|
local func="$1"
|
2018-08-02 02:03:42 +02:00
|
|
|
local label_max_length=45
|
2017-05-08 01:22:46 +02:00
|
|
|
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() {
|
2017-08-14 05:04:00 +02:00
|
|
|
local func="$1"
|
2017-05-08 01:22:46 +02:00
|
|
|
|
|
|
|
case $func in
|
|
|
|
capacity)
|
2017-08-14 05:04:00 +02:00
|
|
|
"$zpool_cmd" list -H -o name,capacity | sed 's/%$//'
|
2017-05-08 01:22:46 +02:00
|
|
|
;;
|
|
|
|
allocated)
|
2017-08-14 05:04:00 +02:00
|
|
|
( "$zpool_cmd" list -H -o name,allocated \
|
2017-05-08 01:22:46 +02:00
|
|
|
| awk '{ print $1"_allocated", $2 }'
|
2017-08-14 05:04:00 +02:00
|
|
|
"$zpool_cmd" list -H -o name,size \
|
2017-05-08 01:22:46 +02:00
|
|
|
| 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)
|
2017-08-14 05:04:00 +02:00
|
|
|
"$zpool_cmd" list -H -o name,dedup \
|
2017-05-08 01:22:46 +02:00
|
|
|
| sed 's/x$//' \
|
|
|
|
| awk '{ print $1"_dedup", $2 }'
|
2017-08-14 05:04:00 +02:00
|
|
|
# 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 \
|
2017-05-08 01:22:46 +02:00
|
|
|
| sed 's/x$//' \
|
|
|
|
| awk '{ print $1"_compress", $2 }'
|
2017-08-14 05:04:00 +02:00
|
|
|
# example output:
|
|
|
|
# $ zfs get -H -o name,value compressratio rpool
|
|
|
|
# rpool 1.00x
|
2017-05-08 01:22:46 +02:00
|
|
|
;;
|
|
|
|
esac
|
|
|
|
}
|
|
|
|
|
|
|
|
do_fetch() {
|
2017-08-14 05:04:00 +02:00
|
|
|
local func="$1"
|
2017-05-08 01:22:46 +02:00
|
|
|
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
|
|
|
|
|
2017-08-14 05:04:00 +02:00
|
|
|
pool_list=$( "$zpool_cmd" list -H -o name )
|
2017-05-08 01:22:46 +02:00
|
|
|
|
|
|
|
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
|
2018-04-07 02:11:05 +02:00
|
|
|
if [ "${MUNIN_CAP_DIRTYCONFIG:-0}" = "1" ]; then fetch; fi
|
2017-05-08 01:22:46 +02:00
|
|
|
;;
|
|
|
|
*)
|
|
|
|
fetch
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
|
|
|
|
exit 0
|