hotsanic |
Subversion Repositories: |
Compare with Previous - Blame - Download
#
# $Id: HotSaNICparser.pm,v 1.47 2004/07/11 22:39:39 bernisys Exp $
#
package HotSaNICparser;
use HotSaNIClog;
($VERSION = '$Revision: 1.47 $') =~ s/.*(\d+\.\d+).*/$1/;
######################################################################
#
# evaluate name of module by its subdir
#
# Usage:
#
# $modname=get_module_name();
#
sub get_module_name {
require Cwd;
my $dir=Cwd::cwd();
my @array=split /MODULES\//,uc $dir;
my $name=pop @array;
if($name=~ /\//) { $name="UNKNOWN ($dir)"; }
chomp $name;
HotSaNIClog::set_modulename($name);
return $name;
}
######################################################################
#
# scan given directory for modules
#
# this function automatically weeds out all "." ".." and "CVS" entries
#
# Usage:
#
# @modules=scan_for_modules(<directory>,<debuglevel>,<FILTER>);
#
# <directory>
#
# <debuglevel> 1: function introduces itself
# >1: list all activity
#
# <FILTER> a space-separated list of modules that should be
# inserted if found or "*" for all found modules
#
sub scan_for_modules {
my ($directory,$FILTER)=@_;
undef my @modules;
if (HotSaNIClog::check_debuglevel("MAIN_SCAN_MODULES")) { HotSaNIClog::info("scanning $directory for modules."); }
opendir DIR,$directory;
my @mods=sort(readdir DIR);
closedir DIR;
# weed out non-module entries
foreach (@mods) {
if ($_ eq ".") { next; }
if ($_ eq "..") { next; }
if ($_ eq "CVS") { next; }
if ( -d "$directory/$_") {
if ( ! -e "$directory/$_/rrd" ) { mkdir "$directory/$_/rrd",0755; }
if ($FILTER =~ /\*|(^| )$_( |$)/) {
if (HotSaNIClog::check_debuglevel("MAIN_SCAN_MODULES_VERBOSE")) { HotSaNIClog::info(" found module ".uc $_); }
push @modules,$_;
}
}
}
return @modules;
}
######################################################################
#
# 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);
my %config;
foreach (read_settings($location)) {
($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{"VARDIR"}=check_config_item("VARDIR","path","\$DAEMONDIR/var","","path to HotSaNIC's logfiles",%config);
$config{"LOGDIR"}=check_config_item("LOGDIR","path","\$DAEMONDIR/var/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","NONE","","debug level",%config);
$config{"SCHEDULE_MIN"}=check_config_item("SCHEDULE_MIN","var","50","ms","minimum scheduling interval",%config);
$config{"SCHEDULE_MAX"}=check_config_item("SCHEDULE_MAX","var","100","ms","maximum scheduling interval",%config);
$config{"AUTOINDEX"}=check_config_item("AUTOINDEX","var","no","","call makindex on startup",%config);
return %config;
}
######################################################################
#
# read settings-file and strip comments and empty entries
#
# Usage:
#
# @parsed_config=read_settings($path_to_settings_file);
#
# returns just the lines actually containing data - stripped by comments.
#
sub read_settings {
my $location=shift;
my @config;
if ( (! defined $location) || ($location eq "")) { $location="."; }
if (-e "$location/settings") {
push @config,"settings file exisits. (Dummy added by HotSaNICparser.pm::read_settings)";
open CONF,"$location/settings";
while (<CONF>) {
chomp;
next if $_ eq "";
my ($important,$comment)=split /#/;
if ((defined $important) && ( index($important,"=") >= 0)) {
push @config,$important
}
}
}
close CONF;
return @config;
}
######################################################################
#
# read defaults-file and settings-file, into a hash
#
# Usage:
#
# %moduleconfig=get_moduleconfig($path_to_settings_file,%types);
#
# returns a hash with all settings items.
# items beginning with "COLOR_" or "GRAPH_" are strings
# only exception is the "GRAPH_ADDLINE" statement which may be
# stated multiple times.
# other items are (unless defined otherwhise using %types hash)
# arrays containing all instances of this item
#
# Possible types are "array", "var" and "bool".
# Items of the "bool" type will be parsed to "1" for the values
# "1","on","yes","true", and to "0" for everything else.
#
sub get_moduleconfig {
my $location=shift || ".";
my %types=@_;
if ($location eq "") { $location="."; }
my %config=(GRAPH_FORCE_LEGEND=>[0],GRAPH_RIGID=>[0],GRAPH_STYLE=>["lin"]);
for my $file ("$location/.settings.default","$location/settings") {
if (-e $file) {
open CONF,$file;
while (<CONF>) {
chomp;
next if $_ eq "";
my ($var,$value,$comment)=parse_line($_);
push @{$config{$var}},$value if ($var ne "");
}
close CONF;
}
}
foreach (keys %config) {
my $type="array";
if (defined $types{$_}) { $type=$types{$_}; }
if ( (index($_,"DEBUGLEVEL") == 0) or (index($_,"GRAPH_") == 0) or (index($_,"COLOR_") == 0) ) {
$type="var";
if (index ($_,"GRAPH_RIGID") >=0 ) { $type="bool"; }
if (index ($_,"GRAPH_FORCE_LEGEND") >=0 ) { $type="bool"; }
if (index ($_,"GRAPH_ADDLINE") >=0 ) { $type="array"; }
}
if ($type eq "var") { $config{$_}=pop @{$config{$_}}; }
if ($type eq "bool") {
my $value=pop @{$config{$_}};
if (index("1 on yes true",$value) >=0) { $config{$_}=1, } else { $config{$_}=0; }
}
}
if (defined $config{GRAPH_FORBID_STYLE_LOG}) { $config{GRAPH_STYLE}="lin"; }
else {
if (! defined $config{GRAPH_STYLE}) { $config{GRAPH_STYLE}="lin"; }
elsif ($config{GRAPH_STYLE} =~ /log/) { $config{GRAPH_STYLE}="log"; }
else { $config{GRAPH_STYLE}="lin"; }
}
# initialize undefined entries
#
foreach (keys %types) {
if (!defined $config{$_}) {
if ($types{$_} eq "array") { @{$config{$_}}=(); }
if ($types{$_} eq "var") { $config{$_}=""; }
if ($types{$_} eq "bool") { $config{$_}=0; }
}
}
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 "")) {
HotSaNIClog::warn("$name ($description) not configured.");
if ($default eq "") { die "no default value available.\n"; }
else {
HotSaNIClog::info("using default value: $default $unit");
($var=$default)=~ s/\$DAEMONDIR/$DAEMONDIR/g;
}
}
if ( ! -e $var) {
HotSaNIClog::warn("$name ($description) does not exist.");
HotSaNIClog::info("Trying to create path...");
mkdir $var,0755;
}
}
if ($type eq "var") {
if ((! defined $var) || ($var eq "")) {
HotSaNIClog::warn("$name ($description) not configured.");
if ($default eq "") { die "no default value available.\n"; }
else {
HotSaNIClog::info("using default value: $default $unit");
$var=$default;
}
}
}
return $var;
}
######################################################################
#
# identify Kernel version
#
# Usage:
#
# $kernel=identify_kernel();
#
sub identify_kernel {
require POSIX;
my ($ostype, $nodename, $release, $version, $machine) = POSIX::uname();
my $kernel=2.0;
$kernel=2.2 if $release =~ /^2\.[12]\./;
$kernel=2.4 if $release =~ /^2\.[34]\./;
$kernel=2.6 if $release =~ /^2\.[56]\./;
return $kernel;
}
######################################################################
#
# identify OS type
#
# Usage:
#
# $ostype=identify_os_type();
#
sub identify_os_type {
require POSIX;
my ($ostype, undef, undef, undef, undef) = POSIX::uname();
return $ostype;
}
######################################################################
#
# 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/;
$bytes = (eval "$i");
push @out, $bytes;
}
return @out;
}
######################################################################
#
# returns the PID of the running "read-data" or "rrdtimer" process
#
# Usage:
# $pid = get_pid(<path_to_pidfile>,<name>);
#
# if no parameters are given, the "running.pid" file in the current directory
# will be used as default.
#
# "name" is the name of the program to check for
#
# if no process can be found, "0" will be returned.
#
sub get_pid {
my $pidfile=shift || "./running.pid";
my $name=shift || "read-data";
my $PID=0;
if (-e "$pidfile") {
open FILE,"$pidfile";
$PID=<FILE> || "";
close FILE;
chomp $PID;
my $PROC_USABLE=0;
if ($^O ne "solaris") {
if (-d "/proc") {
opendir DIR,"/proc";
my @files=grep /^[0-9]/,readdir DIR;
closedir DIR;
if (@files) { $PROC_USABLE="1"; }
}
}
if ((defined $PID) && ($PID ne "")) {
if ($PROC_USABLE == 0) {
if (HotSaNIClog::check_debuglevel("MAIN_VERBOSE,MODULE_VERBOSE")) {
HotSaNIClog::warn("/proc filesystem not available");
HotSaNIClog::info("falling back to \"ps\"");
}
my $line="";
open RESULT,"ps -aef|";
while (<RESULT>) { $line=$_ if ((/$PID/) && (/$name/)) }
close RESULT;
if ($line eq "") { $PID=0; }
}
else {
if (-d "/proc/$PID") {
$delta=0;
open FILE,"/proc/$PID/cmdline";
$line=<FILE> || "";
close FILE;
if (index($line,$name) < 0) { $PID=0; }
}
else { $PID=0; }
}
}
else { $PID=0; }
}
# make sure PID dosn't belong to a vial system process
if ($PID <= 20) { $PID=0; }
return $PID;
}
######################################################################
#
# make a backup of the given file to the "./backup" directory
#
# Usage:
#
# backup_file($filename,$subdir);
#
# if $subdir is omitted, the current dir "./" will be used.
#
sub backup_file {
my $file=shift;
my $subdir=shift || ".";
mkdir "backup",0755 if ! -e "backup";
my ($sec,$min,$hour,$mday,$mon,$year,undef,undef,undef) = localtime(time);
$year+=1900;
$mon++;
$NOW=sprintf"%i%02i%02i-%02i%02i%02i",$year,$mon,$mday,$hour,$min,$sec;
rename "$subdir/$file","backup/$file-$NOW";
HotSaNIClog::info("a backup of \"$subdir/$file\" has been saved as \"./backup/$file-$NOW\"");
}
######################################################################
#
# calls syscmd: locate and returns a list of files that match the pattern
#
# Usage:
#
# locate_file($pattern);
#
sub locate_files {
my $pattern=shift;
my @results;
open LOCATERESULT,"locate $pattern|" || HotSaNIClog::error("could not run \"locate $pattern\"");
@results=(<LOCATERESULT>);
close LOCATERESULT;
return @results;
}
######################################################################
#
# return all selected entries found in the given config-array
# if no entry is found, and the default valus is present, create one
#
# the generated string can directly be printed into a settings file
#
# Usage:
#
# $text=get_items($pattern,$default_value,@config);
#
sub get_items {
my $pattern=shift;
my $default=shift;
my @config=@_;
undef my @results;
foreach (@config) {
push @results,"$_\n" if /^$pattern *=/;
}
if ( (!@results) and ($default ne "") ) {
push @results,"$pattern=\"$default\"\n";
}
return join ("",@results);
}
1;