#!/usr/bin/perl # -*- cperl -*- =head1 NAME zenus_ - Munin plugin to monitor the usage of a Zen Internet Broadband account =head1 APPLICABLE SYSTEMS Any (Though most likely those connected to a Zen Internet Broadband connection) =head1 CONFIGURATION This plugin requires the C module to be installed. This can be fetched from L. Tip: To see if it's already setup correctly, just run this plugin with the parameter 'autoconf'. If you get a "yes", everything should work like a charm already. This configuration section shows the defaults of the plugin: [zenus_*] env.user env.pass env.account env.tick 60 You must supply C and C. These will be your PORTAL username and password, NOT your ADSL account details. You may either specify the account to report through C (e.g. zen12345@zen) or by naming the symlink in your plugins directory (e.g. zenus_zen12345_zen). If no account is specified, the default account will be chosen. C specifies how often (in minutes) the data will be refreshed from upstream. This is to avoid hitting the Zen servers every five minutes. Data is cached between runs. =head1 INTERPRETATION The plugin shows the amount of data downloaded and uploaded since the beginning of the chargable period (i.e. the calendar month). A thick line shows the current download allowance (planned plus banked). A thinner line shows the estimated amount remaining at the end of the month. If you are estimated to exceed your allowance before the end of the month, a second line appears showing the rate at which you're downloading beyond the sustainable rate. Warnings are sent if your estimated allowance drops below 25% of your cap and if the overspeed rate rises above zero. Critical warnings are sent if your estimated allowance drops below 10% of your cap. =head1 MAGIC MARKERS #%# family=auto contrib #%# capabilities=autoconf suggest =head1 AUTHOR Paul Saunders L =cut use strict; use warnings; use lib $ENV{'MUNIN_LIBDIR'}; use Munin::Plugin; use Data::Dump qw(pp); use Time::Local; my $ret = undef; # Load modules like so if ( !eval "require zenus;" ) { $ret = "Could not load zenus. Get it from http://www.rachaelandtom.info/zenus\n"; $ret .= "(BTW, \@INC is: " . join( ', ', @INC ) . ")\n"; } my $USER = $ENV{user}; my $PASS = $ENV{pass}; my $ACCT = $ENV{account} || ""; my $TICK = $ENV{tick} || 60; # minutes my @name_fields = split /_/, $0; if ( scalar @name_fields == 3 ) { if ( $name_fields[1] eq '' or $name_fields[2] eq '' ) { print "Misconfigured symlink. See Documentation\n"; exit 1; } else { $ACCT = $name_fields[1] . '@' . $name_fields[2]; } } # If there are more or less than 3 components to the filename, # we just carry on with the default account my $lastread; sub save_data { my $hashref = shift; # Do we need to save this info if ( time > $lastread + ( $TICK * 60 ) ) { $lastread = time; my @save_vector; push @save_vector, $lastread; # Push the hash values on to the array foreach ( keys %$hashref ) { push @save_vector, $_ . '¬' . $hashref->{$_}; } #Go! save_state(@save_vector); } } sub load_data { # Bring the data back in my @save_vector = restore_state(); # Read the timestamp. Do we need to refresh the data? $lastread = shift @save_vector; my $hashref; foreach (@save_vector) { my ( $key, $value ) = split /¬/; $hashref->{$key} = $value; } if ( !defined $lastread or time >= ( $lastread + ( $TICK * 60 ) ) ) { # Data is stale #print STDERR "REFRESHING DATA\n"; my $temphash; eval { zenus::login( $USER, $PASS ); ( $temphash->{name}, $temphash->{used}, $temphash->{avail}, $temphash->{per}, $temphash->{uploadAmount} ) = zenus::getUsage($ACCT); ( $temphash->{dayofmonth}, $temphash->{permonth}, $temphash->{avedaily}, $temphash->{maxdaily}, $temphash->{daysremain}, $temphash->{estusage}, $temphash->{daysinmonth} ) = zenus::estimateRemaining( $temphash->{used}, $temphash->{avail} ); $hashref = $temphash; # If zenus threw an error we won't copy the data over, # so we still use the cached data. }; } return $hashref; } if ( defined $ARGV[0] and $ARGV[0] eq "autoconf" ) { if ($ret) { print "no ($ret)\n"; exit 1; } print "yes\n"; exit 0; } if ( defined $ARGV[0] and $ARGV[0] eq "suggest" ) { if ( defined $USER and defined $PASS ) { zenus::login( $USER, $PASS ); for my $account ( zenus::getAccounts() ) { if ( defined $account ) { $account =~ s/\@/_/g; print "$account\n"; } } } exit 0; } if ( defined $ARGV[0] and $ARGV[0] eq "config" ) { if ($ret) { print $ret; exit 1; } my $data = load_data(); my $cap = sprintf( "%.3f", $data->{avail} ); my $warn = sprintf( "%.3f", $cap * 0.25 ); my $crit = sprintf( "%.3f", $cap * 0.1 ); my $datestr = scalar( localtime($lastread) ); print <{name} upload.label Uploaded upload.type GAUGE upload.info Amount of data uploaded (No upper limit) upload.draw AREA upload.graph no upload.colour 00CC00EE download.label Transfer download.type GAUGE download.info Amount of data downloaded (Limit is $cap GB) download.draw AREA download.extinfo Last Read was $datestr download.negative upload download.colour 00CC00EE allowance.label Allowance allowance.type GAUGE allowance.info Amount of data you are allowed to download this month allowance.draw LINE2 remaining.label Est'd Remaining remaining.type GAUGE remaining.info Estimated amount of data transfer remaining at the end of the month remaining.draw LINE1 remaining.min 0 remaining.max $cap remaining.warning $warn: remaining.critical $crit: overrate.label Overspeed Rate overrate.type GAUGE overrate.info Rate at which you're downloading beyond the sustainable rate overrate.draw LINE1 overrate.min 0 overrate.warning 0: #graph_order download upload allowance remaining overrate EOF save_data($data); exit 0; } my $data = load_data(); print "upload.value " . $data->{uploadAmount} . "\n"; print "download.value " . $data->{used} . "\n"; print "allowance.value " . $data->{avail} . "\n"; my $remain = $data->{avail} - $data->{estusage}; $remain = 0 if $remain < 0; print "remaining.value " . $remain . "\n"; my $overrate = $data->{avedaily} - $data->{maxdaily}; $overrate = 0 if $overrate < 0; print "overrate.value " . $overrate . "\n"; save_data($data); exit 0;