From: Jan Willamowius Date: Tue, 27 Sep 2005 16:13:13 +0000 (+0000) Subject: Plugin to monitor RealServer v4 by Andrew Ruthven X-Git-Tag: spong-2_8_0-beta1~4 X-Git-Url: http://git.etc.gen.nz/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0f6aee341bc7e10662b1355d17c465da772a88ed;p=spong.git Plugin to monitor RealServer v4 by Andrew Ruthven --- diff --git a/src/lib/Spong/Client/plugins/check_realserver b/src/lib/Spong/Client/plugins/check_realserver new file mode 100755 index 0000000..c446ceb --- /dev/null +++ b/src/lib/Spong/Client/plugins/check_realserver @@ -0,0 +1,242 @@ +=head1 NAME + +B - spong-client module to check the local RealServer + +=head1 DESCRIPTION + +This is a plugin module for the Spong L program. The +B module checks the status of the locally running +RealServer process using the rssm command. It is known to work with +version 4 of the software, it may work with others (the latest is v9). + +It not only alerts you to a problem if it can't connect, but it also +checks to make sure that certain specified encoders are running +(useful if you're doing live streaming) and returns all the players +currently connected. + +The number of players listening to each live stream can be +graphed using L. + +This module should really be for L but I don't have the +rssm program for the version of Linux I'm running, nor do I know the +protocol which rssm uses. Someday I may try and find out the protocol, +but not yet. If someone can supply me with a rssm that runs in Debian +GNU/Linux Woody then I'll modify it to work as a spong-network module. + +=cut + + +# Register this routine with the plugin reqistry +$CHECKFUNCS{'realserver'} = \&check_realserver; + +# This routine checks RealServer process running locally using rssm. + +use Expect; + +sub check_realserver { + my ($color) = 'green'; + my ($message) = ''; + my ($summary) = ''; + my ($password) = $REALSERVER_PASSWORD; + + if (! defined $password || $password eq '') { + $color = 'red'; + $summary = 'failed - no password'; + $message = "Please supply me with a password.\n"; + } else { + + my ($exp); + if ($exp = new Expect ("$REALSERVER_RSSM -i localhost")) { + $exp->log_stdout(0); + + my ($state) = 'start'; + my (@list); + + $exp->expect(10, [ + qr'password:', + sub { + $spawn_ok = 1; + my $fh = shift; + $fh->send("$password\n"); + $state = 'password'; + exp_continue; + } + ], + [ + 'Command:', + sub { + my ($fh) = shift; + if ($state eq 'password') { + $fh->send("l\n"); + $state = 'list'; + exp_continue; + } elsif ($state eq 'list') { + @list = sort split(/^/m, $exp->before()); + $fh->send("x\n"); + $state = 'exit'; + exp_continue; + } + } + ], + [ + 'rssm: cannot connect to', + sub { + $state = 'login failed'; + exp_continue; + } + ]); + + if ($state eq 'login failed') { + $color = 'red'; + $summary = 'failed'; + $message = "Connection to RealServer failed. Do you have the correct password?\n"; + } else { + shift(@list); + + my ($encoder_count) = 0; + my ($player_count) = 0; + my (%encoders_present); + + foreach my $line (@list) { + $line =~ s/\r\n//; + + if ($line =~ /^\s*(\w+)\s+([.0-9]+)(\s+(\w+))?/) { + my ($type) = $1; + my ($ip) = $2; + my ($stream) = $4 || undef; + + if ($type eq 'Encoder') { + $encoder_count++; + $encoders_present{$ip} = 1; + $line = $line . "$REALSERVER_ENCODERS_CRIT{$ip}[1] ($REALSERVER_ENCODERS_CRIT{$ip}[0])" + if defined $REALSERVER_ENCODERS_CRIT{$ip}; + $line = $line . "$REALSERVER_ENCODERS_WARN{$ip}[1] ($REALSERVER_ENCODERS_WARN{$ip}[0])" + if defined $REALSERVER_ENCODERS_WARN{$ip}; + } elsif ($type eq 'Player') { + $player_count++; + } + } + } + + my $expected_encoder_count = $#{ [ keys %REALSERVER_ENCODERS_CRIT ] }+1 + + $#{ [ keys %REALSERVER_ENCODERS_WARN ] }+1; + + if ($expected_encoder_count != $encoder_count) { + $color = 'yellow'; + $summary = "$encoder_count encoders, expected $expected_encoder_count"; + $message = "Missing encoder"; + $message .= 's' if $expected_encoder_count - $encoder_count > 1; + $message .= "\n"; + + foreach my $encoder (keys %REALSERVER_ENCODERS_WARN) { + $message .= "\t$encoder\t$REALSERVER_ENCODERS_WARN{$encoder}[1]\n" + unless defined $encoders_present{$encoder}; + } + foreach my $encoder (keys %REALSERVER_ENCODERS_CRIT) { + if (! defined $encoders_present{$encoder}) { + $color = 'red'; + $message + .= "\t$encoder\t$REALSERVER_ENCODERS_CRIT{$encoder}[1]\n"; + } + } + $message .= "\n"; + } else { + $summary = "ok - players: $player_count"; + } + + $message .= "Players connected: $player_count\n\n"; + + $message .= join("\n", @list) . "\n"; + } + } else { + $color = 'red'; + $summary = 'failed'; + $message = "Failed to execute rssm: $!\n"; + } + } + +# print "c: $color\n"; +# print "s: $summary\n"; +# print "m: $message\n"; + + &debug( "realserver - $color, $summary" ); + &status( $SPONGSERVER, $HOST, "realserver", $color, $summary, $message ); +} + +=head2 Output Returned + +=over 4 + +=item Status + +If the RealServer process is contactable and any specified encoders are +running then a 'green' status is returned. + +Otherwise, 'yellow' is return if any of the encoders are not running. + +'red' is returned if no password is supplied, the server is not accessible +or rssm fails to execute. + +=item Summary Field + +If there are no problems then 'ok' and the numbner of players currently +connected is returned. + +If there are problems then a short summary is presented. If there are +encoders not running then the number of encoders not present and the +number expected is returned. + +=item Detail Message Field + +Are full list of all players and encoders currently connected is returned. +Along with a count of the number of players connected. + +If any encoders which are expected aren't found then they are listed. + +=back + +=head2 Configuration + +It is necessary to add the following to L: + + $REALSERVER_PASSWORD = 'password'; + %REALSERVER_ENCODERS_WARN = ( + '10.1.1.1' => [ 'streamfile1', 'Stream pretty name 1' ], + ); + %REALSERVER_ENCODERS_CRIT = ( + '10.1.1.2' => [ 'streamfile2', 'Stream pretty name 2' ] + ); + $REALSERVER_RSSM = "/local/pnserver/bin/rssm"; + +Configure C<$REALSERVER_RSSM> to be where rssm is installed on your system. + +In C<%REALSERVER_ENCODERS_WARN> and +C<%REALSERVER_ENCODERS_CRIT> the IP address is the IP address of the encoder. +In the array, 'streamfile1' is the name that clients request (the filename +the encoder encodes to). 'Stream pretty name1' is more human readable +form. It is inserted in the list of encoders that is returned to +L and is used for the L graphs. + +=back + +=head1 SEE ALSO + +L, +L, +L + +=head1 RESTRICTIONS + +B uses rssm, and the Perl Expect module. Run: + +=over 4 + + perl -MCPAN -e shell + i Expect + +=back 4 + +=head1 AUTHOR + +Andrew Ruthven - 2002/06/20 +