jablonka.czprosek.czf

hotsanic

Subversion Repositories:
[/] [trunk/] [lib/] [HotSaNIC.pm] - Rev 30 Go to most recent revision

Compare with Previous - Blame - Download


#
# $Id: HotSaNIC.pm,v 1.2 2002/11/24 18:50:06 tinheap Exp $
#

package HotSaNIC;

use Exporter;

# our ($VERSION, @ISA, @EXPORT);

($VERSION = '$Revision: 1.2 $') =~ s/.*(\d+\.\d+).*/$1/;

@ISA = qw(Exporter);
@EXPORT = qw (
  snmp_sysbulk
  snmp_sysquery
  get_module_name
  get_config
  read_settings
  check_config
  strip_unwanted
  identify_os_type
  parse_line
  get_diagram_properties
  opt2arg
  arg2opt
  check_args
  dupe_control
  convert_units
  );

######################################################################
#
# control function to make sure that a module is running only once
#
# Usage:
#   dupe_control($what,$module-name,$message);
#
#   $what:
#     start -> call this method at the head of a module to touch the
#               dupe-detection checkfile.
#     stop  -> remove checkfile and exit normally.
#     warn  -> print $message as warning and continue execution.
#     die   -> remove checkfile and stop process with error.
#
#   The given message will be preceded with a timestamp (in seconds
#   since 1970) and the module-name:
# 
#     <time> MODULE:message\n
#
sub dupe_control {
  my ($what,$mod,$message)=@_;
  if (!defined $mod) { $mod=get_module_name(); }
  if (!defined $message) { $message="(unknown reason)"; }
  if ($what eq "start") {
    if (-e "running.dat") {
      open FILE,"running.dat";
      $pid=<FILE>;
      close FILE;
      chomp $pid;
      if ((defined $pid) && ($pid ne "") && (-e "/proc/$pid")) {
        open FILE,"/proc/$pid/stat";
        $line=<FILE>;
        close FILE;
        if( index($line,"read-data") >= 0) {
          @fileds=split / /,$line;
          $starttime=$fileds[21]/100;
          open FILE,"/proc/uptime";
          $line=<FILE>;
          close FILE;
          ($uptime)=split / /,$line;
          $delta=int(($uptime-$starttime)*100)/100;
          if ( ($uptime-$starttime) > 3600) {
            print time," ",$mod,": process running >1 hour --> KILLING!\n";
            system "kill -9 $pid";
            }
          else {
            print time," ",$mod,": process already running on PID $pid for $delta seconds.\n";
            exit 1;
            }
          }
        }
      }
    open FILE,">running.dat";
    print FILE $$;
    close FILE;
    }
  elsif ($what eq "stop") {
    if (-e "running.dat") { unlink "running.dat"; }
    exit 0;
    }
  elsif ($what eq "die") {
    if (-e "running.dat") { unlink "running.dat"; }
    die time." ".$mod.": ".$message."\n";
    }
  elsif ($what eq "warn") {
    print time," ",$mod," warn: ",$message,"\n";
    }
  else { print time," ",$mod," method \"",$what,"\" not supported.\n"; }
  }

######################################################################
#
# checks if all necessary arguments are given in the corosponding
# hash. If not, try to reconstruct them or to set defaults.
#
# Usage:
#   %arguments=check_args(%arguments);
#
sub check_args {
  ($check,%ARGS)=@_;
  foreach $value (split /,/,$check) {
    if ( (!defined $ARGS{$value}) || ($ARGS{$value} eq "") || ($ARGS{$value} eq "not configured") ) {
      if ($value eq "MODNAME") { $ARGS{$value}=get_module_name(); }
      if ($value eq "DEBUGLEVEL") { $ARGS{$value}=-1; }
      if ($value eq "OSTYPE") { $ARGS{$value}=identify_os_type(); }
      if ($value eq "SNMPWALK") {
        my @found=grep /snmpwalk$/, `locate bin\/snmpwalk`;
        if (@found) { $found=$found[0];chomp $found; $result=" Found: ".$found; $ARGS{$value}=$found; } else { $ARGS{$value}="echo >/dev/null"; }
        dupe_control("warn",$ARGS{"MODNAME"},"SNMPWALK not given on commandline! $result");
        }
      if ($value eq "SNMPGET") {
        my @found=grep /snmpget$/, `locate bin\/snmpget`;
        if (@found) { $found=$found[0];chomp $found; $result=" Found: ".$found; $ARGS{$value}=$found; } else { $ARGS{$value}="echo >/dev/null"; }
        dupe_control("warn",$ARGS{"MODNAME"},"SNMPGET not given on commandline! $result");
        }
      }
    }
  return %ARGS;
  }

