From: Stephen L Johnson Date: Thu, 25 Nov 1999 05:07:45 +0000 (+0000) Subject: Initial import X-Git-Tag: start~1 X-Git-Url: http://git.etc.gen.nz/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e28b5b120451bbda0bf87850d39d5ffa73e7e4b5;p=spong.git Initial import --- diff --git a/src/lib/Spong/Host.pm b/src/lib/Spong/Host.pm new file mode 100755 index 0000000..dc3cb17 --- /dev/null +++ b/src/lib/Spong/Host.pm @@ -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 "\n"; + + if( $main::WWW_USE_IMAGES == 1 ) { + print "$color"; + } else { + print ""; + print "
"; + print "___
\n"; + } + print "
"; + } elsif( $format eq "standard" || $format eq "full" ) { + print "$name\n"; + + # This breaks the generic interactive vs non-interactive model + $self->add_action_bar(); + + my $color = $self->color(); + + print ""; + print ""; + print "
 

"; + + my $acklist = $self->acks(); + if( $acklist ) { + print "Acknowledgments


\n"; + $acklist->display( "html", $format ); } + + my $servicelist = $self->services(); + if( $servicelist ) { + print "

Services


\n"; + $servicelist->display( "html", $format ); } + + my $info = Spong::Info->new( $self->name() ); + if( $info ) { + print "

Information


\n"; + $info->display( "html", $format ); } + + my $historylist = $self->history(); + if( $historylist ) { + print "

History


\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 = "      "; + my( $prob, $summ, $time ) = $self->_problem_service(); + + if( $main::WWW_USE_IMAGES == 1 ) { + print "$color"; + print "$name
"; + } else { + print ""; + print "
  "; + print "$name"; + print "
\n"; + } + + if( $prob eq "multiple problems" ) { + print "$spacer problem: $prob
\n"; + } else { + print "$spacer problem: $prob
"; + } + + # if( $summ ) { print "$spacer summary: $summ
\n"; } + if( $time ) { + print "$spacer updated: "; + print POSIX::strftime( "%H:%M, %D", localtime($time) ), "
\n"; + } + + print "$spacer contact: "; + print ""; + print "$human

\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 "


"; + print "Connect || "; + print "Acknowledge Problem "; + + if( $main::WWWCONTACT ) { + print "|| "; + print "Contact Help"; + } + + if ($main::WWW_ACTIONBAR_CUSTOM) { + my($text) = eval '"' . $main::WWW_ACTIONBAR_CUSTOM . '"'; + print " || " . $text; + } + + print "
\n"; +} + +sub escape { + my($toencode) = @_; + $toencode=~s/([^a-zA-Z0-9_\-.])/uc sprintf("%%%02x",ord($1))/eg; + return $toencode; +} + +1; +