]> git.etc.gen.nz Git - spong.git/commitdiff
new 'page' message type and initial client autoconfigation support
authorStephen L Johnson <sjohnson@monsters.org>
Thu, 17 Feb 2000 03:03:33 +0000 (03:03 +0000)
committerStephen L Johnson <sjohnson@monsters.org>
Thu, 17 Feb 2000 03:03:33 +0000 (03:03 +0000)
src/spong-server.pl

index 128517f28a1a82a97861288f7a8364d68e53cfd6..b23426a45085054bafae6a7a95108133a78e9ec1 100755 (executable)
@@ -24,10 +24,12 @@ use Spong::History;
 use Spong::Daemon;
 use Spong::Log;
 use Spong::HostGroups;
+use Spong::ConfigFile;
 
 use Sys::Hostname;
 use File::Path;
 use Socket;
+use IO::Socket;
 use Config;
 use Time::Local;
 use Getopt::Long;
@@ -40,17 +42,20 @@ if (! GetOptions("debug:i" => \$debuglevel, "restart" => \$restart,
    exit 1;
 }
 
-
+Spong::Log::set_debug_context( 'debuglevel' => $debuglevel );
 
 #if( $ARGV[0] eq "--debug" )   { $debug = 1;   shift; }
 #if( $ARGV[0] eq "--restart" ) { $restart = 1; shift; }
 #if( $ARGV[0] eq "--kill" )    { $kill = 1;    shift; }
 
-$me          = "@@BINDIR@@/spong-server";
-$smessage    = "@@BINDIR@@/spong-message";
-$conf_file   = $ARGV[0] || "@@ETCDIR@@/spong.conf";
-$hosts_file  = "@@ETCDIR@@/spong.hosts";
-$groups_file = "@@ETCDIR@@/spong.groups";
+$ETCDIR = '@@ETCDIR@@';
+$BINDIR = '@@BINDIR@@';
+
+$me          = "$BINDIR/spong-server";
+$smessage    = "$BINDIR/spong-message";
+$conf_file   = $ARGV[0] || "$ETCDIR/spong.conf";
+$hosts_file  = "$ETCDIR/spong.hosts";
+$groups_file = "$ETCDIR/spong.groups";
 $datafunc_path  = "@@LIBDIR@@/Spong/plugins";
 ($HOST)      = gethostbyname(&Sys::Hostname::hostname());
 $HOST        =~ tr/A-Z/a-z/;
@@ -79,6 +84,10 @@ if (defined $SPONG_UPDATE_PORT ) {
    $PROCS{'spong-update'} = { func => \&listen_for_updates, pid => undef };
 }
 
+if (defined $SPONG_CLIENT_PORT ) {
+   $PROCS{'client'} = { func => \&listen_for_clients, pid => undef }; 
+}
+
 
 # Establish a list of all the services that we monitor so that we can be
 # consistant in the output that we display regardless of the group that we
@@ -141,6 +150,54 @@ sub usage {
 
 }
 
+# This procedure listens for client connections connections (the client port),
+# and reponse to queries or request for configuration files.
+
+sub listen_for_clients {
+   my ( $sock, $client );
+
+   # Set up the socket to listen to
+   $SIG{'PIPE'} = 'IGNORE';
+   $SIG{'TERM'} = $SIG{'HUP'} = $SIG{'QUIT'} = sub {
+      &debug('spong client caught QUIT signal, exiting',3);
+      undef $sock; exit;
+   };
+
+   $sock = IO::Socket::INET->new( Listen   => SOMAXCONN,
+#                                 LocalHost => INADDR_ANY,
+                                  LocalPort => $main::SPONG_CLIENT_PORT,
+                                  Proto    => 'tcp',
+                                  Timeout  => 30,
+                                  Reuse    => 1,
+                                );
+   if (! defined $sock ) { die "socket: $!"; }
+
+   &debug( "client socket setup, listening for connections" );
+
+   while( 1 ) {
+      next unless ( $client = $sock->accept() );
+
+      $paddr = $client->peerhost();
+
+&debug("[$$] Connection from $paddr");
+
+      # &validate_connection( $paddr );  - need to do something here...
+
+      # Read all from the client, and disconnect, we process the message next.
+
+      my $header = <$client>; chomp $header;
+&debug("[$$] header = $header");
+
+      # Now depending on what kind of message it is, pass it off to a routine
+      # that can process the message. 
+
+      if( $header =~ /^status\b/ ) { &client_status( $client, $header ); }
+      if( $header =~ /^get\b/ ) { &client_get( $client, $header ); }
+
+      undef $client;
+
+   }
+}
 
 # This procedure listens for connections at port 1970 (the update port), and
 # each time a connection is made, it grabs the info that is being sent to us,
@@ -190,6 +247,7 @@ sub listen_for_updates {
 
       if( $header =~ /^status\b/ ) { &save_status( $header, $message ); next; }
       if( $header =~ /^event\b/ ) { &save_event( $header, $message ); next; }
+      if( $header =~ /^page\b/ ) { &save_page( $header, $message ); next; }
       if( $header =~ /^ack-del\b/ ) { &del_ack( $header, $message ); next; }
       if( $header =~ /^ack\b/ )     { &save_ack( $header, $message ); next; }
       #   if( $header =~ /^config\b/ ) { &save_config( $header, $message ); }
@@ -321,6 +379,64 @@ sub listen_for_queries {
    }
 }
 
+# ===========================================================================
+# Client configuare methods.  These all take messages from clients and sends 
+# configuration file or info about configuration file back
+# ===========================================================================
+
+# Return status information about configuration files for a host
+
+sub client_status {
+   my( $client, $header ) = @_;
+
+   my( $host, $file ) = ( "", "" );
+   if ( $header =~ /\S+ (\S+) (\S+)/ ) { $host = $1; $file = $2; }
+
+   if ( ! $main::HOSTS{$host} && $host ne 'DEFAULT') {
+      $client->print("ERROR Host $host is not defined");
+      return;
+   }
+
+   # Get a Configuration file object for the host
+   my $cf = new Spong::ConfigFile( $host, $file );
+   if ( ! $cf ) {
+      $client->print("ERROR Configuration file $file not found");
+      return;
+   }
+
+   # Build the status line and return it to the client
+   $sts = "OK " . $cf->host() . " " . $cf->name() . " " . $cf->timestamp() .
+          " " . $cf->size() . " " . $cf->lines();
+   $client->print("$sts\n");
+
+}
+
+sub client_get {
+   my( $client, $header ) = @_;
+
+   my( $host, $file ) = ( "", "" );
+   if ( $header =~ /\S+ (\S+) (\S+)/ ) { $host = $1; $file = $2; }
+
+   if ( ! $main::HOSTS{$host} && $host ne 'DEFAULT') {
+      $client->print("ERROR Host $host is not defined");
+      return;
+   }
+
+   # Get a Configuration file object for the host
+   my $cf = new Spong::ConfigFile( $host, $file );
+   if ( ! $cf ) {
+      $client->print("ERROR Configuration file $file not found");
+      return;
+   }
+
+  my $contents = $cf->contents();
+
+  foreach ( @$contents ) { $client->print($_); }
+
+}
+
+
+
 # ===========================================================================
 # Database update methods.  These all take messages from clients and update
 # specific parts of the database.
@@ -466,6 +582,65 @@ sub save_event {
 
 }
 
+
+# Take the incoming page message, run it through some error checking,
+# and send the information off to spong-message and let it decide if it 
+# should page/email someone...
+
+sub save_page {
+   my( $header, $message ) = @_;
+   my( $cmd, $host, $service, $color, $time, $sum, $path, $start, $duration );
+   my( $ttl ) = 0;
+
+   # Do some checking on the message.  If it appears bogus, then just
+   # log a message, and close the connection.
+
+   if( $header =~ /^(\w+) (\S+) (\w+) (\w+) (\d+) (.*)$/ ) {
+      ($cmd, $host, $service, $color, $time, $sum) = ($1, $2, $3, $4, $5, $6);
+
+      if( $host !~ m/^[a-z0-9_\-\.]+$/ ) { 
+        &error( "save_status: invalid host [$host]" ); return; }
+      if( $service !~ m/^[a-z0-9_\-\.]+$/ ) {
+        &error( "save_status: invalid service [$service]" ); return; }
+      if( $color ne "red" && $color ne "yellow" && $color ne "green" ) {
+        &error( "save_status: invalid color [$color]" ); return;}
+      if( $time !~ m/^\d+$/ ) {
+        &error( "save_status: invalid time [$time]" ); return; }
+   } else {
+      &error( "save_status: invalid header [$header]" ); return; 
+   }
+
+   if ($main::HOSTS{$host} eq "") {
+      &error("save_status: undefined host [$host]");
+      return;
+   }
+
+   # Call message_user()...
+
+#   $duration = $time - $start;
+   &message_user( "page", $host, $service, $color, $time, $sum );
+
+   # Save the status information to the history table and state file as well.
+
+   # Update the history file
+   if (0) {
+   $data = "page $time $service $color $sum\n";
+   &save_data( ">>", "$SPONGDB/$host/history/current", $data);
+
+   # If status history is enabled, save status message for history event
+   if ( $STATUS_HISTORY ) {
+      # Save the status update information
+      $data = "timestamp $start $time\ncolor $color\n$time $sum\n$message\n";
+      &save_data( ">>", "$SPONGDB/$host/history/status/$time-$service",
+                 $data);
+   }
+   }
+
+}
+
+
+
+
 # Take a BigBrother status message and convert it to a Spong status
 # message and send it to save_status for processing
 
@@ -763,7 +938,7 @@ sub init_logging {
       $debug = ($debuglevel == 0) ? 1 : $debuglevel
    }
 
-   Spong::Log::set_debug_context( "debuglevel" => $debug );
+   Spong::Log::set_debug_context( 'debuglevel' => $debug );
 
    my $filename = ($SPONG_LOG_FILE) ? "$SPONGTMP/spong-server.log" : "";
    my $syslog = ($SPONG_LOG_SYSLOG) ? 1 : 0;
@@ -786,13 +961,12 @@ sub init_logging {
 sub message_user {
    my ( $cmd, $host, $service, $color, $time, $sum, $duration ) = @_; 
 
-   if ($SEND_MESSAGE eq 'NONE') { return; }
-
    if (! defined $duration || $duration eq "") { $duration = 0; }
 
    $SIG{'CHLD'} = 'IGNORE';
 
-   if ( $cmd eq "status" ) {
+   # if message type was 'status' and messaging is allowed
+   if ( $cmd eq "status" && $SEND_MESSAGE ne 'NONE' ) {
 
       # If the color is 'red' and duration is non-zero, call spong-message for
       # escalation notifications
@@ -831,6 +1005,9 @@ sub message_user {
             &send_message( $host, $service, $color, $time, $sum, $duration );
          }
       }
+   } elsif ( $cmd eq "page" && $PAGE_MESSAGE eq 'PAGE' ) {
+      &debug("sending a page message notification",2);
+      &send_message( $host, $service, $color, $time, $sum, $duration );
    }
 
    $SIG{'CHLD'} = \&chld_handler;