1
0
Fork 0
mirror of https://github.com/munin-monitoring/contrib.git synced 2025-07-25 18:38:30 +00:00

lxc: working on buster (gandalf), and almost working on virtual (jessie), except lxc_net

This commit is contained in:
Marc SCHAEFER 2019-08-10 11:33:27 +02:00 committed by Lars Kruse
parent 0e0de01136
commit ce6e67fffc
7 changed files with 371 additions and 303 deletions

63
plugins/lxc/lxc-lib Normal file
View file

@ -0,0 +1,63 @@
: << =cut
=head1 NAME
lxc-lib -- some base functions for the lxc_* plugins
=head1 AUTHOR
schaefer@alphanet.ch
=head1 LICENSE
GPLv3
=cut
lxcpath=${lxcpath:-/var/lib/lxc}
function active_guests {
local g active i ok
for g in $(lxc-ls | sort -u)
do
# handle optional exclude list in $1
ok=1
for i in $1
do
if [ "$i" = "$g" ]; then
ok=0
fi
done
if [ $ok = 1 ]; then
if lxc-info -n $g 2>&1 | grep -qs RUNNING; then
active="$active $g"
fi
fi
done
echo $active
}
function lxc_cgroup {
# lxc3
lxc-cgroup -o /dev/stdout -l INFO $* | sed 's/^.*lxc_cgroup.c:main:[0-9][0-9]* - //'
# lxc < 3
#lxc-cgroup $*
}
function lxc_clean_fieldname {
# workaround for bug leaving out the first number
echo $(clean_fieldname ${1::1}$1)
}
function lxc_netdev {
local g=$1 dev
if [ -f $lxcpath/$g/config ]; then
grep lxc.net.0.veth.pair $lxcpath/$g/config | awk '{print $NF;}'
else
echo unknown
fi
}

View file

@ -20,10 +20,12 @@ This plugin needs root privilege.
vajtsz vajtsz@gmail.com vajtsz vajtsz@gmail.com
mitty mitty@mitty.jp mitty mitty@mitty.jp
(many changes schaefer@alphanet.ch)
=head1 LICENSE =head1 LICENSE
Unknown license 2-clause BSD License
or GPLv3 license, at your option
=head1 MAGIC MARKERS =head1 MAGIC MARKERS
@ -34,59 +36,49 @@ Unknown license
. $MUNIN_LIBDIR/plugins/plugin.sh . $MUNIN_LIBDIR/plugins/plugin.sh
guest_names=`lxc-ls | sort -u` . $MUNIN_LIBDIR/plugins/lxc-lib
for guest in $guest_names; do
if lxc-info -n $guest 2>&1 | grep -qs RUNNING ; then
active="$active $guest"
fi
done
guest_names="$active"
active_guests=$(active_guests)
f_comm='lxc-cgroup '
if [ "$1" = "autoconf" ]; then if [ "$1" = "autoconf" ]; then
if [ -r /proc/stat ]; then if [ -r /proc/stat ]; then
echo yes echo yes
exit 0 exit 0
else else
echo "no (no /proc/stat)" echo "no (no /proc/stat)"
exit 0 exit 0
fi fi
fi fi
if [ "$1" = "config" ]; then if [ "$1" = "config" ]; then
cat <<EOF
echo 'graph_title CPU Usage ' graph_title CPU Usage
echo 'graph_args -l 0 --base 1000' graph_args -l 0 --base 1000
echo 'graph_vlabel USER_HZ' graph_vlabel USER_HZ
echo 'graph_category cpu' graph_category lxc
EOF
for guest_name in $guest_names; do for n in $active_guests
guest="$(clean_fieldname $guest_name)" do
echo 'cpu_user_'$guest'.label '$guest_name': User' g=$(lxc_clean_fieldname $n)
echo 'cpu_user_'$guest'.type DERIVE' for i in user system
echo 'cpu_user_'$guest'.min 0' do
echo 'cpu_system_'$guest'.label '$guest_name': System' cat <<EOF
echo 'cpu_system_'$guest'.type DERIVE' cpu_${i}_${g}.label $n: $(echo ${i:0:1} | tr "[:lower:]" "[:upper:]")${i:1}
echo 'cpu_system_'$guest'.min 0' cpu_${i}_${g}.type DERIVE
done cpu_${i}_${g}.min 0
exit 0 EOF
done
done
exit 0
fi fi
for guest_name in $guest_names; do for n in $active_guests
guest="$(clean_fieldname $guest_name)" do
g=$(lxc_clean_fieldname $n)
tmp_g=`$f_comm -n $guest_name cpuacct.stat | grep user`
tmp_v=`echo $tmp_g | awk '{print($2)}'` for i in user system
echo 'cpu_user_'$guest'.value '$tmp_v do
echo "cpu_${i}_${g}.value $(lxc_cgroup -n $n cpuacct.stat | grep $i | awk '{ print $2; }')"
tmp_g=`$f_comm -n $guest_name cpuacct.stat | grep system` done
tmp_v=`echo $tmp_g | awk '{print($2)}'` done
echo 'cpu_system_'$guest'.value '$tmp_v
done

