]> git.etc.gen.nz Git - spong.git/commitdiff
Plugin to monitor RealServer v4 by Andrew Ruthven
authorJan Willamowius <jan@willamowius.de>
Tue, 27 Sep 2005 16:13:13 +0000 (16:13 +0000)
committerJan Willamowius <jan@willamowius.de>
Tue, 27 Sep 2005 16:13:13 +0000 (16:13 +0000)
src/lib/Spong/Client/plugins/check_realserver [new file with mode: 0755]

diff --git a/src/lib/Spong/Client/plugins/check_realserver b/src/lib/Spong/Client/plugins/check_realserver
new file mode 100755 (executable)
index 0000000..c446ceb
--- /dev/null
@@ -0,0 +1,242 @@
+=head1 NAME
+
+B<check_realserver> - spong-client module to check the local RealServer
+
+=head1 DESCRIPTION
+
+This is a plugin module for the Spong L<spong-client> program.  The
+B<check_realserver> 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<spong-rrd>.
+
+This module should really be for L<spong-network> 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<spong.conf>:
+
+  $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<spong-server> and is used for the L<spong-rrd> graphs.
+
+=back
+
+=head1 SEE ALSO
+
+L<spong-client>,
+L<spong-client Modules Template|spong-client-mod-template>,
+L<Spong Developer's Guide|developer-guide>
+
+=head1 RESTRICTIONS
+
+B<check_realserver> uses rssm, and the Perl Expect module.  Run:
+
+=over 4
+
+  perl -MCPAN -e shell
+  i Expect
+
+=back 4
+
+=head1 AUTHOR
+
+Andrew Ruthven <andrew@etc.gen.nz> - 2002/06/20
+