use Collectd qw( :all );
-my @cpu_instances = ('user', 'nice', 'system', 'idle', 'wait', 'interrupt', 'softirq', 'steal');
-my @if_instances = ('if_octets', 'if_packets', 'if_errors');
my $vzctl = '/usr/sbin/vzctl';
my $vzlist = '/usr/sbin/vzlist';
-my $last_stat = {};
+# Since OpenVZ is container based, all guests see all the host's CPUs,
+# and would report the same data. So we disable CPU by default.
+my $enable_interface = 1;
+my $enable_cpu = 0;
+my $enable_df = 1;
+my $enable_load = 1;
+my $enable_processes = 1;
+my $enable_users = 1;
+
+sub interface_read($$) {
+ my $veid = shift;
+ my $name = shift;
+ my ($key, $val, @lines, @parts, @counters);
+ my @if_instances = ('if_octets', 'if_packets', 'if_errors');
+ my %v = _build_report_hash($name);
+
+ $v{'plugin'} = 'interface';
+ delete $v{'plugin_instance'};
+
+ @lines = split(/\n/, `$vzctl exec $veid cat /proc/net/dev`);
+ foreach (@lines) {
+ next if (!/:/);
+
+ @parts = split(/:/);
+ ($key = $parts[0]) =~ s/^\s*(.*?)\s*$/$1/;
+ ($val = $parts[1]) =~ s/^\s*(.*?)\s*$/$1/;
+ @counters = split(/ +/, $val);
+
+ $v{'type_instance'} = $key;
+ for ($key = 0; $key <= $#if_instances; ++$key) {
+ $v{'type'} = $if_instances[$key];
+ $v{'values'} = [ $counters[$key], $counters[$key + 8] ];
+ plugin_dispatch_values(\%v);
+ }
+}
+}
-sub openvz_read
-{
- my %v = (time => time(), interval => plugin_get_interval());
- my (@veids, $veid, $name, $key, $val, $i, @lines, @parts, @counters);
+sub cpu_read($$) {
+ my $veid = shift;
+ my $name = shift;
+ my ($key, $val, $i, @lines, @counters);
+ my @cpu_instances = ('user', 'nice', 'system', 'idle', 'wait', 'interrupt', 'softirq', 'steal');
+ my $last_stat = {};
+ my %v = _build_report_hash($name);
+
+ $v{'plugin'} = 'cpu';
+ $v{'type'} = 'cpu';
+
+ $i = 0;
+ @lines = split(/\n/, `$vzctl exec $veid cat /proc/stat`);
+ foreach (@lines) {
+ next if (!/^cpu[0-9]/);
+
+ @counters = split(/ +/);
+ shift(@counters);
+
+ # Remove once OpenVZ bug 1376 is resolved
+ if (48485 == $counters[3]) {
+ $counters[3] = $last_stat->{"$veid-$i-idle"};
+ $counters[4] = $last_stat->{"$veid-$i-wait"};
+ }
+ else {
+ $last_stat->{"$veid-$i-idle"} = $counters[3];
+ $last_stat->{"$veid-$i-wait"} = $counters[4];
+ }
- @veids = map { s/ //g; $_; } split(/\n/, `$vzlist -Ho veid`);
+ $v{'plugin_instance'} = $i++;
+ for ($key = 0; $key <= $#counters; ++$key) {
+ $v{'type_instance'} = $cpu_instances[$key];
+ $v{'values'} = [ $counters[$key] ];
+ plugin_dispatch_values(\%v);
+ }
+}
+}
- foreach $veid (@veids)
- {
- ($name = `$vzlist -Ho name $veid`) =~ s/^\s*(.*?)\s*$/$1/;
- $name = $veid if ($name =~ /^-$/);
+sub df_read($$) {
+ my $veid = shift;
+ my $name = shift;
+ my ($key, $val, @lines, @parts);
+ my %v = _build_report_hash($name);
- $v{'host'} = $name;
+ $v{'plugin'} = 'df';
+ delete $v{'plugin_instance'};
+ $v{'type'} = 'df';
- #####################################################################
- # interface
+ $val = join(' ', map { (split)[1] } split(/\n/, `$vzctl exec $veid cat /proc/mounts`));
+ @lines = split(/\n/, `$vzctl exec $veid stat -tf $val`);
+ foreach (@lines) {
+ @parts = split(/ /);
+ next if (0 == $parts[7]);
- $v{'plugin'} = 'interface';
- delete $v{'plugin_instance'};
+ $val = substr($parts[0], 1);
+ $val = 'root' if ($val =~ /^$/);
+ $val =~ s#/#-#g;
- @lines = split(/\n/, `$vzctl exec $veid cat /proc/net/dev`);
- foreach (@lines)
- {
- next if (!/:/);
+ $v{'type_instance'} = $val;
+ $v{'values'} = [ $parts[5] * ($parts[6] - $parts[7]), $parts[5] * $parts[7] ];
+ plugin_dispatch_values(\%v);
+}
+}
- @parts = split(/:/);
- ($key = $parts[0]) =~ s/^\s*(.*?)\s*$/$1/;
- ($val = $parts[1]) =~ s/^\s*(.*?)\s*$/$1/;
- @counters = split(/ +/, $val);
+sub load_read($$) {
+ my $veid = shift;
+ my $name = shift;
+ my ($key, $val, @lines, @parts);
+ my %v = _build_report_hash($name);
- $v{'type_instance'} = $key;
- for ($key = 0; $key <= $#if_instances; ++$key)
- {
- $v{'type'} = $if_instances[$key];
- $v{'values'} = [ $counters[$key], $counters[$key + 8] ];
- plugin_dispatch_values(\%v);
- }
- }
+ $v{'plugin'} = 'load';
+ delete $v{'plugin_instance'};
+ $v{'type'} = 'load';
+ delete $v{'type_instance'};
- #####################################################################
- # cpu
-
- $v{'plugin'} = 'cpu';
- $v{'type'} = 'cpu';
-
- $i = 0;
- @lines = split(/\n/, `$vzctl exec $veid cat /proc/stat`);
- foreach (@lines)
- {
- next if (!/^cpu[0-9]/);
-
- @counters = split(/ +/);
- shift(@counters);
-
- # Remove once OpenVZ bug 1376 is resolved
- if (48485 == $counters[3])
- {
- $counters[3] = $last_stat->{"$veid-$i-idle"};
- $counters[4] = $last_stat->{"$veid-$i-wait"};
- }
- else
- {
- $last_stat->{"$veid-$i-idle"} = $counters[3];
- $last_stat->{"$veid-$i-wait"} = $counters[4];
- }
-
- $v{'plugin_instance'} = $i++;
- for ($key = 0; $key <= $#counters; ++$key)
- {
- $v{'type_instance'} = $cpu_instances[$key];
- $v{'values'} = [ $counters[$key] ];
- plugin_dispatch_values(\%v);
- }
- }
+ @parts = split(/ +/, `$vzctl exec $veid cat /proc/loadavg`);
+ $v{'values'} = [ $parts[0], $parts[1], $parts[2] ];
+ plugin_dispatch_values(\%v);
+}
- #####################################################################
- # df
+sub processes_read($$) {
+ my $veid = shift;
+ my $name = shift;
+ my ($key, $val, @lines);
+ my %v = _build_report_hash($name);
- $v{'plugin'} = 'df';
- delete $v{'plugin_instance'};
- $v{'type'} = 'df';
+ my $ps_states = { 'paging' => 0, 'blocked' => 0, 'zombies' => 0, 'stopped' => 0,
+ 'running' => 0, 'sleeping' => 0 };
+ my $state_map = { 'R' => 'running', 'S' => 'sleeping', 'D' => 'blocked',
+ 'Z' => 'zombies', 'T' => 'stopped', 'W' => 'paging' };
- $val = join(' ', map { (split)[1] } split(/\n/, `$vzctl exec $veid cat /proc/mounts`));
- @lines = split(/\n/, `$vzctl exec $veid stat -tf $val`);
- foreach (@lines)
- {
- @parts = split(/ /);
- next if (0 == $parts[7]);
+ $v{'plugin'} = 'processes';
+ delete $v{'plugin_instance'};
+ $v{'type'} = 'ps_state';
- $val = substr($parts[0], 1);
- $val = 'root' if ($val =~ /^$/);
- $val =~ s#/#-#g;
+ @lines = map { (split)[2] } split(/\n/, `$vzctl exec $veid cat '/proc/[0-9]*/stat'`);
+ foreach $key (@lines) {
+ ++$ps_states->{$state_map->{$key}};
+ }
- $v{'type_instance'} = $val;
- $v{'values'} = [ $parts[5] * ($parts[6] - $parts[7]), $parts[5] * $parts[7] ];
- plugin_dispatch_values(\%v);
- }
+ foreach $key (keys %{$ps_states}) {
+ $v{'type_instance'} = $key;
+ $v{'values'} = [ $ps_states->{$key} ];
+ plugin_dispatch_values(\%v);
+}
+}
- #####################################################################
- # load
+sub users_read($$) {
+ my $veid = shift;
+ my $name = shift;
+ my ($key, $val, @lines);
+ my %v = _build_report_hash($name);
- $v{'plugin'} = 'load';
- delete $v{'plugin_instance'};
- $v{'type'} = 'load';
- delete $v{'type_instance'};
+ $v{'plugin'} = 'users';
+ delete $v{'plugin_instance'};
+ $v{'type'} = 'users';
+ delete $v{'type_instance'};
- @parts = split(/ +/, `$vzctl exec $veid cat /proc/loadavg`);
- $v{'values'} = [ $parts[0], $parts[1], $parts[2] ];
- plugin_dispatch_values(\%v);
+ @lines = split(/\n/, `$vzctl exec $veid w -h`);
+ $v{'values'} = [ scalar(@lines) ];
+ plugin_dispatch_values(\%v);
+}
+
+sub _build_report_hash($) {
+ my $name = shift;
+ return (time => time(), interval => plugin_get_interval(), host => $name);
+}
+
+sub openvz_read {
+ my (@veids, $veid, $name);
+
+ @veids = map { s/ //g; $_; } split(/\n/, `$vzlist -Ho veid`);
- #####################################################################
- # processes
+ foreach $veid (@veids) {
+ ($name = `$vzlist -Ho name $veid`) =~ s/^\s*(.*?)\s*$/$1/;
+ $name = $veid if ($name =~ /^-$/);
- my $ps_states = { 'paging' => 0, 'blocked' => 0, 'zombies' => 0, 'stopped' => 0,
- 'running' => 0, 'sleeping' => 0 };
- my $state_map = { 'R' => 'running', 'S' => 'sleeping', 'D' => 'blocked',
- 'Z' => 'zombies', 'T' => 'stopped', 'W' => 'paging' };
+ if($enable_interface) {
+ interface_read($veid, $name);
+ }
- $v{'plugin'} = 'processes';
- delete $v{'plugin_instance'};
- $v{'type'} = 'ps_state';
+ if($enable_cpu) {
+ cpu_read($veid, $name);
+ }
- @lines = map { (split)[2] } split(/\n/, `$vzctl exec $veid cat '/proc/[0-9]*/stat'`);
- foreach $key (@lines)
- {
- ++$ps_states->{$state_map->{$key}};
+ if($enable_df) {
+ df_read($veid, $name);
}
- foreach $key (keys %{$ps_states})
- {
- $v{'type_instance'} = $key;
- $v{'values'} = [ $ps_states->{$key} ];
- plugin_dispatch_values(\%v);
+ if($enable_load) {
+ load_read($veid, $name);
}
- #####################################################################
- # users
+ if($enable_processes) {
+ processes_read($veid, $name);
+ }
- $v{'plugin'} = 'users';
- delete $v{'plugin_instance'};
- $v{'type'} = 'users';
- delete $v{'type_instance'};
+ if($enable_users) {
+ users_read($veid, $name);
+ }
- @lines = split(/\n/, `$vzctl exec $veid w -h`);
- $v{'values'} = [ scalar(@lines) ];
- plugin_dispatch_values(\%v);
+ return 1;
}
-
- return 1;
}
plugin_register(TYPE_READ, 'OpenVZ', 'openvz_read');