View file

@ -5,7 +5,7 @@
=head1 NAME =head1 NAME
lxc_cpu_time - Plugin to monitor LXC CPU time usage lxc_cpu_time - Plugin to monitor LXC CPU time usage
=head1 CONFIGURATION =head1 CONFIGURATION
@ -20,10 +20,12 @@ This plugin needs root privilege.
vajtsz vajtsz@gmail.com vajtsz vajtsz@gmail.com
mitty mitty@mitty.jp mitty mitty@mitty.jp
(many changes schaefer@alphanet.ch)
=head1 LICENSE =head1 LICENSE
Unknown license 2-clause BSD License
or GPLv3 license, at your option
=head1 MAGIC MARKERS =head1 MAGIC MARKERS
@ -34,48 +36,42 @@ Unknown license
. $MUNIN_LIBDIR/plugins/plugin.sh . $MUNIN_LIBDIR/plugins/plugin.sh
guest_names=`lxc-ls | sort -u` . $MUNIN_LIBDIR/plugins/lxc-lib
for guest in $guest_names; do
if lxc-info -n $guest 2>&1 | grep -qs RUNNING ; then
active="$active $guest"
fi
done
guest_names="$active"
active_guests=$(active_guests)
f_comm='lxc-cgroup '
if [ "$1" = "autoconf" ]; then if [ "$1" = "autoconf" ]; then
if [ -r /proc/stat ]; then if [ -r /proc/stat ]; then
echo yes echo yes
exit 0 exit 0
else else
echo "no (no /proc/stat)" echo "no (no /proc/stat)"
exit 0 exit 0
fi fi
fi fi
if [ "$1" = "config" ]; then if [ "$1" = "config" ]; then
cat <<EOF
graph_title CPU time
graph_args -l 0 --base 1000
graph_vlabel nanosec
graph_category lxc
EOF
echo 'graph_title CPU time ' for n in $active_guests
echo 'graph_args -l 0 --base 1000' do
echo 'graph_vlabel nanosec' g=$(lxc_clean_fieldname $n)
echo 'graph_category cpu' cat <<EOF
cpu_time_${g}.label $n: CPU time
for guest_name in $guest_names; cpu_time_${g}.type DERIVE
do cpu_time_${g}.min 0
guest="$(clean_fieldname $guest_name)" EOF
echo 'cpu_time_'$guest'.label '$guest_name': CPU time' done
echo 'cpu_time_'$guest'.type DERIVE' exit 0
echo 'cpu_time_'$guest'.min 0'
done
exit 0
fi fi
for guest_name in $guest_names; for n in $active_guests
do do
guest="$(clean_fieldname $guest_name)" g=$(lxc_clean_fieldname $n)
tmp_g=`$f_comm -n $guest_name cpuacct.usage ` echo "cpu_time_${g}.value $(lxc_cgroup -n $n cpuacct.usage)"
echo 'cpu_time_'$guest'.value '$tmp_g done
done

71
plugins/lxc/lxc_logins Executable file
View file

