check_UBC.pl

A Nagios-plugin to monitor fail-counts of OpenVZ containers.

OpenVZ containers may have limited resources, if they reach their maximum and try to request more of a single resource they produce a fail-count that is displayed in /proc/user_beancounters. Maybe you want to get notified about that problem, this script monitors the file and alerts if any fail-counter increases.
To reset the fail-counts you have to restart the container, but sometimes there isn’t the chance to reboot a virtual machine. So this script copies the /proc/user_beancounters (at default the copy is located at /tmp/user_beancounters) and alerts about diffs. To disable the alert just delete the copy, the script will create a new copy when it is called the next time. So there won’t be a diff anymore.

To get read access to /proc/user_beancounters for the user nagios don’t forget to set the s-bit (chmod +s check_UBC.pl).

Here is the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#!/usr/bin/perl -w
###################################
#
#     Monitor the UserBeanCounter
#     of OpenVZ vservers. This is
#     the way vservers tell it's
#     host about ressource issues.
#     written by Martin Scharm
#       see http://binfalse.de
#
###################################

use warnings;
use strict;
use lib "/usr/lib/nagios/plugins";
use utils qw(%ERRORS);

$ENV{'PATH'} = '/bin:/usr/bin:/usr/sbin/';
my $UBC = "/proc/user_beancounters";
my $UBC_CPY = "/tmp/nagios_user_beancounters";
my %CONTAINER = ();
my $RETURN = "";
my $RETURN_STAT = $ERRORS{'OK'};

if (! -e $UBC_CPY)
{
    if (! open IN, "<", $UBC )
    {
        print "could not read $UBC\n";
        exit $ERRORS{'CITICAL'};
    }
    if (! open OUT, ">", $UBC_CPY)
    {
        close IN;
        print "could not write $UBC_CPY\n";
        exit $ERRORS{'CITICAL'};
    }
    while ( my $line = <IN> )
    {
        print OUT $line;
    }
    close IN;
    close OUT;
    chmod 0600, $UBC_CPY;
    print "copied file first time\n";
    exit $ERRORS{'OK'};
}

my $original = parse ($UBC);
my $copy = parse ($UBC_CPY);

foreach my $key ( keys %$original )
{
    if (! $copy->{$key})
    {
        $CONTAINER{$key} .= "out of date;";
        $RETURN_STAT = $ERRORS{'WARNING'} if ($RETURN_STAT != $ERRORS{'CRITICAL'});
        next;
    }
    foreach my $key2 ( keys %{$original->{$key}} )
    {
        if ($original->{$key}->{$key2} > $copy->{$key}->{$key2})
        {
            $CONTAINER{$key} .= $key2 . "=>" . $original->{$key}->{$key2} . " (" . $copy->{$key}->{$key2} . "); ";
            $RETURN_STAT = $ERRORS{'CRITICAL'};
        }
        elsif ($original->{$key}->{$key2} < $copy->{$key}->{$key2})
        {
            $CONTAINER{$key} .= $key2 . "=>" . $original->{$key}->{$key2} . " (" . $copy->{$key}->{$key2} . " out of date); ";
            $RETURN_STAT = $ERRORS{'WARNING'} if ($RETURN_STAT != $ERRORS{'CRITICAL'});
        }
    }
}

foreach my $key ( keys %CONTAINER )
{
    my $zone = "";
    chomp ($zone = `/usr/sbin/vzctl exec $key hostname`) if (-e "/usr/sbin/vzctl" && -x "/usr/sbin/vzctl" && $key > 0);
    $RETURN .= "[" . ($zone ? $zone : $key) . "]: " . $CONTAINER{$key};
}

if ($RETURN)
{
    print keys( %CONTAINER ) . " container with failcounts:  " . $RETURN . "\n";
    exit $RETURN_STAT;
}

print "everything is fine..\n";
exit $ERRORS{'OK'};




sub parse
{
    my $file = shift;

    if (!open (FILE, "<".$file))
    {
        print "Could not open " . $file . "\n";
        exit $ERRORS{CRITICAL};
    }

    my $container = {};
    my $aktzone = -1;

    while (my $line = <FILE>)
    {
        next if ($line =~ m/^version/i);
        my @vals = split(/\s+/, $line);
        my $descr = scalar (@vals) > 7 ? $vals[2] : $vals[1];
        my $failcnt = scalar (@vals) > 7 ? $vals[7] : $vals[6];
        next if ($failcnt =~ m/fail/i);
        $aktzone = substr ($vals[1], 0, -1) if (scalar (@vals) == 8);
        $container->{$aktzone}->{$descr} = $failcnt;
    }

    close(FILE);
    return $container;
}

Dependencies

  • Expects the beancounters in /proc/user_beancounters
  • Expects vzctl to be found in /usr/sbin/vzctl

Please consider to take a look at my general setup notes.

Download:
Perl: check_UBC.pl
(Please take a look at the man-page. Browse bugs and feature requests.)

One response to “check_UBC.pl”

  1. looks like it depends on some nagios libs as well, which makes it less portable.

Leave a Reply