# # $Id: HotSaNICmod.pm,v 1.42 2004/08/30 11:21:22 bernisys Exp $ # package HotSaNICmod; use HotSaNICparser; use HotSaNIClog; use RRDs; my $MODNAME; my %MODARGS; my %CONFglob; my $SAMPLING=0; my $SAMPLE_LAST=0; my $SAMPLE_DURATION=0; ($VERSION = '$Revision: 1.42 $') =~ s/.*(\d+\.\d+).*/$1/; ###################################################################### # # control function to make sure that a module is running only once # # Usage: # dupe_control($what,@messages); # # $what: # start -> call this method at the head of a module to touch the # dupe-detection checkfile. # stop -> remove PIDfile and exit normally. # die -> stop process with error. # warn -> print $message as warning and continue execution. # FOR COMPATIBILITY REASONS ONLY! # please use HotSaNIClog::warn # info -> print $message and continue execution. # FOR COMPATIBILITY REASONS ONLY! # please use HotSaNIClog::info # # each message will be preceded with a timestamp and the module name # sub dupe_control { my $what=shift; my $pid=0; my $delta=0; my $line; if ( ($what eq "check") || ($what eq "start") ) { $pid=HotSaNICparser::get_pid(); } if ($what eq "info") { HotSaNIClog::error("HotSaNICmod::dupe_control(\"info\",...); is deprecated, use HotSaNIClog::info instead!"); HotSaNIClog::info(@_); } elsif ($what eq "warn") { HotSaNIClog::error("HotSaNICmod::dupe_control(\"warn\",...); is deprecated, use HotSaNIClog::warn instead!"); HotSaNIClog::warn(@_); } elsif ($what eq "start") { if ($pid > 0) { HotSaNIClog::error("process already running on PID $pid for $delta seconds."); exit 1; } open FILE,">running.pid"; print FILE $$; close FILE; HotSaNIClog::info("process forked to background."); } elsif ($what eq "stop") { HotSaNIClog::info("exiting normally."); if (-e "running.pid") { unlink "running.pid"; } exit 0; } elsif ($what eq "die") { HotSaNIClog::error(@_); exit 1; } elsif ($what eq "check") { if (!defined $pid) { $pid=0; } if (($pid > 0) && (-e "/proc/$pid/stat")) { open FILE,"/proc/$pid/stat"; @fileds=split / /,; close FILE; $starttime=$fileds[21]/100; open FILE,"/proc/uptime"; $line=; close FILE; ($uptime)=split / /,$line; $delta=int(($uptime-$starttime)*100)/100; } if (($pid > 0) && ($^O =~ /bsd/)) { open FILE,"/proc/$pid/status"; @fileds=split / /,; close FILE; ($starttime, $msec)= split /,/, $fileds[7]; $delta=int((time-$starttime)*100)/100; } if (!defined $delta) { $delta=0; } return ($pid,$delta); } else { HotSaNIClog::error("HotSaNICmod::dupe_control method \"$what\" not supported."); } } ###################################################################### # # check cmdline arguments # sub init { $args=shift || ""; $MODNAME=HotSaNICparser::get_module_name(); %CONFglob=HotSaNICparser::get_config("../..",$MODNAME); if (scalar(keys(%CONFglob)) == 0) { HotSaNICmod::dupe_control("die","missing global settings file"); } HotSaNIClog::set_timestamping($CONFglob{TIMESTAMPING}); my $found=0; my @possible_args=("nodaemon","start","stop","status","configure","sample","update","version","help","showargs"); foreach (@possible_args) { if ($args eq $_) { $found++; } } if ($found == 0) { $args=""; } if ( $args eq "" ) { print "usage: $0 [".join("/",@possible_args)."]\n"; print "\n"; exit 1; } if ( $args =~ /help/) { print "usage: $0 [".join("/",@possible_args)."]\n"; print "\n"; print "alternative usage: send a signal to \n"; print "\n"; print "argument signal function\n"; print "--------- ------- --------------------------------------------------\n"; print "nodaemon start module in foreground\n"; print "start start module daemon\n"; print "stop SIGTERM terminate module daemon\n"; print "status show status of module daemon\n"; print "configure SIGHUP daemon re-reads its config file\n"; print "sample SIGUSR1 sample now\n"; print "update SIGUSR2 (not implemented yet)\n"; print "version show version of OS-dependant module used\n"; print "showargs show settings hash\n"; print "\n"; exit 0; } # import common functions # my $COM_LIB="./platform/common.pm"; if ( -e $COM_LIB ) { eval { require $COM_LIB; }; if ($@) { HotSaNICmod::dupe_control("die","can't import common library: $COM_LIB",$!,$@); } } else { HotSaNICmod::dupe_control("die","can't import common library: $COM_LIB","file not found."); } # import OS-specific functions # my $fallback=0; my $OS_LIB="./platform/$^O.pm"; if ( -e $OS_LIB ) { eval { require $OS_LIB; }; if ($@) { HotSaNIClog::error("can't import library: $OS_LIB",$!,$@); $fallback=1; } } else { HotSaNIClog::info("no special library available for \"$^O\""); $fallback=1; } # OS-lib not found -> try to load default lib # if ($fallback == 1) { HotSaNIClog::info("falling back to library \"default\""); eval { require "./platform/default.pm"; }; if ($@) { HotSaNICmod::dupe_control("die","can't import library ./platform/default.pm",$!,$@); } } # read configuration, but don't initalize module (parameter "0") configure(0); if ( ($args =~ /version/) or (HotSaNIClog::check_debuglevel("MODULE_VERBOSE"))) { undef my @VERSIONS; push @VERSIONS,HotSaNICmod::common::version() if defined &HotSaNICmod::common::version; push @VERSIONS,HotSaNICmod::OSdep::version() if defined &HotSaNICmod::OSdep::version; push @VERSIONS,HotSaNICmod::syssnmp::version() if defined &HotSaNICmod::syssnmp::version; HotSaNIClog::info("using libs: ".join(" / ",@VERSIONS)); } if ( ($args =~ /start/) or ($args =~ /nodaemon/) ) { my ($pid,$uptime)=HotSaNICmod::dupe_control("check",""); if ($pid > 0) { HotSaNIClog::info("module already running on PID $pid"); } else { # initialize module # unlink "*.dat","*.old"; if ( -e "init" ) { HotSaNIClog::info("-- begin init --"); system "./init"; HotSaNIClog::info("-- end init --"); } elsif (defined &HotSaNICmod::OSdep::init) { HotSaNIClog::info("-- begin init --"); HotSaNICmod::OSdep::init(%MODARGS); HotSaNIClog::info("-- end init --"); } # set signal handlers and create background childprocess # $SIG{TERM} = \&terminate; $SIG{HUP} = \&configure; $SIG{USR1} = \&sample; $SIG{USR2} = \&update; if ($args =~ /start/) { fork && exit; } HotSaNICmod::dupe_control("start",""); while (1 == 1) { sleep; } } } if ( $args =~ /status/) { my ($pid,$uptime)=HotSaNICmod::dupe_control("check",""); if ($pid > 0) { print "module \"$MODNAME\" running on PID $pid for $uptime sec.\n"; } else { print "$MODNAME: no process running.\n"; } my @DBs=HotSaNICmod::get_DBs(); my ($min,$max)=HotSaNICmod::get_last_DB_changes(); if ($min>=0) { print "last DB update: $min"; if ($max != $min) { print " (max: $max)"; } print " seconds ago\n"; print "DBs found: ",join("\n ",@DBs),"\n"; } } if ( $args =~ /sample/) { my ($pid,$uptime)=HotSaNICmod::dupe_control("check",""); if ($pid > 0) { kill "SIGUSR1",$pid; } else { print "$MODNAME: no process running.\n"; } } if ( $args =~ /stop/) { my ($pid,$uptime)=HotSaNICmod::dupe_control("check",""); if ($pid > 0) { kill "SIGTERM",$pid; } else { print "$MODNAME: no process running.\n"; } } if ( $args =~ /configure/) { my ($pid,$uptime)=HotSaNICmod::dupe_control("check",""); if ($pid > 0) { kill "SIGHUP",$pid; } else { print "$MODNAME: no process running.\n"; } } if ( $args =~ /update/) { my ($pid,$uptime)=HotSaNICmod::dupe_control("check",""); if ($pid > 0) { kill "SIGUSR2",$pid; } else { print "$MODNAME: no process running.\n"; } } if ( $args =~ /showargs/) { print "---------- CONFIGURATION ----------\n"; # # alternative code - higher memory usage! # # use Data::Dumper; # $Data::Dumper::Varname="MODARGS"; # $Data::Dumper::Sortkeys=1; # print Dumper(\%MODARGS); # for (sort keys %MODARGS) { print " $_ = ".$MODARGS{$_}."\n"; if (ref $MODARGS{$_} eq "ARRAY") { if (! @{$MODARGS{$_}}) { print " " x ((length $_)+5),"(empty)\n"; } foreach $line (@{$MODARGS{$_}}) { print " " x ((length $_)+5),"-> $line\n"; } } } print "-----------------------------------\n"; } } ###################################################################### # # terminate module daemon # sub terminate { HotSaNICmod::dupe_control("stop",""); } ###################################################################### # # interface to OS-dependent functions # sub sample { my $DIFF=time-$SAMPLE_LAST; if (HotSaNIClog::check_debuglevel("MODULE_SAMPLING")) { HotSaNIClog::info("last sampling $DIFF seconds ago took $SAMPLE_DURATION seconds."); } if ( $DIFF >= 9) { if ($SAMPLING == 0) { # auto throttling # skip sample if last sampling process took > 5 seconds and divide last duration by 2 if ($SAMPLE_DURATION > 5) { $SAMPLE_DURATION/=2; if (HotSaNIClog::check_debuglevel("MODULE_SAMPLING")) { HotSaNIClog::warn("can't sample now, last sampling took > 5s."); } } else { $SAMPLING=1; $SAMPLE_LAST=time; HotSaNICmod::OSdep::sample(%MODARGS); if ( (defined $MODARGS{USE_SNMP}) and (defined &HotSaNICmod::syssnmp::sample) ) { HotSaNICmod::syssnmp::sample(%MODARGS); } $SAMPLING=0; $SAMPLE_DURATION=(time-$SAMPLE_LAST); } } elsif (HotSaNIClog::check_debuglevel("MODULE_SAMPLING")) { HotSaNIClog::warn("can't sample now, old sampling process running."); } } elsif (HotSaNIClog::check_debuglevel("MODULE_SAMPLING")) { HotSaNIClog::warn("can't sample now, last sample taken less than 10s ago."); } } sub update { HotSaNICmod::OSdep::update; } ###################################################################### # # configure # - parse main settings # - parse module settings # - set module-specific configuration sub configure { $initmode=shift || 0; my @CONFmod=HotSaNICparser::read_settings(".",$MODNAME); if (scalar(@CONFmod) == 0) { HotSaNICmod::dupe_control("die","missing module settings file"); } my $modvar=$CONFglob{VARDIR}."/modules/".lc $MODNAME; $modvar=~ s/\/+/\//g; if (! -d $CONFglob{VARDIR}."/modules") { mkdir $CONFglob{VARDIR}."/modules",0755; } if (! -d $modvar) { mkdir $modvar,0755; } # configure module-specific settings # %MODARGS=HotSaNICmod::common::configure(@CONFmod); # import module's SNMP library if necessary # if (defined $MODARGS{USE_SNMP}) { my $SNMP_LIB="./platform/syssnmp.pm"; $MODARGS{SNMPWALK}=$CONFglob{SNMPWALK}; $MODARGS{SNMPGET}=$CONFglob{SNMPGET}; if ( -e $SNMP_LIB ) { eval { require $SNMP_LIB; }; if ($@) { HotSaNIClog::error("can't import library: $SNMP_LIB",$!,$@); } } else { HotSaNIClog::info("no SNMP library available"); } } # configure common module settings # foreach (@CONFmod) { ($var,$value)=HotSaNICparser::parse_line($_); if ($var eq "DEBUGLEVEL") { $MODARGS{DEBUGLEVEL}=HotSaNIClog::get_debuglevel($value); } } # add global settings # $MODARGS{MODNAME}=$MODNAME; $MODARGS{VARDIR}=$modvar; $MODARGS{DEBUGLEVEL} |= HotSaNIClog::get_debuglevel($CONFglob{DEBUGLEVEL}); HotSaNIClog::set_debuglevel($MODARGS{DEBUGLEVEL}); if ($initmode eq "HUP") { HotSaNICmod::OSdep::init(%MODARGS) if defined &HotSaNICmod::OSdep::init; } } ###################################################################### # # returns an array containing all "*.rrd" files in the current module's "rrd" directory # sub get_DBs { opendir(DIR,"rrd") || HotSaNICmod::dupe_control("die",$MODARGS{"MODNAME"},"error opening database dir - $!"); my @DBs=grep(/\.rrd/,readdir(DIR)); closedir(DIR); return @DBs; } ###################################################################### # # returns an array containing the min and max seconds since last DB changes # # if no DBs are found, (-1,-1) will be returned. # sub get_last_DB_changes { my @DBs=get_DBs(); if (!@DBs) { return (-1,-1); } my ($min,$max)=(999999999999,0); foreach $test (@DBs) { (undef,undef,undef,undef,undef,undef,undef,undef,undef,$mtime,undef,undef,undef)=stat("rrd/".$test); $mtime=time-$mtime; if ($mtime<$min) { $min=$mtime; } if ($mtime>$max) { $max=$mtime; } } return ($min,$max); } ###################################################################### # # updates a database, creates a new one if necessary # # USAGE: # # do_rrd($database,$maxvalue,$sampletime,@values); # # $database name of the database (without ".rrd" suffix) # # $maxvalue the maximum value to be expected on this datasource # (needed for DB creation) # # $sampletime timestamp of the current sample # # @values array of all values for this timestamp # sub do_rrd { my $dbname = shift; my $dbmax = shift; my $sampletime = shift; if ( $#_ < 0 ) { HotSaNIClog::warn("no values passed for $dbname"); } my $values=join(":",@_); if (HotSaNIClog::check_debuglevel("MODULE_DB_UPDATE")) { HotSaNIClog::info("updating $dbname with $values"); } # build new database if needed if ( ! -e "rrd/$dbname.rrd" ) { system("./makerrd","$dbname","$dbmax") } # update database RRDs::update "rrd/$dbname.rrd",$sampletime.":$values"; if ($ERROR = RRDs::error) { HotSaNIClog::error("unable to update '$dbname.rrd': $ERROR"); } } 1; WebSVN - hotsanic - Blame - Rev 29 - /branches/HotSaNIC-0.5.0-pre6/lib/HotSaNICmod.pm
  jablonka.czprosek.czf

hotsanic

Subversion Repositories:
[/] [branches/] [HotSaNIC-0.5.0-pre6/] [lib/] [HotSaNICmod.pm] - Blame information for rev 29

 

Line No. Rev Author Line

Powered by WebSVN 2.2.1