]> git.etc.gen.nz Git - spong.git/commitdiff
Initial import
authorStephen L Johnson <sjohnson@monsters.org>
Thu, 25 Nov 1999 05:07:45 +0000 (05:07 +0000)
committerStephen L Johnson <sjohnson@monsters.org>
Thu, 25 Nov 1999 05:07:45 +0000 (05:07 +0000)
src/lib/Spong/Host.pm [new file with mode: 0755]

diff --git a/src/lib/Spong/Host.pm b/src/lib/Spong/Host.pm
new file mode 100755 (executable)
index 0000000..dc3cb17
--- /dev/null
@@ -0,0 +1,432 @@
+#!/usr/local/bin/perl
+#
+# This class encapsulates information about a Host that is monitored by spong.
+#
+# This class knows about the internals of how data is stored, because it needs
+# to do tricks in order to get at information in a fast way (like a list of 
+# services running on a host, and the current state of a host).
+#
+#   name          - name of the group the HostList represents
+#   services      - a ServiceList object representing the services on the host
+#   acks          - a AckList object representing the Acks on the host
+#   history       - a HistoryList object representing events that have happen
+#   info          - a Info object that provides some documentation
+#
+# + new()         - constructor (sets instance vars to arguments passed in)
+# + gets/sets()   - magical set/get functions (autoloaded based on func name)
+# + display()     - output format and view
+#
+# + display_problem() - displays info about specific problems on the host
+# + service()         - returns a specific service object based on name
+# + service_objects() - returns a list of service objects
+# + service_names()   - returns a list of service names
+# + color()           - returns the LCD color of the host
+# + has_color()       - returns if the host has a service of the given color
+# + has_problem()     - returns true if the host has a problem
+# + problem()         - need to clean this up...
+#
+# History:
+# (1) Cleaned up (Ed July 31, 1997);
+
+use Spong::AckList;
+use Spong::Ack;
+use Spong::ServiceList;
+use Spong::Service;
+use Spong::HistoryList;
+use Spong::History;
+use Spong::Info;
+use POSIX;
+
+package Spong::Host;
+
+# Constructor.  This is a lazy constructor in that it doesn't get all it's
+# instance vars set at the time of creation. The only thing that is set at
+# construction is the name of the host and the ServiceList, the rest of the
+# host attributes are loaded as they are needed (performance reasons).  This
+# returns undef if there is no host information associated with the FQDN given
+
+sub new {
+   my( $class, $host ) = @_;
+   my $self = {};
+   my( %servicehash );
+
+   return undef if ! -d "$main::SPONGDB/$host";
+
+   # We only load the data that is needed almost everytime this object is 
+   # used.  The rest of the data gets loaded on demand, as it is needed.
+
+   $self->{'name'}     = $host;
+   $self->{'services'} = Spong::ServiceList->new( $host );
+   $self->{'acks'}     = "";
+   $self->{'history'}  = "";
+   $self->{'info'}     = "";
+
+   bless $self;
+   return $self;
+}
+
+
+# Get/Set methods, nothing fancy here...
+
+sub name { my $var = 'name';
+   if( defined $_[1] ) { $_[0]->{$var} = $_[1]; } return $_[0]->{$var}; }
+sub services { my $var = 'services';
+   if( defined $_[1] ) { $_[0]->{$var} = $_[1]; } return $_[0]->{$var}; }
+
+
+# Some lazy loading functions, these go out and grab the data if we don't
+# already have it loaded.
+
+sub info {
+   my $self = $_[0];
+   
+   if( defined( $_[1] ) ) {
+      $self->{'info'} = $_[1]; 
+   } else {
+      if( $self->{'info'} eq "" ) {
+        $self->{'info'} = Spong::Info->new( $self->name() ); }
+   }
+
+   return $self->{'info'};
+}
+
+sub acks {
+   my $self = $_[0];
+   
+   if( defined( $_[1] ) ) {
+      $self->{'acks'} = $_[1]; 
+   } else {
+      if( $self->{'acks'} eq "" ) {
+        $self->{'acks'} = Spong::AckList->new( $self->name() ); }
+   }
+
+   return $self->{'acks'};
+}
+
+sub history {
+   my $self = $_[0];
+   
+   if( defined( $_[1] ) ) {
+      $self->{'history'} = $_[1]; 
+   } else {
+      if( $self->{'history'} eq "" ) {
+        $self->{'history'} = Spong::HistoryList->new( $self->name() ); }
+   }
+
+   return $self->{'history'};
+}
+
+
+# These methods allow you to get at specific instance in a quicker way.
+
+sub service { 
+   my( $self, $name ) = @_; 
+   my $servicelist = $self->services();
+   return $servicelist->service( $name ) if $servicelist;
+}
+
+sub service_objects {
+   my( $self, $name ) = @_; 
+   my $servicelist = $self->services();
+   return $servicelist->services() if $servicelist;
+}
+
+sub service_names { 
+   my $self = shift;
+   my $servicelist = $self->services();
+   return $servicelist->names() if $servicelist;
+}
+
+sub color {
+   my $self = shift;
+   my $servicelist = $self->services();
+   return $servicelist->color() if $servicelist;
+}
+                                 
+sub has_color {
+   my( $self, $color ) = @_;
+
+   foreach( $self->service_objects() ) {
+      if( $_->color() eq $color ) { return 1; } }
+
+   return 0;
+}
+
+sub has_problem {
+   my $self = shift;
+
+   return( $self->color() eq "red" );
+}
+
+sub problem {
+   my( $self ) = @_;
+   my $name = $self->name();
+   my $problem;
+
+   foreach( $self->servce_objects() ) { 
+      if( $_ && ($_->color() eq "red") ) { $problem = "red"; }
+      if( $_ && ($_->color() eq "purple") ) {
+        $problem = "purple" unless $problem eq "red"; }
+   }
+
+   return $problem;
+}
+
+
+# Display summary.  Does both text and html.  This relies on pretty much every
+# other object to do the actual displaying of information
+#
+# brief:      Just show the color of the host
+# standard:   Shows a page with the standard views from the other objects
+# full:       Shows a page with the full views from the other objects
+
+sub display {
+   my( $self, $type, $view ) = @_;
+
+   if( $type eq "text" ) { return $self->display_text( $view ); }
+   if( $type eq "html" ) { return $self->display_html( $view ); }
+}
+      
+sub display_text {
+   my( $self, $format ) = @_;
+
+   if( $format eq "brief" ) {
+      print $self->color(), "\n";
+   } elsif( $format eq "standard" || $format eq "full" ) {
+
+      my $acklist = $self->acks();
+      if( $acklist ) {
+        print "Acknowledgments\n", "="x78, "\n";
+        $acklist->display( "text", $format ); }
+
+      my $servicelist = $self->services();
+      if( $servicelist ) {
+        print "\n\nServices\n", "="x78, "\n";
+        $servicelist->display( "text", $format ); }
+      
+      my $info = Spong::Info->new( $self->name() );
+      if( $info ) {
+        print "\n\nInformation\n", "="x78, "\n"; 
+        $info->display( "text", $format ); }
+
+      my $historylist = $self->history();
+      if( $historylist ) {
+        print "\n\nHistory\n", "="x78, "\n";
+        $historylist->display( "text", $format ); }
+   }
+}
+
+sub display_html {
+   my( $self, $format ) = @_;
+   my $name = $self->name();
+
+   if( $format eq "brief" ) {
+      my $color = $self->color();
+
+      print "<a href=\"!!WWWSPONG!!/host/$name\">\n";
+
+      if( $main::WWW_USE_IMAGES == 1 ) {
+        print "<img src=\"!!WWWGIFS!!/$color.gif\" alt=$color border=0>";
+      } else {
+        print "<table border=0 cellspacing=0 cellpadding=0><tr>";
+        print "<td width=20 bgcolor=\"" . $main::WWW_COLOR{$color} ;
+        print "\"><font color=\"" . $main::WWW_COLOR{$color} . "\">";
+        print "___</font></td></tr></table>\n";
+      }
+      print "</a>";
+   } elsif( $format eq "standard" || $format eq "full" ) {
+      print "<font size=+2><b>$name</b></font>\n";
+
+      # This breaks the generic interactive vs non-interactive model
+      $self->add_action_bar();
+
+      my $color = $self->color();
+
+      print "<table width=100% cellspacing=0 cellpadding=0 border=0>";
+      print "<tr><td bgcolor=\"" . $main::WWW_COLOR{$color} . "\">&nbsp;</td>";
+      print "</tr></table><p>";
+
+      my $acklist = $self->acks();
+      if( $acklist ) {
+        print "<font size=+1><b>Acknowledgments</b></font><br><hr>\n";
+        $acklist->display( "html", $format ); }
+
+      my $servicelist = $self->services();
+      if( $servicelist ) {
+        print "<p><font size=+1><b>Services</b></font><br><hr>\n";
+        $servicelist->display( "html", $format ); }
+      
+      my $info = Spong::Info->new( $self->name() );
+      if( $info ) {
+        print "<p><font size=+1><b>Information</b></font><br><hr>\n";
+        $info->display( "html", $format ); }
+
+      my $historylist = $self->history();
+      if( $historylist ) {
+        print "<p><font size=+1><b>History</b></font><br><hr>\n";
+        $historylist->display( "html", $format ); }
+   }
+}
+
+
+# These functions display a textual record of any problems that the host is
+# currently having, this would include a summary of the problem services,
+# date/time the problem occurred, and contact information (as well as
+# acknowledgments if they are available).
+
+sub display_problem {
+   my( $self, $type ) = @_;
+
+   if( $type eq "text" ) { return $self->display_problem_text(); }
+   if( $type eq "html" ) { return $self->display_problem_html(); }
+}
+
+sub display_problem_text {
+   my $self    = shift;
+   my $contact = $main::HOSTS{$self->name()}->{'contact'};
+   my $human   = $main::HUMANS{$contact}->{'name'};
+   my $email   = $main::HUMANS{$contact}->{'email'};
+   my( $prob, $summ, $time ) = $self->_problem_service();
+
+   print "(", $self->color(), ") ", $self->name(), "\n";
+   print "-"x(length($self->color()) + 3 + length($self->name())), "\n";
+   print "  problem: $prob ";
+   if( $summ ) { print "($summ)\n"; } else { print "\n"; }
+   if( $time ) {
+      print "  updated: ", POSIX::strftime( "%H:%M, %D", localtime($time) );
+      print "\n";
+   }
+   print "  contact: $human ($email)\n";
+   print "\n";
+}
+
+sub display_problem_html {
+   my $self    = shift;
+   my $contact = $main::HOSTS{$self->name()}->{'contact'};
+   my $human   = $main::HUMANS{$contact}->{'name'};
+   my $email   = $main::HUMANS{$contact}->{'email'};
+   my $color   = $self->color();
+   my $name    = $self->name();
+   my $message = &escape( "Host: $name, " . $self->_problem_message() );
+   my $spacer  = "&nbsp &nbsp &nbsp ";
+   my( $prob, $summ, $time ) = $self->_problem_service();
+
+   if( $main::WWW_USE_IMAGES == 1 ) {
+      print "<img src=\"!!WWWGIFS!!/$color.gif\" alt=$color border=0>";
+      print "<b><a href=\"!!WWWSPONG!!/host/$name\">$name</a></b><br> ";
+   } else {
+      print "<table border=0 cellspacing=0 cellpadding=0><tr>";
+      print "<td width=20 bgcolor=\"" . $main::WWW_COLOR{$color} ;
+      print "\">&nbsp;</td><td>&nbsp;";
+      print "<b><a href=\"!!WWWSPONG!!/host/$name\">$name</a></b>";
+      print "</td></tr></table>\n";
+   }
+   
+   if( $prob eq "multiple problems" ) {
+      print "$spacer problem: $prob<br>\n";
+   } else {
+      print "$spacer problem: <a href=\"!!WWWSPONG!!/service/$name/";
+      print "$prob\">$prob</a><br>";
+   }
+   
+   # if( $summ ) { print "$spacer summary: $summ<br>\n"; }
+   if( $time ) { 
+      print "$spacer updated: ";
+      print POSIX::strftime( "%H:%M, %D", localtime($time) ), "<br>\n";
+   }
+   
+   print "$spacer contact: ";
+   print "<a href=\"$main::WWWCONTACT?host=$name&message=$message\">";
+   print "$human</a><p>\n";
+}
+
+
+
+# Returns the name (or a string indicating there are multiple problems), the
+# summary information about the service (if only one service is having
+# problems) and the time of the service having a problem on this host.
+
+sub _problem_service {
+   my $self = shift;
+   my( $services, @problist, $probtime, $summary );
+
+   foreach $service ( $self->service_objects() ) {
+      if( $service->has_problem() ) {
+        push( @problist, $service->name() );
+        $summary = $service->summary();
+        if( $probtime == 0 || ($service->rtime() < $probtime) ) {
+           $probtime = $service->rtime();
+        }
+      }
+   }
+
+   if( $#problist == -1 ) {
+      return();
+   } elsif( $#problist == 0 ) {
+      return( $problist[0], $summary, $probtime );
+   } else {
+      return( "multiple problems", "", $probtime );
+   }
+}
+
+# Returns a message that can be sent to the person who is on call for this
+# machine which indicates the problem with this machine.
+
+sub _problem_message {
+   my $self = shift;
+   my( $services, @problist, $probtime, $summary );
+
+   foreach $service ( $self->service_objects() ) {
+      if( $service->has_problem() ) {
+        push( @problist, $service->name() );
+        $summary = $service->summary();
+        if( $probtime == 0 || ($service->rtime() < $probtime) ) {
+           $probtime = $service->rtime();
+        }
+      }
+   }
+
+   if( $#problist == -1 ) {
+      return "No Problem";
+   } elsif( $#problist == 0 ) {
+      return "Problem: " . $problist[0] . ", $summary";
+   } else {
+      my $str = "Multiple Problems: ";
+
+      foreach( @problist ) { $str .= "$_, "; }
+
+      chop( $str ); chop( $str );
+      return $str;
+   }
+}
+
+sub add_action_bar {
+   my( $self ) = shift;
+   my $name = $self->name();
+   my $message = &escape( "Host: $name, " . $self->_problem_message() );
+
+   print "<hr>";
+   print "<a href=\"telnet://$name\">Connect</a> || ";
+   print "<a href=\"$main::WWWACK/$name\">Acknowledge Problem</a> ";
+
+   if( $main::WWWCONTACT ) {
+      print "|| <a href=\"$main::WWWCONTACT?host=$name&message=$message\">";
+      print "Contact Help</a>"; 
+   }
+   
+   if ($main::WWW_ACTIONBAR_CUSTOM) {
+      my($text) = eval '"' . $main::WWW_ACTIONBAR_CUSTOM . '"';
+      print " || " . $text;
+   }
+
+   print "<hr>\n";
+}
+
+sub escape {
+    my($toencode) = @_;
+    $toencode=~s/([^a-zA-Z0-9_\-.])/uc sprintf("%%%02x",ord($1))/eg;
+    return $toencode;
+}
+
+1;
+