52754d1b71537e29da781182c21f9a7f11ab9c44
1 #
2 # collectd - OpenVZ collectd plugin
3 # Copyright (C) 2009 Jonathan Kolb
4 #
5 # This program is free software; you can redistribute it and/or modify it under
6 # the terms of the GNU General Public License as published by the Free Software
7 # Foundation; either version 2 of the License, or (at your option) any later
8 # version.
9 #
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License along
16 # with this program; if not, write to the Free Software Foundation, Inc.,
17 # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 #
19 # Author:
20 # Jonathan Kolb <jon at b0g.us>
21 #
23 package Collectd::Plugins::OpenVZ;
25 use strict;
26 use warnings;
28 use Collectd qw( :all );
30 my @cpu_instances = ('user', 'nice', 'system', 'idle', 'wait', 'interrupt', 'softirq', 'steal');
31 my @if_instances = ('if_octets', 'if_packets', 'if_errors');
32 my $vzctl = '/usr/sbin/vzctl';
33 my $vzlist = '/usr/sbin/vzlist';
35 my $last_stat = {};
37 sub openvz_read
38 {
39 my %v = (time => time(), interval => $interval_g);
40 my (@veids, $veid, $name, $key, $val, $i, @lines, @parts, @counters);
42 @veids = map { s/ //g; $_; } split(/\n/, `$vzlist -Ho veid`);
44 foreach $veid (@veids)
45 {
46 ($name = `$vzlist -Ho name $veid`) =~ s/^\s*(.*?)\s*$/$1/;
47 $name = $veid if ($name =~ /^-$/);
49 $v{'host'} = $name;
51 #####################################################################
52 # interface
54 $v{'plugin'} = 'interface';
55 delete $v{'plugin_instance'};
57 @lines = split(/\n/, `$vzctl exec $veid cat /proc/net/dev`);
58 foreach (@lines)
59 {
60 next if (!/:/);
62 @parts = split(/:/);
63 ($key = $parts[0]) =~ s/^\s*(.*?)\s*$/$1/;
64 ($val = $parts[1]) =~ s/^\s*(.*?)\s*$/$1/;
65 @counters = split(/ +/, $val);
67 $v{'type_instance'} = $key;
68 for ($key = 0; $key <= $#if_instances; ++$key)
69 {
70 $v{'type'} = $if_instances[$key];
71 $v{'values'} = [ $counters[$key], $counters[$key + 8] ];
72 plugin_dispatch_values($if_instances[$key], \%v);
73 }
74 }
76 #####################################################################
77 # cpu
79 $v{'plugin'} = 'cpu';
80 $v{'type'} = 'cpu';
82 $i = 0;
83 @lines = split(/\n/, `$vzctl exec $veid cat /proc/stat`);
84 foreach (@lines)
85 {
86 next if (!/^cpu[0-9]/);
88 @counters = split(/ +/);
89 shift(@counters);
91 # Remove once OpenVZ bug 1376 is resolved
92 if (48485 == $counters[3])
93 {
94 $counters[3] = $last_stat->{"$veid-$i-idle"};
95 $counters[4] = $last_stat->{"$veid-$i-wait"};
96 }
97 else
98 {
99 $last_stat->{"$veid-$i-idle"} = $counters[3];
100 $last_stat->{"$veid-$i-wait"} = $counters[4];
101 }
103 $v{'plugin_instance'} = $i++;
104 for ($key = 0; $key <= $#counters; ++$key)
105 {
106 $v{'type_instance'} = $cpu_instances[$key];
107 $v{'values'} = [ $counters[$key] ];
108 plugin_dispatch_values('cpu', \%v);
109 }
110 }
112 #####################################################################
113 # df
115 $v{'plugin'} = 'df';
116 delete $v{'plugin_instance'};
117 $v{'type'} = 'df';
119 $val = join(' ', map { (split)[1] } split(/\n/, `$vzctl exec $veid cat /proc/mounts`));
120 @lines = split(/\n/, `$vzctl exec $veid stat -tf $val`);
121 foreach (@lines)
122 {
123 @parts = split(/ /);
124 next if (0 == $parts[7]);
126 $val = substr($parts[0], 1);
127 $val = 'root' if ($val =~ /^$/);
128 $val =~ s#/#-#g;
130 $v{'type_instance'} = $val;
131 $v{'values'} = [ $parts[5] * ($parts[6] - $parts[7]), $parts[5] * $parts[7] ];
132 plugin_dispatch_values('df', \%v);
133 }
135 #####################################################################
136 # load
138 $v{'plugin'} = 'load';
139 delete $v{'plugin_instance'};
140 $v{'type'} = 'load';
141 delete $v{'type_instance'};
143 @parts = split(/ +/, `$vzctl exec $veid cat /proc/loadavg`);
144 $v{'values'} = [ $parts[0], $parts[1], $parts[2] ];
145 plugin_dispatch_values('load', \%v);
147 #####################################################################
148 # processes
150 my $ps_states = { 'paging' => 0, 'blocked' => 0, 'zombies' => 0, 'stopped' => 0,
151 'running' => 0, 'sleeping' => 0 };
152 my $state_map = { 'R' => 'running', 'S' => 'sleeping', 'D' => 'blocked',
153 'Z' => 'zombies', 'T' => 'stopped', 'W' => 'paging' };
155 $v{'plugin'} = 'processes';
156 delete $v{'plugin_instance'};
157 $v{'type'} = 'ps_state';
159 @lines = map { (split)[2] } split(/\n/, `$vzctl exec $veid cat '/proc/[0-9]*/stat'`);
160 foreach $key (@lines)
161 {
162 ++$ps_states->{$state_map->{$key}};
163 }
165 foreach $key (keys %{$ps_states})
166 {
167 $v{'type_instance'} = $key;
168 $v{'values'} = [ $ps_states->{$key} ];
169 plugin_dispatch_values('ps_state', \%v);
170 }
172 #####################################################################
173 # users
175 $v{'plugin'} = 'users';
176 delete $v{'plugin_instance'};
177 $v{'type'} = 'users';
178 delete $v{'type_instance'};
180 @lines = split(/\n/, `$vzctl exec $veid w -h`);
181 $v{'values'} = [ scalar(@lines) ];
182 plugin_dispatch_values('users', \%v);
183 }
185 return 1;
186 }
188 plugin_register(TYPE_READ, 'OpenVZ', 'openvz_read');
190 return 1;