From e4afc5f7ea6b39c03d5423e7bd7e1cb84a9a5c75 Mon Sep 17 00:00:00 2001 From: Nicolas MASSE Date: Sat, 3 May 2014 13:02:29 +0200 Subject: [PATCH] Almost the final version. Implement config. --- .../request.pl | 149 ++++++++++++++++-- 1 file changed, 139 insertions(+), 10 deletions(-) diff --git a/Munin-Plugin-For-Freebox-Revolution/request.pl b/Munin-Plugin-For-Freebox-Revolution/request.pl index 8dabc91..3f17413 100755 --- a/Munin-Plugin-For-Freebox-Revolution/request.pl +++ b/Munin-Plugin-For-Freebox-Revolution/request.pl @@ -4,9 +4,82 @@ use LWP::UserAgent; use JSON::PP; use MIME::Base64; use Digest::SHA qw/hmac_sha1_hex/; +use Data::Dumper; use strict; -my $ua = LWP::UserAgent->new; +# Consider the RRD data for the last 5 minutes +my $interval = 5*60; +my $debug = 0; +my %db_fields = ( + net => [ qw/bw_up bw_down rate_up rate_down/ ], + temp => [ qw/cpum cpub sw hdd fan_speed/ ], + dsl => [ qw/rate_up rate_down snr_up snr_down/ ], +); + +my %graph = ( + net => { + graph_category => 'Network', + graph_args => '--base 1000 -l 0', + graph_scale => 'yes', + graph_info => 'The upload and download rate of the Freebox Revolution.', + (map { + ("$_.info" => ($_ =~ m/^up/ ? "Upstream " : "Downstream ") . ($_ =~ m/rate/ ? "Rate" : "Bandwidth"), + "$_.type" => "GAUGE", + "$_.label" => "bytes/s" ) + } qw/bw_up bw_down rate_up rate_down/), + '.db' => "net", + }, + temp => { + graph_category => 'Sensors', + graph_args => '--base 1000 -0', + graph_scale => 'no', + graph_info => 'The temperature of various sensors on the Freebox Revolution', + (map { + ("$_.warning" => "70", + "$_.critical" => "80", + "$_.info" => "Temperature of the $_ component", + "$_.type" => "GAUGE", + "$_.label" => "°C" ) + } qw/cpum cpub sw hdd/), + '.db' => "temp", + }, + fan => { + graph_category => 'Sensors', + graph_args => '--base 1000 -0', + graph_scale => 'no', + graph_info => 'The fan speed of the Freebox Revolution', + (map { + ("$_.info" => "Fan speed", + "$_.type" => "GAUGE", + "$_.label" => "RPM" ) + } qw/fan_speed/), + '.db' => "temp", + }, + dsl_rate => { + graph_category => 'Network', + graph_args => '--base 1000 -l 0', + graph_scale => 'yes', + graph_info => 'The xDSL rate stats of the Freebox Revolution', + (map { + ("$_.info" => ($_ =~ m/^up/ ? "Upstream " : "Downstream ") . "Rate", + "$_.type" => "GAUGE", + "$_.label" => "kb/s") + } qw/rate_up rate_down/), + '.db' => "dsl", + }, + dsl_snr => { + graph_category => 'Network', + graph_args => '--base 1000 -l 0', + graph_scale => 'no', + graph_info => 'The xDSL SNR stats of the Freebox Revolution', + (map { + ("$_.info" => ($_ =~ m/^up/ ? "Upstream " : "Downstream ") . "SNR Ratio", + "$_.type" => "GAUGE", + "$_.label" => "dB") + } qw/snr_up snr_down/), + '.db' => "dsl", + }, +); sub get_json { my $resp = shift; @@ -15,15 +88,36 @@ sub get_json { warn "$method: www: ".$resp->status_line unless $resp->is_success; my $json = decode_json($resp->decoded_content); - die "$method: fb: method call failed: ".$json->{msg} + die "$method: api: method call failed: ".$json->{msg} unless $json->{success}; return $json; } +# Determine which graph is asked by munin +my @mode = grep { $0 =~ m/fb_${_}/ } keys %graph; +die "please symlink this script with a valid suffix (",(join ",", keys %graph),"). Exemple: fb_net. " + unless @mode; +my $mode = $mode[0]; +warn "mode is $mode" if $debug; + +# Print out config when asked to do so +my $arg = shift; +my $graph_info = $graph{$mode}; +my @fields = sort map { m/\.info/ ? m/(.*)\./ : () } keys %{$graph_info}; +if (defined $arg and $arg eq 'config') { + print "graph_order ", (join " ", @fields), "\n"; + foreach my $key (sort grep /^[^.]/, keys %{$graph_info}) { + print $key, " ", $graph_info->{$key}, "\n"; + } + exit 0; +} + +my $ua = LWP::UserAgent->new; + my $auth_response = $ua->get("http://mafreebox.freebox.fr/api/v1/login/"); my $json_auth_response = get_json($auth_response, "login"); my $challenge = $json_auth_response->{result}->{challenge}; -print "Current challenge is $challenge\n"; +warn "Current challenge is $challenge" if $debug; my $filename = "apptoken"; open TOKENFILE, "<", $filename @@ -32,25 +126,60 @@ my $apptoken = ; close TOKENFILE; my $pw = hmac_sha1_hex($challenge, $apptoken); -print "Computed password is $pw\n"; +warn "Computed password is $pw" if $debug; my %auth_request = ( app_id => "fr.itix.munin", password => $pw ); +# Get a session token $auth_response = $ua->post("http://mafreebox.freebox.fr/api/v1/login/session", Content => encode_json(\%auth_request)); -$json_auth_response = get_json($auth_response, "login"); +$json_auth_response = get_json($auth_response, "session"); my $session_token = $json_auth_response->{result}->{session_token}; die "post: session: no session_token in response" unless defined $session_token; +# Use it in follwowing calls $ua->default_header('X-Fbx-App-Auth', $session_token); -my %rrd_request = ( - db => "net", - date_start => time - 5*60, + +# Do not forget to logout +END { + if (defined $session_token) { + my $logout_response = $ua->post("http://mafreebox.freebox.fr/api/v1/login/session", Content => encode_json(\%auth_request)); + my $json_logout_response = get_json($auth_response, "session"); + } +} + +my $db = $graph_info->{'.db'}; +my %json_request = ( + db => $db, + date_start => time - $interval, date_end => time, + fields => \@fields, ); -my $rrd_response = $ua->post("http://mafreebox.freebox.fr/api/v1/rrd", Content => encode_json(\%rrd_request)); -my $json_rrd_response = get_json($rrd_response, "rrd"); + +# Get actual values +my $rest_response = $ua->post("http://mafreebox.freebox.fr/api/v1/rrd", Content => encode_json(\%json_request)); +my $json_rrd_response = get_json($rest_response, "rrd_$db"); + +my %sum; +my $count = 0; +foreach my $data (@{$json_rrd_response->{result}->{data}}) { + foreach my $field (@fields) { + my $value = $data->{$field}; + $sum{$field} = 0 + unless exists $sum{$field}; + $sum{$field} += $value; + } + $count++; +} + +# Average every result +while (my ($field, $sum) = each(%sum)) { + my $average = int($sum / $count); + print "${db}_${field}.value $average\n"; +} + +exit 0