jablonka.czprosek.czf

hotsanic

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

 

Line No. Rev Author Line
11simandl#
2# $Id: HotSaNICmod.pm,v 1.42 2004/08/30 11:21:22 bernisys Exp $
3#
4 
5package HotSaNICmod;
6 
7use HotSaNICparser;
8use HotSaNIClog;
9use RRDs;
10 
11my $MODNAME;
12my %MODARGS;
13my %CONFglob;
14my $SAMPLING=0;
15my $SAMPLE_LAST=0;
16my $SAMPLE_DURATION=0;
17 
18($VERSION = '$Revision: 1.42 $') =~ s/.*(\d+\.\d+).*/$1/;
19 
20######################################################################
21#
22# control function to make sure that a module is running only once
23#
24# Usage:
25# dupe_control($what,@messages);
26#
27# $what:
28# start -> call this method at the head of a module to touch the
29# dupe-detection checkfile.
30# stop -> remove PIDfile and exit normally.
31# die -> stop process with error.
32# warn -> print $message as warning and continue execution.
33# FOR COMPATIBILITY REASONS ONLY!
34# please use HotSaNIClog::warn
35# info -> print $message and continue execution.
36# FOR COMPATIBILITY REASONS ONLY!
37# please use HotSaNIClog::info
38#
39# each message will be preceded with a timestamp and the module name
40#
41sub dupe_control {
42 my $what=shift;
43 my $pid=0;
44 my $delta=0;
45 my $line;
46 
47 if ( ($what eq "check") || ($what eq "start") ) { $pid=HotSaNICparser::get_pid(); }
48 
49 if ($what eq "info") {
50 HotSaNIClog::error("HotSaNICmod::dupe_control(\"info\",...); is deprecated, use HotSaNIClog::info instead!");
51 HotSaNIClog::info(@_);
52 }
53 elsif ($what eq "warn") {
54 HotSaNIClog::error("HotSaNICmod::dupe_control(\"warn\",...); is deprecated, use HotSaNIClog::warn instead!");
55 HotSaNIClog::warn(@_);
56 }
57 elsif ($what eq "start") {
58 if ($pid > 0) {
59 HotSaNIClog::error("process already running on PID $pid for $delta seconds.");
60 exit 1;
61 }
62 open FILE,">running.pid";
63 print FILE $$;
64 close FILE;
65 HotSaNIClog::info("process forked to background.");
66 }
67 elsif ($what eq "stop") {
68 HotSaNIClog::info("exiting normally.");
69 if (-e "running.pid") { unlink "running.pid"; }
70 exit 0;
71 }
72 elsif ($what eq "die") {
73 HotSaNIClog::error(@_);
74 exit 1;
75 }
76 elsif ($what eq "check") {
77 if (!defined $pid) { $pid=0; }
78 if (($pid > 0) && (-e "/proc/$pid/stat")) {
79 open FILE,"/proc/$pid/stat";
80 @fileds=split / /,<FILE>;
81 close FILE;
82 $starttime=$fileds[21]/100;
83 open FILE,"/proc/uptime";
84 $line=<FILE>;
85 close FILE;
86 ($uptime)=split / /,$line;
87 $delta=int(($uptime-$starttime)*100)/100;
88 }
89 if (($pid > 0) && ($^O =~ /bsd/)) {
90 open FILE,"/proc/$pid/status";
91 @fileds=split / /,<FILE>;
92 close FILE;
93 ($starttime, $msec)= split /,/, $fileds[7];
94 $delta=int((time-$starttime)*100)/100;
95 }
96 if (!defined $delta) { $delta=0; }
97 return ($pid,$delta);
98 }
99 else { HotSaNIClog::error("HotSaNICmod::dupe_control method \"$what\" not supported."); }
100 }
101 
102 
103######################################################################
104#
105# check cmdline arguments
106#
107sub init {
108 $args=shift || "";
109 $MODNAME=HotSaNICparser::get_module_name();
110 %CONFglob=HotSaNICparser::get_config("../..",$MODNAME);
111 if (scalar(keys(%CONFglob)) == 0) { HotSaNICmod::dupe_control("die","missing global settings file"); }
112 HotSaNIClog::set_timestamping($CONFglob{TIMESTAMPING});
113 
114 my $found=0;
115 my @possible_args=("nodaemon","start","stop","status","configure","sample","update","version","help","showargs");
116 foreach (@possible_args) { if ($args eq $_) { $found++; } }
117 if ($found == 0) { $args=""; }
118 
119 if ( $args eq "" ) {
120 print "usage: $0 [".join("/",@possible_args)."]\n";
121 print "\n";
122 exit 1;
123 }
124 
125 if ( $args =~ /help/) {
126 print "usage: $0 [".join("/",@possible_args)."]\n";
127 print "\n";
128 print "alternative usage: send a signal to <module PID>\n";
129 print "\n";
130 print "argument signal function\n";
131 print "--------- ------- --------------------------------------------------\n";
132 print "nodaemon start module in foreground\n";
133 print "start start module daemon\n";
134 print "stop SIGTERM terminate module daemon\n";
135 print "status show status of module daemon\n";
136 print "configure SIGHUP daemon re-reads its config file\n";
137 print "sample SIGUSR1 sample now\n";
138 print "update SIGUSR2 (not implemented yet)\n";
139 print "version show version of OS-dependant module used\n";
140 print "showargs show settings hash\n";
141 print "\n";
142 exit 0;
143 }
144 
145# import common functions
146#
147 my $COM_LIB="./platform/common.pm";
148 if ( -e $COM_LIB ) {
149 eval { require $COM_LIB; };
150 if ($@) { HotSaNICmod::dupe_control("die","can't import common library: $COM_LIB",$!,$@); }
151 }
152 else { HotSaNICmod::dupe_control("die","can't import common library: $COM_LIB","file not found."); }
153 
154# import OS-specific functions
155#
156 my $fallback=0;
157 my $OS_LIB="./platform/$^O.pm";
158 if ( -e $OS_LIB ) {
159 eval { require $OS_LIB; };
160 if ($@) {
161 HotSaNIClog::error("can't import library: $OS_LIB",$!,$@);
162 $fallback=1;
163 }
164 }
165 else { HotSaNIClog::info("no special library available for \"$^O\""); $fallback=1; }
166 
167# OS-lib not found -> try to load default lib
168#
169 if ($fallback == 1) {
170 HotSaNIClog::info("falling back to library \"default\"");
171 eval { require "./platform/default.pm"; };
172 if ($@) {
173 HotSaNICmod::dupe_control("die","can't import library ./platform/default.pm",$!,$@);
174 }
175 }
176 
177 # read configuration, but don't initalize module (parameter "0")
178 configure(0);
179 
180 if ( ($args =~ /version/) or (HotSaNIClog::check_debuglevel("MODULE_VERBOSE"))) {
181 undef my @VERSIONS;
182 push @VERSIONS,HotSaNICmod::common::version() if defined &HotSaNICmod::common::version;
183 push @VERSIONS,HotSaNICmod::OSdep::version() if defined &HotSaNICmod::OSdep::version;
184 push @VERSIONS,HotSaNICmod::syssnmp::version() if defined &HotSaNICmod::syssnmp::version;
185 HotSaNIClog::info("using libs: ".join(" / ",@VERSIONS));
186 }
187 
188 if ( ($args =~ /start/) or ($args =~ /nodaemon/) ) {
189 my ($pid,$uptime)=HotSaNICmod::dupe_control("check","");
190 if ($pid > 0) { HotSaNIClog::info("module already running on PID $pid"); }
191 else {
192 
193 # initialize module
194 #
195 unlink "*.dat","*.old";
196 if ( -e "init" ) {
197 HotSaNIClog::info("-- begin init --");
198 system "./init";
199 HotSaNIClog::info("-- end init --");
200 }
201 elsif (defined &HotSaNICmod::OSdep::init) {
202 HotSaNIClog::info("-- begin init --");
203 HotSaNICmod::OSdep::init(%MODARGS);
204 HotSaNIClog::info("-- end init --");
205 }
206 
207 # set signal handlers and create background childprocess
208 #
209 $SIG{TERM} = \&terminate;
210 $SIG{HUP} = \&configure;
211 $SIG{USR1} = \&sample;
212 $SIG{USR2} = \&update;
213 if ($args =~ /start/) { fork && exit; }
214 HotSaNICmod::dupe_control("start","");
215 while (1 == 1) { sleep; }
216 }
217 }
218 
219 if ( $args =~ /status/) {
220 my ($pid,$uptime)=HotSaNICmod::dupe_control("check","");
221 if ($pid > 0) {
222 print "module \"$MODNAME\" running on PID $pid for $uptime sec.\n";
223 }
224 else { print "$MODNAME: no process running.\n"; }
225 my @DBs=HotSaNICmod::get_DBs();
226 my ($min,$max)=HotSaNICmod::get_last_DB_changes();
227 if ($min>=0) {
228 print "last DB update: $min";
229 if ($max != $min) { print " (max: $max)"; }
230 print " seconds ago\n";
231 print "DBs found: ",join("\n ",@DBs),"\n";
232 }
233 }
234 
235 if ( $args =~ /sample/) {
236 my ($pid,$uptime)=HotSaNICmod::dupe_control("check","");
237 if ($pid > 0) { kill "SIGUSR1",$pid; }
238 else { print "$MODNAME: no process running.\n"; }
239 }
240 
241 if ( $args =~ /stop/) {
242 my ($pid,$uptime)=HotSaNICmod::dupe_control("check","");
243 if ($pid > 0) { kill "SIGTERM",$pid; }
244 else { print "$MODNAME: no process running.\n"; }
245 }
246 
247 if ( $args =~ /configure/) {
248 my ($pid,$uptime)=HotSaNICmod::dupe_control("check","");
249 if ($pid > 0) { kill "SIGHUP",$pid; }
250 else { print "$MODNAME: no process running.\n"; }
251 }
252 
253 if ( $args =~ /update/) {
254 my ($pid,$uptime)=HotSaNICmod::dupe_control("check","");
255 if ($pid > 0) { kill "SIGUSR2",$pid; }
256 else { print "$MODNAME: no process running.\n"; }
257 }
258 
259 if ( $args =~ /showargs/) {
260 print "---------- CONFIGURATION ----------\n";
261 #
262 # alternative code - higher memory usage!
263 #
264 # use Data::Dumper;
265 # $Data::Dumper::Varname="MODARGS";
266 # $Data::Dumper::Sortkeys=1;
267 # print Dumper(\%MODARGS);
268 #
269 for (sort keys %MODARGS) {
270 print " $_ = ".$MODARGS{$_}."\n";
271 if (ref $MODARGS{$_} eq "ARRAY") {
272 if (! @{$MODARGS{$_}}) { print " " x ((length $_)+5),"(empty)\n"; }
273 foreach $line (@{$MODARGS{$_}}) { print " " x ((length $_)+5),"-> $line\n"; }
274 }
275 }
276 print "-----------------------------------\n";
277 }
278 }
279 
280 
281######################################################################
282#
283# terminate module daemon
284#
285sub terminate {
286 HotSaNICmod::dupe_control("stop","");
287 }
288 
289######################################################################
290#
291# interface to OS-dependent functions
292#
293sub sample {
294 my $DIFF=time-$SAMPLE_LAST;
295 if (HotSaNIClog::check_debuglevel("MODULE_SAMPLING")) {
296 HotSaNIClog::info("last sampling $DIFF seconds ago took $SAMPLE_DURATION seconds.");
297 }
298 if ( $DIFF >= 9) {
299 if ($SAMPLING == 0) {
300 # auto throttling
301 # skip sample if last sampling process took > 5 seconds and divide last duration by 2
302 if ($SAMPLE_DURATION > 5) {
303 $SAMPLE_DURATION/=2;
304 if (HotSaNIClog::check_debuglevel("MODULE_SAMPLING")) {
305 HotSaNIClog::warn("can't sample now, last sampling took > 5s.");
306 }
307 }
308 else {
309 $SAMPLING=1;
310 $SAMPLE_LAST=time;
311 HotSaNICmod::OSdep::sample(%MODARGS);
312 if ( (defined $MODARGS{USE_SNMP}) and (defined &HotSaNICmod::syssnmp::sample) ) { HotSaNICmod::syssnmp::sample(%MODARGS); }
313 $SAMPLING=0;
314 $SAMPLE_DURATION=(time-$SAMPLE_LAST);
315 }
316 }
317 elsif (HotSaNIClog::check_debuglevel("MODULE_SAMPLING")) {
318 HotSaNIClog::warn("can't sample now, old sampling process running.");
319 }
320 }
321 elsif (HotSaNIClog::check_debuglevel("MODULE_SAMPLING")) {
322 HotSaNIClog::warn("can't sample now, last sample taken less than 10s ago.");
323 }
324 }
325 
326sub update {
327 HotSaNICmod::OSdep::update;
328 }
329 
330######################################################################
331#
332# configure
333# - parse main settings
334# - parse module settings
335# - set module-specific configuration
336sub configure {
337 $initmode=shift || 0;
338 
339 my @CONFmod=HotSaNICparser::read_settings(".",$MODNAME);
340 if (scalar(@CONFmod) == 0) { HotSaNICmod::dupe_control("die","missing module settings file"); }
341 
342 my $modvar=$CONFglob{VARDIR}."/modules/".lc $MODNAME;
343 $modvar=~ s/\/+/\//g;
344 if (! -d $CONFglob{VARDIR}."/modules") { mkdir $CONFglob{VARDIR}."/modules",0755; }
345 if (! -d $modvar) { mkdir $modvar,0755; }
346 
347# configure module-specific settings
348#
349 %MODARGS=HotSaNICmod::common::configure(@CONFmod);
350 
351# import module's SNMP library if necessary
352#
353 if (defined $MODARGS{USE_SNMP}) {
354 my $SNMP_LIB="./platform/syssnmp.pm";
355 $MODARGS{SNMPWALK}=$CONFglob{SNMPWALK};
356 $MODARGS{SNMPGET}=$CONFglob{SNMPGET};
357 if ( -e $SNMP_LIB ) {
358 eval { require $SNMP_LIB; };
359 if ($@) { HotSaNIClog::error("can't import library: $SNMP_LIB",$!,$@); }
360 }
361 else { HotSaNIClog::info("no SNMP library available"); }
362 }
363 
364# configure common module settings
365#
366 foreach (@CONFmod) {
367 ($var,$value)=HotSaNICparser::parse_line($_);
368 if ($var eq "DEBUGLEVEL") { $MODARGS{DEBUGLEVEL}=HotSaNIClog::get_debuglevel($value); }
369 }
370 
371# add global settings
372#
373 $MODARGS{MODNAME}=$MODNAME;
374 $MODARGS{VARDIR}=$modvar;
375 $MODARGS{DEBUGLEVEL} |= HotSaNIClog::get_debuglevel($CONFglob{DEBUGLEVEL});
376 HotSaNIClog::set_debuglevel($MODARGS{DEBUGLEVEL});
377 if ($initmode eq "HUP") { HotSaNICmod::OSdep::init(%MODARGS) if defined &HotSaNICmod::OSdep::init; }
378 }
379 
380######################################################################
381#
382# returns an array containing all "*.rrd" files in the current module's "rrd" directory
383#
384sub get_DBs {
385 opendir(DIR,"rrd") || HotSaNICmod::dupe_control("die",$MODARGS{"MODNAME"},"error opening database dir - $!");
386 my @DBs=grep(/\.rrd/,readdir(DIR));
387 closedir(DIR);
388 return @DBs;
389 }
390 
391 
392######################################################################
393#
394# returns an array containing the min and max seconds since last DB changes
395#
396# if no DBs are found, (-1,-1) will be returned.
397#
398sub get_last_DB_changes {
399 
400 my @DBs=get_DBs();
401 
402 if (!@DBs) { return (-1,-1); }
403 
404 my ($min,$max)=(999999999999,0);
405 foreach $test (@DBs) {
406 (undef,undef,undef,undef,undef,undef,undef,undef,undef,$mtime,undef,undef,undef)=stat("rrd/".$test);
407 $mtime=time-$mtime;
408 if ($mtime<$min) { $min=$mtime; }
409 if ($mtime>$max) { $max=$mtime; }
410 }
411 
412 return ($min,$max);
413 }
414 
415 
416######################################################################
417#
418# updates a database, creates a new one if necessary
419#
420# USAGE:
421#
422# do_rrd($database,$maxvalue,$sampletime,@values);
423#
424# $database name of the database (without ".rrd" suffix)
425#
426# $maxvalue the maximum value to be expected on this datasource
427# (needed for DB creation)
428#
429# $sampletime timestamp of the current sample
430#
431# @values array of all values for this timestamp
432#
433sub do_rrd {
434 my $dbname = shift;
435 my $dbmax = shift;
436 my $sampletime = shift;
437 
438 if ( $#_ < 0 ) {
439 HotSaNIClog::warn("no values passed for $dbname");
440 }
441 
442 my $values=join(":",@_);
443 
444 if (HotSaNIClog::check_debuglevel("MODULE_DB_UPDATE")) {
445 HotSaNIClog::info("updating $dbname with $values");
446 }
447 
448 # build new database if needed
449 if ( ! -e "rrd/$dbname.rrd" ) { system("./makerrd","$dbname","$dbmax") }
450 
451 # update database
452 RRDs::update "rrd/$dbname.rrd",$sampletime.":$values";
453 if ($ERROR = RRDs::error) { HotSaNIClog::error("unable to update '$dbname.rrd': $ERROR"); }
454 }
455 
4561;
457 

Powered by WebSVN 2.2.1