######################################################################
#
# converts an option-hash to cmdline argument string which can be
# passed to a module script
#
# Usage:
#   $commandline_args=opt2arg(%options);
#
sub opt2arg {
  my $line="";
  my %opts=@_;
  foreach $var (keys(%opts)) {
    if (index("DEBUGLEVEL MODNAME OSTYPE SNMPWALK SNMPGET",$var) >= 0) {
      $line=$line." ".$var."=\"".$opts{$var}."\"";
      }
    }
  if ($opts{"DEBUGLEVEL"}>=0) { print "CLIENT-LINE: $line\n" };
  return $line;
  }

######################################################################
#
# converts cmdline arguments array to an options-hash
#
# Usage:
#   %options=arg2opt($commandline_args)
#
sub arg2opt {
  my %HASH;
  foreach $pair (@_) {
    ($var,$value)=split /=/, $pair;
    $HASH{$var}=$value;
    }
  if (! defined $HASH{"MODNAME"}) { $HASH{"MODNAME"}=get_module_name(); }
  if (! defined $HASH{"OSTYPE"}) { $HASH{"OSTYPE"}=`uname`; chomp $HASH{"OSTYPE"}; }
  if (! defined $HASH{"DEBUGLEVEL"}) { $HASH{"DEBUGLEVEL"}=-1; }
  if ($HASH{"DEBUGLEVEL"} >=6 ) {
    print "\n";
    foreach (keys %HASH) { printf "     %-15s %s\n",$_,$HASH{$_}; }
    }
  return %HASH;
  }

######################################################################
#
# evaluates some diagram properties from the given range
#
# Usage:
#   ($description,$file_description,$build_interval,$diagram_range)=get_diagram_properties($range);
#
sub get_diagram_properties {
  my ($range)=@_;
  my ($descr,$file,$build,$fullrange);
  if    ($range eq "1h")     { $descr="hour";    $file=$descr; $build=0;     $fullrange=3600; }
  elsif ($range eq "6h")     { $descr="6 hours"; $file="6h";   $build=30;    $fullrange=21600; }
  elsif ($range eq "1day")   { $descr="day";     $file=$descr; $build=120;   $fullrange=86400; }
  elsif ($range eq "1week")  { $descr="week";    $file=$descr; $build=1000;  $fullrange=604800; }
  elsif ($range eq "1month") { $descr="month";   $file=$descr; $build=4300;  $fullrange=2592000; }
  elsif ($range eq "1year")  { $descr="year";    $file=$descr; $build=52500; $fullrange=31536000; }
  return ($descr,$file,$build,$fullrange);
  }

######################################################################
#
# Query remote host via SNMP and store data in tempfile
# GetBulk method
#
# Usage:
#
# snmp_sysbulk($path_to_snmpbulkget,$host,$community,$OIDs,$nums);
#
# syscall: snmpbulkget $host $community with all $OIDs permutated
#            with all $nums
#
#   $nums refers to the last part of the OIDs.
#
#   $OIDs and $nums have to be given space-separated.
#
sub snmp_sysbulk {
  my ($binpath,$host,$community,$OIDs,$nums)=@_;
  my $query="";
  my @OIDs=split / /,$OIDs;
  my @nums=split / /,$nums;
  my $OIDcount=(@OIDs);
  foreach $num (@nums) {
    foreach $OID (@OIDs) {
      $query=$query.$OID.".".$num." ";
      }
    }
  my @result=`$binpath $host $community $query`;

  $num=0;
  $count=0;
  foreach (@result) {
    chomp;
    s/.* = //; 
    $num++;
    if ($num==1) { $line=$nums[$count]; $count++ }
    $line=$line." ".$_;
    if ($num>=$OIDcount) {$num=0; push @results,$line;}
    }

  return @results;
  }