@ -0,0 +1,71 @@
#!/bin/bash
# -*- sh -*-
: << =cut
=head1 NAME
lxc_logins - Plugin to monitor LXC logins
=head1 CONFIGURATION
[lxc_*]
user root
=head1 INTERPRETATION
This plugin needs root privilege.
=head1 AUTHOR
schaefer@alphanet.ch
=head1 LICENSE
GPLv3
=head1 MAGIC MARKERS
#%# family=auto
#%# capabilities=autoconf
=cut
. $MUNIN_LIBDIR/plugins/plugin.sh
. $MUNIN_LIBDIR/plugins/lxc-lib
active_guests=$(active_guests)
if [ "$1" = "autoconf" ]; then
if [ -r /proc/stat ]; then
echo yes
exit 0
else
echo "no (no /proc/stat)"
exit 0
fi
fi
if [ "$1" = "config" ]; then
cat <<EOF
graph_title Logins
graph_category lxc
EOF
for n in $active_guests
do
g=$(lxc_clean_fieldname $n)
cat <<EOF
logins_${g}.label $n: logins
logins_${g}.type GAUGE
EOF
done
exit 0
fi
for n in $active_guests
do
g=$(lxc_clean_fieldname $n)
echo "logins_${g}.value $(lxc-attach -n $n users | wc -w | bc)"
done

View file

@ -22,110 +22,95 @@ env.exclude - Removing containers from graphs, default: empty
=head1 INTERPRETATION =head1 INTERPRETATION
This plugin reads a "lxc.network.veth.pair" setting from "config" file of each container, This plugin reads a "lxc.network.veth.pair" setting from "config" file of each container,
because lxc-start command creates a random named veth device without the setting. because lxc-start command creates a random named veth device without the setting, which
changes at each run.
If your xen config (/var/lib/lxc/GUEST_NAME/config does not contain this parameter,
then you have to fill it, because if every guest restart generate new device name, then the graph will be useless
( example config : lxc.network.veth.pair = vethsamba )
=head1 AUTHOR =head1 AUTHOR
mitty mitty@mitty.jp mitty mitty@mitty.jp
(many changes schaefer@alphanet.ch)
=head1 LICENSE =head1 LICENSE
2-clause BSD License 2-clause BSD License
or GPLv3 license, at your option
=head1 MAGIC MARKERS =head1 MAGIC MARKERS
#%# familiy=auto #%# family=auto
#%# capabilities=autoconf #%# capabilities=autoconf
=cut =cut
. $MUNIN_LIBDIR/plugins/plugin.sh . $MUNIN_LIBDIR/plugins/plugin.sh
lxcpath=${lxcpath:-/var/lib/lxc} . $MUNIN_LIBDIR/plugins/lxc-lib
active_guests=$(active_guests $exclude)
if [ "$1" = "autoconf" ]; then if [ "$1" = "autoconf" ]; then
if [ ! -r /proc/net/dev ]; then if [ ! -r /proc/net/dev ]; then
echo "no (/proc/net/dev cannot be read)" echo "no (/proc/net/dev cannot be read)"
exit 0 exit 0
fi fi
if [ ! -e "$lxcpath" ]; then if [ ! -e "$lxcpath" ]; then
echo "no ($lxcdir is not present)" echo "no ($lxcdir is not present)"
exit 0 exit 0
fi fi
echo yes echo yes
exit 0
fi fi
actives=""
for guest in `ls $lxcpath`; do
if [ `echo $exclude | grep -c "\b$guest\b"` -eq 1 ]; then
continue;
fi
if [ -f "$lxcpath/$guest/config" ]; then
devices=`grep '^lxc\.network\.veth\.pair[ \t]*=[ \t]*' $lxcpath/$guest/config | \
awk '{ split($0, a, /=/); gsub(/[ \t]/, "", a[2]); print a[2]; }'`
if [ -n "$devices" ]; then
for device in $devices; do
device_re=`echo $device | sed -e 's/\./\\\\./g'`
if [ `grep -c "^ *$device_re:" /proc/net/dev` -eq 1 ]; then
actives="$actives $guest"
eval "dev_$(clean_fieldname $guest)=$device"
fi
done
fi
fi
done
if [ "$1" = "config" ]; then if [ "$1" = "config" ]; then
echo "graph_title Network traffic" cat <<EOF
echo "graph_args --base 1000" graph_title Network traffic
echo "graph_vlabel bits in (-) / out (+) per ${graph_period}" graph_args --base 1000
echo "graph_category network" graph_vlabel bits in (-) / out (+) per ${graph_period}
echo "graph_info This graph shows the traffic of active LXC containers." graph_category lxc
graph_info This graph shows the traffic of active LXC containers.
for guestname in $actives; do EOF
guest=$(clean_fieldname $guestname)
device=$(eval 'echo $dev_'$guest) for n in $active_guests
bps="U" do
if [ -r /sys/class/net/$device/speed ]; then g=$(lxc_clean_fieldname $n)
bps=$(cat /sys/class/net/$device/speed) device=$(lxc_netdev $n)
bps=$(($bps * 1000 * 1000)) if [ "$device" = "unknown" ]; then
fi continue
fi
echo "${guest}_down.label $guestname" bps="U"
echo "${guest}_down.type DERIVE" if [ -r /sys/class/net/$device/speed ]; then
echo "${guest}_down.graph no" bps=$(($(cat /sys/class/net/$device/speed) * 1000 * 1000))
echo "${guest}_down.cdef ${guest}_down,8,*" fi
echo "${guest}_down.min 0" cat <<EOF
echo "${guest}_down.max $bps" net_${g}_down.label $n
echo "${guest}_up.label $guestname" net_${g}_down.type DERIVE
echo "${guest}_up.type DERIVE" net_${g}_down.graph no
echo "${guest}_up.negative ${guest}_down" net_${g}_down.cdef net_${g}_down,8,*
echo "${guest}_up.cdef ${guest}_up,8,*" net_${g}_down.min 0
echo "${guest}_up.min 0" net_${g}_down.max $bps
echo "${guest}_up.max $bps" net_${g}_up.label $n
net_${g}_up.type DERIVE
net_${g}_up.negative net_${g}_down
net_${g}_up.cdef net_${g}_up,8,*
net_${g}_up.min 0
net_${g}_up.max $bps
EOF
done done
exit 0 exit 0
fi fi
for n in $active_guests
do
g=$(lxc_clean_fieldname $n)
device=$(lxc_netdev $n)
if [ "$device" = "unknown" ]; then
continue
fi
for guest in $actives; do cat <<EOF
guest=$(clean_fieldname $guest) net_${g}_up.value $(egrep "^ *${device}:" /proc/net/dev | awk '{print $10;}')
device=$(eval 'echo $dev_'$guest) net_${g}_down.value $(egrep "^ *${device}:" /proc/net/dev | awk '{print $2;}')
device_re=`echo $device | sed -e 's/\./\\\\./g'` EOF
line=`grep "^ *$device_re:" /proc/net/dev`
echo -n "${guest}_down.value "
echo $line | awk '{
split($0, a, /: */);
print $2;
}'
echo -n "${guest}_up.value "
echo $line | awk '{
split($0, a, /: */);
print $10;
}'
done done

