#!/usr/bin/perl use Tk; use Tk::Graph; use POE qw/Component::SNMP Component::Client::TCP/; use Time::HiRes qw/time/; use Data::Dumper; use warnings; use strict; use constant SNMP_HOSTS => 1; use constant STATUS_LINE => 1; use constant SHOW_ALL_LOADS => 0; # do 'trace_calls.pl'; my $VERBOSE = 0; my $POLL_DELAY = 5; my $REDRAW_DELAY = 1; $|++; $POLL_DELAY = $ENV{DELAY} if $ENV{DELAY}; # {{{ SNMP variables # snmpget -v1 -c public localhost 1.3.6.1.4.1.2021.10.1.3.1 # snmpget -v1 -c public localhost enterprises.ucdavis.laTable.laEntry.laLoad.1 #my $load1_oid = 'enterprises.ucdavis.laTable.laEntry.laLoad.1'; my $load1_oid = '.1.3.6.1.4.1.2021.10.1.3.1'; my $load5_oid = '.1.3.6.1.4.1.2021.10.1.3.2'; my $load15_oid = '.1.3.6.1.4.1.2021.10.1.3.3'; # hostname oid: system.sysName => 1.3.6.1.2.1.1.5.0 my $host_oid = '.1.3.6.1.2.1.1.5.0'; # }}} SNMP variables # {{{ HOSTS # it wants to complain about the '#' chars in the qw// for the color # values, so hush! no warnings; # name => [ hostname_or_ip color ] my %snmp_host = ( localhost => [qw( 127.0.0.1 #FF0000 )], # red ); my %snmp_community = ( localhost => 'not_public_of_course' ); use warnings; # }}} HOSTS ## STATES ## # {{{ _start sub _start { my($kernel, $heap, $session) = @_[KERNEL, HEAP, SESSION]; my %config; $kernel->alias_set('graph_window'); # {{{ snmp hosts if (SNMP_HOSTS) { while (my ($name, $etc) = each %snmp_host) { my ($host, $one, $five, $fifteen) = @$etc; my $name_01 = "${name}_01"; $config{$name_01} = { -title => $name, -color => $one, }; ## setup the snmp processes POE::Component::SNMP->create( hostname => $host, community => $snmp_community{$host} || 'public', alias => "snmp_$name", timeout => 2, retries => 0, # debug => 0x3E, # debug => 0x04, # transport ); $heap->{snmp_hostnames}->{$host} = $name; $heap->{fields}->{$name} = [ $name_01 ]; $heap->{time}{$name} = time; # $kernel->yield( snmp_poll => $name, $host ); $kernel->call( $session => snmp_poll => $name, $host ); } } # }}} snmp hosts # {{{ set up the graph widget $heap->{ca} = $poe_main_window->Graph( -type => 'LINE', -linewidth => 2, -look => 100, -sortnames => 'alpha', -legend => 1, # -lineheight => 30, # -threed => 3, -headroom => 10, -config => \%config, -shadowdepth => 2, ); $poe_main_window->configure(-title => "load averages"); $poe_main_window->iconbitmap('@/usr/share/xemacs/xemacs-packages/etc/frame-icon/radioactive.xbm'); $heap->{ca}->pack( -expand => 1, -fill => 'both', ); $heap->{vars} = []; # empty update list; $kernel->call( $session => 'redraw_graph' ); # }}} set up the graph widget } # }}} _start # {{{ snmp_got_data sub snmp_got_data { my($kernel, $heap, $request, $response) = @_[KERNEL, HEAP, ARG0, ARG1]; my ($alias, $host, $cmd, @args) = @$request; my ($results, $error) = @$response; my $one; my ($name) = $alias =~ /snmp_(.*)/; $VERBOSE and print Dumper [ $request, $response ]; if (ref $results) { # GOOD ANSWER! unless ($name) { $host = $results->{$host_oid}; $name = $heap->{snmp_hostnames}{$host}; } ($one) = @{$results}{ $load1_oid }; } elsif (($host) = $results =~ /No response from remote host '(.*)'/) { # NO RESPONSE $VERBOSE and warn "SNMP $alias ($host): $results\n"; # $name ||= $heap->{snmp_hostnames}{$host}; } else { $VERBOSE and warn "SNMP $_[ARG0][0] ($_[ARG0][1]): $results\n"; } unless (defined $name) { warn "\$name is NOT defined!!!!!!!!\n"; warn Dumper( $_[ARG0] ); return; } my $time = time; my $delay = $POLL_DELAY - ($time - $heap->{time}{$name}); $delay = 0 if $delay < 0; $kernel->delay_add( snmp_poll => $POLL_DELAY, $name, $host ); $heap->{time}{$name} = $time; my $fields = $heap->{fields}->{$name}; unless (defined $fields) { warn "No such name $name"; } # stash the incoming values on the heap, to be updated in # redraw_graph() push @{$heap->{vars}}, ($fields->[0] => $one); } # }}} snmp_got_data # {{{ snmp_poll sub snmp_poll { my($kernel, $heap, $name, $host) = @_[KERNEL, HEAP, ARG0, ARG1]; $host ||= ''; # poll an SNMP host $kernel->post( "snmp_$name" => 'get', "snmp_got_data", -varbindlist => [ $load1_oid ] ); } # }}} snmp_poll # {{{ redraw_graph sub redraw_graph { my ($kernel, $heap) = @_[KERNEL, HEAP]; # defer the call to $heap->{ca}->set() to be the *LAST* call in # this function. this works around weird POE/Tk bugs in weird # versions of perl, like 5.8.0. my %v = @{$heap->{vars}}; $heap->{vars} = []; # empty update list; $kernel->delay_add( redraw_graph => $REDRAW_DELAY ); return unless scalar keys %v; $heap->{ca}->set(\%v); } # }}} redraw_graph POE::Session->create ( inline_states => { _start => \&_start, snmp_poll => \&snmp_poll, snmp_got_data => \&snmp_got_data, redraw_graph => \&redraw_graph, } ); POE::Kernel->run;