Projet

Général

Profil

Paste
Télécharger au format
Statistiques
| Branche: | Révision:

root / plugins / network / zenus_ @ 33e95e6f

Historique | Voir | Annoter | Télécharger (9,77 ko)

1
#!/usr/bin/perl
2
# -*- cperl -*-
3

    
4
=head1 NAME
5

    
6
zenus_ - Munin plugin to monitor the usage of a Zen Internet Broadband account
7

    
8
=head1 APPLICABLE SYSTEMS
9

    
10
Any (Though most likely those connected to a Zen Internet Broadband connection)
11

    
12
=head1 CONFIGURATION
13

    
14
This plugin requires the C<zenus> module to be installed. This can be fetched
15
from L<http://www.rachaelandtom.info/zenus>.
16

    
17
Tip: To see if it's already setup correctly, just run this plugin
18
with the parameter 'autoconf'. If you get a "yes", everything should
19
work like a charm already.
20

    
21
This configuration section shows the defaults of the plugin:
22

    
23
	[zenus_*]
24
		env.user
25
		env.pass
26
		env.account
27
		env.tick	60
28

    
29
You must supply C<env.user> and C<env.pass>. These will be your PORTAL username and password, NOT your ADSL account details.
30

    
31
You may either specify the account to report through C<env.account> (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.
32

    
33
C<env.tick> 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.
34

    
35
=head1 INTERPRETATION
36

    
37
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.
38

    
39
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.
40

    
41
=head1 MAGIC MARKERS
42

    
43
	#%# family=auto contrib
44
	#%# capabilities=autoconf suggest
45

    
46
=head1 AUTHOR
47

    
48
Paul Saunders L<darac+munin@darac.org.uk>
49

    
50
=cut
51

    
52
use strict;
53
use warnings;
54

    
55
use lib $ENV{'MUNIN_LIBDIR'};
56
use Munin::Plugin;
57
use Data::Dump qw(pp);
58
use Time::Local;
59

    
60
my $ret = undef;
61

    
62
# Load modules like so
63
if ( !eval "require zenus;" ) {
64
    $ret =
65
      "Could not load zenus. Get it from http://www.rachaelandtom.info/zenus\n";
66
    $ret .= "(BTW, \@INC is: " . join( ', ', @INC ) . ")\n";
67
}
68

    
69
my $CAN_LOG = 1;
70
if ( !eval "require Log::Log4perl;" ) {
71
    $CAN_LOG = 0;
72
}
73
elsif ( !eval "require Log::Dispatch::FileRotate;" ) {
74
    $CAN_LOG = 0;
75
}
76

    
77
my $USER = $ENV{user};
78
my $PASS = $ENV{pass};
79
my $ACCT = $ENV{account} || "";
80
my $TICK = $ENV{tick} || 60;      # minutes
81

    
82
my @name_fields = split /_/, $0;
83
if ( scalar @name_fields == 3 ) {
84
    if ( $name_fields[1] eq '' or $name_fields[2] eq '' ) {
85
        print "Misconfigured symlink. See Documentation\n";
86
        exit 1;
87
    }
88
    else {
89
        $ACCT = $name_fields[1] . '@' . $name_fields[2];
90
    }
91
}
92

    
93
# If there are more or less than 3 components to the filename,
94
# we just carry on with the default account
95

    
96
if ($CAN_LOG) {
97
    my $loggerconf = q(
98
		log4perl.rootLogger 				= DEBUG, LOG1
99
		log4perl.appender.LOG1 				= Log::Dispatch::FileRotate
100
		log4perl.appender.LOG1.filename		= /var/log/munin/zenus.log
101
		log4perl.appender.LOG1.mode			= append
102
		log4perl.appender.LOG1.DatePattern	= yyyy-ww
103
		log4perl.appender.LOG1.layout		= Log::Log4perl::Layout::PatternLayout
104
		log4perl.appender.LOG1.layout.ConversionPattern = %d %p %c: %m%n
105
	);
106
    Log::Log4perl::init( \$loggerconf );
107
    our $logger = Log::Log4perl->get_logger($ACCT);
108
} else {
109
	our $logger = "";
110
}
111

    
112
my $lastread;
113

    
114
sub save_data {
115
    my $hashref = shift;
116
    my $update_lastread = shift || 1;
117

    
118
    # Do we need to save this info
119
    if ( !defined $lastread or time > $lastread + ( $TICK * 60 ) ) {
120

    
121
        $lastread = time if $update_lastread;
122
        print "# Updating LastRead to " . localtime($lastread) . "\n";
123

    
124
        my @save_vector;
125
        push @save_vector, $lastread;
126

    
127
        # Push the hash values on to the array
128
        foreach ( keys %$hashref ) {
129
            push @save_vector, $_ . '?' . $hashref->{$_};
130
        }
131

    
132
        $::logger->info(
133
            "Saving Data (LastRead is " . localtime($lastread) . "\n" )
134
          if $CAN_LOG;
135

    
136
        #Go!
137
        save_state(@save_vector);
138
    }
139
}
140

    
141
sub load_data {
142

    
143
    # Bring the data back in
144
    my @save_vector = restore_state();
145

    
146
    # Read the timestamp. Do we need to refresh the data?
147
    $lastread = shift @save_vector;
148

    
149
    my $hashref;
150
    foreach (@save_vector) {
151
        my ( $key, $value ) = split /?/;
152
        $hashref->{$key} = $value;
153
    }
154
    my $force_save = 0;
155
    if ( !defined $lastread or time >= ( $lastread + ( $TICK * 60 ) ) ) {
156

    
157
        # Data is stale
158
        print "# Data is " . ( time - $lastread ) . " seconds old\n";
159
        $::logger->info( "Data is " . ( time - $lastread ) . " seconds old\n" )
160
          if $CAN_LOG;
161

    
162
        if ( exists $hashref->{backoff} ) {
163
            if ( time <= $hashref->{backoff} ) {
164

    
165
                # We're in a back-off period
166
                print "# Back-off in effect\n";
167
                $::logger->info("Back-off in effect\n") if $CAN_LOG;
168
                exit 0;
169
            }
170
            else {
171
                # We've just come out of a back-off period
172
                print "# Back-off ends\n";
173
                $::logger->info("Back-off ends\n") if $CAN_LOG;
174
                delete $hashref->{backoff};
175
            }
176
        }
177
        elsif ( !defined $lastread ) {
178

    
179
            # Initial run. Carry on
180
            print "# Initial Run\n";
181
            my $force_save = 1;
182
        }
183
        elsif ( time >= ( $lastread + ( 120 * 60 ) ) ) {
184

    
185
            # Data is VERY Stale. Assume a login issue and
186
            # back-off for 24 hours.
187
            print "# Starting Back-Off\n";
188
            $hashref->{backoff} = time + ( 24 * 60 * 60 );
189
            $::logger->info(
190
                "Backing off until " . localtime( $hashref->{backoff} ) . "\n" )
191
              if $CAN_LOG;
192
            save_data( $hashref, 0 );
193
            exit 1;
194
        }
195

    
196
        print "# REFRESHING DATA\n";
197
        $::logger->info("Refreshing Data\n") if $CAN_LOG;
198
        my $temphash;
199
        eval {
200
            zenus::login( $USER, $PASS );
201

    
202
            (
203
                $temphash->{name},  $temphash->{used},
204
                $temphash->{avail}, $temphash->{per},
205
                $temphash->{uploadAmount}
206
            ) = zenus::getUsage($ACCT);
207
            (
208
                $temphash->{dayofmonth}, $temphash->{permonth},
209
                $temphash->{avedaily},   $temphash->{maxdaily},
210
                $temphash->{daysremain}, $temphash->{estusage},
211
                $temphash->{daysinmonth}
212
              )
213
              = zenus::estimateRemaining( $temphash->{used},
214
                $temphash->{avail} );
215
            $hashref = $temphash;
216
            1;
217

    
218
            # If zenus threw an error we won't copy the data over,
219
            #  so we still use the cached data.
220
        } or do {
221
            print "# Zenus Error $@\n";
222
        };
223
    }
224
    else {
225
        print "# Using existing data\n";
226
        $::logger->info("Using existing data\n") if $CAN_LOG;
227
    }
228
    save_data( $hashref, 1 ) if $force_save;
229
    return $hashref;
230

    
231
}
232

    
233
if ( defined $ARGV[0] and $ARGV[0] eq "autoconf" ) {
234
    if ($ret) {
235
        print "no ($ret)\n";
236
        exit 1;
237
    }
238
    print "yes\n";
239
    exit 0;
240
}
241

    
242
if ( defined $ARGV[0] and $ARGV[0] eq "suggest" ) {
243
    if ( defined $USER and defined $PASS ) {
244
        zenus::login( $USER, $PASS );
245
        for my $account ( zenus::getAccounts() ) {
246
            if ( defined $account ) {
247
                $account =~ s/\@/_/g;
248
                print "$account\n";
249
            }
250
        }
251
    }
252
    exit 0;
253
}
254

    
255
if ( defined $ARGV[0] and $ARGV[0] eq "config" ) {
256
    if ($ret) {
257
        print $ret;
258
        exit 1;
259
    }
260
    my $data    = load_data();
261
    my $datestr = scalar( localtime($lastread) );
262
    print <<EOF;
263
graph_args --base 1000
264
graph_vlabel GBytes out (-) / in (+)
265
graph_category network
266
graph_title Zen Broadband Usage ($ACCT)
267
graph_info Usage of your Zen Broadband account: $data->{name}
268
upload.label Uploaded
269
upload.type GAUGE
270
upload.info Amount of data uploaded (No upper limit)
271
upload.draw AREA
272
upload.graph no
273
upload.colour 00CC00EE
274
download.label Transfer
275
download.type GAUGE
276
download.draw AREA
277
download.extinfo Last Read was $datestr
278
download.negative upload
279
download.colour 00CC00EE
280
EOF
281
    if ( defined $data->{avail} and $data->{avail} != 0 ) {
282
        my $cap  = sprintf( "%.3f", $data->{avail} );
283
        my $warn = sprintf( "%.3f", $cap * 0.25 );
284
        my $crit = sprintf( "%.3f", $cap * 0.1 );
285
        print <<EOF;
286
download.info Amount of data downloaded (Limit is $cap GB)
287
allowance.label Allowance
288
allowance.type GAUGE
289
allowance.info Amount of data you are allowed to download this month
290
allowance.draw LINE2
291
remaining.label Est'd Remaining
292
remaining.type GAUGE
293
remaining.info Estimated amount of data transfer remaining at the end of the month
294
remaining.draw LINE1
295
remaining.min 0
296
remaining.max $cap
297
remaining.warning $warn:
298
remaining.critical $crit:
299
overrate.label Overspeed Rate
300
overrate.type GAUGE
301
overrate.info Rate at which you're downloading beyond the sustainable rate
302
overrate.draw LINE1
303
overrate.min 0
304
overrate.warning 0:
305
EOF
306
    }
307
    else {
308
        # Probably an unlimited contract
309
        print "download.info Amount of data downloaded\n";
310
    }
311

    
312
    save_data($data);
313
    exit 0;
314
}
315

    
316
my $data = load_data();
317
print "upload.value " . $data->{uploadAmount} . "\n";
318
print "download.value " . $data->{used} . "\n";
319
if ( defined $data->{avail} and $data->{avail} != 0 ) {
320
    print "allowance.value " . $data->{avail} . "\n";
321
    my $remain = $data->{avail} - $data->{estusage};
322
    $remain = 0 if $remain < 0;
323
    print "remaining.value " . $remain . "\n";
324
    my $overrate = $data->{avedaily} - $data->{maxdaily};
325
    $overrate = 0 if $overrate < 0;
326
    print "overrate.value " . $overrate . "\n";
327
}
328
save_data($data);
329
exit 0;