######################################################################
#
# Query remote host via SNMP and store data in tempfile
# snmpwalk method
#
# Usage:
#
#   snmp_sysquery($path_to_snmpwalk,$host,$community,$item,@grep)
#
#   $item: refers to the MIB you want to query ommitting the last part
#          of the OID
#
#   @grep: an array of the OID's last parts you's like to query.
#
sub snmp_sysquery {
  my ($binpath,$host,$community,$item,@grep)=@_;
  @result=`$binpath $host $community $item`;
  foreach $contains (@grep) {
    foreach (grep /$contains/, @result) {
      chomp;
      if (/\.([0-9]*) = /, $num=$1) {
        ($var,$value)=split / = /;
        if (defined $lines{$num}) { $lines{$num}=$lines{$num}." $value"; } else { $lines{$num}=$value; }
        }
      }
    }

  foreach $line (keys %lines) {
    push @results,$line." ".$lines{$line};
    }

  return @results;
  }

######################################################################
#
#  evaluate name of module by its subdir
#
# Usage:
#
#  $modname=get_module_name();
#
sub get_module_name {
  my $pwd=uc `pwd`;
  chomp $pwd;
  my (undef,$name)=split /MODULES\//,$pwd;
  return $name;
}


######################################################################
#
#  strip unwanted chars like " and multiple spaces at end / beginning
#  of each element and return the processed array.
#
# Usage:
#
#  $stripped_string=strip_unwanted($raw_string);
#
sub strip_unwanted {
  foreach (@_) {
    $_ =~ s/ *= */=/g;    # spaces near a =
    $_ =~ s/\"//g;        # " chars
    $_ =~ s/  +/ /g;      # multiple spaces to single
    $_ =~ s/^ *//g;       # spaces at beginning
    $_ =~ s/ *$//g;       # spaces at end
    }
  return @_;
  }


######################################################################
#
# Parse a line, strip all unwanted chars, split it by "=" into
# a VAR and a VALUE part and make sure those parts are defined.
#
# Usage:
#
#   ($var,$value,$comment)=parse_line($settings_line);
#
sub parse_line {
  my ($line)=@_;
  chomp $line;

# remove leading spaces
  $line =~ s/^ *//g;

# weed out comments (i.e. everything following a "#"
  my ($important,$comment)=split /#/,$line,2;
  if ((! defined $comment) || ( $comment eq "" )) {
    if (index($line,"#")>=0) { $comment=" "; }
    else { $comment=""; }
    }
  if ((! defined $important) || ($important eq "")) { return ("","",$comment); }

# trim the edges ;)
  ($important)=strip_unwanted($important);

# separate the variable name from its assigned value
  my ($var,$value)=split /=/,$important,2;

# avoid undefined variables
  $var="" if (! defined $var);
  $value="" if (! defined $value);

# force varnames to be upcase
  $var=uc $var;

  return ($var,$value,$comment)
}


######################################################################
#
#  evaluate settings file and check config...
#
# Usage:
#
#   %config=get_config($path_to_settings_file);
#
sub get_config {
  my ($location)=@_;
  my ($var,$value,$BINPATH,$DAEMONDIR,$LOGDIR,$PIDFILE,$DTIME,$CTIME,$STIME,$WEBDIR,$ORDER,$LOGSIZE,$LOGBACKUPS);

  my @lines=read_settings($location);
  foreach (@lines) {
    ($var,$value)=parse_line($_);
    $config{$var}=$value;
    }

  # sanity check for all config variables
  #
  $config{"BINPATH"}=check_config_item("BINPATH","path","","","path to \"rrdtool\"",%config);
  $config{"DAEMONDIR"}=check_config_item("DAEMONDIR","path","","","path to \"HotSaNIC\"",%config);
  $config{"WEBDIR"}=check_config_item("WEBDIR","path","","","path to HotSaNIC's output directory",%config);
  $config{"LOGDIR"}=check_config_item("LOGDIR","path","\$DAEMONDIR/log","","path to HotSaNIC's logfiles",%config);
  $config{"PIDFILE"}=check_config_item("PIDFILE","var","\$DAEMONDIR/log/rrdtimer.pid","","path to HotSaNIC's PID file",%config);
  $config{"DTIME"}=60*check_config_item("DTIME","var","15","minutes","diagram rebuild time",%config);
  $config{"CTIME"}=3600*check_config_item("CTIME","var","12","hours","diagram conversion time",%config);
  $config{"STIME"}=check_config_item("STIME","var","120","seconds","module scan time",%config);
  $config{"LOGSIZE"}=check_config_item("LOGSIZE","var","500000","bytes","max. logfile size",%config);
  $config{"LOGBACKUPS"}=check_config_item("LOGBACKUPS","var","4","","logfiles to keep as backups",%config);
  $config{"IMAGEFORMAT"}=check_config_item("IMAGEFORMAT","var","gif","","format of generated pictures",%config);
  $config{"ORDER"}=check_config_item("ORDER","var","","","order of modules",%config);
  $config{"DEBUGLEVEL"}=check_config_item("DEBUGLEVEL","var","-1","","debug level",%config);

  return %config;
  }


