|
#!/usr/bin/perl |
|
|
|
=head1 NAME |
|
|
|
dummy script doing nothing |
|
|
|
=cut |
|
|
|
use strict; |
|
|
|
# use FindBin; |
|
# use lib "$FindBin::Bin"; |
|
|
|
use Data::Dumper; |
|
$Data::Dumper::Indent= 1; |
|
|
|
use Util::Simple_CSV; |
|
use Util::Matrix; |
|
# use Module; |
|
|
|
my $x_flag= 0; |
|
my $is_dsh= 1; |
|
|
|
# BEGIN module data |
|
my @fld_ids= qw( wwn deviceID serialNumber vendorID productID ); |
|
my @fld_diag= qw(critical warnings); |
|
my @fld_errors= qw( mediumErrors smartError numParityErrors hwErrors smartWarning linkFailures abortedCmds ); |
|
my @fld= (@fld_ids, @fld_diag, @fld_errors); |
|
# END module data |
|
|
|
my %limits= |
|
( |
|
# 'mediumErrors' => { 'type' => 'num', 'warn' => 10000, 'crit' => 20000 }, |
|
# 'abortedCmds' => { 'type' => 'num', 'warn' => 10, 'crit' => 20 }, |
|
'smartError' => { 'type' => 'bool', 'xwarn' => 'true', 'crit' => 'true' }, |
|
); |
|
|
|
my @PARS; |
|
my $arg; |
|
while (defined ($arg= shift (@ARGV))) |
|
{ |
|
if ($arg eq '--') { push (@PARS, @ARGV); @ARGV= (); } |
|
elsif ($arg =~ /^--(.+)/) |
|
{ |
|
my ($opt, $val)= split ('=', $1, 2); |
|
if ($opt eq 'help') { usage(); } |
|
else { usage(); } |
|
} |
|
elsif ($arg =~ /^-(.+)/) |
|
{ |
|
foreach my $opt (split ('', $1)) |
|
{ |
|
if ($opt eq 'h') { usage(); exit (0); } |
|
elsif ($opt eq 'x') { $x_flag= 1; } |
|
else { usage(); } |
|
} |
|
} |
|
else |
|
{ |
|
push (@PARS, $arg); |
|
} |
|
} |
|
|
|
# print join (' ', __FILE__, __LINE__, 'caller=['. caller() . ']'), "\n"; |
|
|
|
my $arclog= new Arcconf::Log('is_dsh' => $is_dsh); |
|
|
|
while (defined ($arg= shift (@PARS))) |
|
{ |
|
$arclog->parse_file ($arg); |
|
} |
|
|
|
# print "arclog: ", Dumper ($arclog); |
|
|
|
|
|
my ($data, $crit, $warn)= $arclog->convert_to_csv_rows (\%limits); |
|
# print "data: ", Dumper ($data); |
|
# print "crit: ", Dumper ($crit); |
|
# print "warn: ", Dumper ($warn); |
|
|
|
my $level= 'OK'; |
|
$level= 'WARNING' if (@$warn); |
|
$level= 'CRITICAL' if (@$crit); |
|
print "level=[$level]\n"; |
|
|
|
my $fnm_nagios= 'out-nagios.txt'; |
|
|
|
if (defined ($fnm_nagios)) |
|
{ |
|
open (FO, '>:utf8', $fnm_nagios) or die "...TODO..."; |
|
|
|
=begin comment |
|
|
|
Preparing data for the nagios check |
|
|
|
The generalized service check script e.g. for Phaidra uses this |
|
format. |
|
* First line: code plus timestamp |
|
* after that: information that might be helpful for ops |
|
|
|
TODO: |
|
The nagios check script (on the nagios machine) currently uses localtime |
|
which triggers alerts during summertime switch because data is then |
|
either too old or too fresh. Thus the nagios check script needs to |
|
pickup the timezone code "Z" to handle gmt times properly. |
|
|
|
=end comment |
|
=cut |
|
|
|
# my @ts= gmtime(time()); my $tz_info= 'Z'; |
|
my @ts= localtime(time()); my $tz_info= ''; |
|
|
|
printf FO ("%s - %04d%02d%02dT%02d%02d%02d%s\n\n", $level, $ts[5]+1900, $ts[4]+1, $ts[3], $ts[2], $ts[1], $ts[0], $tz_info); |
|
|
|
if (@$crit) |
|
{ |
|
print FO "\n", scalar(@$crit), " critical errors\n", Dumper($crit); |
|
# print FO join (' ', %$_), "\n" foreach (@$crit); |
|
# Util::Matrix::print (\@fld, $crit, *FO); |
|
} |
|
|
|
if (@$warn) |
|
{ |
|
print FO "\n", scalar(@$warn), " warnings\n", Dumper ($warn); |
|
# print FO join (' ', %$_), "\n" foreach (@$warn); |
|
# Util::Matrix::print (\@fld, $warn, *FO); |
|
} |
|
|
|
close (FO); |
|
} |
|
|
|
my $csv_fnm= 'out-data.csv'; |
|
my $csv= new Util::Simple_CSV ('separator' => "\t"); # TODO: set CSV attributes as needed |
|
$csv->{'data'}= $data; |
|
$csv->define_columns(@fld); |
|
$csv->save_csv_file('filename' => $csv_fnm); |
|
print "saved to $csv_fnm\n"; |
|
|
|
exit (0); |
|
|
|
sub usage |
|
{ |
|
print <<EOX; |
|
usage: $0 [-opts] pars |
|
|
|
template ... |
|
|
|
options: |
|
-h ... help |
|
-x ... set x flag |
|
-- ... remaining args are parameters |
|
EOX |
|
|
|
exit (0); |
|
} |
|
|
|
# ---------------------------------------------------------------------------- |
|
sub main_function |
|
{ |
|
my $fnm= shift; |
|
print "main_function: $fnm\n"; |
|
} |
|
|
|
package Arcconf::Log; |
|
|
|
sub new |
|
{ |
|
my $class= shift; |
|
my $obj= {}; |
|
bless $obj, $class; |
|
$obj->set (@_); |
|
$obj; |
|
} |
|
|
|
sub set |
|
{ |
|
my $self= shift; |
|
my %par= @_; |
|
foreach my $par (keys %par) |
|
{ |
|
$self->{$par}= $par{$par}; |
|
} |
|
} |
|
|
|
sub parse_file |
|
{ |
|
my $self= shift; |
|
my $fnm= shift; |
|
|
|
open (FI, '<:utf8', $fnm) or die; |
|
$self->parse_fh(*FI); |
|
close (FI); |
|
} |
|
|
|
sub parse_fh |
|
{ |
|
my $self= shift; |
|
my $fh= shift; |
|
|
|
my $is_dsh= $self->{'is_dsh'}; |
|
my $host_name= 'nohost'; # TODO or get that from $self |
|
my $last_host= '<none>'; |
|
|
|
my ($host, $ctrl); # pointer to current objects |
|
while (<$fh>) |
|
{ |
|
chop; |
|
|
|
# print ">> [$_]\n"; |
|
|
|
if ($is_dsh) |
|
{ # filter out host info |
|
if ($_ =~ s#^([\w\d\-\.]+): ##) { $host_name= $1; } |
|
} |
|
|
|
if ($host_name ne $last_host) |
|
{ |
|
$last_host= $host_name; |
|
# print __LINE__, " new_host=[$host_name]\n"; |
|
$host= $self->{'host'}->{$host_name}= {}; # TODO: or new object of some class |
|
} |
|
|
|
if ($_ =~ m#<ControllerLog (.+)>#) |
|
{ |
|
my $c_attr= get_attr_list($1); |
|
$ctrl= |
|
{ |
|
'attr' => $c_attr, |
|
'drives' => [], |
|
}; |
|
# print "new controller: ", main::Dumper($ctrl); |
|
push (@{$host->{'controller'}}, $ctrl); |
|
} |
|
elsif ($_ =~ m#<driveErrorEntry (.+)\s*/>#) |
|
{ |
|
my $d_attr= get_attr_list($1); |
|
# print "new drive: ", main::Dumper ($d_attr); |
|
push (@{$ctrl->{'drives'}}, $d_attr); |
|
} |
|
elsif ($_ eq '</ControllerLog>') {} # close tags |
|
elsif ($_ eq '' || $_ eq 'Command completed successfully.') {} |
|
elsif ($_ =~ m#Controllers found: (\d+)#) |
|
{ |
|
# TODO: maybe we need that sometime ... |
|
} |
|
else |
|
{ |
|
print "unknown line: [$_]\n"; |
|
} |
|
} |
|
|
|
# TODO: return something |
|
} |
|
|
|
sub convert_to_csv_rows |
|
{ |
|
my $self= shift; |
|
my $limits= shift; |
|
|
|
my @rows; |
|
my @host_names= sort keys %{$self->{'host'}}; |
|
# print "host_names: ", join (' ', @host_names), "\n"; |
|
|
|
my @crit; |
|
my @warn; |
|
my $level= 0; |
|
my @check; |
|
|
|
if (defined ($limits)) |
|
{ |
|
@check= sort keys %$limits; |
|
print "check limits: ", join (' ', @check), "\n"; |
|
} |
|
|
|
foreach my $host (@host_names) |
|
{ |
|
# print "host=[$host]\n"; |
|
my $p_host= $self->{'host'}->{$host}; |
|
|
|
foreach my $p_ctrl (@{$p_host->{'controller'}}) |
|
{ |
|
my $ctrl_id= $p_ctrl->{'attr'}->{'controllerID'}; |
|
# print "ctrl_id=[$ctrl_id]\n"; |
|
foreach my $p_drive (@{$p_ctrl->{'drives'}}) |
|
{ |
|
my %row= %$p_drive; |
|
$row{'host'}= $host; |
|
$row{'ControllerID'}= $ctrl_id; |
|
push (@rows, \%row); |
|
|
|
if (defined ($limits)) |
|
{ |
|
# use either counter or array |
|
my $c_warn= 0; |
|
my $c_crit= 0; |
|
my (@r_warn, @r_crit); |
|
|
|
foreach my $an (@check) |
|
{ |
|
my $c= $limits->{$an}; |
|
my $av= $row{$an}; |
|
|
|
if ($c->{'type'} eq 'bool') |
|
{ |
|
if ($av eq $c->{'crit'}) { push (@crit, \%row); $c_crit++; push (@r_crit, $an); } |
|
elsif ($av eq $c->{'warn'}) { push (@warn, \%row); $c_warn++; push (@r_warn, $an); } |
|
# else that's fine |
|
} |
|
elsif ($c->{'type'} eq 'num') |
|
{ |
|
if ($av >= $c->{'crit'}) { push (@crit, \%row); $c_crit++; push (@r_crit, $an); } |
|
elsif ($av >= $c->{'warn'}) { push (@warn, \%row); $c_warn++; push (@r_warn, $an); } |
|
# else that's fine |
|
} |
|
# TOOD: more check types?? |
|
|
|
} |
|
|
|
# $row{'warnings'}= $c_warn; |
|
# $row{'critical'}= $c_crit; |
|
$row{'warnings'}= join (',', @r_warn); |
|
$row{'critical'}= join (',', @r_crit); |
|
} |
|
} |
|
} |
|
} |
|
|
|
(\@rows, \@crit, \@warn); |
|
} |
|
|
|
=head1 INTERNAL FUNCTIONS |
|
|
|
... |
|
|
|
=cut |
|
|
|
sub set_attr |
|
{ |
|
my ($a, $an, $av)= @_; |
|
# print __LINE__, " >>>> an=[$an] av=[$av]\n"; |
|
$av =~ s#^\s+##; |
|
$av =~ s#\s+$##; |
|
$a->{$an}= $av; |
|
''; |
|
} |
|
|
|
sub get_attr_list |
|
{ |
|
my $s= shift; |
|
|
|
# print ">>> s=[$s]\n"; |
|
my $attr= {}; |
|
|
|
# $s =~ s#(\w+)="([^"]+)"#{$attr{$1}=$2;''}#ge; |
|
$s =~ s#(\w+)="([^"]+)"#set_attr($attr, $1,$2)#ge; |
|
# print "<<< s=[$s]\n"; |
|
# print __LINE__, " attr: ", main::Dumper($attr); |
|
|
|
$attr; |
|
} |
|
|
|
__END__ |
|
|
|
|