View file

@ -22,10 +22,12 @@ This plugin needs root privilege.
=head1 AUTHOR =head1 AUTHOR
vajtsz vajtsz@gmail.com vajtsz vajtsz@gmail.com
(many changes schaefer@alphanet.ch)
=head1 LICENSE =head1 LICENSE
Unknown license 2-clause BSD License
or GPLv3 license, at your option
=head1 MAGIC MARKERS =head1 MAGIC MARKERS
@ -36,12 +38,16 @@ Unknown license
. $MUNIN_LIBDIR/plugins/plugin.sh . $MUNIN_LIBDIR/plugins/plugin.sh
. $MUNIN_LIBDIR/plugins/lxc-lib
active_guests=$(active_guests)
## find proper sysfs and count it ## find proper sysfs and count it
# Debian 6.0: /sys/fs/cgroup/<container>/tasks # Debian 6.0: /sys/fs/cgroup/<container>/tasks
# Ubuntu 12.04 with fstab: /sys/fs/cgroup/lxc/<container>/tasks # Ubuntu 12.04 with fstab: /sys/fs/cgroup/lxc/<container>/tasks
# Ubuntu 12.04 with cgroup-lite: /sys/fs/cgroup/cpuacct/lxc/<container>/tasks # Ubuntu 12.04 with cgroup-lite: /sys/fs/cgroup/cpuacct/lxc/<container>/tasks
# Ubuntu 12.04 with cgroup-bin: /sys/fs/cgroup/cpuacct/sysdefault/lxc/<container>/tasks # Ubuntu 12.04 with cgroup-bin: /sys/fs/cgroup/cpuacct/sysdefault/lxc/<container>/tasks
# Ubuntu 14.04: /sys/fs/cgroup/systemd/lxc/<container>/tasks # and with cgmanager on jessie
count_processes () { count_processes () {
[ -z "$1" ] && return 0 [ -z "$1" ] && return 0
@ -51,11 +57,10 @@ count_processes () {
return `wc -l < $SYSFS` return `wc -l < $SYSFS`
fi fi
fi fi
for SYSFS in \ for SYSFS in \
/sys/fs/cgroup/$1/tasks \ /sys/fs/cgroup/$1/tasks \
/sys/fs/cgroup/lxc/$1/tasks \ /sys/fs/cgroup/lxc/$1/tasks \
/sys/fs/cgroup/systemd/lxc/$1/tasks \
/sys/fs/cgroup/cpuacct/lxc/$1/tasks \ /sys/fs/cgroup/cpuacct/lxc/$1/tasks \
/sys/fs/cgroup/cpuacct/sysdefault/lxc/$1/tasks \ /sys/fs/cgroup/cpuacct/sysdefault/lxc/$1/tasks \
; do ; do
@ -64,60 +69,51 @@ count_processes () {
fi fi
done done
if [ -e /usr/bin/cgm ]; then
return `cgm getvalue cpu lxc/$1 tasks 2>/dev/null | wc -l`
fi
return 0 return 0
} }
guest_names=`lxc-ls | sort -u`
for guest in $guest_names; do
if lxc-info -n $guest 2>&1 | grep -qs RUNNING ; then
active="$active $guest"
fi
done
guest_names="$active"
f_comm='lxc-cgroup '
if [ "$1" = "autoconf" ]; then if [ "$1" = "autoconf" ]; then
if [ -r /proc/stat ]; then if [ -r /proc/stat ]; then
echo yes echo yes
exit 0 exit 0
else else
echo "no (no /proc/stat)" echo "no (no /proc/stat)"
exit 0 exit 0
fi fi
fi fi
if [ "$1" = "config" ]; then if [ "$1" = "config" ]; then
cat <<EOF
echo 'graph_title Processes ' graph_title Processes
echo 'graph_args -l 0 --base 1000' graph_args -l 0 --base 1000
echo 'graph_vlabel Number of processes' graph_vlabel Number of processes
echo 'graph_category processes' graph_category lxc
EOF
for guest_name in $guest_names; do for n in $active_guests
guest="$(clean_fieldname $guest_name)" do
echo 'lxc_proc_'$guest'.label '$guest_name': processes' g=$(lxc_clean_fieldname $n)
echo 'lxc_proc_'$guest'.type GAUGE' cat <<EOF
echo 'lxc_proc_'$guest'.min 0' lxc_proc_${g}.label $n: processes
done lxc_proc_${g}.type GAUGE
exit 0 lxc_proc_${g}.min 0
EOF
done
exit 0
fi fi
for guest_name in $guest_names; do for n in $active_guests
guest="$(clean_fieldname $guest_name)" do
g=$(lxc_clean_fieldname $n)
count_processes $guest_name
tmp_g=$? count_processes $n
if [ $tmp_g -eq 0 ]; then tmp_g=$?
tmp_g=`$f_comm -n $guest_name tasks | wc -l` if [ $tmp_g -eq 0 ]; then
fi tmp_g=$(lxc_cgroup -n $n tasks | wc -l)
echo 'lxc_proc_'$guest'.value '$tmp_g fi
echo "lxc_proc_${g}.value $tmp_g"
done
done

View file

@ -1,4 +1,4 @@
#!/bin/sh #!/bin/bash
# -*- sh -*- # -*- sh -*-
: << =cut : << =cut
@ -12,26 +12,20 @@ lxc_ram - Plugin to monitor LXC memory usage.
[lxc_*] [lxc_*]
user root user root
[lxc_ram]
env.areastack true
=head1 INTERPRETATION =head1 INTERPRETATION
This plugin needs root privilege. This plugin needs root privilege.
If env.areastack is set to true, all memory usages of containers will be
drawn as stacked area charts.
This option changes graph order, all of 'Mem usage' comes first and then others.
(default: false)
=head1 AUTHOR =head1 AUTHOR
vajtsz vajtsz@gmail.com vajtsz vajtsz@gmail.com
mitty mitty@mitty.jp mitty mitty@mitty.jp
(many changes schaefer@alphanet.ch)
=head1 LICENSE =head1 LICENSE
Unknown license 2-clause BSD License
or GPLv3 license, at your option
=head1 MAGIC MARKERS =head1 MAGIC MARKERS
@ -40,83 +34,54 @@ Unknown license
=cut =cut
. $MUNIN_LIBDIR/plugins/plugin.sh
# configurable: true/false . $MUNIN_LIBDIR/plugins/lxc-lib
areastack=${areastack:-false}
# shellcheck disable=SC1090
. "$MUNIN_LIBDIR/plugins/plugin.sh"
guest_names=$(lxc-ls | sort -u)
for guest in $guest_names; do
if lxc-info -n "$guest" 2>&1 | grep -qs RUNNING ; then
active="$active $guest"
fi
done
guest_names="$active"
f_comm='lxc-cgroup '
do_autoconf() {
if [ -r /proc/stat ]; then
echo yes
else
echo "no (no /proc/stat)"
fi
}
do_config() {
echo 'graph_title Memory '
echo 'graph_args -l 0 --base 1024'
echo 'graph_vlabel byte'
echo 'graph_category memory'
for guest_name in $guest_names; do
guest="$(clean_fieldname "$guest_name")"
echo "mem_usage_$guest.label $guest_name: Mem usage"
echo "mem_usage_$guest.type GAUGE"
if [ "$areastack" = "true" ]; then
echo "mem_usage_$guest.draw AREASTACK"
fi
echo "mem_cache_$guest.label $guest_name: Cache"
echo "mem_cache_$guest.type GAUGE"
echo "mem_active_$guest.label $guest_name: Active"
echo "mem_active_$guest.type GAUGE"
echo "mem_inactive_$guest.label $guest_name: Inactive"
echo "mem_inactive_$guest.type GAUGE"
done
}
do_fetch() {
for guest_name in $guest_names; do
guest="$(clean_fieldname "$guest_name")"
value=$($f_comm -n "$guest_name" memory.usage_in_bytes)
echo "mem_usage_$guest.value $value"
value=$($f_comm -n "$guest_name" memory.stat | grep total_cache | awk '{print($2)}')
echo "mem_cache_$guest.value $value"
value=$($f_comm -n "$guest_name" memory.stat | grep total_active_anon | awk '{print($2)}')
echo "mem_active_$guest.value $value"
value=$($f_comm -n "$guest_name" memory.stat | grep total_inactive_anon | awk '{print($2)}')
echo "mem_inactive_$guest.value $value"
done
}
active_guests=$(active_guests)
if [ "$1" = "autoconf" ]; then if [ "$1" = "autoconf" ]; then
do_autoconf if [ -r /proc/stat ]; then
elif [ "$1" = "config" ]; then echo yes
do_config exit 0
if [ "${MUNIN_CAP_DIRTYCONFIG:-0}" = "1" ]; then do_fetch; fi else
else echo "no (no /proc/stat)"
do_fetch exit 0
fi
fi fi
if [ "$1" = "config" ]; then
cat <<EOF
graph_title Memory
graph_args -l 0 --base 1024
graph_vlabel byte
graph_category lxc
EOF
for n in $active_guests
do
g=$(lxc_clean_fieldname $n)
cat <<EOF
mem_usage_${g}.label ${n}: Mem usage
mem_usage_${g}.type GAUGE
mem_cache_${g}.label ${n}: Cache
mem_cache_${g}.type GAUGE
mem_active_${g}.label ${n}: Active
mem_active_${g}.type GAUGE
mem_inactive_${g}.label ${n}: Inactive
mem_inactive_${g}.type GAUGE
EOF
done
exit 0
fi
for n in $active_guests
do
g=$(lxc_clean_fieldname $n)
cat <<EOF
mem_usage_${g}.value $(lxc_cgroup -n $n memory.usage_in_bytes)
mem_cache_${g}.value $(lxc_cgroup -n $n memory.stat | grep total_cache | awk '{print $2;}')
mem_active_${g}.value $(lxc_cgroup -n $n memory.stat | grep total_active_anon | awk '{print $2;}')
mem_inactive_${g}.value $(lxc_cgroup -n $n memory.stat | grep total_inactive_anon | awk '{print $2;}')
EOF
done