#!/bin/sh # -*- sh -*- : << =cut =head1 NAME lxc_guests - collect statistics about containers virtualized via LXC =head1 CONFIGURATION [lxc_guests] user root # The memory usage of containers are by default drawn as stacked area # charts. Alternatively a non-stacked graph with lines can be configured. # Default: true #env.ram_display_stacked true # lxc container path, default below #env.lxcpath /var/lib/lxc # exclude the following containers # (default none excluded) #env.exclude container1 container2 # path where tasks sysfs files are stored, # set this if the various attempts in the # code don't work # (default none) #env.cgrouppath /sys/fs/cgroup/cpuacct/lxc/ =head1 INTERPRETATION This plugin needs root privilege. This plugin has been tested with lxc 3 and lx2 (on Debian buster and Debian jessie, respectively). If using lxc 2, make sure you do not have cruft in your container config files, you can test it with: lxc-cgroup -o /dev/stdout -l INFO -n 104 cpuacct.usage -- with 104 a valid lxc instance), if you get a warning, fix the config file. For the logins graph, the "users" command is required in each container. Tested on Debian buster and Debian jessie. =head1 AUTHOR vajtsz vajtsz@gmail.com mitty mitty@mitty.jp alphanet schaefer@alphanet.ch (many changes and multigraph) Lars Kruse =head1 LICENSE 2-clause BSD License or GPLv3 license or later, at your option =head1 MAGIC MARKERS #%# family=auto #%# capabilities=autoconf =cut set -eu . "$MUNIN_LIBDIR/plugins/plugin.sh" lxcpath=${lxcpath:-/var/lib/lxc} # containers to be ignored exclude=${exclude:-} ram_display_stacked=${ram_display_stacked:-true} # try to guess the location, if empty cgrouppath=${cgrouppath:-} # --- FUNCTIONS get_active_guests() { local excludes="$1" local guest_name for guest_name in $(lxc-ls) do # handle optional exclude list in $1 if ! echo "$excludes" | grep -qwF "$guest_name"; then if lxc-info -n "$guest_name" --state 2>/dev/null | grep -qw RUNNING; then echo "$guest_name" fi fi done } get_lxc_cgroup_info() { local guest_name="$1" local field="$2" # lxc3 (lxc < 3: may output some warnings if there is cruft in your config dir) lxc-cgroup -o /dev/stdout -l INFO -n "$guest_name" "$field" | sed 's/^.*lxc_cgroup.c:main:[0-9][0-9]* - //' | grep -v set_config_idmaps } # find proper sysfs and count it # Debian 6.0: /sys/fs/cgroup//tasks # Ubuntu 12.04 with fstab: /sys/fs/cgroup/lxc//tasks # Ubuntu 12.04 with cgroup-lite: /sys/fs/cgroup/cpuacct/lxc//tasks # Ubuntu 12.04 with cgroup-bin: /sys/fs/cgroup/cpuacct/sysdefault/lxc//tasks # Ubuntu 14.04 /sys/fs/cgroup/systemd/lxc//tasks # and with cgmanager on jessie lxc_count_processes () { local guest_name="$1" local SYSFS [ -z "$guest_name" ] && return 0 if [ -n "$cgrouppath" ]; then SYSFS="$cgrouppath/$guest_name/tasks" if [ -e "$SYSFS" ]; then wc -l <"$SYSFS" return fi fi for SYSFS in \ "/sys/fs/cgroup/$guest_name/tasks" \ "/sys/fs/cgroup/lxc/$guest_name/tasks" \ "/sys/fs/cgroup/cpuacct/lxc/$guest_name/tasks" \ "/sys/fs/cgroup/systemd/lxc/$guest_name/tasks" \ "/sys/fs/cgroup/cpuacct/sysdefault/lxc/$guest_name/tasks" \ "/sys/fs/cgroup/cpu/lxc.payload.$guest_name/tasks" do if [ -e "$SYSFS" ]; then wc -l <"$SYSFS" return fi done if [ -e /usr/bin/cgm ]; then cgm getvalue cpu "lxc/$guest_name" tasks 2>/dev/null | wc -l else get_lxc_cgroup_info "$guest_name" "tasks" | wc -l fi } # change the first character of a string to upper case title_case() { local text="$1" printf "%s%s" "$(echo "$text" | cut -c 1 | tr "[:lower:]" "[:upper:]")" "$(echo "$text" | cut -c 2-)" } do_autoconf() { if [ ! -r /proc/net/dev ]; then echo "no (/proc/net/dev cannot be read)" elif [ ! -e "$lxcpath" ]; then echo "no ($lxcpath is not present)" elif [ -z "$(which lxc-ls)" ]; then echo "no ('lxc-ls' is not available in PATH)" else echo yes fi } do_config() { local active_guests guest_name draw_style active_guests=$(get_active_guests "$exclude") cat <&2 "Invalid action requested (none of: autoconf / config / '')" exit 1 esac