[hobbit] BBwin (who test)
DKDeckert at Hormel.com
DKDeckert at Hormel.com
Thu Jul 30 13:40:54 CEST 2009
Thanks for the help....the script works and i also found out something else
for anyone who falls in this category.
Actually if i would have RTFM it says in there the "WHO" test for BBWin
is not configurable.
That answers my questions and thanks everyone for the responses.
Derek
From: David Baldwin <david.baldwin at ausport.gov.au>
To: "hobbit at hswn.dk" <hobbit at hswn.dk>
Date: 07/29/2009 07:30 PM
Subject: Re: [hobbit] BBwin (who test)
Derek,
> I was wondering if anyone has tried to use the 'who' test to see if
anyone
> is logged on and if someone is logged on have the test go yellow?
>
> I am looking at doing this and instead of trying to re-invent the wheel i
> was wondering if anyone has tried/or did this already?
>
>
I have done it using a client channel test based on Henrik's template,
which can be extended for various other functionality - I've put some
stuff in there for checking whether the client has a default gateway on
.1 (this bit me once with a host with static IP but gateway coming - or
not - from DHCP), and also a check for amount of memory allocated to the
service console on an ESX host.
You need the following in ~hobbit/server/etc/hobbitlaunch.cfg
|#
# script that checks incoming "client" messages for various conditions
#
[client-check]
ENVFILE /usr/lib/hobbit/server/etc/hobbitserver.cfg
NEEDS hobbitd
CMD hobbitd_channel --channel=client
--log=$BBSERVERLOGS/client-check.log $BBHOME/ext/client-check.pl
|The client-check.pl script attached sits in the ext directory. It uses
the hacked version of BigBrother.pm (also attached). It was originally
from deadcat but I've tweaked it a bit - there's also some ancient
history in there no longer relevant to xymon. Really need a
Xymon::Client module that Buchan suggested.
David.
--
David Baldwin - IT Unit
Australian Sports Commission www.ausport.gov.au
Tel 02 62147830 Fax 02 62141830 PO Box 176 Belconnen ACT 2616
david.baldwin at ausport.gov.au Leverrier Street Bruce ACT 2617
-------------------------------------------------------------------------------------
Keep up to date with what's happening in Australian sport visit
http://www.ausport.gov.au
This message is intended for the addressee named and may contain
confidential and privileged information. If you are not the intended
recipient please note that any form of distribution, copying or use of this
communication or the information in it is strictly prohibited and may be
unlawful. If you receive this message in error, please delete it and notify
the sender.
-------------------------------------------------------------------------------------
package BigBrother;
use 5.008005;
use strict 'subs';
use strict 'vars';
use warnings;
require Exporter;
#use AutoLoader qw(AUTOLOAD);
our @ISA = qw(Exporter);
# Items to export into callers namespace by default. Note: do not export
# names by default without a very good reason. Use EXPORT_OK instead.
# Do not simply export all your public functions/methods/constants.
# This allows declaration use BigBrother ':all';
# If you do not need this, moving things directly into @EXPORT or
@EXPORT_OK
# will save memory.
our %EXPORT_TAGS = ( 'all' => [ qw(
) ] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw(
);
our $VERSION = '0.01';
=pod
=head1 NAME
BigBrother - Perl extension to simplify writing Big Brother external
scripts in PERL.
=head1 SYNOPSIS
use BigBrother;
BigBrother->import();
test stuff...
BigBrother->Report($HostName,$function,$color,$status);
=head1 DESCRIPTION
Requires: $BBHOME environment variable to be set
=head2 EXPORT
None by default.
=head2 Methods
=over 12
=item import()
This function imports the BigBrother environment referenced using $ENV
{BBHOME}
=cut
my(%bbhosts,%bbhost,%bbhostsIP,%positional,%bbitems,%parms);
my(%fromtime,%tilltime);
sub import {
my ($caller_package)=caller;
#print "BBHOME: $ENV{BBHOME}\n";
if (!exists $ENV{BBHOME}) {
my($work,$script)=$0=~/(.*?)\/?([^\/]*)$/;
# now strip out the dir and our name
$work="$work/../";
# we assume a subdir of BBHOME
chomp(my $dir=`pwd`);
# change to BBHOME
chdir($work);
# to get
chomp($work=`pwd`);
# the real dir name
$ENV{BBHOME}=$work;
# now set BBHOME to something real
chdir($dir);
# and retunr to our dir
}
my $BBHOME=$ENV{BBHOME};
#warn "BBHOME: $ENV{BBHOME}\n";
#printf "Running $0 at %s\n",scalar localtime;
if (!exists $ENV{BBTMP}) {
# only run if not set
foreach (`sh -c 'cd
$BBHOME;. /etc/hobbit/hobbitserver.cfg;set'`) {
chomp;
# drop EOL
if(my ($var,$val)=/^\s*(.*?)\s*=
\s*(.*)/) { # get var and value
$ENV{$var}=$val unless
$var eq "SHELLOPTS"; # and set
}
}
}
foreach my $env_key (keys %ENV) {
next if ($env_key=~/^\s*$/sig);
*{"${caller_package}::${env_key}"}=\$ENV
{$env_key};
}
if( -x "$BBHOME/bin/bbhostshow") {
open(IN,"$BBHOME/bin/bbhostshow|"); #
run bbhostshow (handles includes)
} else {
open(IN,"$ENV{BBHOSTS}");
# open bb-hosts - better than nothing...
}
foreach (<IN>) { #
read contents
chomp;
# trim EOL
next if (/^\s*#/);
# Skip comments
my($ip,$host,$pound, at parms)=split; # Split
into pieces
my $name=lc($host);
# force lower case to make finding easier
next unless (defined $pound && $pound eq '#');
# Skip if token 3 isn't a '#'
foreach my $parm (@parms) { #
Process all the parms
$bbhosts{"$name~$parm"}=$parm;
# and store as keys in %bbhosts "$name~$parm"
$bbhost{"$name~$parm"}=$host;
# and store as keys in %bbhost "$name~$parm"
$bbhostsIP{$name}=$ip unless $ip
=~ /^0+\.0+\.0+\.0+$/; # and store as keys in %bbhostsIP "$ip~
$parm"
}
}
close(IN);
# and close
foreach my $key (keys %bbhosts) {
# We also need to parse parms
my($host,$function,$parms);
if (($host,$function,$parms)=$key=~/^(.*)~(\w
+)\((.*)\)/) {
} elsif (($host,$function,$parms)=$key=~/^(.*)~(\w
+)=(.*)/) {
} else {
($host,$function)=$key=~/^(.*)~(.*)/;
# so break it into host, function
$parms=$function;
}
my $name=$bbhost{"$key"};
# and retrieve the name
my %temp=();
# clear the work hash
my @positional=();
foreach (split(/,/,$parms)) {
# split up and process each parm
if (/=/) {
# two choices, positional or keyword
my ($var,$val)=split(/=/);
# split it on the on the '='
$var=lc($var);
# store as lower case to be sure it's unique
$temp{$var}=$val;
# and save for when it is needed
} else {
push @positional,$_;
# it is positional
}
}
if (@positional) {
} else {
$positional[0]=$function;
}
my $positional=join(':', at positional);
$bbitems{"$bbhost{$key}.$positional[0]"}=
$function;
$positional{"$function"}.="$positional ";
foreach (keys %temp) {
$parms{"$positional~$function~$_"}=
$temp{$_};
}
}
#my $hosts=join(' ',keys %host);
use Date::Manip qw(ParseDate DateCalc Date_Cmp);
if (-r "$BBHOME/ext/down.cfg") {
open(DOWN,"$BBHOME/ext/down.cfg");
my $now=ParseDate("now");
my %index = ();
foreach (<DOWN>) {
chomp;
s/#.*//sig;
next if /^\s*$/sig;
my($name,$duration,$when)=split(',');
my $key="$name~".++$index{$name};
$fromtime{$key}=ParseDate($when);
$tilltime{$key}=DateCalc
($when,$duration);
}
}
}
=pod
=item InitStatus()
Resets test status to "green"
=item UpdateStatus($status)
Updates test status to $status if more severe than cureent status
=item GetStatus()
Returns current test status
=cut
my $bbstatus;
sub InitStatus { $bbstatus = "green"; }
sub UpdateStatus {
my ($package,$sigsts) = @_;
if (($sigsts eq "red") ||
($bbstatus ne "red" && $sigsts eq "yellow")) {
$bbstatus = $sigsts;
}
}
sub GetStatus { return $bbstatus; }
=pod
=item IsDown($string)
returns true if the file $BBHOME/ext/down.cfg contains a line for
$string,from,to that the current time
falls between from and to. From and to are specified in the syntax of
Date::Manip (see perldoc for it to see how to specify).
=cut
sub IsDown {
my ($package,$key)=@_;
my $now = "today";
foreach my $temp (grep /^$key~/,keys %fromtime) {
if ((Date_Cmp($fromtime{$temp},$now)<0) and
(Date_Cmp($tilltime{$temp},$now)>0)) {
return 1;
}
}
return 0;
}
=pod
=item Positional($forkey)
=cut
sub Positional {
my ($package,$forkey)=@_;
my $hosts='';
foreach (grep(/^$forkey$/,keys %positional)) {
$hosts.=$positional{$_}.' ';
}
return $hosts;
}
=pod
=item Parms($key,$default)
=cut
sub Parms {
my ($package,$key,$default)=@_;
if (exists $parms{$key}) {
return $parms{$key};
} else {
return $default;
}
}
=pod
=item Items($forkey)
returns space separated list of items that match $forkey
=cut
sub Items {
my ($package,$forkey)=@_;
my $items='';
my @items = ();
if ($forkey) {
foreach (keys %bbitems) {
next unless $bbitems{$_}=~/^$forkey$/;
push @items,$_;
}
$items=join(' ', at items);
} else {
$items=join(' ',keys %bbitems);
}
return $items;
}
=pod
=item HostItems($host,$forkey)
returns space separated list of items for $host that match $forkey
=cut
sub HostItems {
my ($package,$host,$forkey)=@_;
my $items='';
my @items = ();
if ($forkey) {
foreach (keys %bbhosts) {
next unless /^$host~$forkey$/;
push @items,$bbhosts{$_};
}
$items=join(' ', at items);
} else {
$items=join(' ',keys %bbhosts);
}
return $items;
}
=pod
=item HostsByTest($test)
returns list of hosts for plain $test
=cut
sub HostsByTest {
my ($package,$test)=@_;
my $host='';
my @hosts = ();
if ($test) {
foreach (keys %bbhost) {
next unless /([^~]*)\~$test/;
push @hosts,($bbhost{$_});
}
}
return @hosts;
}
=pod
=item HostIP($host)
returns IP for $host
=cut
sub HostIP {
my ($package,$host)=@_;
return $bbhostsIP{$host};
}
=pod
=item Report($HostName,$test,$color,$status)
Reports to BB server that $Hostname.$test has status $colour and with
status message $status
=cut
sub Report {
my($package,$HostName, $inst, $color, $status) = @_ ;
($inst)=split(/\./,$inst);
# Substitute dots by commas in the host name
$HostName =~ s/\./,/g;
# Build the command to report to Big Brother
$color=lc($color);
# delete trailing spaces before line feeds in message
$status =~ s/[ \t]+\n/\n/g;
my $MyCmd= "$ENV{BB} $ENV{BBDISP} ".'"'."status $HostName.$inst
$color ".localtime(time).' '.$status.'"';
# For debugging purposes
# Execute the command.
# print "$MyCmd\n";
`$MyCmd`;
}
=item Client($HostName,$ostype,$configclass,$rep)
Reports client report for $Hostname with OS type $ostype (linux,bbwin,etc)
and config class $configclass (linux,win32,etc)
client report details in $rep
=cut
sub Client {
my($package,$HostName, $ostype,$configclass,$rep) = @_ ;
# Substitute dots by commas in the host name
$HostName =~ s/\./,/g;
# Build the command to report to Big Brother
$ostype=lc($ostype);
$configclass=lc($configclass);
$rep =~ s/^(\s*\n)*//g; # delete leading blank lines
# redirect STDOUT and STDERR to /dev/null since client report
returns local config updates
my $MyCmd= "$ENV{BB} $ENV{BBDISP} \"\@\" 2>&1 >/dev/null";
# For debugging purposes
# Execute the command.
#print "$MyCmd\n" if $debug > 1;
open CL,"|$MyCmd";
print CL "client $HostName.$ostype $configclass\n$rep";
close CL;
}
sub QueryColor {
my($package,$HostName, $test) = @_ ;
#my $MyCmd= "$ENV{BB} $ENV{BBDISP} \"hobbitdboard host=$HostName
test=$test field=$field\"";
my $MyCmd= "$ENV{BB} $ENV{BBDISP} \"query $HostName.$test\"";
# For debugging purposes
# Execute the command.
#print "$MyCmd\n";
my $str = `$MyCmd`;
#chomp $str;
#print "PRE: $str\n";
$str =~ s/^\s*(\S+)(\s.*)?$/$1/;
#print "POST: $str\n";
return $str;
}
sub Dump_Vars {
use Data::Dumper;
print "Dumping \%bbhosts:\n";
print Dumper(\%bbhosts);
print "Dumping \%bbhost:\n";
print Dumper(\%bbhost);
print "Dumping \%bbhostsIP:\n";
print Dumper(\%bbhostsIP);
print "Dumping \%positional:\n";
print Dumper(\%positional);
print "Dumping \%bbitems:\n";
print Dumper(\%bbitems);
print "Dumping \%parms:\n";
print Dumper(\%parms);
}
=pod
=back
=head1 SEE ALSO
=head1 AUTHOR
David Baldwin
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2006 by David Baldwin
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.5 or,
at your option, any later version of Perl 5 you may have available.
=cut
1;
__END__
#!/usr/bin/perl -w
#*----------------------------------------------------------------------------*/
#* Xymon client message processor.
*/
#*
*/
#* This perl program shows how to create a server-side module using the
*/
#* data sent by the Xymon clients. This program is fed data from the
*/
#* Xymon "client" channel via the hobbitd_channel program; each client
*/
#* message is processed by looking at the [who] section and generates
*/
#* a "login" status that goes red when an active "root" login is found.
*/
#*
*/
#* Written 2007-Jan-28 by Henrik Storner <henrik at hswn.dk>
*/
#*
*/
#* This program is in the public domain, and may be used freely for
*/
#* creating your own Xymon server-side modules.
*/
#*
*/
#*----------------------------------------------------------------------------*/
#
# add to hobbitlaunch.cfg
#[client-check]
# ENVFILE /usr/lib/hobbit/server/etc/hobbitserver.cfg
# NEEDS hobbitd
# CMD hobbitd_channel --channel=client --log=
$BBSERVERLOGS/rootlogin.log $BBHOME/ext/client-check.pl
# $Id: client-check.pl,v 1.1 2007/01/28 12:42:34 henrik Exp $
use strict;
use lib "/usr/lib/hobbit/server/ext";
use BigBrother;
my $bb;
my $bbdisp;
my $hostname = "";
my $clientip = "";
my $clientname = "";
my $clientos = "";
my $msgtxt = "";
my %sections = ();
my $cursection = "";
my $debug=0;
my $ipsubre = qr/\d|\d\d|1\d\d|2[0-4]\d|25[0-5]/;
my $ipre = qr/$ipsubre\.$ipsubre\.$ipsubre\.$ipsubre/;
$|=1;
# Get the BB and BBDISP environment settings.
$bb = $ENV{"BB"} || die "BB not defined";
$bbdisp = $ENV{"BBDISP"} || die "BBDISP not defined";
for(my $i=0; $i<=$#ARGV; $i++) {
if($ARGV[$i] =~ /^-(d|-debug)$/) {
$debug++;
} elsif($i=$#ARGV) {
$debug ||= 1;
$clientname=$ARGV[$i];
}
}
if($clientname ne "") {
open CL,"bb logmon \'clientlog $clientname\'|";
$hostname = $clientname;
$clientip = BigBrother->HostIP($hostname);
warn "DBG: using clientlog for $hostname ($clientip)\n" if $debug;
} else {
open CL,"/dev/stdin";
}
# Main routine.
#
# This reads client messages from <CL>, looking for the
# delimiters that separate each message, and also looking for the
# section markers that delimit each part of the client message.
# When a message is complete, the processmessage() subroutine
# is invoked. $msgtxt contains the complete message, and the
# %sections hash contains the individual sections of the client
# message.
while (my $line = <CL>) {
if ($line =~ /^\@\@client\#/) {
# It's the start of a new client message - the
header looks like this:
# @@client#830759/HOSTNAME|1169985951.340108|
10.60.65.152|HOSTNAME|sunos|sunos
# Grab the hostname field from the header
my @hdrfields = split(/\|/, $line);
$hostname = $hdrfields[3];
$hostname =~ s/,/./g;
#$clientip = $hdrfields[2];
BigBrother->import; # if don't do this, won't see
changes....
$clientip = BigBrother->HostIP($hostname);
warn "DBG: processing $hostname ($clientip)\n" if
$debug;
# Clear the variables we use to store the message
in
$msgtxt = "";
%sections = ();
$cursection = ""; # none found yet!
$clientname = "";
$clientos = "";
}
elsif ($line =~ /^\@\@/) {
# End of a message. Do something with it.
whoCheck();
netCheck();
memCheck();
}
elsif ($line =~ /^\[(.+)\]/) {
# Start of new message section.
$cursection = $1;
$sections{ $cursection } = "\n";
}
elsif ($line =~ /^client\s+\S+\.([^.]+)\s+(\w+)/) {
# client header
# client esxsv01,ausport,gov,au.linux linux
# client sa01sv1.ausport.gov.au.bbwin win32
$msgtxt .= $line;
$clientname = $1;
$clientos = $2;
warn "DBG: clientID $clientname ($clientos)\n" if
$debug;
}
else {
# Add another line to the entire message text
variable,
# and the the current section.
$msgtxt .= $line;
if($cursection) {
$sections{ $cursection } .= $line;
} else {
my $time = scalar localtime;
warn "$time client-check: no current
section for client $hostname\n$line";
}
}
}
# End of a message. Do something with it. Will only get here using
clientlog (we hope)
whoCheck();
netCheck();
memCheck();
sub report {
my($hostname, $hobbitcolumn, $color, $summary, $statusmsg) =
@_;
# Build the command we use to send a status to the Xymon
daemon
my $cmd = $bb . " " . $bbdisp . " \"status " . $hostname .
"." . $hobbitcolumn . " " . $color . " " . $summary . "\n\n" . $statusmsg .
"\"";
if($debug) {
print "$cmd\n\n";
} else {
# And send the message
system $cmd;
}
}
# This subroutine processes the client message. In this case,
# we watch the [who] section of the client message and alert
# if there is a root login active.
sub whoCheck {
my $color;
my $summary;
my $statusmsg;
my $sec = "who";
my $hobbitcolumn = "who";
# Dont do anything unless we have the "who" section
return unless ( $sections{$sec} );
# Is there a "root" login somewhere in the "who" section?
# Note that we must match with /m because there are multiple
# lines in the [who] section.
if ( $sections{$sec} =~ /^root /m ) {
$color = "yellow";
$summary = "ROOT login active";
$statusmsg = "&yellow ROOT login detected!\n\n" .
$sections{$sec};
}
else {
$color = "green";
$summary = "OK";
$statusmsg = "&green No root login active\n\n" .
$sections{$sec};
}
report($hostname, $hobbitcolumn, $color, $summary,
$statusmsg);
}
# This subroutine processes the client message. In this case,
# we watch the [route] section of the client message and alert
# if the default route is incorrect
sub netCheck {
my $color;
my $summary;
my $statusmsg;
my $sec = "route";
my $hobbitcolumn = "route";
# Dont do anything unless we have the "route" section
return unless ( $sections{$sec} );
# Is there a default gateway somewhere in the "route" section?
# Note that we must match with /m because there are multiple
# lines
$color = "green";
$summary = "OK";
$statusmsg = "&green Default route OK\n\n" . $sections{$sec};
#darwin form:
# default 10.1.0.190 UGSc 6 91
en0
# 10.1/16 link#4 UCS 40 0
en0
# 10.1.0.1 0:12:1e:ae:ce:87 UHLW 0 0
en0 1196
if ( $sections{$sec} =~ /^(?:0\.0\.0\.0|default)\s+($ipre)\s+
($ipre|\w+)\s+(\S+)\s/m ) {
my $gw = ($clientname eq "bbwin") ? $2 : $1;
my $sm = ($clientname eq "bbwin") ? $1 : $2;
warn "DBG: netCheck $hostname ($clientip) GW: $gw
SM: $sm\n" if $debug;
my $isok = 1;
if( $gw =~ /^(.*)\.1$/) {
my $net = $1;
$isok = 0 unless $clientip =~ /^$net/;
}
if(!$isok) {
$color = "red";
$summary = "Bad default route $gw for
$clientip found";
$statusmsg = "&red Bad default route
$gw for $clientip found\n\n" . $sections{$sec};
}
} else {
$color = "red";
$summary = "Error";
$statusmsg = "&red No default route found\n\n" .
$sections{$sec};
}
report($hostname, $hobbitcolumn, $color, $summary,
$statusmsg);
}
# This subroutine processes the client message. In this case,
# we watch the [free] section of the client message and alert
# if the machine is an ESX server and the physical memory size is not 800MB
sub memCheck {
my $color;
my $summary;
my $statusmsg;
my $sec = "free";
my $hobbitcolumn = "pmem";
my $min = 799000;
# Dont do anything unless we have the "free" section
return unless ( $sections{$sec} && $hostname =~ /^esx/ );
# Get the Mem: line
# Note that we must match with /m because there are multiple
# lines
$color = "green";
$summary = "OK";
if ( $sections{$sec} =~ /^Mem:\s+(\d+)\s+(\d+)\s+(\d+)\s/m ) {
my $tot = $1;
$statusmsg = sprintf("&green memory allocation %dMB OK
(at least %dMB)\n\n",$tot/1024,$min/1024) . $sections{$sec};
warn "DBG: memCheck $hostname ($clientip) PhysMEM:
$tot\n" if $debug;
my $isok = $tot > $min;
if(!$isok) {
$color = "red";
$summary = sprintf("Bad memory
allocation %dMB for %s found (require at least
%dMB)",$tot/1024,$hostname,$min/1024);
$statusmsg = "&red ". sprintf("Bad
memory allocation %dMB for %s found (require at least %dMB)\n
\n",$tot/1024,$hostname,$min/1024) . $sections{$sec};
}
} else {
$color = "red";
$summary = "Error";
$statusmsg = "&red No Mem: line found\n\n" .
$sections{$sec};
}
report($hostname, $hobbitcolumn, $color, $summary,
$statusmsg);
}
To unsubscribe from the hobbit list, send an e-mail to
hobbit-unsubscribe at hswn.dk
Notice:
This communication is an electronic communication within the meaning of the Electronic Communications Privacy Act, 18 U.S.C. § 2510. Its disclosure is strictly limited to the recipient(s) intended by the sender of this message. This transmission and any attachments may contain proprietary, confidential, attorney-client privileged information and/or attorney work product. If you are not the intended recipient, any disclosure, copying, distribution, reliance on, or use of any of the information contained herein is STRICTLY PROHIBITED. Please destroy the original transmission and its attachments without reading or saving in any matter and confirm by return email.
More information about the Xymon
mailing list