######################################################################
#
# read settings-file and strip comments and empty entries
#
# Usage:
#
#   @parsed_config=read_settings($path_to_settings_file,$module_name);
#
#   returns just the lines actually containing data - stripped by comments.
#
sub read_settings {
  my ($location,$modname)=@_;
  if (!defined $modname) {
    $modname="rrdtimer";
    $error="Configuration file \"settings\" missing in HotSaNIC's main directory. Probably you have to run setup.pl first.\n";
    }
  else { $error="Configuration file \"settings\" missing in module.\n"; }
  if ( (! defined $location) || ($location eq "")) { $location="."; }
  open CONF,"$location/settings" or dupe_control("die",$modname,$error);
  while (<CONF>) {
    chomp;
    next if $_ eq "";
    my ($important,$comment)=split /#/;
    if ((defined $important) && ( index($important,"=") >= 0)) {
      push @config,$important
      }
    }
  close CONF;

  return @config;
  }


######################################################################
#
# sanity check config-item
#
# Usage:
#
#   $value=check_config_item($item_name,$type,$default_value,$unit,$description,%config_hash);
#
#   $type:
#     "path" -> assume that value is a path     -> check its existence.
#     "var"  -> assume that value is a variable -> check if the value is set correctly.
#
#   if a fatal config-error is detected, the program dies with an error.
#
sub check_config_item {
  my ($name,$type,$default,$unit,$description,%confhash)=@_;

  my $DAEMONDIR=$confhash{"DAEMONDIR"};
  my $var=$confhash{$name};

  if (defined $var) { $var=~ s/\$DAEMONDIR/$DAEMONDIR/g; }

  if ($type eq "path") {
    if ((! defined $var) || ($var eq "")) {
      print $name," (",$description,") not configured.\n";
      if ($default eq "") { print "no default value given.\n"; exit 1; }
      else { print "using default value: ",$default," ",$unit,"\n"; ($var=$default)=~ s/\$DAEMONDIR/$DAEMONDIR/g; }
      }
    if ( ! -e $var) { print $name," (",$description,") does not exist.\n"; exit 1; }
    }

  if ($type eq "var") {
    if ((! defined $var) || ($var eq "")) {
      print $name," (",$description,") not configured.\n";
      if ($default eq "") { print "no default value given.\n"; exit 1; }
      else { print "using default value: ",$default," ",$unit,"\n"; $var=$default; }
      }
    }
  return $var;
  }


######################################################################
#
# identify OS type
#
# Usage:
#
#   $ostype=identify_os_type();
#
sub identify_os_type {
  my $os=`uname`;
  chomp $os;
  return $os;
  }

######################################################################
#
# convert - converts GB/MB/KB into Bytes
#
# Usage:
#
#   @out=convert_units(@in);
#
#   all values in @in will be checked against existance of a SI-multiplier
#   (K, M or G) and the value stored in @out are multiplied accordingly.
#
sub convert_units {
  my @in = @_;
  my @out = ();

  foreach $i (@in) {
    $i =~ s/(^\d+)K/$1 * 1024/;
    $i =~ s/(^\d+)M/$1 * 1024 * 1024/;
    $i =~ s/(^\d+)G/$1 * 1024 * 1024 * 1024/;
    #print "$i\n";
    $bytes = (eval "$i");
    #print "$bytes\n";
    push @out, $bytes;
  }
  return @out;
}

1;


Powered by WebSVN 2.2.1