#!/usr/bin/perl
#
# This program performs nightly maintanence to the spong database.  
#
#   * Cleans out any history older then 7 days.  It moves the old history
#     for each host into the /local/www/docs/spong/history directory.
#     If you don't think you would ever want to get at that history, then
#     you can just change the script so that it is deleted.
#
#   * Removes any acknowledgements that are no longer valid.
#
#   * Removes any services that don't seem to be reported any more (if
#     you stop monitoring something on a machine - the old entry will
#     still hang around and show up as purple).
#
# This program pokes against the database directly, so if the format of the
# spong database ever changes, this program will need to be updated as well.
#
# History:
# (1) Created (Ed Hill, 06/17/1998)
#
# $Id: spong-cleanup.pl,v 1.6 2000/10/16 15:34:32 sljohnson Exp $

use POSIX;
use Socket;
use Getopt::Long;
use Sys::Hostname;

# Load our configuration variables, including the user specified configuration
# information (spong.conf, spong.hosts, and spong.groups files).

$|++;
$conf_file   = "/etc/spong/spong.conf";
$hosts_file  = "/etc/spong/spong.hosts";
$groups_file = "/etc/spong/spong.groups";
($HOST)      = gethostbyname(&Sys::Hostname::hostname());
$HOST        =~ tr/A-Z/a-z/;

&load_config_files();  # Loads the user specified configuration information

opendir( DIR, $main::SPONGDB ) || die "Can't open $main::SPONGDB: $!";
while( $host = readdir( DIR ) ) {
   next if $host eq ".";
   next if $host eq "..";

   &remove_old_acks( $host );
   &remove_old_services( $host );
   &remove_old_history( $host );    # Yes, I suppose all history is old...
}
closedir( DIR );

exit(0);

# This takes a peek inside the acks directory and removes any acknowledgement
# files that are no longer current.  You can tell because the filename of
# the acknowledgement marks the time that the acknowledgement is good for.

sub remove_old_acks {
   my( $host ) = @_;
   my $dir = "$main::SPONGDB/$host/acks";
   my $ack;

   return if ! -d $dir;

   opendir( ACK, $dir ) || die "Can't open $dir: $!";
   while( $ack = readdir( ACK ) ) {
      next if $ack eq ".";
      next if $ack eq "..";

      if( $ack =~ /^\d+-(\d+)-(\d+)$/ ) {
	 my($start, $end) = ($1, $2);
	 my $now = time();
	 
	 # I don't remove acknowledgements that have not taken effect yet,
	 # only those that have passed...

	 if( $now > $end ) { unlink( "$dir/$ack" ); }
      } else {
	 warn "Odd file in $dir, $ack";
      }
   }
   closedir( ACK );
}

# This looks through the services that are stored in the database for a given
# host, and removes any services that have not gotten a report in 3 days.  My
# guess is that this is probably pretty useless, since if you stop monitoring
# something, you will probably clean it out yourself by hand.  (but at least it
# will slowly kill off the old procs service over time).

sub remove_old_services {
   my( $host ) = @_;
   my $dir = "$main::SPONGDB/$host/services";
   my $service;

   return if ! -d $dir;

   opendir( SERVICE, $dir ) || die "Can't open $dir: $!";
   while( $service = readdir( SERVICE ) ) {
      next if $service eq ".";
      next if $service eq "..";

      $mtime = (stat( "$dir/$service" ))[9];

      if( $mtime < (time() - ($main::OLD_SERVICE*24*60*60)) ) { 
	 unlink( "$dir/$service" ); 
      }
   }
   closedir( SERVICE );
}

# This goes through the history file of a given host, and moves all history
# items that are over N days old to an archive file.  This helps keep the
# history command "speedy".

sub remove_old_history {
   my( $host ) = @_;
   my $file = "$main::SPONGDB/$host/history/current";
   my $archive = "$main::SPONG_ARCHIVE/$host";

   return if ! -f $file;

   open( HISTORY, $file ) || die "Can't open $file: $!";
   open( ARCHIVE, ">> $archive" ) || die "Can't open $archive: $!";
   open( NEW, "> $file.new" ) || die "Can't create $file.new: $!";

   while( <HISTORY> ) {
      $line = $_;
      if( /^\w+\s+(\d+)\s+/ ) {
	 $time = $1;

	 if( $time < (time() - ($main::OLD_HISTORY * 24*60*60)) ) {
	    print ARCHIVE $line;
	 } else {
	    print NEW $line;
	 }
      } else {
	 warn "Hey, there is an odd line in the history for $host";
	 print NEW $line;
      }
   }

   close( HISTORY );
   close( NEW );
   close( ARCHIVE );

   system( "cp $file.new $file && rm $file.new" );
}
	 

# This function just loads in all the configuration information from the 
# spong.conf.  The spong.hosts and spong.group files are not needed - all the
# hosts and groups smarts take place on the spong-server.

sub load_config_files {
   my( $evalme, $inhosts );

   require $conf_file || die "Can't load $conf_file: $!";
   if( -f "$conf_file.$HOST" ) {
      require "$conf_file.$HOST" || die "Can't load $conf_file.$HOST: $!";
   } else {
      my $tmp = (split( /\./, $HOST ))[0];
      if( -f "$conf_file.$tmp" ) { # for lazy typist
	 require "$conf_file.$tmp" || die "Can't load $conf_file.$tmp: $!";
      }
   }
}

