pax_global_header00006660000000000000000000000064124230170350014507gustar00rootroot0000000000000052 comment=be22606b4d65106cbcef8ac41c92656e4585de6d libmonitoring-availability-perl-0.46/000077500000000000000000000000001242301703500177245ustar00rootroot00000000000000libmonitoring-availability-perl-0.46/Changes000066400000000000000000000057041242301703500212250ustar00rootroot00000000000000Revision history for Perl extension Monitoring::Availability. 0.46 Tue Mar 12 16:46:40 CET 2013 - fixed typo 0.44 Tue Mar 12 14:32:48 CET 2013 - added support for livestatus logs from mysql logfilecache - performance tunings 0.42 Thu Feb 21 16:38:30 CET 2013 - fixed breakdown by weeks - fixed calculation when report start is at the same time as log entry 0.40 Sat Dec 29 20:51:55 CET 2012 - changed confess to warning on bogus logentries - fixed breakdown by weeks 0.38 Thu Jun 21 10:25:03 CEST 2012 - don't break on broken logfiles 0.36 Mon May 21 16:53:29 CEST 2012 - fixed breakdown values with uneven report timeperiods - added downtime information to result logs 0.34 Tue May 8 21:25:56 CEST 2012 - another fix in calculation with no logs 0.32 Fri May 4 19:06:03 CEST 2012 - fixed calculation with empty logs from livestatus 0.30 Mon Apr 30 17:35:04 CEST 2012 - fixed breakdown support when no events happen between breakpoints 0.28 Mon Apr 30 17:35:04 CEST 2012 - fixed breakdown support on bsd systems 0.26 Mon Apr 23 17:23:24 CEST 2012 - added breakdown support 0.24 Fri Jan 27 00:34:03 CET 2012 - fixed timeperiod support - report time outside timeperiods as extra item 0.22 Thu Jan 26 01:10:58 CET 2012 - added support for timeperiods (based on livestatus time transitions) 0.20 Sun Jul 31 10:36:44 CEST 2011 - fixed problem with pending states in shinken 0.18 Sat Apr 16 18:01:26 CEST 2011 - fixed tests with use english 0.16 Fri Jun 18 13:18:29 CEST 2010 - added perl 5.8 requirement 0.14 Fri Jun 18 11:53:49 CEST 2010 - excluded some tests on windows hosts 0.12 Sun Feb 21 18:04:47 CET 2010 - fixed initial fake log for empty logs 0.11 Sat Feb 20 20:22:48 CET 2010 - fixed logfile tests on windows 0.10 Sun Feb 7 02:48:47 CET 2010 - fixed initial fake entry 0.08 Sun Jan 24 21:39:55 CET 2010 - added on the fly calculation for livestatus logs 0.07 Sun Jan 24 21:39:55 CET 2010 - fixed report log for hosts with services - fixed test requirements 0.06 Sun Jan 24 00:29:06 CET 2010 - fixed initial states 'current' 0.05 Thu Jan 21 22:05:16 CET 2010 - fixed reports when logfiles are totally out of report range - changed the way of settings options - added new option services_inherit_hostdowntimes - added new option timeformat which is used for log output - moved logfile parsing to extra module - fixed initialassumedservicestate 0.04 Mon Jan 18 08:06:59 CET 2010 - added message when passing wrong services 0.03 Sat Jan 16 20:46:54 CET 2010 - added resulting datastructure - added read string/array/file/dir methods - first tests - implemented assumestatesduringnotrunning option - implemented service availability calculation - implemented hostdowntimes - implemented servicedowntimes - implemented hosts 0.01 Fri Jan 15 16:40:00 CET 2010 - initial version libmonitoring-availability-perl-0.46/MANIFEST000066400000000000000000000023441242301703500210600ustar00rootroot00000000000000Changes inc/Module/AutoInstall.pm inc/Module/Install.pm inc/Module/Install/AutoInstall.pm inc/Module/Install/Base.pm inc/Module/Install/Can.pm inc/Module/Install/Fetch.pm inc/Module/Install/Include.pm inc/Module/Install/Makefile.pm inc/Module/Install/Metadata.pm inc/Module/Install/Win32.pm inc/Module/Install/WriteAll.pm lib/Monitoring/Availability.pm lib/Monitoring/Availability/Logs.pm Makefile.PL MANIFEST This list of files META.yml MYMETA.json MYMETA.yml README t/00_test_utils.pm t/01-availability-basic_tests.t t/10-availability-load_logs.t t/11-availability-load_logs_livestatus.t t/20-availability-host_up.t t/21-availability-host_down.t t/22-availability-host_unreachable.t t/23-availability-service_ok.t t/24-availability-service_warning.t t/25-availability-service_critical.t t/26-availability-service_unknown.t t/30-availability-host_with_downtime.t t/30-availability-service_with_hostdowntimes.t t/31-availability-host_with_services.t t/32-availability-service.t t/33-availability-service_ok_logs.t t/34-availability-breakdown.t t/35-availability-timeperiods.t t/36-availability-nologs.t t/37-availability-no_initial_log.t t/92_clean_debug.t t/92_todo.t t/93-manifest.t t/97-Pod.t t/98-Pod-Coverage.t t/99-Perl-Critic.t t/perlcriticrc libmonitoring-availability-perl-0.46/META.yml000066400000000000000000000010621242301703500211740ustar00rootroot00000000000000--- abstract: 'Calculate Availability Data from' author: - 'Sven Nierlein, ' build_requires: ExtUtils::MakeMaker: 6.59 configure_requires: ExtUtils::MakeMaker: 6.59 distribution_type: module dynamic_config: 1 generated_by: 'Module::Install version 1.06' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: Monitoring-Availability no_index: directory: - inc - t requires: Test::More: 0.87 perl: 5.8.0 resources: license: http://dev.perl.org/licenses/ version: 0.46 libmonitoring-availability-perl-0.46/MYMETA.json000066400000000000000000000016371242301703500216220ustar00rootroot00000000000000{ "abstract" : "Calculate Availability Data from", "author" : [ "Sven Nierlein, " ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 6.62, CPAN::Meta::Converter version 2.112150", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "Monitoring-Availability", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "6.59" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : 0 } }, "runtime" : { "requires" : { "Test::More" : "0.87", "perl" : "5.008" } } }, "release_status" : "stable", "version" : "0.46" } libmonitoring-availability-perl-0.46/MYMETA.yml000066400000000000000000000010151242301703500214400ustar00rootroot00000000000000--- abstract: 'Calculate Availability Data from' author: - 'Sven Nierlein, ' build_requires: ExtUtils::MakeMaker: 6.59 configure_requires: ExtUtils::MakeMaker: 0 dynamic_config: 0 generated_by: 'ExtUtils::MakeMaker version 6.62, CPAN::Meta::Converter version 2.112150' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: Monitoring-Availability no_index: directory: - t - inc requires: Test::More: 0.87 perl: 5.008 version: 0.46 libmonitoring-availability-perl-0.46/Makefile.PL000066400000000000000000000010661242301703500217010ustar00rootroot00000000000000use inc::Module::Install; name 'Monitoring-Availability'; all_from 'lib/Monitoring/Availability.pm'; perl_version '5.008'; license 'perl'; requires 'Test::More' => '0.87'; #test_requires 'Test::Pod' => 1.14; #test_requires 'Test::Perl::Critic'; #test_requires 'Test::Pod::Coverage'; #test_requires 'Perl::Critic::Policy::Dynamic::NoIndirect'; #test_requires 'Perl::Critic::Policy::NamingConventions::ProhibitMixedCaseSubs'; #test_requires 'Perl::Critic::Policy::ValuesAndExpressions::ProhibitAccessOfPrivateData'; auto_install; WriteAll; libmonitoring-availability-perl-0.46/README000066400000000000000000000012631242301703500206060ustar00rootroot00000000000000Monitoring-Availability ======================= Monitoring::Availability can be used to calculate the availability based on Nagios / Icinga and Shinken Logfiles. INSTALLATION To install this module type the following: perl Makefile.PL make make test make install DEPENDENCIES This module requires no other modules. SYNOPSIS my $ma = Monitoring::Availability->new(); my $availability = $ma->calculate(); AUTHOR Sven Nierlein COPYRIGHT AND LICENCE Copyright (C) 2010 by Sven Nierlein This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. libmonitoring-availability-perl-0.46/inc/000077500000000000000000000000001242301703500204755ustar00rootroot00000000000000libmonitoring-availability-perl-0.46/inc/Module/000077500000000000000000000000001242301703500217225ustar00rootroot00000000000000libmonitoring-availability-perl-0.46/inc/Module/AutoInstall.pm000066400000000000000000000621621242301703500245260ustar00rootroot00000000000000#line 1 package Module::AutoInstall; use strict; use Cwd (); use File::Spec (); use ExtUtils::MakeMaker (); use vars qw{$VERSION}; BEGIN { $VERSION = '1.06'; } # special map on pre-defined feature sets my %FeatureMap = ( '' => 'Core Features', # XXX: deprecated '-core' => 'Core Features', ); # various lexical flags my ( @Missing, @Existing, %DisabledTests, $UnderCPAN, $InstallDepsTarget, $HasCPANPLUS ); my ( $Config, $CheckOnly, $SkipInstall, $AcceptDefault, $TestOnly, $AllDeps, $UpgradeDeps ); my ( $PostambleActions, $PostambleActionsNoTest, $PostambleActionsUpgradeDeps, $PostambleActionsUpgradeDepsNoTest, $PostambleActionsListDeps, $PostambleActionsListAllDeps, $PostambleUsed, $NoTest); # See if it's a testing or non-interactive session _accept_default( $ENV{AUTOMATED_TESTING} or ! -t STDIN ); _init(); sub _accept_default { $AcceptDefault = shift; } sub _installdeps_target { $InstallDepsTarget = shift; } sub missing_modules { return @Missing; } sub do_install { __PACKAGE__->install( [ $Config ? ( UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config} ) : () ], @Missing, ); } # initialize various flags, and/or perform install sub _init { foreach my $arg ( @ARGV, split( /[\s\t]+/, $ENV{PERL_AUTOINSTALL} || $ENV{PERL_EXTUTILS_AUTOINSTALL} || '' ) ) { if ( $arg =~ /^--config=(.*)$/ ) { $Config = [ split( ',', $1 ) ]; } elsif ( $arg =~ /^--installdeps=(.*)$/ ) { __PACKAGE__->install( $Config, @Missing = split( /,/, $1 ) ); exit 0; } elsif ( $arg =~ /^--upgradedeps=(.*)$/ ) { $UpgradeDeps = 1; __PACKAGE__->install( $Config, @Missing = split( /,/, $1 ) ); exit 0; } elsif ( $arg =~ /^--default(?:deps)?$/ ) { $AcceptDefault = 1; } elsif ( $arg =~ /^--check(?:deps)?$/ ) { $CheckOnly = 1; } elsif ( $arg =~ /^--skip(?:deps)?$/ ) { $SkipInstall = 1; } elsif ( $arg =~ /^--test(?:only)?$/ ) { $TestOnly = 1; } elsif ( $arg =~ /^--all(?:deps)?$/ ) { $AllDeps = 1; } } } # overrides MakeMaker's prompt() to automatically accept the default choice sub _prompt { goto &ExtUtils::MakeMaker::prompt unless $AcceptDefault; my ( $prompt, $default ) = @_; my $y = ( $default =~ /^[Yy]/ ); print $prompt, ' [', ( $y ? 'Y' : 'y' ), '/', ( $y ? 'n' : 'N' ), '] '; print "$default\n"; return $default; } # the workhorse sub import { my $class = shift; my @args = @_ or return; my $core_all; print "*** $class version " . $class->VERSION . "\n"; print "*** Checking for Perl dependencies...\n"; my $cwd = Cwd::cwd(); $Config = []; my $maxlen = length( ( sort { length($b) <=> length($a) } grep { /^[^\-]/ } map { ref($_) ? ( ( ref($_) eq 'HASH' ) ? keys(%$_) : @{$_} ) : '' } map { +{@args}->{$_} } grep { /^[^\-]/ or /^-core$/i } keys %{ +{@args} } )[0] ); # We want to know if we're under CPAN early to avoid prompting, but # if we aren't going to try and install anything anyway then skip the # check entirely since we don't want to have to load (and configure) # an old CPAN just for a cosmetic message $UnderCPAN = _check_lock(1) unless $SkipInstall || $InstallDepsTarget; while ( my ( $feature, $modules ) = splice( @args, 0, 2 ) ) { my ( @required, @tests, @skiptests ); my $default = 1; my $conflict = 0; if ( $feature =~ m/^-(\w+)$/ ) { my $option = lc($1); # check for a newer version of myself _update_to( $modules, @_ ) and return if $option eq 'version'; # sets CPAN configuration options $Config = $modules if $option eq 'config'; # promote every features to core status $core_all = ( $modules =~ /^all$/i ) and next if $option eq 'core'; next unless $option eq 'core'; } print "[" . ( $FeatureMap{ lc($feature) } || $feature ) . "]\n"; $modules = [ %{$modules} ] if UNIVERSAL::isa( $modules, 'HASH' ); unshift @$modules, -default => &{ shift(@$modules) } if ( ref( $modules->[0] ) eq 'CODE' ); # XXX: bugward combatability while ( my ( $mod, $arg ) = splice( @$modules, 0, 2 ) ) { if ( $mod =~ m/^-(\w+)$/ ) { my $option = lc($1); $default = $arg if ( $option eq 'default' ); $conflict = $arg if ( $option eq 'conflict' ); @tests = @{$arg} if ( $option eq 'tests' ); @skiptests = @{$arg} if ( $option eq 'skiptests' ); next; } printf( "- %-${maxlen}s ...", $mod ); if ( $arg and $arg =~ /^\D/ ) { unshift @$modules, $arg; $arg = 0; } # XXX: check for conflicts and uninstalls(!) them. my $cur = _version_of($mod); if (_version_cmp ($cur, $arg) >= 0) { print "loaded. ($cur" . ( $arg ? " >= $arg" : '' ) . ")\n"; push @Existing, $mod => $arg; $DisabledTests{$_} = 1 for map { glob($_) } @skiptests; } else { if (not defined $cur) # indeed missing { print "missing." . ( $arg ? " (would need $arg)" : '' ) . "\n"; } else { # no need to check $arg as _version_cmp ($cur, undef) would satisfy >= above print "too old. ($cur < $arg)\n"; } push @required, $mod => $arg; } } next unless @required; my $mandatory = ( $feature eq '-core' or $core_all ); if ( !$SkipInstall and ( $CheckOnly or ($mandatory and $UnderCPAN) or $AllDeps or $InstallDepsTarget or _prompt( qq{==> Auto-install the } . ( @required / 2 ) . ( $mandatory ? ' mandatory' : ' optional' ) . qq{ module(s) from CPAN?}, $default ? 'y' : 'n', ) =~ /^[Yy]/ ) ) { push( @Missing, @required ); $DisabledTests{$_} = 1 for map { glob($_) } @skiptests; } elsif ( !$SkipInstall and $default and $mandatory and _prompt( qq{==> The module(s) are mandatory! Really skip?}, 'n', ) =~ /^[Nn]/ ) { push( @Missing, @required ); $DisabledTests{$_} = 1 for map { glob($_) } @skiptests; } else { $DisabledTests{$_} = 1 for map { glob($_) } @tests; } } if ( @Missing and not( $CheckOnly or $UnderCPAN) ) { require Config; my $make = $Config::Config{make}; if ($InstallDepsTarget) { print "*** To install dependencies type '$make installdeps' or '$make installdeps_notest'.\n"; } else { print "*** Dependencies will be installed the next time you type '$make'.\n"; } # make an educated guess of whether we'll need root permission. print " (You may need to do that as the 'root' user.)\n" if eval '$>'; } print "*** $class configuration finished.\n"; chdir $cwd; # import to main:: no strict 'refs'; *{'main::WriteMakefile'} = \&Write if caller(0) eq 'main'; return (@Existing, @Missing); } sub _running_under { my $thing = shift; print <<"END_MESSAGE"; *** Since we're running under ${thing}, I'll just let it take care of the dependency's installation later. END_MESSAGE return 1; } # Check to see if we are currently running under CPAN.pm and/or CPANPLUS; # if we are, then we simply let it taking care of our dependencies sub _check_lock { return unless @Missing or @_; if ($ENV{PERL5_CPANM_IS_RUNNING}) { return _running_under('cpanminus'); } my $cpan_env = $ENV{PERL5_CPAN_IS_RUNNING}; if ($ENV{PERL5_CPANPLUS_IS_RUNNING}) { return _running_under($cpan_env ? 'CPAN' : 'CPANPLUS'); } require CPAN; if ($CPAN::VERSION > '1.89') { if ($cpan_env) { return _running_under('CPAN'); } return; # CPAN.pm new enough, don't need to check further } # last ditch attempt, this -will- configure CPAN, very sorry _load_cpan(1); # force initialize even though it's already loaded # Find the CPAN lock-file my $lock = MM->catfile( $CPAN::Config->{cpan_home}, ".lock" ); return unless -f $lock; # Check the lock local *LOCK; return unless open(LOCK, $lock); if ( ( $^O eq 'MSWin32' ? _under_cpan() : == getppid() ) and ( $CPAN::Config->{prerequisites_policy} || '' ) ne 'ignore' ) { print <<'END_MESSAGE'; *** Since we're running under CPAN, I'll just let it take care of the dependency's installation later. END_MESSAGE return 1; } close LOCK; return; } sub install { my $class = shift; my $i; # used below to strip leading '-' from config keys my @config = ( map { s/^-// if ++$i; $_ } @{ +shift } ); my ( @modules, @installed ); while ( my ( $pkg, $ver ) = splice( @_, 0, 2 ) ) { # grep out those already installed if ( _version_cmp( _version_of($pkg), $ver ) >= 0 ) { push @installed, $pkg; } else { push @modules, $pkg, $ver; } } if ($UpgradeDeps) { push @modules, @installed; @installed = (); } return @installed unless @modules; # nothing to do return @installed if _check_lock(); # defer to the CPAN shell print "*** Installing dependencies...\n"; return unless _connected_to('cpan.org'); my %args = @config; my %failed; local *FAILED; if ( $args{do_once} and open( FAILED, '.#autoinstall.failed' ) ) { while () { chomp; $failed{$_}++ } close FAILED; my @newmod; while ( my ( $k, $v ) = splice( @modules, 0, 2 ) ) { push @newmod, ( $k => $v ) unless $failed{$k}; } @modules = @newmod; } if ( _has_cpanplus() and not $ENV{PERL_AUTOINSTALL_PREFER_CPAN} ) { _install_cpanplus( \@modules, \@config ); } else { _install_cpan( \@modules, \@config ); } print "*** $class installation finished.\n"; # see if we have successfully installed them while ( my ( $pkg, $ver ) = splice( @modules, 0, 2 ) ) { if ( _version_cmp( _version_of($pkg), $ver ) >= 0 ) { push @installed, $pkg; } elsif ( $args{do_once} and open( FAILED, '>> .#autoinstall.failed' ) ) { print FAILED "$pkg\n"; } } close FAILED if $args{do_once}; return @installed; } sub _install_cpanplus { my @modules = @{ +shift }; my @config = _cpanplus_config( @{ +shift } ); my $installed = 0; require CPANPLUS::Backend; my $cp = CPANPLUS::Backend->new; my $conf = $cp->configure_object; return unless $conf->can('conf') # 0.05x+ with "sudo" support or _can_write($conf->_get_build('base')); # 0.04x # if we're root, set UNINST=1 to avoid trouble unless user asked for it. my $makeflags = $conf->get_conf('makeflags') || ''; if ( UNIVERSAL::isa( $makeflags, 'HASH' ) ) { # 0.03+ uses a hashref here $makeflags->{UNINST} = 1 unless exists $makeflags->{UNINST}; } else { # 0.02 and below uses a scalar $makeflags = join( ' ', split( ' ', $makeflags ), 'UNINST=1' ) if ( $makeflags !~ /\bUNINST\b/ and eval qq{ $> eq '0' } ); } $conf->set_conf( makeflags => $makeflags ); $conf->set_conf( prereqs => 1 ); while ( my ( $key, $val ) = splice( @config, 0, 2 ) ) { $conf->set_conf( $key, $val ); } my $modtree = $cp->module_tree; while ( my ( $pkg, $ver ) = splice( @modules, 0, 2 ) ) { print "*** Installing $pkg...\n"; MY::preinstall( $pkg, $ver ) or next if defined &MY::preinstall; my $success; my $obj = $modtree->{$pkg}; if ( $obj and _version_cmp( $obj->{version}, $ver ) >= 0 ) { my $pathname = $pkg; $pathname =~ s/::/\\W/; foreach my $inc ( grep { m/$pathname.pm/i } keys(%INC) ) { delete $INC{$inc}; } my $rv = $cp->install( modules => [ $obj->{module} ] ); if ( $rv and ( $rv->{ $obj->{module} } or $rv->{ok} ) ) { print "*** $pkg successfully installed.\n"; $success = 1; } else { print "*** $pkg installation cancelled.\n"; $success = 0; } $installed += $success; } else { print << "."; *** Could not find a version $ver or above for $pkg; skipping. . } MY::postinstall( $pkg, $ver, $success ) if defined &MY::postinstall; } return $installed; } sub _cpanplus_config { my @config = (); while ( @_ ) { my ($key, $value) = (shift(), shift()); if ( $key eq 'prerequisites_policy' ) { if ( $value eq 'follow' ) { $value = CPANPLUS::Internals::Constants::PREREQ_INSTALL(); } elsif ( $value eq 'ask' ) { $value = CPANPLUS::Internals::Constants::PREREQ_ASK(); } elsif ( $value eq 'ignore' ) { $value = CPANPLUS::Internals::Constants::PREREQ_IGNORE(); } else { die "*** Cannot convert option $key = '$value' to CPANPLUS version.\n"; } push @config, 'prereqs', $value; } elsif ( $key eq 'force' ) { push @config, $key, $value; } elsif ( $key eq 'notest' ) { push @config, 'skiptest', $value; } else { die "*** Cannot convert option $key to CPANPLUS version.\n"; } } return @config; } sub _install_cpan { my @modules = @{ +shift }; my @config = @{ +shift }; my $installed = 0; my %args; _load_cpan(); require Config; if (CPAN->VERSION < 1.80) { # no "sudo" support, probe for writableness return unless _can_write( MM->catfile( $CPAN::Config->{cpan_home}, 'sources' ) ) and _can_write( $Config::Config{sitelib} ); } # if we're root, set UNINST=1 to avoid trouble unless user asked for it. my $makeflags = $CPAN::Config->{make_install_arg} || ''; $CPAN::Config->{make_install_arg} = join( ' ', split( ' ', $makeflags ), 'UNINST=1' ) if ( $makeflags !~ /\bUNINST\b/ and eval qq{ $> eq '0' } ); # don't show start-up info $CPAN::Config->{inhibit_startup_message} = 1; # set additional options while ( my ( $opt, $arg ) = splice( @config, 0, 2 ) ) { ( $args{$opt} = $arg, next ) if $opt =~ /^(?:force|notest)$/; # pseudo-option $CPAN::Config->{$opt} = $arg; } if ($args{notest} && (not CPAN::Shell->can('notest'))) { die "Your version of CPAN is too old to support the 'notest' pragma"; } local $CPAN::Config->{prerequisites_policy} = 'follow'; while ( my ( $pkg, $ver ) = splice( @modules, 0, 2 ) ) { MY::preinstall( $pkg, $ver ) or next if defined &MY::preinstall; print "*** Installing $pkg...\n"; my $obj = CPAN::Shell->expand( Module => $pkg ); my $success = 0; if ( $obj and _version_cmp( $obj->cpan_version, $ver ) >= 0 ) { my $pathname = $pkg; $pathname =~ s/::/\\W/; foreach my $inc ( grep { m/$pathname.pm/i } keys(%INC) ) { delete $INC{$inc}; } my $rv = do { if ($args{force}) { CPAN::Shell->force( install => $pkg ) } elsif ($args{notest}) { CPAN::Shell->notest( install => $pkg ) } else { CPAN::Shell->install($pkg) } }; $rv ||= eval { $CPAN::META->instance( 'CPAN::Distribution', $obj->cpan_file, ) ->{install} if $CPAN::META; }; if ( $rv eq 'YES' ) { print "*** $pkg successfully installed.\n"; $success = 1; } else { print "*** $pkg installation failed.\n"; $success = 0; } $installed += $success; } else { print << "."; *** Could not find a version $ver or above for $pkg; skipping. . } MY::postinstall( $pkg, $ver, $success ) if defined &MY::postinstall; } return $installed; } sub _has_cpanplus { return ( $HasCPANPLUS = ( $INC{'CPANPLUS/Config.pm'} or _load('CPANPLUS::Shell::Default') ) ); } # make guesses on whether we're under the CPAN installation directory sub _under_cpan { require Cwd; require File::Spec; my $cwd = File::Spec->canonpath( Cwd::cwd() ); my $cpan = File::Spec->canonpath( $CPAN::Config->{cpan_home} ); return ( index( $cwd, $cpan ) > -1 ); } sub _update_to { my $class = __PACKAGE__; my $ver = shift; return if _version_cmp( _version_of($class), $ver ) >= 0; # no need to upgrade if ( _prompt( "==> A newer version of $class ($ver) is required. Install?", 'y' ) =~ /^[Nn]/ ) { die "*** Please install $class $ver manually.\n"; } print << "."; *** Trying to fetch it from CPAN... . # install ourselves _load($class) and return $class->import(@_) if $class->install( [], $class, $ver ); print << '.'; exit 1; *** Cannot bootstrap myself. :-( Installation terminated. . } # check if we're connected to some host, using inet_aton sub _connected_to { my $site = shift; return ( ( _load('Socket') and Socket::inet_aton($site) ) or _prompt( qq( *** Your host cannot resolve the domain name '$site', which probably means the Internet connections are unavailable. ==> Should we try to install the required module(s) anyway?), 'n' ) =~ /^[Yy]/ ); } # check if a directory is writable; may create it on demand sub _can_write { my $path = shift; mkdir( $path, 0755 ) unless -e $path; return 1 if -w $path; print << "."; *** You are not allowed to write to the directory '$path'; the installation may fail due to insufficient permissions. . if ( eval '$>' and lc(`sudo -V`) =~ /version/ and _prompt( qq( ==> Should we try to re-execute the autoinstall process with 'sudo'?), ((-t STDIN) ? 'y' : 'n') ) =~ /^[Yy]/ ) { # try to bootstrap ourselves from sudo print << "."; *** Trying to re-execute the autoinstall process with 'sudo'... . my $missing = join( ',', @Missing ); my $config = join( ',', UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config} ) if $Config; return unless system( 'sudo', $^X, $0, "--config=$config", "--installdeps=$missing" ); print << "."; *** The 'sudo' command exited with error! Resuming... . } return _prompt( qq( ==> Should we try to install the required module(s) anyway?), 'n' ) =~ /^[Yy]/; } # load a module and return the version it reports sub _load { my $mod = pop; # method/function doesn't matter my $file = $mod; $file =~ s|::|/|g; $file .= '.pm'; local $@; return eval { require $file; $mod->VERSION } || ( $@ ? undef: 0 ); } # report version without loading a module sub _version_of { my $mod = pop; # method/function doesn't matter my $file = $mod; $file =~ s|::|/|g; $file .= '.pm'; foreach my $dir ( @INC ) { next if ref $dir; my $path = File::Spec->catfile($dir, $file); next unless -e $path; require ExtUtils::MM_Unix; return ExtUtils::MM_Unix->parse_version($path); } return undef; } # Load CPAN.pm and it's configuration sub _load_cpan { return if $CPAN::VERSION and $CPAN::Config and not @_; require CPAN; # CPAN-1.82+ adds CPAN::Config::AUTOLOAD to redirect to # CPAN::HandleConfig->load. CPAN reports that the redirection # is deprecated in a warning printed at the user. # CPAN-1.81 expects CPAN::HandleConfig->load, does not have # $CPAN::HandleConfig::VERSION but cannot handle # CPAN::Config->load # Which "versions expect CPAN::Config->load? if ( $CPAN::HandleConfig::VERSION || CPAN::HandleConfig->can('load') ) { # Newer versions of CPAN have a HandleConfig module CPAN::HandleConfig->load; } else { # Older versions had the load method in Config directly CPAN::Config->load; } } # compare two versions, either use Sort::Versions or plain comparison # return values same as <=> sub _version_cmp { my ( $cur, $min ) = @_; return -1 unless defined $cur; # if 0 keep comparing return 1 unless $min; $cur =~ s/\s+$//; # check for version numbers that are not in decimal format if ( ref($cur) or ref($min) or $cur =~ /v|\..*\./ or $min =~ /v|\..*\./ ) { if ( ( $version::VERSION or defined( _load('version') )) and version->can('new') ) { # use version.pm if it is installed. return version->new($cur) <=> version->new($min); } elsif ( $Sort::Versions::VERSION or defined( _load('Sort::Versions') ) ) { # use Sort::Versions as the sorting algorithm for a.b.c versions return Sort::Versions::versioncmp( $cur, $min ); } warn "Cannot reliably compare non-decimal formatted versions.\n" . "Please install version.pm or Sort::Versions.\n"; } # plain comparison local $^W = 0; # shuts off 'not numeric' bugs return $cur <=> $min; } # nothing; this usage is deprecated. sub main::PREREQ_PM { return {}; } sub _make_args { my %args = @_; $args{PREREQ_PM} = { %{ $args{PREREQ_PM} || {} }, @Existing, @Missing } if $UnderCPAN or $TestOnly; if ( $args{EXE_FILES} and -e 'MANIFEST' ) { require ExtUtils::Manifest; my $manifest = ExtUtils::Manifest::maniread('MANIFEST'); $args{EXE_FILES} = [ grep { exists $manifest->{$_} } @{ $args{EXE_FILES} } ]; } $args{test}{TESTS} ||= 't/*.t'; $args{test}{TESTS} = join( ' ', grep { !exists( $DisabledTests{$_} ) } map { glob($_) } split( /\s+/, $args{test}{TESTS} ) ); my $missing = join( ',', @Missing ); my $config = join( ',', UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config} ) if $Config; $PostambleActions = ( ($missing and not $UnderCPAN) ? "\$(PERL) $0 --config=$config --installdeps=$missing" : "\$(NOECHO) \$(NOOP)" ); my $deps_list = join( ',', @Missing, @Existing ); $PostambleActionsUpgradeDeps = "\$(PERL) $0 --config=$config --upgradedeps=$deps_list"; my $config_notest = join( ',', (UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config}), 'notest', 1 ) if $Config; $PostambleActionsNoTest = ( ($missing and not $UnderCPAN) ? "\$(PERL) $0 --config=$config_notest --installdeps=$missing" : "\$(NOECHO) \$(NOOP)" ); $PostambleActionsUpgradeDepsNoTest = "\$(PERL) $0 --config=$config_notest --upgradedeps=$deps_list"; $PostambleActionsListDeps = '@$(PERL) -le "print for @ARGV" ' . join(' ', map $Missing[$_], grep $_ % 2 == 0, 0..$#Missing); my @all = (@Missing, @Existing); $PostambleActionsListAllDeps = '@$(PERL) -le "print for @ARGV" ' . join(' ', map $all[$_], grep $_ % 2 == 0, 0..$#all); return %args; } # a wrapper to ExtUtils::MakeMaker::WriteMakefile sub Write { require Carp; Carp::croak "WriteMakefile: Need even number of args" if @_ % 2; if ($CheckOnly) { print << "."; *** Makefile not written in check-only mode. . return; } my %args = _make_args(@_); no strict 'refs'; $PostambleUsed = 0; local *MY::postamble = \&postamble unless defined &MY::postamble; ExtUtils::MakeMaker::WriteMakefile(%args); print << "." unless $PostambleUsed; *** WARNING: Makefile written with customized MY::postamble() without including contents from Module::AutoInstall::postamble() -- auto installation features disabled. Please contact the author. . return 1; } sub postamble { $PostambleUsed = 1; my $fragment; $fragment .= <<"AUTO_INSTALL" if !$InstallDepsTarget; config :: installdeps \t\$(NOECHO) \$(NOOP) AUTO_INSTALL $fragment .= <<"END_MAKE"; checkdeps :: \t\$(PERL) $0 --checkdeps installdeps :: \t$PostambleActions installdeps_notest :: \t$PostambleActionsNoTest upgradedeps :: \t$PostambleActionsUpgradeDeps upgradedeps_notest :: \t$PostambleActionsUpgradeDepsNoTest listdeps :: \t$PostambleActionsListDeps listalldeps :: \t$PostambleActionsListAllDeps END_MAKE return $fragment; } 1; __END__ #line 1193 libmonitoring-availability-perl-0.46/inc/Module/Install.pm000066400000000000000000000301351242301703500236700ustar00rootroot00000000000000#line 1 package Module::Install; # For any maintainers: # The load order for Module::Install is a bit magic. # It goes something like this... # # IF ( host has Module::Install installed, creating author mode ) { # 1. Makefile.PL calls "use inc::Module::Install" # 2. $INC{inc/Module/Install.pm} set to installed version of inc::Module::Install # 3. The installed version of inc::Module::Install loads # 4. inc::Module::Install calls "require Module::Install" # 5. The ./inc/ version of Module::Install loads # } ELSE { # 1. Makefile.PL calls "use inc::Module::Install" # 2. $INC{inc/Module/Install.pm} set to ./inc/ version of Module::Install # 3. The ./inc/ version of Module::Install loads # } use 5.005; use strict 'vars'; use Cwd (); use File::Find (); use File::Path (); use vars qw{$VERSION $MAIN}; BEGIN { # All Module::Install core packages now require synchronised versions. # This will be used to ensure we don't accidentally load old or # different versions of modules. # This is not enforced yet, but will be some time in the next few # releases once we can make sure it won't clash with custom # Module::Install extensions. $VERSION = '1.06'; # Storage for the pseudo-singleton $MAIN = undef; *inc::Module::Install::VERSION = *VERSION; @inc::Module::Install::ISA = __PACKAGE__; } sub import { my $class = shift; my $self = $class->new(@_); my $who = $self->_caller; #------------------------------------------------------------- # all of the following checks should be included in import(), # to allow "eval 'require Module::Install; 1' to test # installation of Module::Install. (RT #51267) #------------------------------------------------------------- # Whether or not inc::Module::Install is actually loaded, the # $INC{inc/Module/Install.pm} is what will still get set as long as # the caller loaded module this in the documented manner. # If not set, the caller may NOT have loaded the bundled version, and thus # they may not have a MI version that works with the Makefile.PL. This would # result in false errors or unexpected behaviour. And we don't want that. my $file = join( '/', 'inc', split /::/, __PACKAGE__ ) . '.pm'; unless ( $INC{$file} ) { die <<"END_DIE" } Please invoke ${\__PACKAGE__} with: use inc::${\__PACKAGE__}; not: use ${\__PACKAGE__}; END_DIE # This reportedly fixes a rare Win32 UTC file time issue, but # as this is a non-cross-platform XS module not in the core, # we shouldn't really depend on it. See RT #24194 for detail. # (Also, this module only supports Perl 5.6 and above). eval "use Win32::UTCFileTime" if $^O eq 'MSWin32' && $] >= 5.006; # If the script that is loading Module::Install is from the future, # then make will detect this and cause it to re-run over and over # again. This is bad. Rather than taking action to touch it (which # is unreliable on some platforms and requires write permissions) # for now we should catch this and refuse to run. if ( -f $0 ) { my $s = (stat($0))[9]; # If the modification time is only slightly in the future, # sleep briefly to remove the problem. my $a = $s - time; if ( $a > 0 and $a < 5 ) { sleep 5 } # Too far in the future, throw an error. my $t = time; if ( $s > $t ) { die <<"END_DIE" } Your installer $0 has a modification time in the future ($s > $t). This is known to create infinite loops in make. Please correct this, then run $0 again. END_DIE } # Build.PL was formerly supported, but no longer is due to excessive # difficulty in implementing every single feature twice. if ( $0 =~ /Build.PL$/i ) { die <<"END_DIE" } Module::Install no longer supports Build.PL. It was impossible to maintain duel backends, and has been deprecated. Please remove all Build.PL files and only use the Makefile.PL installer. END_DIE #------------------------------------------------------------- # To save some more typing in Module::Install installers, every... # use inc::Module::Install # ...also acts as an implicit use strict. $^H |= strict::bits(qw(refs subs vars)); #------------------------------------------------------------- unless ( -f $self->{file} ) { foreach my $key (keys %INC) { delete $INC{$key} if $key =~ /Module\/Install/; } local $^W; require "$self->{path}/$self->{dispatch}.pm"; File::Path::mkpath("$self->{prefix}/$self->{author}"); $self->{admin} = "$self->{name}::$self->{dispatch}"->new( _top => $self ); $self->{admin}->init; @_ = ($class, _self => $self); goto &{"$self->{name}::import"}; } local $^W; *{"${who}::AUTOLOAD"} = $self->autoload; $self->preload; # Unregister loader and worker packages so subdirs can use them again delete $INC{'inc/Module/Install.pm'}; delete $INC{'Module/Install.pm'}; # Save to the singleton $MAIN = $self; return 1; } sub autoload { my $self = shift; my $who = $self->_caller; my $cwd = Cwd::cwd(); my $sym = "${who}::AUTOLOAD"; $sym->{$cwd} = sub { my $pwd = Cwd::cwd(); if ( my $code = $sym->{$pwd} ) { # Delegate back to parent dirs goto &$code unless $cwd eq $pwd; } unless ($$sym =~ s/([^:]+)$//) { # XXX: it looks like we can't retrieve the missing function # via $$sym (usually $main::AUTOLOAD) in this case. # I'm still wondering if we should slurp Makefile.PL to # get some context or not ... my ($package, $file, $line) = caller; die <<"EOT"; Unknown function is found at $file line $line. Execution of $file aborted due to runtime errors. If you're a contributor to a project, you may need to install some Module::Install extensions from CPAN (or other repository). If you're a user of a module, please contact the author. EOT } my $method = $1; if ( uc($method) eq $method ) { # Do nothing return; } elsif ( $method =~ /^_/ and $self->can($method) ) { # Dispatch to the root M:I class return $self->$method(@_); } # Dispatch to the appropriate plugin unshift @_, ( $self, $1 ); goto &{$self->can('call')}; }; } sub preload { my $self = shift; unless ( $self->{extensions} ) { $self->load_extensions( "$self->{prefix}/$self->{path}", $self ); } my @exts = @{$self->{extensions}}; unless ( @exts ) { @exts = $self->{admin}->load_all_extensions; } my %seen; foreach my $obj ( @exts ) { while (my ($method, $glob) = each %{ref($obj) . '::'}) { next unless $obj->can($method); next if $method =~ /^_/; next if $method eq uc($method); $seen{$method}++; } } my $who = $self->_caller; foreach my $name ( sort keys %seen ) { local $^W; *{"${who}::$name"} = sub { ${"${who}::AUTOLOAD"} = "${who}::$name"; goto &{"${who}::AUTOLOAD"}; }; } } sub new { my ($class, %args) = @_; delete $INC{'FindBin.pm'}; { # to suppress the redefine warning local $SIG{__WARN__} = sub {}; require FindBin; } # ignore the prefix on extension modules built from top level. my $base_path = Cwd::abs_path($FindBin::Bin); unless ( Cwd::abs_path(Cwd::cwd()) eq $base_path ) { delete $args{prefix}; } return $args{_self} if $args{_self}; $args{dispatch} ||= 'Admin'; $args{prefix} ||= 'inc'; $args{author} ||= ($^O eq 'VMS' ? '_author' : '.author'); $args{bundle} ||= 'inc/BUNDLES'; $args{base} ||= $base_path; $class =~ s/^\Q$args{prefix}\E:://; $args{name} ||= $class; $args{version} ||= $class->VERSION; unless ( $args{path} ) { $args{path} = $args{name}; $args{path} =~ s!::!/!g; } $args{file} ||= "$args{base}/$args{prefix}/$args{path}.pm"; $args{wrote} = 0; bless( \%args, $class ); } sub call { my ($self, $method) = @_; my $obj = $self->load($method) or return; splice(@_, 0, 2, $obj); goto &{$obj->can($method)}; } sub load { my ($self, $method) = @_; $self->load_extensions( "$self->{prefix}/$self->{path}", $self ) unless $self->{extensions}; foreach my $obj (@{$self->{extensions}}) { return $obj if $obj->can($method); } my $admin = $self->{admin} or die <<"END_DIE"; The '$method' method does not exist in the '$self->{prefix}' path! Please remove the '$self->{prefix}' directory and run $0 again to load it. END_DIE my $obj = $admin->load($method, 1); push @{$self->{extensions}}, $obj; $obj; } sub load_extensions { my ($self, $path, $top) = @_; my $should_reload = 0; unless ( grep { ! ref $_ and lc $_ eq lc $self->{prefix} } @INC ) { unshift @INC, $self->{prefix}; $should_reload = 1; } foreach my $rv ( $self->find_extensions($path) ) { my ($file, $pkg) = @{$rv}; next if $self->{pathnames}{$pkg}; local $@; my $new = eval { local $^W; require $file; $pkg->can('new') }; unless ( $new ) { warn $@ if $@; next; } $self->{pathnames}{$pkg} = $should_reload ? delete $INC{$file} : $INC{$file}; push @{$self->{extensions}}, &{$new}($pkg, _top => $top ); } $self->{extensions} ||= []; } sub find_extensions { my ($self, $path) = @_; my @found; File::Find::find( sub { my $file = $File::Find::name; return unless $file =~ m!^\Q$path\E/(.+)\.pm\Z!is; my $subpath = $1; return if lc($subpath) eq lc($self->{dispatch}); $file = "$self->{path}/$subpath.pm"; my $pkg = "$self->{name}::$subpath"; $pkg =~ s!/!::!g; # If we have a mixed-case package name, assume case has been preserved # correctly. Otherwise, root through the file to locate the case-preserved # version of the package name. if ( $subpath eq lc($subpath) || $subpath eq uc($subpath) ) { my $content = Module::Install::_read($subpath . '.pm'); my $in_pod = 0; foreach ( split //, $content ) { $in_pod = 1 if /^=\w/; $in_pod = 0 if /^=cut/; next if ($in_pod || /^=cut/); # skip pod text next if /^\s*#/; # and comments if ( m/^\s*package\s+($pkg)\s*;/i ) { $pkg = $1; last; } } } push @found, [ $file, $pkg ]; }, $path ) if -d $path; @found; } ##################################################################### # Common Utility Functions sub _caller { my $depth = 0; my $call = caller($depth); while ( $call eq __PACKAGE__ ) { $depth++; $call = caller($depth); } return $call; } # Done in evals to avoid confusing Perl::MinimumVersion eval( $] >= 5.006 ? <<'END_NEW' : <<'END_OLD' ); die $@ if $@; sub _read { local *FH; open( FH, '<', $_[0] ) or die "open($_[0]): $!"; my $string = do { local $/; }; close FH or die "close($_[0]): $!"; return $string; } END_NEW sub _read { local *FH; open( FH, "< $_[0]" ) or die "open($_[0]): $!"; my $string = do { local $/; }; close FH or die "close($_[0]): $!"; return $string; } END_OLD sub _readperl { my $string = Module::Install::_read($_[0]); $string =~ s/(?:\015{1,2}\012|\015|\012)/\n/sg; $string =~ s/(\n)\n*__(?:DATA|END)__\b.*\z/$1/s; $string =~ s/\n\n=\w+.+?\n\n=cut\b.+?\n+/\n\n/sg; return $string; } sub _readpod { my $string = Module::Install::_read($_[0]); $string =~ s/(?:\015{1,2}\012|\015|\012)/\n/sg; return $string if $_[0] =~ /\.pod\z/; $string =~ s/(^|\n=cut\b.+?\n+)[^=\s].+?\n(\n=\w+|\z)/$1$2/sg; $string =~ s/\n*=pod\b[^\n]*\n+/\n\n/sg; $string =~ s/\n*=cut\b[^\n]*\n+/\n\n/sg; $string =~ s/^\n+//s; return $string; } # Done in evals to avoid confusing Perl::MinimumVersion eval( $] >= 5.006 ? <<'END_NEW' : <<'END_OLD' ); die $@ if $@; sub _write { local *FH; open( FH, '>', $_[0] ) or die "open($_[0]): $!"; foreach ( 1 .. $#_ ) { print FH $_[$_] or die "print($_[0]): $!"; } close FH or die "close($_[0]): $!"; } END_NEW sub _write { local *FH; open( FH, "> $_[0]" ) or die "open($_[0]): $!"; foreach ( 1 .. $#_ ) { print FH $_[$_] or die "print($_[0]): $!"; } close FH or die "close($_[0]): $!"; } END_OLD # _version is for processing module versions (eg, 1.03_05) not # Perl versions (eg, 5.8.1). sub _version ($) { my $s = shift || 0; my $d =()= $s =~ /(\.)/g; if ( $d >= 2 ) { # Normalise multipart versions $s =~ s/(\.)(\d{1,3})/sprintf("$1%03d",$2)/eg; } $s =~ s/^(\d+)\.?//; my $l = $1 || 0; my @v = map { $_ . '0' x (3 - length $_) } $s =~ /(\d{1,3})\D?/g; $l = $l . '.' . join '', @v if @v; return $l + 0; } sub _cmp ($$) { _version($_[1]) <=> _version($_[2]); } # Cloned from Params::Util::_CLASS sub _CLASS ($) { ( defined $_[0] and ! ref $_[0] and $_[0] =~ m/^[^\W\d]\w*(?:::\w+)*\z/s ) ? $_[0] : undef; } 1; # Copyright 2008 - 2012 Adam Kennedy. libmonitoring-availability-perl-0.46/inc/Module/Install/000077500000000000000000000000001242301703500233305ustar00rootroot00000000000000libmonitoring-availability-perl-0.46/inc/Module/Install/AutoInstall.pm000066400000000000000000000041621242301703500261300ustar00rootroot00000000000000#line 1 package Module::Install::AutoInstall; use strict; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.06'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } sub AutoInstall { $_[0] } sub run { my $self = shift; $self->auto_install_now(@_); } sub write { my $self = shift; $self->auto_install(@_); } sub auto_install { my $self = shift; return if $self->{done}++; # Flatten array of arrays into a single array my @core = map @$_, map @$_, grep ref, $self->build_requires, $self->requires; my @config = @_; # We'll need Module::AutoInstall $self->include('Module::AutoInstall'); require Module::AutoInstall; my @features_require = Module::AutoInstall->import( (@config ? (-config => \@config) : ()), (@core ? (-core => \@core) : ()), $self->features, ); my %seen; my @requires = map @$_, map @$_, grep ref, $self->requires; while (my ($mod, $ver) = splice(@requires, 0, 2)) { $seen{$mod}{$ver}++; } my @build_requires = map @$_, map @$_, grep ref, $self->build_requires; while (my ($mod, $ver) = splice(@build_requires, 0, 2)) { $seen{$mod}{$ver}++; } my @configure_requires = map @$_, map @$_, grep ref, $self->configure_requires; while (my ($mod, $ver) = splice(@configure_requires, 0, 2)) { $seen{$mod}{$ver}++; } my @deduped; while (my ($mod, $ver) = splice(@features_require, 0, 2)) { push @deduped, $mod => $ver unless $seen{$mod}{$ver}++; } $self->requires(@deduped); $self->makemaker_args( Module::AutoInstall::_make_args() ); my $class = ref($self); $self->postamble( "# --- $class section:\n" . Module::AutoInstall::postamble() ); } sub installdeps_target { my ($self, @args) = @_; $self->include('Module::AutoInstall'); require Module::AutoInstall; Module::AutoInstall::_installdeps_target(1); $self->auto_install(@args); } sub auto_install_now { my $self = shift; $self->auto_install(@_); Module::AutoInstall::do_install(); } 1; libmonitoring-availability-perl-0.46/inc/Module/Install/Base.pm000066400000000000000000000021471242301703500245440ustar00rootroot00000000000000#line 1 package Module::Install::Base; use strict 'vars'; use vars qw{$VERSION}; BEGIN { $VERSION = '1.06'; } # Suspend handler for "redefined" warnings BEGIN { my $w = $SIG{__WARN__}; $SIG{__WARN__} = sub { $w }; } #line 42 sub new { my $class = shift; unless ( defined &{"${class}::call"} ) { *{"${class}::call"} = sub { shift->_top->call(@_) }; } unless ( defined &{"${class}::load"} ) { *{"${class}::load"} = sub { shift->_top->load(@_) }; } bless { @_ }, $class; } #line 61 sub AUTOLOAD { local $@; my $func = eval { shift->_top->autoload } or return; goto &$func; } #line 75 sub _top { $_[0]->{_top}; } #line 90 sub admin { $_[0]->_top->{admin} or Module::Install::Base::FakeAdmin->new; } #line 106 sub is_admin { ! $_[0]->admin->isa('Module::Install::Base::FakeAdmin'); } sub DESTROY {} package Module::Install::Base::FakeAdmin; use vars qw{$VERSION}; BEGIN { $VERSION = $Module::Install::Base::VERSION; } my $fake; sub new { $fake ||= bless(\@_, $_[0]); } sub AUTOLOAD {} sub DESTROY {} # Restore warning handler BEGIN { $SIG{__WARN__} = $SIG{__WARN__}->(); } 1; #line 159 libmonitoring-availability-perl-0.46/inc/Module/Install/Can.pm000066400000000000000000000061571242301703500244000ustar00rootroot00000000000000#line 1 package Module::Install::Can; use strict; use Config (); use ExtUtils::MakeMaker (); use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.06'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } # check if we can load some module ### Upgrade this to not have to load the module if possible sub can_use { my ($self, $mod, $ver) = @_; $mod =~ s{::|\\}{/}g; $mod .= '.pm' unless $mod =~ /\.pm$/i; my $pkg = $mod; $pkg =~ s{/}{::}g; $pkg =~ s{\.pm$}{}i; local $@; eval { require $mod; $pkg->VERSION($ver || 0); 1 }; } # Check if we can run some command sub can_run { my ($self, $cmd) = @_; my $_cmd = $cmd; return $_cmd if (-x $_cmd or $_cmd = MM->maybe_command($_cmd)); for my $dir ((split /$Config::Config{path_sep}/, $ENV{PATH}), '.') { next if $dir eq ''; require File::Spec; my $abs = File::Spec->catfile($dir, $cmd); return $abs if (-x $abs or $abs = MM->maybe_command($abs)); } return; } # Can our C compiler environment build XS files sub can_xs { my $self = shift; # Ensure we have the CBuilder module $self->configure_requires( 'ExtUtils::CBuilder' => 0.27 ); # Do we have the configure_requires checker? local $@; eval "require ExtUtils::CBuilder;"; if ( $@ ) { # They don't obey configure_requires, so it is # someone old and delicate. Try to avoid hurting # them by falling back to an older simpler test. return $self->can_cc(); } # Do we have a working C compiler my $builder = ExtUtils::CBuilder->new( quiet => 1, ); unless ( $builder->have_compiler ) { # No working C compiler return 0; } # Write a C file representative of what XS becomes require File::Temp; my ( $FH, $tmpfile ) = File::Temp::tempfile( "compilexs-XXXXX", SUFFIX => '.c', ); binmode $FH; print $FH <<'END_C'; #include "EXTERN.h" #include "perl.h" #include "XSUB.h" int main(int argc, char **argv) { return 0; } int boot_sanexs() { return 1; } END_C close $FH; # Can the C compiler access the same headers XS does my @libs = (); my $object = undef; eval { local $^W = 0; $object = $builder->compile( source => $tmpfile, ); @libs = $builder->link( objects => $object, module_name => 'sanexs', ); }; my $result = $@ ? 0 : 1; # Clean up all the build files foreach ( $tmpfile, $object, @libs ) { next unless defined $_; 1 while unlink; } return $result; } # Can we locate a (the) C compiler sub can_cc { my $self = shift; my @chunks = split(/ /, $Config::Config{cc}) or return; # $Config{cc} may contain args; try to find out the program part while (@chunks) { return $self->can_run("@chunks") || (pop(@chunks), next); } return; } # Fix Cygwin bug on maybe_command(); if ( $^O eq 'cygwin' ) { require ExtUtils::MM_Cygwin; require ExtUtils::MM_Win32; if ( ! defined(&ExtUtils::MM_Cygwin::maybe_command) ) { *ExtUtils::MM_Cygwin::maybe_command = sub { my ($self, $file) = @_; if ($file =~ m{^/cygdrive/}i and ExtUtils::MM_Win32->can('maybe_command')) { ExtUtils::MM_Win32->maybe_command($file); } else { ExtUtils::MM_Unix->maybe_command($file); } } } } 1; __END__ #line 236 libmonitoring-availability-perl-0.46/inc/Module/Install/Fetch.pm000066400000000000000000000046271242301703500247300ustar00rootroot00000000000000#line 1 package Module::Install::Fetch; use strict; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.06'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } sub get_file { my ($self, %args) = @_; my ($scheme, $host, $path, $file) = $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return; if ( $scheme eq 'http' and ! eval { require LWP::Simple; 1 } ) { $args{url} = $args{ftp_url} or (warn("LWP support unavailable!\n"), return); ($scheme, $host, $path, $file) = $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return; } $|++; print "Fetching '$file' from $host... "; unless (eval { require Socket; Socket::inet_aton($host) }) { warn "'$host' resolve failed!\n"; return; } return unless $scheme eq 'ftp' or $scheme eq 'http'; require Cwd; my $dir = Cwd::getcwd(); chdir $args{local_dir} or return if exists $args{local_dir}; if (eval { require LWP::Simple; 1 }) { LWP::Simple::mirror($args{url}, $file); } elsif (eval { require Net::FTP; 1 }) { eval { # use Net::FTP to get past firewall my $ftp = Net::FTP->new($host, Passive => 1, Timeout => 600); $ftp->login("anonymous", 'anonymous@example.com'); $ftp->cwd($path); $ftp->binary; $ftp->get($file) or (warn("$!\n"), return); $ftp->quit; } } elsif (my $ftp = $self->can_run('ftp')) { eval { # no Net::FTP, fallback to ftp.exe require FileHandle; my $fh = FileHandle->new; local $SIG{CHLD} = 'IGNORE'; unless ($fh->open("|$ftp -n")) { warn "Couldn't open ftp: $!\n"; chdir $dir; return; } my @dialog = split(/\n/, <<"END_FTP"); open $host user anonymous anonymous\@example.com cd $path binary get $file $file quit END_FTP foreach (@dialog) { $fh->print("$_\n") } $fh->close; } } else { warn "No working 'ftp' program available!\n"; chdir $dir; return; } unless (-f $file) { warn "Fetching failed: $@\n"; chdir $dir; return; } return if exists $args{size} and -s $file != $args{size}; system($args{run}) if exists $args{run}; unlink($file) if $args{remove}; print(((!exists $args{check_for} or -e $args{check_for}) ? "done!" : "failed! ($!)"), "\n"); chdir $dir; return !$?; } 1; libmonitoring-availability-perl-0.46/inc/Module/Install/Include.pm000066400000000000000000000010151242301703500252460ustar00rootroot00000000000000#line 1 package Module::Install::Include; use strict; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.06'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } sub include { shift()->admin->include(@_); } sub include_deps { shift()->admin->include_deps(@_); } sub auto_include { shift()->admin->auto_include(@_); } sub auto_include_deps { shift()->admin->auto_include_deps(@_); } sub auto_include_dependent_dists { shift()->admin->auto_include_dependent_dists(@_); } 1; libmonitoring-availability-perl-0.46/inc/Module/Install/Makefile.pm000066400000000000000000000274371242301703500254200ustar00rootroot00000000000000#line 1 package Module::Install::Makefile; use strict 'vars'; use ExtUtils::MakeMaker (); use Module::Install::Base (); use Fcntl qw/:flock :seek/; use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.06'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } sub Makefile { $_[0] } my %seen = (); sub prompt { shift; # Infinite loop protection my @c = caller(); if ( ++$seen{"$c[1]|$c[2]|$_[0]"} > 3 ) { die "Caught an potential prompt infinite loop ($c[1]|$c[2]|$_[0])"; } # In automated testing or non-interactive session, always use defaults if ( ($ENV{AUTOMATED_TESTING} or -! -t STDIN) and ! $ENV{PERL_MM_USE_DEFAULT} ) { local $ENV{PERL_MM_USE_DEFAULT} = 1; goto &ExtUtils::MakeMaker::prompt; } else { goto &ExtUtils::MakeMaker::prompt; } } # Store a cleaned up version of the MakeMaker version, # since we need to behave differently in a variety of # ways based on the MM version. my $makemaker = eval $ExtUtils::MakeMaker::VERSION; # If we are passed a param, do a "newer than" comparison. # Otherwise, just return the MakeMaker version. sub makemaker { ( @_ < 2 or $makemaker >= eval($_[1]) ) ? $makemaker : 0 } # Ripped from ExtUtils::MakeMaker 6.56, and slightly modified # as we only need to know here whether the attribute is an array # or a hash or something else (which may or may not be appendable). my %makemaker_argtype = ( C => 'ARRAY', CONFIG => 'ARRAY', # CONFIGURE => 'CODE', # ignore DIR => 'ARRAY', DL_FUNCS => 'HASH', DL_VARS => 'ARRAY', EXCLUDE_EXT => 'ARRAY', EXE_FILES => 'ARRAY', FUNCLIST => 'ARRAY', H => 'ARRAY', IMPORTS => 'HASH', INCLUDE_EXT => 'ARRAY', LIBS => 'ARRAY', # ignore '' MAN1PODS => 'HASH', MAN3PODS => 'HASH', META_ADD => 'HASH', META_MERGE => 'HASH', PL_FILES => 'HASH', PM => 'HASH', PMLIBDIRS => 'ARRAY', PMLIBPARENTDIRS => 'ARRAY', PREREQ_PM => 'HASH', CONFIGURE_REQUIRES => 'HASH', SKIP => 'ARRAY', TYPEMAPS => 'ARRAY', XS => 'HASH', # VERSION => ['version',''], # ignore # _KEEP_AFTER_FLUSH => '', clean => 'HASH', depend => 'HASH', dist => 'HASH', dynamic_lib=> 'HASH', linkext => 'HASH', macro => 'HASH', postamble => 'HASH', realclean => 'HASH', test => 'HASH', tool_autosplit => 'HASH', # special cases where you can use makemaker_append CCFLAGS => 'APPENDABLE', DEFINE => 'APPENDABLE', INC => 'APPENDABLE', LDDLFLAGS => 'APPENDABLE', LDFROM => 'APPENDABLE', ); sub makemaker_args { my ($self, %new_args) = @_; my $args = ( $self->{makemaker_args} ||= {} ); foreach my $key (keys %new_args) { if ($makemaker_argtype{$key}) { if ($makemaker_argtype{$key} eq 'ARRAY') { $args->{$key} = [] unless defined $args->{$key}; unless (ref $args->{$key} eq 'ARRAY') { $args->{$key} = [$args->{$key}] } push @{$args->{$key}}, ref $new_args{$key} eq 'ARRAY' ? @{$new_args{$key}} : $new_args{$key}; } elsif ($makemaker_argtype{$key} eq 'HASH') { $args->{$key} = {} unless defined $args->{$key}; foreach my $skey (keys %{ $new_args{$key} }) { $args->{$key}{$skey} = $new_args{$key}{$skey}; } } elsif ($makemaker_argtype{$key} eq 'APPENDABLE') { $self->makemaker_append($key => $new_args{$key}); } } else { if (defined $args->{$key}) { warn qq{MakeMaker attribute "$key" is overriden; use "makemaker_append" to append values\n}; } $args->{$key} = $new_args{$key}; } } return $args; } # For mm args that take multiple space-seperated args, # append an argument to the current list. sub makemaker_append { my $self = shift; my $name = shift; my $args = $self->makemaker_args; $args->{$name} = defined $args->{$name} ? join( ' ', $args->{$name}, @_ ) : join( ' ', @_ ); } sub build_subdirs { my $self = shift; my $subdirs = $self->makemaker_args->{DIR} ||= []; for my $subdir (@_) { push @$subdirs, $subdir; } } sub clean_files { my $self = shift; my $clean = $self->makemaker_args->{clean} ||= {}; %$clean = ( %$clean, FILES => join ' ', grep { length $_ } ($clean->{FILES} || (), @_), ); } sub realclean_files { my $self = shift; my $realclean = $self->makemaker_args->{realclean} ||= {}; %$realclean = ( %$realclean, FILES => join ' ', grep { length $_ } ($realclean->{FILES} || (), @_), ); } sub libs { my $self = shift; my $libs = ref $_[0] ? shift : [ shift ]; $self->makemaker_args( LIBS => $libs ); } sub inc { my $self = shift; $self->makemaker_args( INC => shift ); } sub _wanted_t { } sub tests_recursive { my $self = shift; my $dir = shift || 't'; unless ( -d $dir ) { die "tests_recursive dir '$dir' does not exist"; } my %tests = map { $_ => 1 } split / /, ($self->tests || ''); require File::Find; File::Find::find( sub { /\.t$/ and -f $_ and $tests{"$File::Find::dir/*.t"} = 1 }, $dir ); $self->tests( join ' ', sort keys %tests ); } sub write { my $self = shift; die "&Makefile->write() takes no arguments\n" if @_; # Check the current Perl version my $perl_version = $self->perl_version; if ( $perl_version ) { eval "use $perl_version; 1" or die "ERROR: perl: Version $] is installed, " . "but we need version >= $perl_version"; } # Make sure we have a new enough MakeMaker require ExtUtils::MakeMaker; if ( $perl_version and $self->_cmp($perl_version, '5.006') >= 0 ) { # This previous attempted to inherit the version of # ExtUtils::MakeMaker in use by the module author, but this # was found to be untenable as some authors build releases # using future dev versions of EU:MM that nobody else has. # Instead, #toolchain suggests we use 6.59 which is the most # stable version on CPAN at time of writing and is, to quote # ribasushi, "not terminally fucked, > and tested enough". # TODO: We will now need to maintain this over time to push # the version up as new versions are released. $self->build_requires( 'ExtUtils::MakeMaker' => 6.59 ); $self->configure_requires( 'ExtUtils::MakeMaker' => 6.59 ); } else { # Allow legacy-compatibility with 5.005 by depending on the # most recent EU:MM that supported 5.005. $self->build_requires( 'ExtUtils::MakeMaker' => 6.36 ); $self->configure_requires( 'ExtUtils::MakeMaker' => 6.36 ); } # Generate the MakeMaker params my $args = $self->makemaker_args; $args->{DISTNAME} = $self->name; $args->{NAME} = $self->module_name || $self->name; $args->{NAME} =~ s/-/::/g; $args->{VERSION} = $self->version or die <<'EOT'; ERROR: Can't determine distribution version. Please specify it explicitly via 'version' in Makefile.PL, or set a valid $VERSION in a module, and provide its file path via 'version_from' (or 'all_from' if you prefer) in Makefile.PL. EOT if ( $self->tests ) { my @tests = split ' ', $self->tests; my %seen; $args->{test} = { TESTS => (join ' ', grep {!$seen{$_}++} @tests), }; } elsif ( $Module::Install::ExtraTests::use_extratests ) { # Module::Install::ExtraTests doesn't set $self->tests and does its own tests via harness. # So, just ignore our xt tests here. } elsif ( -d 'xt' and ($Module::Install::AUTHOR or $ENV{RELEASE_TESTING}) ) { $args->{test} = { TESTS => join( ' ', map { "$_/*.t" } grep { -d $_ } qw{ t xt } ), }; } if ( $] >= 5.005 ) { $args->{ABSTRACT} = $self->abstract; $args->{AUTHOR} = join ', ', @{$self->author || []}; } if ( $self->makemaker(6.10) ) { $args->{NO_META} = 1; #$args->{NO_MYMETA} = 1; } if ( $self->makemaker(6.17) and $self->sign ) { $args->{SIGN} = 1; } unless ( $self->is_admin ) { delete $args->{SIGN}; } if ( $self->makemaker(6.31) and $self->license ) { $args->{LICENSE} = $self->license; } my $prereq = ($args->{PREREQ_PM} ||= {}); %$prereq = ( %$prereq, map { @$_ } # flatten [module => version] map { @$_ } grep $_, ($self->requires) ); # Remove any reference to perl, PREREQ_PM doesn't support it delete $args->{PREREQ_PM}->{perl}; # Merge both kinds of requires into BUILD_REQUIRES my $build_prereq = ($args->{BUILD_REQUIRES} ||= {}); %$build_prereq = ( %$build_prereq, map { @$_ } # flatten [module => version] map { @$_ } grep $_, ($self->configure_requires, $self->build_requires) ); # Remove any reference to perl, BUILD_REQUIRES doesn't support it delete $args->{BUILD_REQUIRES}->{perl}; # Delete bundled dists from prereq_pm, add it to Makefile DIR my $subdirs = ($args->{DIR} || []); if ($self->bundles) { my %processed; foreach my $bundle (@{ $self->bundles }) { my ($mod_name, $dist_dir) = @$bundle; delete $prereq->{$mod_name}; $dist_dir = File::Basename::basename($dist_dir); # dir for building this module if (not exists $processed{$dist_dir}) { if (-d $dist_dir) { # List as sub-directory to be processed by make push @$subdirs, $dist_dir; } # Else do nothing: the module is already present on the system $processed{$dist_dir} = undef; } } } unless ( $self->makemaker('6.55_03') ) { %$prereq = (%$prereq,%$build_prereq); delete $args->{BUILD_REQUIRES}; } if ( my $perl_version = $self->perl_version ) { eval "use $perl_version; 1" or die "ERROR: perl: Version $] is installed, " . "but we need version >= $perl_version"; if ( $self->makemaker(6.48) ) { $args->{MIN_PERL_VERSION} = $perl_version; } } if ($self->installdirs) { warn qq{old INSTALLDIRS (probably set by makemaker_args) is overriden by installdirs\n} if $args->{INSTALLDIRS}; $args->{INSTALLDIRS} = $self->installdirs; } my %args = map { ( $_ => $args->{$_} ) } grep {defined($args->{$_} ) } keys %$args; my $user_preop = delete $args{dist}->{PREOP}; if ( my $preop = $self->admin->preop($user_preop) ) { foreach my $key ( keys %$preop ) { $args{dist}->{$key} = $preop->{$key}; } } my $mm = ExtUtils::MakeMaker::WriteMakefile(%args); $self->fix_up_makefile($mm->{FIRST_MAKEFILE} || 'Makefile'); } sub fix_up_makefile { my $self = shift; my $makefile_name = shift; my $top_class = ref($self->_top) || ''; my $top_version = $self->_top->VERSION || ''; my $preamble = $self->preamble ? "# Preamble by $top_class $top_version\n" . $self->preamble : ''; my $postamble = "# Postamble by $top_class $top_version\n" . ($self->postamble || ''); local *MAKEFILE; open MAKEFILE, "+< $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!"; eval { flock MAKEFILE, LOCK_EX }; my $makefile = do { local $/; }; $makefile =~ s/\b(test_harness\(\$\(TEST_VERBOSE\), )/$1'inc', /; $makefile =~ s/( -I\$\(INST_ARCHLIB\))/ -Iinc$1/g; $makefile =~ s/( "-I\$\(INST_LIB\)")/ "-Iinc"$1/g; $makefile =~ s/^(FULLPERL = .*)/$1 "-Iinc"/m; $makefile =~ s/^(PERL = .*)/$1 "-Iinc"/m; # Module::Install will never be used to build the Core Perl # Sometimes PERL_LIB and PERL_ARCHLIB get written anyway, which breaks # PREFIX/PERL5LIB, and thus, install_share. Blank them if they exist $makefile =~ s/^PERL_LIB = .+/PERL_LIB =/m; #$makefile =~ s/^PERL_ARCHLIB = .+/PERL_ARCHLIB =/m; # Perl 5.005 mentions PERL_LIB explicitly, so we have to remove that as well. $makefile =~ s/(\"?)-I\$\(PERL_LIB\)\1//g; # XXX - This is currently unused; not sure if it breaks other MM-users # $makefile =~ s/^pm_to_blib\s+:\s+/pm_to_blib :: /mg; seek MAKEFILE, 0, SEEK_SET; truncate MAKEFILE, 0; print MAKEFILE "$preamble$makefile$postamble" or die $!; close MAKEFILE or die $!; 1; } sub preamble { my ($self, $text) = @_; $self->{preamble} = $text . $self->{preamble} if defined $text; $self->{preamble}; } sub postamble { my ($self, $text) = @_; $self->{postamble} ||= $self->admin->postamble; $self->{postamble} .= $text if defined $text; $self->{postamble} } 1; __END__ #line 544 libmonitoring-availability-perl-0.46/inc/Module/Install/Metadata.pm000066400000000000000000000432771242301703500254230ustar00rootroot00000000000000#line 1 package Module::Install::Metadata; use strict 'vars'; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.06'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } my @boolean_keys = qw{ sign }; my @scalar_keys = qw{ name module_name abstract version distribution_type tests installdirs }; my @tuple_keys = qw{ configure_requires build_requires requires recommends bundles resources }; my @resource_keys = qw{ homepage bugtracker repository }; my @array_keys = qw{ keywords author }; *authors = \&author; sub Meta { shift } sub Meta_BooleanKeys { @boolean_keys } sub Meta_ScalarKeys { @scalar_keys } sub Meta_TupleKeys { @tuple_keys } sub Meta_ResourceKeys { @resource_keys } sub Meta_ArrayKeys { @array_keys } foreach my $key ( @boolean_keys ) { *$key = sub { my $self = shift; if ( defined wantarray and not @_ ) { return $self->{values}->{$key}; } $self->{values}->{$key} = ( @_ ? $_[0] : 1 ); return $self; }; } foreach my $key ( @scalar_keys ) { *$key = sub { my $self = shift; return $self->{values}->{$key} if defined wantarray and !@_; $self->{values}->{$key} = shift; return $self; }; } foreach my $key ( @array_keys ) { *$key = sub { my $self = shift; return $self->{values}->{$key} if defined wantarray and !@_; $self->{values}->{$key} ||= []; push @{$self->{values}->{$key}}, @_; return $self; }; } foreach my $key ( @resource_keys ) { *$key = sub { my $self = shift; unless ( @_ ) { return () unless $self->{values}->{resources}; return map { $_->[1] } grep { $_->[0] eq $key } @{ $self->{values}->{resources} }; } return $self->{values}->{resources}->{$key} unless @_; my $uri = shift or die( "Did not provide a value to $key()" ); $self->resources( $key => $uri ); return 1; }; } foreach my $key ( grep { $_ ne "resources" } @tuple_keys) { *$key = sub { my $self = shift; return $self->{values}->{$key} unless @_; my @added; while ( @_ ) { my $module = shift or last; my $version = shift || 0; push @added, [ $module, $version ]; } push @{ $self->{values}->{$key} }, @added; return map {@$_} @added; }; } # Resource handling my %lc_resource = map { $_ => 1 } qw{ homepage license bugtracker repository }; sub resources { my $self = shift; while ( @_ ) { my $name = shift or last; my $value = shift or next; if ( $name eq lc $name and ! $lc_resource{$name} ) { die("Unsupported reserved lowercase resource '$name'"); } $self->{values}->{resources} ||= []; push @{ $self->{values}->{resources} }, [ $name, $value ]; } $self->{values}->{resources}; } # Aliases for build_requires that will have alternative # meanings in some future version of META.yml. sub test_requires { shift->build_requires(@_) } sub install_requires { shift->build_requires(@_) } # Aliases for installdirs options sub install_as_core { $_[0]->installdirs('perl') } sub install_as_cpan { $_[0]->installdirs('site') } sub install_as_site { $_[0]->installdirs('site') } sub install_as_vendor { $_[0]->installdirs('vendor') } sub dynamic_config { my $self = shift; my $value = @_ ? shift : 1; if ( $self->{values}->{dynamic_config} ) { # Once dynamic we never change to static, for safety return 0; } $self->{values}->{dynamic_config} = $value ? 1 : 0; return 1; } # Convenience command sub static_config { shift->dynamic_config(0); } sub perl_version { my $self = shift; return $self->{values}->{perl_version} unless @_; my $version = shift or die( "Did not provide a value to perl_version()" ); # Normalize the version $version = $self->_perl_version($version); # We don't support the really old versions unless ( $version >= 5.005 ) { die "Module::Install only supports 5.005 or newer (use ExtUtils::MakeMaker)\n"; } $self->{values}->{perl_version} = $version; } sub all_from { my ( $self, $file ) = @_; unless ( defined($file) ) { my $name = $self->name or die( "all_from called with no args without setting name() first" ); $file = join('/', 'lib', split(/-/, $name)) . '.pm'; $file =~ s{.*/}{} unless -e $file; unless ( -e $file ) { die("all_from cannot find $file from $name"); } } unless ( -f $file ) { die("The path '$file' does not exist, or is not a file"); } $self->{values}{all_from} = $file; # Some methods pull from POD instead of code. # If there is a matching .pod, use that instead my $pod = $file; $pod =~ s/\.pm$/.pod/i; $pod = $file unless -e $pod; # Pull the different values $self->name_from($file) unless $self->name; $self->version_from($file) unless $self->version; $self->perl_version_from($file) unless $self->perl_version; $self->author_from($pod) unless @{$self->author || []}; $self->license_from($pod) unless $self->license; $self->abstract_from($pod) unless $self->abstract; return 1; } sub provides { my $self = shift; my $provides = ( $self->{values}->{provides} ||= {} ); %$provides = (%$provides, @_) if @_; return $provides; } sub auto_provides { my $self = shift; return $self unless $self->is_admin; unless (-e 'MANIFEST') { warn "Cannot deduce auto_provides without a MANIFEST, skipping\n"; return $self; } # Avoid spurious warnings as we are not checking manifest here. local $SIG{__WARN__} = sub {1}; require ExtUtils::Manifest; local *ExtUtils::Manifest::manicheck = sub { return }; require Module::Build; my $build = Module::Build->new( dist_name => $self->name, dist_version => $self->version, license => $self->license, ); $self->provides( %{ $build->find_dist_packages || {} } ); } sub feature { my $self = shift; my $name = shift; my $features = ( $self->{values}->{features} ||= [] ); my $mods; if ( @_ == 1 and ref( $_[0] ) ) { # The user used ->feature like ->features by passing in the second # argument as a reference. Accomodate for that. $mods = $_[0]; } else { $mods = \@_; } my $count = 0; push @$features, ( $name => [ map { ref($_) ? ( ref($_) eq 'HASH' ) ? %$_ : @$_ : $_ } @$mods ] ); return @$features; } sub features { my $self = shift; while ( my ( $name, $mods ) = splice( @_, 0, 2 ) ) { $self->feature( $name, @$mods ); } return $self->{values}->{features} ? @{ $self->{values}->{features} } : (); } sub no_index { my $self = shift; my $type = shift; push @{ $self->{values}->{no_index}->{$type} }, @_ if $type; return $self->{values}->{no_index}; } sub read { my $self = shift; $self->include_deps( 'YAML::Tiny', 0 ); require YAML::Tiny; my $data = YAML::Tiny::LoadFile('META.yml'); # Call methods explicitly in case user has already set some values. while ( my ( $key, $value ) = each %$data ) { next unless $self->can($key); if ( ref $value eq 'HASH' ) { while ( my ( $module, $version ) = each %$value ) { $self->can($key)->($self, $module => $version ); } } else { $self->can($key)->($self, $value); } } return $self; } sub write { my $self = shift; return $self unless $self->is_admin; $self->admin->write_meta; return $self; } sub version_from { require ExtUtils::MM_Unix; my ( $self, $file ) = @_; $self->version( ExtUtils::MM_Unix->parse_version($file) ); # for version integrity check $self->makemaker_args( VERSION_FROM => $file ); } sub abstract_from { require ExtUtils::MM_Unix; my ( $self, $file ) = @_; $self->abstract( bless( { DISTNAME => $self->name }, 'ExtUtils::MM_Unix' )->parse_abstract($file) ); } # Add both distribution and module name sub name_from { my ($self, $file) = @_; if ( Module::Install::_read($file) =~ m/ ^ \s* package \s* ([\w:]+) \s* ; /ixms ) { my ($name, $module_name) = ($1, $1); $name =~ s{::}{-}g; $self->name($name); unless ( $self->module_name ) { $self->module_name($module_name); } } else { die("Cannot determine name from $file\n"); } } sub _extract_perl_version { if ( $_[0] =~ m/ ^\s* (?:use|require) \s* v? ([\d_\.]+) \s* ; /ixms ) { my $perl_version = $1; $perl_version =~ s{_}{}g; return $perl_version; } else { return; } } sub perl_version_from { my $self = shift; my $perl_version=_extract_perl_version(Module::Install::_read($_[0])); if ($perl_version) { $self->perl_version($perl_version); } else { warn "Cannot determine perl version info from $_[0]\n"; return; } } sub author_from { my $self = shift; my $content = Module::Install::_read($_[0]); if ($content =~ m/ =head \d \s+ (?:authors?)\b \s* ([^\n]*) | =head \d \s+ (?:licen[cs]e|licensing|copyright|legal)\b \s* .*? copyright .*? \d\d\d[\d.]+ \s* (?:\bby\b)? \s* ([^\n]*) /ixms) { my $author = $1 || $2; # XXX: ugly but should work anyway... if (eval "require Pod::Escapes; 1") { # Pod::Escapes has a mapping table. # It's in core of perl >= 5.9.3, and should be installed # as one of the Pod::Simple's prereqs, which is a prereq # of Pod::Text 3.x (see also below). $author =~ s{ E<( (\d+) | ([A-Za-z]+) )> } { defined $2 ? chr($2) : defined $Pod::Escapes::Name2character_number{$1} ? chr($Pod::Escapes::Name2character_number{$1}) : do { warn "Unknown escape: E<$1>"; "E<$1>"; }; }gex; } elsif (eval "require Pod::Text; 1" && $Pod::Text::VERSION < 3) { # Pod::Text < 3.0 has yet another mapping table, # though the table name of 2.x and 1.x are different. # (1.x is in core of Perl < 5.6, 2.x is in core of # Perl < 5.9.3) my $mapping = ($Pod::Text::VERSION < 2) ? \%Pod::Text::HTML_Escapes : \%Pod::Text::ESCAPES; $author =~ s{ E<( (\d+) | ([A-Za-z]+) )> } { defined $2 ? chr($2) : defined $mapping->{$1} ? $mapping->{$1} : do { warn "Unknown escape: E<$1>"; "E<$1>"; }; }gex; } else { $author =~ s{E}{<}g; $author =~ s{E}{>}g; } $self->author($author); } else { warn "Cannot determine author info from $_[0]\n"; } } #Stolen from M::B my %license_urls = ( perl => 'http://dev.perl.org/licenses/', apache => 'http://apache.org/licenses/LICENSE-2.0', apache_1_1 => 'http://apache.org/licenses/LICENSE-1.1', artistic => 'http://opensource.org/licenses/artistic-license.php', artistic_2 => 'http://opensource.org/licenses/artistic-license-2.0.php', lgpl => 'http://opensource.org/licenses/lgpl-license.php', lgpl2 => 'http://opensource.org/licenses/lgpl-2.1.php', lgpl3 => 'http://opensource.org/licenses/lgpl-3.0.html', bsd => 'http://opensource.org/licenses/bsd-license.php', gpl => 'http://opensource.org/licenses/gpl-license.php', gpl2 => 'http://opensource.org/licenses/gpl-2.0.php', gpl3 => 'http://opensource.org/licenses/gpl-3.0.html', mit => 'http://opensource.org/licenses/mit-license.php', mozilla => 'http://opensource.org/licenses/mozilla1.1.php', open_source => undef, unrestricted => undef, restrictive => undef, unknown => undef, ); sub license { my $self = shift; return $self->{values}->{license} unless @_; my $license = shift or die( 'Did not provide a value to license()' ); $license = __extract_license($license) || lc $license; $self->{values}->{license} = $license; # Automatically fill in license URLs if ( $license_urls{$license} ) { $self->resources( license => $license_urls{$license} ); } return 1; } sub _extract_license { my $pod = shift; my $matched; return __extract_license( ($matched) = $pod =~ m/ (=head \d \s+ L(?i:ICEN[CS]E|ICENSING)\b.*?) (=head \d.*|=cut.*|)\z /xms ) || __extract_license( ($matched) = $pod =~ m/ (=head \d \s+ (?:C(?i:OPYRIGHTS?)|L(?i:EGAL))\b.*?) (=head \d.*|=cut.*|)\z /xms ); } sub __extract_license { my $license_text = shift or return; my @phrases = ( '(?:under )?the same (?:terms|license) as (?:perl|the perl (?:\d )?programming language)' => 'perl', 1, '(?:under )?the terms of (?:perl|the perl programming language) itself' => 'perl', 1, 'Artistic and GPL' => 'perl', 1, 'GNU general public license' => 'gpl', 1, 'GNU public license' => 'gpl', 1, 'GNU lesser general public license' => 'lgpl', 1, 'GNU lesser public license' => 'lgpl', 1, 'GNU library general public license' => 'lgpl', 1, 'GNU library public license' => 'lgpl', 1, 'GNU Free Documentation license' => 'unrestricted', 1, 'GNU Affero General Public License' => 'open_source', 1, '(?:Free)?BSD license' => 'bsd', 1, 'Artistic license 2\.0' => 'artistic_2', 1, 'Artistic license' => 'artistic', 1, 'Apache (?:Software )?license' => 'apache', 1, 'GPL' => 'gpl', 1, 'LGPL' => 'lgpl', 1, 'BSD' => 'bsd', 1, 'Artistic' => 'artistic', 1, 'MIT' => 'mit', 1, 'Mozilla Public License' => 'mozilla', 1, 'Q Public License' => 'open_source', 1, 'OpenSSL License' => 'unrestricted', 1, 'SSLeay License' => 'unrestricted', 1, 'zlib License' => 'open_source', 1, 'proprietary' => 'proprietary', 0, ); while ( my ($pattern, $license, $osi) = splice(@phrases, 0, 3) ) { $pattern =~ s#\s+#\\s+#gs; if ( $license_text =~ /\b$pattern\b/i ) { return $license; } } return ''; } sub license_from { my $self = shift; if (my $license=_extract_license(Module::Install::_read($_[0]))) { $self->license($license); } else { warn "Cannot determine license info from $_[0]\n"; return 'unknown'; } } sub _extract_bugtracker { my @links = $_[0] =~ m#L<( https?\Q://rt.cpan.org/\E[^>]+| https?\Q://github.com/\E[\w_]+/[\w_]+/issues| https?\Q://code.google.com/p/\E[\w_\-]+/issues/list )>#gx; my %links; @links{@links}=(); @links=keys %links; return @links; } sub bugtracker_from { my $self = shift; my $content = Module::Install::_read($_[0]); my @links = _extract_bugtracker($content); unless ( @links ) { warn "Cannot determine bugtracker info from $_[0]\n"; return 0; } if ( @links > 1 ) { warn "Found more than one bugtracker link in $_[0]\n"; return 0; } # Set the bugtracker bugtracker( $links[0] ); return 1; } sub requires_from { my $self = shift; my $content = Module::Install::_readperl($_[0]); my @requires = $content =~ m/^use\s+([^\W\d]\w*(?:::\w+)*)\s+(v?[\d\.]+)/mg; while ( @requires ) { my $module = shift @requires; my $version = shift @requires; $self->requires( $module => $version ); } } sub test_requires_from { my $self = shift; my $content = Module::Install::_readperl($_[0]); my @requires = $content =~ m/^use\s+([^\W\d]\w*(?:::\w+)*)\s+([\d\.]+)/mg; while ( @requires ) { my $module = shift @requires; my $version = shift @requires; $self->test_requires( $module => $version ); } } # Convert triple-part versions (eg, 5.6.1 or 5.8.9) to # numbers (eg, 5.006001 or 5.008009). # Also, convert double-part versions (eg, 5.8) sub _perl_version { my $v = $_[-1]; $v =~ s/^([1-9])\.([1-9]\d?\d?)$/sprintf("%d.%03d",$1,$2)/e; $v =~ s/^([1-9])\.([1-9]\d?\d?)\.(0|[1-9]\d?\d?)$/sprintf("%d.%03d%03d",$1,$2,$3 || 0)/e; $v =~ s/(\.\d\d\d)000$/$1/; $v =~ s/_.+$//; if ( ref($v) ) { # Numify $v = $v + 0; } return $v; } sub add_metadata { my $self = shift; my %hash = @_; for my $key (keys %hash) { warn "add_metadata: $key is not prefixed with 'x_'.\n" . "Use appopriate function to add non-private metadata.\n" unless $key =~ /^x_/; $self->{values}->{$key} = $hash{$key}; } } ###################################################################### # MYMETA Support sub WriteMyMeta { die "WriteMyMeta has been deprecated"; } sub write_mymeta_yaml { my $self = shift; # We need YAML::Tiny to write the MYMETA.yml file unless ( eval { require YAML::Tiny; 1; } ) { return 1; } # Generate the data my $meta = $self->_write_mymeta_data or return 1; # Save as the MYMETA.yml file print "Writing MYMETA.yml\n"; YAML::Tiny::DumpFile('MYMETA.yml', $meta); } sub write_mymeta_json { my $self = shift; # We need JSON to write the MYMETA.json file unless ( eval { require JSON; 1; } ) { return 1; } # Generate the data my $meta = $self->_write_mymeta_data or return 1; # Save as the MYMETA.yml file print "Writing MYMETA.json\n"; Module::Install::_write( 'MYMETA.json', JSON->new->pretty(1)->canonical->encode($meta), ); } sub _write_mymeta_data { my $self = shift; # If there's no existing META.yml there is nothing we can do return undef unless -f 'META.yml'; # We need Parse::CPAN::Meta to load the file unless ( eval { require Parse::CPAN::Meta; 1; } ) { return undef; } # Merge the perl version into the dependencies my $val = $self->Meta->{values}; my $perl = delete $val->{perl_version}; if ( $perl ) { $val->{requires} ||= []; my $requires = $val->{requires}; # Canonize to three-dot version after Perl 5.6 if ( $perl >= 5.006 ) { $perl =~ s{^(\d+)\.(\d\d\d)(\d*)}{join('.', $1, int($2||0), int($3||0))}e } unshift @$requires, [ perl => $perl ]; } # Load the advisory META.yml file my @yaml = Parse::CPAN::Meta::LoadFile('META.yml'); my $meta = $yaml[0]; # Overwrite the non-configure dependency hashs delete $meta->{requires}; delete $meta->{build_requires}; delete $meta->{recommends}; if ( exists $val->{requires} ) { $meta->{requires} = { map { @$_ } @{ $val->{requires} } }; } if ( exists $val->{build_requires} ) { $meta->{build_requires} = { map { @$_ } @{ $val->{build_requires} } }; } return $meta; } 1; libmonitoring-availability-perl-0.46/inc/Module/Install/Win32.pm000066400000000000000000000034031242301703500245700ustar00rootroot00000000000000#line 1 package Module::Install::Win32; use strict; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.06'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } # determine if the user needs nmake, and download it if needed sub check_nmake { my $self = shift; $self->load('can_run'); $self->load('get_file'); require Config; return unless ( $^O eq 'MSWin32' and $Config::Config{make} and $Config::Config{make} =~ /^nmake\b/i and ! $self->can_run('nmake') ); print "The required 'nmake' executable not found, fetching it...\n"; require File::Basename; my $rv = $self->get_file( url => 'http://download.microsoft.com/download/vc15/Patch/1.52/W95/EN-US/Nmake15.exe', ftp_url => 'ftp://ftp.microsoft.com/Softlib/MSLFILES/Nmake15.exe', local_dir => File::Basename::dirname($^X), size => 51928, run => 'Nmake15.exe /o > nul', check_for => 'Nmake.exe', remove => 1, ); die <<'END_MESSAGE' unless $rv; ------------------------------------------------------------------------------- Since you are using Microsoft Windows, you will need the 'nmake' utility before installation. It's available at: http://download.microsoft.com/download/vc15/Patch/1.52/W95/EN-US/Nmake15.exe or ftp://ftp.microsoft.com/Softlib/MSLFILES/Nmake15.exe Please download the file manually, save it to a directory in %PATH% (e.g. C:\WINDOWS\COMMAND\), then launch the MS-DOS command line shell, "cd" to that directory, and run "Nmake15.exe" from there; that will create the 'nmake.exe' file needed by this module. You may then resume the installation process described in README. ------------------------------------------------------------------------------- END_MESSAGE } 1; libmonitoring-availability-perl-0.46/inc/Module/Install/WriteAll.pm000066400000000000000000000023761242301703500254210ustar00rootroot00000000000000#line 1 package Module::Install::WriteAll; use strict; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.06'; @ISA = qw{Module::Install::Base}; $ISCORE = 1; } sub WriteAll { my $self = shift; my %args = ( meta => 1, sign => 0, inline => 0, check_nmake => 1, @_, ); $self->sign(1) if $args{sign}; $self->admin->WriteAll(%args) if $self->is_admin; $self->check_nmake if $args{check_nmake}; unless ( $self->makemaker_args->{PL_FILES} ) { # XXX: This still may be a bit over-defensive... unless ($self->makemaker(6.25)) { $self->makemaker_args( PL_FILES => {} ) if -f 'Build.PL'; } } # Until ExtUtils::MakeMaker support MYMETA.yml, make sure # we clean it up properly ourself. $self->realclean_files('MYMETA.yml'); if ( $args{inline} ) { $self->Inline->write; } else { $self->Makefile->write; } # The Makefile write process adds a couple of dependencies, # so write the META.yml files after the Makefile. if ( $args{meta} ) { $self->Meta->write; } # Experimental support for MYMETA if ( $ENV{X_MYMETA} ) { if ( $ENV{X_MYMETA} eq 'JSON' ) { $self->Meta->write_mymeta_json; } else { $self->Meta->write_mymeta_yaml; } } return 1; } 1; libmonitoring-availability-perl-0.46/lib/000077500000000000000000000000001242301703500204725ustar00rootroot00000000000000libmonitoring-availability-perl-0.46/lib/Monitoring/000077500000000000000000000000001242301703500226175ustar00rootroot00000000000000libmonitoring-availability-perl-0.46/lib/Monitoring/Availability.pm000066400000000000000000001733611242301703500256020ustar00rootroot00000000000000package Monitoring::Availability; use 5.008; use strict; use warnings; use Data::Dumper; use Carp; use POSIX qw(strftime mktime); use Monitoring::Availability::Logs; our $VERSION = '0.46'; =head1 NAME Monitoring::Availability - Calculate Availability Data from Nagios / Icinga and Shinken Logfiles. =head1 SYNOPSIS use Monitoring::Availability; my $ma = Monitoring::Availability->new(); =head1 DESCRIPTION This module calculates the availability for hosts/server from given logfiles. The Logfileformat is Nagios/Icinga only. =head1 REPOSITORY Git: http://github.com/sni/Monitoring-Availability =head1 CONSTRUCTOR =head2 new ( [ARGS] ) Creates an C object. C takes at least the logs parameter. Arguments are in key-value pairs. =over 4 =item rpttimeperiod report timeperiod. defines a timeperiod for this report. Will use 24x7 if not specified. =item assumeinitialstates Assume the initial host/service state if none is found, default: yes =item assumestateretention Assume state retention, default: yes =item assumestatesduringnotrunning Assume state during times when the monitoring process is not running, default: yes =item includesoftstates Include soft states in the calculation. Only hard states are used otherwise, default: no =item initialassumedhoststate Assumed host state if none is found, default: unspecified valid options are: unspecified, current, up, down and unreachable =item initialassumedservicestate Assumed service state if none is found, default: unspecified valid options are: unspecified, current, ok, warning, unknown and critical =item backtrack Go back this amount of days to find initial states, default: 4 =item showscheduleddowntime Include downtimes in calculation, default: yes =item timeformat Time format for the log output, default: %s =item verbose verbose mode =item breakdown Breakdown availability into 'months', 'weeks', 'days', 'none' adds additional 'breakdown' hash to each result with broken down results =back =cut use constant { TRUE => 1, FALSE => 0, STATE_NOT_RUNNING => -3, STATE_UNSPECIFIED => -2, STATE_CURRENT => -1, STATE_UP => 0, STATE_DOWN => 1, STATE_UNREACHABLE => 2, STATE_OK => 0, STATE_WARNING => 1, STATE_CRITICAL => 2, STATE_UNKNOWN => 3, START_NORMAL => 1, START_RESTART => 2, STOP_NORMAL => 0, STOP_ERROR => -1, HOST_ONLY => 2, SERVICE_ONLY => 3, BREAK_NONE => 0, BREAK_DAYS => 1, BREAK_WEEKS => 2, BREAK_MONTHS => 3, }; my $verbose = 0; my $report_options_start; my $report_options_end; my $report_options_includesoftstates; my $report_options_calc_all; sub new { my $class = shift; my(%options) = @_; my $self = { 'verbose' => 0, # enable verbose output 'logger' => undef, # logger object used for verbose output 'timeformat' => undef, 'rpttimeperiod' => undef, 'assumeinitialstates' => undef, 'assumestateretention' => undef, 'assumestatesduringnotrunning' => undef, 'includesoftstates' => undef, 'initialassumedhoststate' => undef, 'initialassumedservicestate' => undef, 'backtrack' => undef, 'showscheduleddowntime' => undef, 'breakdown' => undef, }; bless $self, $class; # verify the options we got so far $self = $self->_verify_options($self); for my $opt_key (keys %options) { if(exists $self->{$opt_key}) { $self->{$opt_key} = $options{$opt_key}; } else { croak("unknown option: $opt_key"); } } # translation hash $self->{'state_string_2_int'} = { 'ok' => STATE_OK, 'warning' => STATE_WARNING, 'unknown' => STATE_UNKNOWN, 'critical' => STATE_CRITICAL, 'up' => STATE_UP, 'down' => STATE_DOWN, 'unreachable' => STATE_UNREACHABLE, '0' => STATE_OK, '1' => STATE_WARNING, '2' => STATE_CRITICAL, '3' => STATE_UNKNOWN, }; # allow setting debug mode from env if(defined $ENV{'MONITORING_AVAILABILITY_DEBUG'}) { $self->{'verbose'} = 1; } # init log4perl, may require additional modules if($self->{'verbose'} and !defined $self->{'logger'}) { require Log::Log4perl; Log::Log4perl->import(qw(:easy)); Log::Log4perl->easy_init({ level => 'DEBUG', file => ">/tmp/Monitoring-Availability-Debug.log" }); $self->{'logger'} = get_logger(); } $self->_log('initialized '.$class) if $self->{'verbose'}; $self->_log($self) if $self->{'verbose'}; $verbose = $self->{'verbose'}; return $self; } ######################################## =head1 METHODS =head2 calculate calculate() Calculate the availability =over 4 =item start Timestamp of start =item end Timestamp of end =item log_string String containing the logs =item log_file File containing the logs =item log_dir Directory containing *.log files =item log_livestatus Array with logs from a livestatus query a sample query could be: selectall_arrayref(GET logs...\nColumns: time type options, {Slice => 1}) =item log_iterator Iterator object for logentry objects. For example a L object. =item hosts array with hostnames for which the report should be generated =item services array with hashes of services for which the report should be generated. The array should look like this: [{host => 'hostname', service => 'description'}, ...] =item initial_states if you use the "current" option for initialassumedservicestate or initialassumedhoststate you have to provide the current states with a hash like this: { hosts => { 'hostname' => 'ok', ... }, services => { 'hostname' => { 'description' => 'warning', ... } } } valid values for hosts are: up, down and unreachable valid values for services are: ok, warning, unknown and critical =back =cut sub calculate { my $self = shift; my(%opts) = @_; # clean up namespace $self->_reset(); $self->{'report_options'} = { 'start' => undef, 'end' => undef, 'hosts' => [], 'services' => [], 'initial_states' => {}, 'log_string' => undef, # logs from string 'log_livestatus' => undef, # logs from a livestatus query 'log_file' => undef, # logs from a file 'log_dir' => undef, # logs from a dir 'log_iterator' => undef, # logs from a iterator object 'rpttimeperiod' => $self->{'rpttimeperiod'} || '', 'assumeinitialstates' => $self->{'assumeinitialstates'}, 'assumestateretention' => $self->{'assumestateretention'}, 'assumestatesduringnotrunning' => $self->{'assumestatesduringnotrunning'}, 'includesoftstates' => $self->{'includesoftstates'}, 'initialassumedhoststate' => $self->{'initialassumedhoststate'}, 'initialassumedservicestate' => $self->{'initialassumedservicestate'}, 'backtrack' => $self->{'backtrack'}, 'showscheduleddowntime' => $self->{'showscheduleddowntime'}, 'timeformat' => $self->{'timeformat'}, 'breakdown' => $self->{'breakdown'}, }; $self->_log('calculate()') if $self->{'verbose'}; $self->_log($self->{'report_options'}) if $self->{'verbose'}; my $result; for my $opt_key (keys %opts) { if(exists $self->{'report_options'}->{$opt_key}) { $self->{'report_options'}->{$opt_key} = $opts{$opt_key}; } else { croak("unknown option: $opt_key"); } } $verbose = $self->{'verbose'}; $self->{'report_options'} = $self->_set_default_options($self->{'report_options'}); $self->{'report_options'} = $self->_verify_options($self->{'report_options'}); # create lookup hash for faster access $result->{'hosts'} = {}; $result->{'services'} = {}; for my $host (@{$self->{'report_options'}->{'hosts'}}) { $result->{'hosts'}->{$host} = 1; } for my $service (@{$self->{'report_options'}->{'services'}}) { if(ref $service ne 'HASH') { croak("services have to be an array of hashes, for example: [{host => 'hostname', service => 'description'}, ...]\ngot: ".Dumper($service)); } if(!defined $service->{'host'} or !defined $service->{'service'}) { croak("services have to be an array of hashes, for example: [{host => 'hostname', service => 'description'}, ...]\ngot: ".Dumper($service)); } $result->{'services'}->{$service->{'host'}}->{$service->{'service'}} = 1; } # if we have more than one host or service, we dont build up a log if(scalar @{$self->{'report_options'}->{'hosts'}} == 1) { $self->{'report_options'}->{'build_log'} = HOST_ONLY; } elsif(scalar @{$self->{'report_options'}->{'services'}} == 1) { $self->{'report_options'}->{'build_log'} = SERVICE_ONLY; } else { $self->{'report_options'}->{'build_log'} = FALSE; } $self->{'report_options'}->{'calc_all'} = FALSE; if(scalar keys %{$result->{'services'}} == 0 and scalar keys %{$result->{'hosts'}} == 0) { $self->_log('will calculate availability for all hosts/services found') if $self->{'verbose'}; $self->{'report_options'}->{'calc_all'} = TRUE; } $self->_set_breakpoints(); unless($self->{'report_options'}->{'calc_all'}) { $self->_set_empty_hosts($result); $self->_set_empty_services($result); } # set some variables for faster access $report_options_start = $self->{'report_options'}->{'start'}; $report_options_end = $self->{'report_options'}->{'end'}; $report_options_includesoftstates = $self->{'report_options'}->{'includesoftstates'}; $report_options_calc_all = $self->{'report_options'}->{'calc_all'}; # read in logs if($self->{'report_options'}->{'log_file'} and !$self->{'report_options'}->{'log_string'} and !$self->{'report_options'}->{'log_dir'}) { # single file can be read line by line to save memory $self->_compute_availability_line_by_line($result, $self->{'report_options'}->{'log_file'}); } elsif(defined $self->{'report_options'}->{'log_string'} or $self->{'report_options'}->{'log_file'} or $self->{'report_options'}->{'log_dir'}) { my $mal = Monitoring::Availability::Logs->new( 'log_string' => $self->{'report_options'}->{'log_string'}, 'log_file' => $self->{'report_options'}->{'log_file'}, 'log_dir' => $self->{'report_options'}->{'log_dir'}, ); my $logs = $mal->get_logs(); $self->_compute_availability_from_log_store($result, $logs); } elsif(defined $self->{'report_options'}->{'log_livestatus'}) { $self->_compute_availability_on_the_fly($result, $self->{'report_options'}->{'log_livestatus'}); } elsif(defined $self->{'report_options'}->{'log_iterator'}) { $self->_compute_availability_from_iterator($result, $self->{'report_options'}->{'log_iterator'}); } return($result); } ######################################## =head2 get_condensed_logs get_condensed_logs() returns an array of hashes with the condensed log used for this report =cut sub get_condensed_logs { my $self = shift; return if $self->{'report_options'}->{'build_log'} == FALSE; $self->_calculate_log() unless $self->{'log_output_calculated'}; return $self->{'log_output'}; } ######################################## =head2 get_full_logs get_full_logs() returns an array of hashes with the full log used for this report =cut sub get_full_logs { my $self = shift; return if $self->{'report_options'}->{'build_log'} == FALSE; $self->_calculate_log() unless $self->{'log_output_calculated'}; return $self->{'full_log_output'}; } ######################################## # INTERNAL SUBS ######################################## sub _reset { my $self = shift; $self->_log('_reset()') if $self->{'verbose'}; undef $self->{'full_log_store'}; $self->{'full_log_store'} = []; delete $self->{'first_known_state_before_report'}; delete $self->{'first_known_proc_before_report'}; delete $self->{'log_output_calculated'}; delete $self->{'report_options'}; delete $self->{'full_log_output'}; delete $self->{'log_output'}; return 1; } ######################################## sub _set_empty_hosts { my $self = shift; my $data = shift; my $initial_assumend_state = STATE_UNSPECIFIED; if($self->{'report_options'}->{'assumeinitialstates'}) { $initial_assumend_state = $self->{'report_options'}->{'initialassumedhoststate'}; } $self->_log('_set_empty_hosts()') if $self->{'verbose'}; for my $hostname (keys %{$data->{'hosts'}}) { my $first_state = $initial_assumend_state; if($initial_assumend_state == STATE_CURRENT) { eval { $first_state = $self->_state_to_int($self->{'report_options'}->{'initial_states'}->{'hosts'}->{$hostname}); }; if($@) { croak("found no initial state for host '$hostname'\ngot: ".Dumper($self->{'report_options'}->{'initial_states'}).Dumper($@)); } $self->{'report_options'}->{'first_state'} = $first_state; } $data->{'hosts'}->{$hostname} = $self->_new_host_data($self->{'report_options'}->{'breakdown'}); $self->{'host_data'}->{$hostname} = { 'in_downtime' => 0, 'last_state' => $initial_assumend_state, 'last_known_state' => undef, 'last_state_time' => 0, }; } return 1; } ######################################## sub _set_empty_services { my $self = shift; my $data = shift; $self->_log('_set_empty_services()') if $self->{'verbose'}; my $initial_assumend_state = STATE_UNSPECIFIED; my $initial_assumend_host_state = STATE_UNSPECIFIED; if($self->{'report_options'}->{'assumeinitialstates'}) { $initial_assumend_state = $self->{'report_options'}->{'initialassumedservicestate'}; $initial_assumend_host_state = $self->{'report_options'}->{'initialassumedhoststate'}; } for my $hostname (keys %{$data->{'services'}}) { for my $service_description (keys %{$data->{'services'}->{$hostname}}) { my $first_state = $initial_assumend_state; if($initial_assumend_state == STATE_CURRENT) { eval { $first_state = $self->_state_to_int($self->{'report_options'}->{'initial_states'}->{'services'}->{$hostname}->{$service_description}); }; if($@) { croak("found no initial state for service '$service_description' on host '$hostname'\ngot: ".Dumper($self->{'report_options'}->{'initial_states'}).Dumper($@)); } $self->{'report_options'}->{'first_state'} = $first_state; } $data->{'services'}->{$hostname}->{$service_description} = $self->_new_service_data($self->{'report_options'}->{'breakdown'}); # create last service data $self->{'service_data'}->{$hostname}->{$service_description} = { 'in_downtime' => 0, 'last_state' => $first_state, 'last_known_state' => undef, 'last_state_time' => 0, }; } my $first_host_state = $initial_assumend_host_state; if($initial_assumend_host_state == STATE_CURRENT) { eval { $first_host_state = $self->_state_to_int($self->{'report_options'}->{'initial_states'}->{'hosts'}->{$hostname}); }; if($@) { $first_host_state = STATE_UNSPECIFIED; } } $self->{'host_data'}->{$hostname} = { 'in_downtime' => 0, 'last_state' => $first_host_state, 'last_known_state' => undef, 'last_state_time' => 0, }; } return 1; } ######################################## sub _compute_for_data { my($self, $last_time, $data, $result) = @_; # if we reach the start date of our report, insert a fake entry if($last_time < $report_options_start and $data->{'time'} >= $report_options_start) { $self->_insert_fake_event($result, $report_options_start); } # if we passed a breakdown point, insert fake event if($self->{'report_options'}->{'breakdown'} != BREAK_NONE) { my $breakpoint = $self->{'breakpoints'}->[0]; while(defined $breakpoint and $last_time < $breakpoint and $data->{'time'} >= $breakpoint) { $self->_log('_compute_for_data(): inserted breakpoint: '.$breakpoint." (".scalar localtime($breakpoint).")") if $self->{'verbose'}; $self->_insert_fake_event($result, $breakpoint); shift(@{$self->{'breakpoints'}}); $breakpoint = $self->{'breakpoints'}->[0]; } } # end of report reached, insert fake end event if($data->{'time'} >= $report_options_end and $last_time < $report_options_end) { $self->_insert_fake_event($result, $report_options_end); # set a log entry $self->_add_log_entry( 'full_only' => 1, 'log' => { 'start' => $report_options_end, }, ) unless defined $data->{'fake'}; } # now process the real line &_process_log_line($self,$result, $data) unless defined $data->{'fake'}; return 1; } ######################################## sub _compute_availability_line_by_line { my($self,$result,$file) = @_; if($self->{'verbose'}) { $self->_log('_compute_availability_line_by_line()'); $self->_log('_compute_availability_line_by_line() report start: '.(scalar localtime $self->{'report_options'}->{'start'})); $self->_log('_compute_availability_line_by_line() report end: '.(scalar localtime $self->{'report_options'}->{'end'})); } my $last_time = -1; open(my $fh, '<', $file) or die("cannot read ".$file.": ".$!); binmode($fh); # process all log lines we got # logs should be sorted already while(<$fh>) { chop; my $data = &Monitoring::Availability::Logs::parse_line($_); next unless $data; &_compute_for_data($self,$last_time, $data, $result); # set timestamp of last log line $last_time = $data->{'time'}; } close($fh); $self->_add_last_time_event($last_time, $result); return 1; } ######################################## sub _compute_availability_from_iterator { my $self = shift; my $result = shift; my $logs = shift; if($self->{'verbose'}) { $self->_log('_compute_availability_from_iterator()'); $self->_log('_compute_availability_from_iterator() report start: '.(scalar localtime $self->{'report_options'}->{'start'})); $self->_log('_compute_availability_from_iterator() report end: '.(scalar localtime $self->{'report_options'}->{'end'})); } my $last_time = -1; # no logs at all? unless($logs->has_next) { $self->_compute_for_data(-1, {time => $self->{'report_options'}->{'end'}, fake => 1}, $result); $last_time = $self->{'report_options'}->{'end'}; } # process all log lines we got # logs should be sorted already while(my $data = $logs->next) { $self->_compute_for_data($last_time, Monitoring::Availability::Logs->_parse_livestatus_entry($data), $result); # set timestamp of last log line $last_time = $data->{'time'}; } # processing logfiles finished $self->_add_last_time_event($last_time, $result); return 1; } ######################################## sub _compute_availability_on_the_fly { my $self = shift; my $result = shift; my $logs = shift; if($self->{'verbose'}) { $self->_log('_compute_availability_on_the_fly()'); $self->_log('_compute_availability_on_the_fly() report start: '.(scalar localtime $self->{'report_options'}->{'start'})); $self->_log('_compute_availability_on_the_fly() report end: '.(scalar localtime $self->{'report_options'}->{'end'})); } my $last_time = -1; if(scalar @{$logs} == 0) { $self->_compute_for_data(-1, {time => $self->{'report_options'}->{'end'}, fake => 1}, $result); $last_time = $self->{'report_options'}->{'end'}; } # process all log lines we got # make sure our logs are sorted by time for my $data ( sort { $a->{'time'} <=> $b->{'time'} } @{$logs} ) { eval { $self->_compute_for_data($last_time, Monitoring::Availability::Logs->_parse_livestatus_entry($data), $result); # set timestamp of last log line $last_time = $data->{'time'}; } } # processing logfiles finished $self->_add_last_time_event($last_time, $result); return 1; } ######################################## sub _compute_availability_from_log_store { my $self = shift; my $result = shift; my $logs = shift; if($self->{'verbose'}) { $self->_log('_compute_availability_from_log_store()'); $self->_log('_compute_availability_from_log_store() report start: '.(scalar localtime $self->{'report_options'}->{'start'})); $self->_log('_compute_availability_from_log_store() report end: '.(scalar localtime $self->{'report_options'}->{'end'})); } # make sure our logs are sorted by time @{$logs} = sort { $a->{'time'} <=> $b->{'time'} } @{$logs}; $self->_log('_compute_availability_from_log_store() sorted logs') if $self->{'verbose'}; # process all log lines we got my $last_time = -1; for my $data (@{$logs}) { $self->_compute_for_data($last_time, $data, $result); # set timestamp of last log line $last_time = $data->{'time'}; } # processing logfiles finished $self->_add_last_time_event($last_time, $result); return 1; } ######################################## sub _add_last_time_event { my($self, $last_time, $result) = @_; # no start event yet, insert a fake entry if($last_time < $self->{'report_options'}->{'start'}) { $self->_insert_fake_event($result, $self->{'report_options'}->{'start'}); } # breakpoints left? my $breakpoint = $self->{'breakpoints'}->[0]; while(defined $breakpoint) { $self->_log('_add_last_time_event(): inserted breakpoint: '.$breakpoint." (".scalar localtime($breakpoint).")") if $self->{'verbose'}; $self->_insert_fake_event($result, $breakpoint); shift(@{$self->{'breakpoints'}}); $breakpoint = $self->{'breakpoints'}->[0]; } # no end event yet, insert fake end event if($last_time < $self->{'report_options'}->{'end'}) { $self->_insert_fake_event($result, $self->{'report_options'}->{'end'}); } return 1; } ######################################## sub _process_log_line { my($self, $result, $data) = @_; if($verbose) { $self->_log('#######################################'); $self->_log('_process_log_line() at '.(scalar localtime $data->{'time'})); $self->_log($data); } # only hard states? if(exists $data->{'hard'} and !$report_options_includesoftstates and $data->{'hard'} != 1) { $self->_log(' -> skipped soft state') if $verbose; return; } # process starts / stops? if(defined $data->{'proc_start'}) { unless($self->{'report_options'}->{'assumestatesduringnotrunning'}) { if($data->{'proc_start'} == START_NORMAL or $data->{'proc_start'} == START_RESTART) { # set an event for all services and set state to no_data $self->_log('_process_log_line() process start, inserting fake event for all services') if $verbose; for my $host_name (keys %{$self->{'service_data'}}) { for my $service_description (keys %{$self->{'service_data'}->{$host_name}}) { my $last_known_state = $self->{'service_data'}->{$host_name}->{$service_description}->{'last_known_state'}; my $last_state = STATE_UNSPECIFIED; $last_state = $last_known_state if(defined $last_known_state and $last_known_state >= 0); &_set_service_event($self, $host_name, $service_description, $result, { 'start' => $data->{'start'}, 'end' => $data->{'end'}, 'time' => $data->{'time'}, 'state' => $last_state }); } } for my $host_name (keys %{$self->{'host_data'}}) { my $last_known_state = $self->{'host_data'}->{$host_name}->{'last_known_state'}; my $last_state = STATE_UNSPECIFIED; $last_state = $last_known_state if(defined $last_known_state and $last_known_state >= 0); &_set_host_event($self, $host_name, $result, { 'time' => $data->{'time'}, 'state' => $last_state }); } } else { # set an event for all services and set state to not running $self->_log('_process_log_line() process stop, inserting fake event for all services') if $verbose; for my $host_name (keys %{$self->{'service_data'}}) { for my $service_description (keys %{$self->{'service_data'}->{$host_name}}) { &_set_service_event($self, $host_name, $service_description, $result, { 'time' => $data->{'time'}, 'state' => STATE_NOT_RUNNING }); } } for my $host_name (keys %{$self->{'host_data'}}) { &_set_host_event($self, $host_name, $result, { 'time' => $data->{'time'}, 'state' => STATE_NOT_RUNNING }); } } } # set a log entry if($data->{'proc_start'} == START_NORMAL or $data->{'proc_start'} == START_RESTART) { my $plugin_output = 'Program start'; $plugin_output = 'Program restart' if $data->{'proc_start'} == START_RESTART; $self->_add_log_entry( 'full_only' => 1, 'proc_start' => $data->{'proc_start'}, 'log' => { 'start' => $data->{'time'}, 'type' => 'PROGRAM (RE)START', 'plugin_output' => $plugin_output, 'class' => 'INDETERMINATE', }, ); } else { my $plugin_output = 'Normal program termination'; $plugin_output = 'Abnormal program termination' if $data->{'proc_start'} == STOP_ERROR; $self->_add_log_entry( 'full_only' => 1, 'log' => { 'start' => $data->{'time'}, 'type' => 'PROGRAM END', 'plugin_output' => $plugin_output, 'class' => 'INDETERMINATE', }, ); } return; } # timeperiod transitions elsif(defined $data->{'timeperiod'}) { if($self->{'report_options'}->{'rpttimeperiod'} eq $data->{'timeperiod'} ) { $self->_log('_process_log_line() timeperiod translation, inserting fake event for all hosts/services') if $verbose; for my $host_name (keys %{$self->{'service_data'}}) { for my $service_description (keys %{$self->{'service_data'}->{$host_name}}) { my $last_known_state = $self->{'service_data'}->{$host_name}->{$service_description}->{'last_known_state'}; my $last_state = STATE_UNSPECIFIED; $last_state = $last_known_state if(defined $last_known_state and $last_known_state >= 0); &_set_service_event($self, $host_name, $service_description, $result, { 'start' => $data->{'start'}, 'end' => $data->{'end'}, 'time' => $data->{'time'}, 'state' => $last_state }); } } for my $host_name (keys %{$self->{'host_data'}}) { my $last_known_state = $self->{'host_data'}->{$host_name}->{'last_known_state'}; my $last_state = STATE_UNSPECIFIED; $last_state = $last_known_state if(defined $last_known_state and $last_known_state >= 0); &_set_host_event($self,$host_name, $result, { 'time' => $data->{'time'}, 'state' => $last_state }); } $self->{'in_timeperiod'} = $data->{'to'}; # set a log entry my $start = 'STOP'; my $plugin_output = 'leaving timeperiod: '.$data->{'timeperiod'}; if($self->{'in_timeperiod'}) { $plugin_output = 'entering timeperiod: '.$data->{'timeperiod'}; $start = 'START'; } $self->_add_log_entry( 'full_only' => 1, 'log' => { 'start' => $data->{'time'}, 'type' => 'TIMEPERIOD '.$start, 'plugin_output' => $plugin_output, 'class' => 'INDETERMINATE', }, ); } return; } # skip hosts we dont need if($report_options_calc_all == 0 and defined $data->{'host_name'} and !defined $self->{'host_data'}->{$data->{'host_name'}} and !defined $self->{'service_data'}->{$data->{'host_name'}}) { $self->_log(' -> skipped not needed host event') if $verbose; return; } # skip services we dont need if($report_options_calc_all == 0 and $data->{'host_name'} and $data->{'service_description'} and !defined $self->{'service_data'}->{$data->{'host_name'}}->{$data->{'service_description'}} ) { $self->_log(' -> skipped not needed service event') if $verbose; return; } # service events if($data->{'service_description'}) { my $service_hist = $self->{'service_data'}->{$data->{'host_name'}}->{$data->{'service_description'}}; if($data->{'type'} eq 'CURRENT SERVICE STATE' or $data->{'type'} eq 'SERVICE ALERT' or $data->{'type'} eq 'INITIAL SERVICE STATE') { &_set_service_event($self,$data->{'host_name'}, $data->{'service_description'}, $result, $data); # set a log entry my $state_text; if( $data->{'state'} == STATE_OK ) { $state_text = "OK"; } elsif($data->{'state'} == STATE_WARNING) { $state_text = "WARNING"; } elsif($data->{'state'} == STATE_UNKNOWN) { $state_text = "UNKNOWN"; } elsif($data->{'state'} == STATE_CRITICAL) { $state_text = "CRITICAL"; } if(defined $state_text) { my $hard = ""; $hard = " (HARD)" if $data->{'hard'}; $self->_add_log_entry( 'log' => { 'start' => $data->{'time'}, 'type' => 'SERVICE '.$state_text.$hard, 'plugin_output' => $data->{'plugin_output'}, 'class' => $state_text, 'in_downtime' => $service_hist->{'in_downtime'}, }, ) unless $self->{'report_options'}->{'build_log'} == HOST_ONLY; } } elsif($data->{'type'} eq 'SERVICE DOWNTIME ALERT') { next unless $self->{'report_options'}->{'showscheduleddowntime'}; undef $data->{'state'}; # we dont know the current state, so make sure it wont be overwritten &_set_service_event($self,$data->{'host_name'}, $data->{'service_description'}, $result, $data); my $start; my $plugin_output; if($data->{'start'}) { $start = "START"; $plugin_output = 'Start of scheduled downtime'; $service_hist->{'in_downtime'} = 1; } else { $start = "END"; $plugin_output = 'End of scheduled downtime'; $service_hist->{'in_downtime'} = 0; } # set a log entry $self->_add_log_entry( 'log' => { 'start' => $data->{'time'}, 'type' => 'SERVICE DOWNTIME '.$start, 'plugin_output' => $plugin_output, 'class' => 'INDETERMINATE', 'in_downtime' => $service_hist->{'in_downtime'}, }, ) unless $self->{'report_options'}->{'build_log'} == HOST_ONLY; } else { $self->_log(' -> unknown log type') if $verbose; } } # host events elsif(defined $data->{'host_name'}) { my $host_hist = $self->{'host_data'}->{$data->{'host_name'}}; if($data->{'type'} eq 'CURRENT HOST STATE' or $data->{'type'} eq 'HOST ALERT' or $data->{'type'} eq 'INITIAL HOST STATE') { &_set_host_event($self,$data->{'host_name'}, $result, $data); # set a log entry my $state_text; if( $data->{'state'} == STATE_UP) { $state_text = "UP"; } elsif($data->{'state'} == STATE_DOWN) { $state_text = "DOWN"; } elsif($data->{'state'} == STATE_UNREACHABLE) { $state_text = "UNREACHABLE"; } if(defined $state_text) { my $hard = ""; $hard = " (HARD)" if $data->{'hard'}; $self->_add_log_entry( 'log' => { 'start' => $data->{'time'}, 'type' => 'HOST '.$state_text.$hard, 'plugin_output' => $data->{'plugin_output'}, 'class' => $state_text, 'in_downtime' => $host_hist->{'in_downtime'}, }, ); } } elsif($data->{'type'} eq 'HOST DOWNTIME ALERT') { next unless $self->{'report_options'}->{'showscheduleddowntime'}; my $last_state_time = $host_hist->{'last_state_time'}; $self->_log('_process_log_line() hostdowntime, inserting fake event for all hosts/services') if $verbose; # set an event for all services for my $service_description (keys %{$self->{'service_data'}->{$data->{'host_name'}}}) { $last_state_time = $self->{'service_data'}->{$data->{'host_name'}}->{$service_description}->{'last_state_time'}; &_set_service_event($self, $data->{'host_name'}, $service_description, $result, { 'start' => $data->{'start'}, 'end' => $data->{'end'}, 'time' => $data->{'time'} }); } undef $data->{'state'}; # we dont know the current state, so make sure it wont be overwritten # set the host event itself &_set_host_event($self,$data->{'host_name'}, $result, $data); my $start; my $plugin_output; if($data->{'start'}) { $start = "START"; $plugin_output = 'Start of scheduled downtime'; $host_hist->{'in_downtime'} = 1; } else { $start = "STOP"; $plugin_output = 'End of scheduled downtime'; $host_hist->{'in_downtime'} = 0; } # set a log entry $self->_add_log_entry( 'log' => { 'start' => $data->{'time'}, 'type' => 'HOST DOWNTIME '.$start, 'plugin_output' => $plugin_output, 'class' => 'INDETERMINATE', 'in_downtime' => $host_hist->{'in_downtime'}, }, ); } else { $self->_log(' -> unknown log type') if $verbose; } } else { $self->_log(' -> unknown log type') if $verbose; } return 1; } ######################################## sub _set_service_event { my($self, $host_name, $service_description, $result, $data) = @_; $self->_log('_set_service_event()') if $verbose; my $host_hist = $self->{'host_data'}->{$host_name}; my $service_hist = $self->{'service_data'}->{$host_name}->{$service_description}; my $service_data = $result->{'services'}->{$host_name}->{$service_description}; # check if we are inside the report time if($report_options_start < $data->{'time'} and $report_options_end >= $data->{'time'}) { # we got a last state? if(defined $service_hist->{'last_state'}) { my $diff = $data->{'time'} - $service_hist->{'last_state_time'}; # outside timeperiod if(defined $self->{'in_timeperiod'} and !$self->{'in_timeperiod'}) { $self->_add_time($service_data, $data->{'time'}, 'time_indeterminate_outside_timeperiod', $diff); } # ok elsif($service_hist->{'last_state'} == STATE_OK) { $self->_add_time($service_data, $data->{'time'}, 'time_ok', $diff, ($service_hist->{'in_downtime'} or $host_hist->{'in_downtime'})); } # warning elsif($service_hist->{'last_state'} == STATE_WARNING) { $self->_add_time($service_data, $data->{'time'}, 'time_warning', $diff, ($service_hist->{'in_downtime'} or $host_hist->{'in_downtime'})); } # critical elsif($service_hist->{'last_state'} == STATE_CRITICAL) { $self->_add_time($service_data, $data->{'time'}, 'time_critical', $diff, ($service_hist->{'in_downtime'} or $host_hist->{'in_downtime'})); } # unknown elsif($service_hist->{'last_state'} == STATE_UNKNOWN) { $self->_add_time($service_data, $data->{'time'}, 'time_unknown', $diff, ($service_hist->{'in_downtime'} or $host_hist->{'in_downtime'})); } # no data yet elsif($service_hist->{'last_state'} == STATE_UNSPECIFIED) { $self->_add_time($service_data, $data->{'time'}, 'time_indeterminate_nodata', $diff, ($service_hist->{'in_downtime'} or $host_hist->{'in_downtime'}), 'scheduled_time_indeterminate'); } # not running elsif($service_hist->{'last_state'} == STATE_NOT_RUNNING) { $self->_add_time($service_data, $data->{'time'}, 'time_indeterminate_notrunning', $diff); } } } # set last state if(defined $data->{'state'}) { $self->_log('_set_service_event() set last state = '.$data->{'state'}) if $verbose; $service_hist->{'last_state'} = $data->{'state'}; $service_hist->{'last_known_state'} = $data->{'state'} if $data->{'state'} >= 0; } $service_hist->{'last_state_time'} = $data->{'time'}; return 1; } ######################################## sub _set_host_event { my($self, $host_name, $result, $data) = @_; $self->_log('_set_host_event()') if $verbose; my $host_hist = $self->{'host_data'}->{$host_name}; my $host_data = $result->{'hosts'}->{$host_name}; # check if we are inside the report time if($report_options_start < $data->{'time'} and $report_options_end >= $data->{'time'}) { # we got a last state? if(defined $host_hist->{'last_state'}) { my $diff = $data->{'time'} - $host_hist->{'last_state_time'}; # outside timeperiod if(defined $self->{'in_timeperiod'} and !$self->{'in_timeperiod'}) { $self->_add_time($host_data, $data->{'time'}, 'time_indeterminate_outside_timeperiod', $diff); } # up elsif($host_hist->{'last_state'} == STATE_UP) { $self->_add_time($host_data, $data->{'time'}, 'time_up', $diff, $host_hist->{'in_downtime'}); } # down elsif($host_hist->{'last_state'} == STATE_DOWN) { $self->_add_time($host_data, $data->{'time'}, 'time_down', $diff, $host_hist->{'in_downtime'}); } # unreachable elsif($host_hist->{'last_state'} == STATE_UNREACHABLE) { $self->_add_time($host_data, $data->{'time'}, 'time_unreachable', $diff, $host_hist->{'in_downtime'}); } # no data yet elsif($host_hist->{'last_state'} == STATE_UNSPECIFIED) { $self->_add_time($host_data, $data->{'time'}, 'time_indeterminate_nodata', $diff, $host_hist->{'in_downtime'}, 'scheduled_time_indeterminate'); } # not running elsif($host_hist->{'last_state'} == STATE_NOT_RUNNING) { $self->_add_time($host_data, $data->{'time'}, 'time_indeterminate_notrunning', $diff); } } } # set last state if(defined $data->{'state'}) { $self->_log('_set_host_event() set last state = '.$data->{'state'}) if $verbose; $host_hist->{'last_state'} = $data->{'state'}; $host_hist->{'last_known_state'} = $data->{'state'} if $data->{'state'} >= 0; } $host_hist->{'last_state_time'} = $data->{'time'}; return 1; } ######################################## sub _add_time { my($self, $data, $date, $type, $diff, $in_downtime, $scheduled_type) = @_; $scheduled_type = 'scheduled_'.$type unless defined $scheduled_type; $self->_log('_add_time() '.$type.' + '.$diff.' seconds ('.$self->_duration($diff).')') if $verbose; $data->{$type} += $diff; if($in_downtime) { $self->_log('_add_time() '.$type.' scheduled + '.$diff.' seconds') if $verbose; $data->{$scheduled_type} += $diff; } # breakdowns? if($self->{'report_options'}->{'breakdown'} != BREAK_NONE) { my $timestr = $self->_get_break_timestr($date-1); $data->{'breakdown'}->{$timestr}->{$type} += $diff; $self->_log('_add_time() breakdown('.$timestr.') '.$type.' + '.$diff.' seconds ('.$self->_duration($diff).')') if $verbose; if($in_downtime) { $self->_log('_add_time() breakdown('.$timestr.') '.$type.' scheduled + '.$diff.' seconds ('.$self->_duration($diff).')') if $verbose; $data->{'breakdown'}->{$timestr}->{$scheduled_type} += $diff; } } return; } ######################################## sub _log { my($self, $text) = @_; return 1 unless $verbose; if(ref $text ne '') { $Data::Dumper::Sortkeys = \&_logging_filter; $text = Dumper($text); } $self->{'logger'}->debug($text); return 1; } ######################################## sub _logging_filter { my ($hash) = @_; my @keys = keys %{$hash}; # filter a few keys we don't want to log @keys = grep {!/^(state_string_2_int |logger |peer_addr |peer_name |peer_key |log_string |log_livestatus |log_file |log_dir |log_iterator |current_host_groups )$/mx} @keys; return \@keys; } ############################################## # calculate a duration in the # format: 0d 0h 29m 43s sub _duration { my($self, $duration) = @_; croak("undef duration in duration(): ".$duration) unless defined $duration; $duration = $duration * -1 if $duration < 0; if($duration < 0) { $duration = time() + $duration; } my $days = 0; my $hours = 0; my $minutes = 0; my $seconds = 0; if($duration >= 86400) { $days = int($duration/86400); $duration = $duration%86400; } if($duration >= 3600) { $hours = int($duration/3600); $duration = $duration%3600; } if($duration >= 60) { $minutes = int($duration/60); $duration = $duration%60; } $seconds = $duration; return($days."d ".$hours."h ".$minutes."m ".$seconds."s"); } ######################################## sub _insert_fake_event { my($self, $result, $time) = @_; $self->_log('_insert_fake_event()') if $verbose; for my $host (keys %{$result->{'services'}}) { for my $service (keys %{$result->{'services'}->{$host}}) { my $last_service_state = STATE_UNSPECIFIED; if(defined $self->{'service_data'}->{$host}->{$service}->{'last_known_state'}) { $last_service_state = $self->{'service_data'}->{$host}->{$service}->{'last_known_state'}; } elsif(defined $self->{'service_data'}->{$host}->{$service}->{'last_state'}) { $last_service_state = $self->{'service_data'}->{$host}->{$service}->{'last_state'}; } my $fakedata = { 'service_description' => $service, 'time' => $time, 'host_name' => $host, 'type' => 'INITIAL SERVICE STATE', 'hard' => 1, 'state' => $last_service_state, }; $self->_set_service_event($host, $service, $result, $fakedata); } } for my $host (keys %{$result->{'hosts'}}) { my $last_host_state = STATE_UNSPECIFIED; if(defined $self->{'host_data'}->{$host}->{'last_known_state'}) { $last_host_state = $self->{'host_data'}->{$host}->{'last_known_state'}; } elsif(defined $self->{'host_data'}->{$host}->{'last_state'}) { $last_host_state = $self->{'host_data'}->{$host}->{'last_state'}; } my $fakedata = { 'time' => $time, 'host_name' => $host, 'type' => 'INITIAL HOST STATE', 'hard' => 1, 'state' => $last_host_state, }; &_set_host_event($self, $host, $result, $fakedata); } return 1; } ######################################## sub _set_default_options { my $self = shift; my $options = shift; $options->{'backtrack'} = 4 unless defined $options->{'backtrack'}; $options->{'assumeinitialstates'} = 'yes' unless defined $options->{'assumeinitialstates'}; $options->{'assumestateretention'} = 'yes' unless defined $options->{'assumestateretention'}; $options->{'assumestatesduringnotrunning'} = 'yes' unless defined $options->{'assumestatesduringnotrunning'}; $options->{'includesoftstates'} = 'no' unless defined $options->{'includesoftstates'}; $options->{'initialassumedhoststate'} = 'unspecified' unless defined $options->{'initialassumedhoststate'}; $options->{'initialassumedservicestate'} = 'unspecified' unless defined $options->{'initialassumedservicestate'}; $options->{'showscheduleddowntime'} = 'yes' unless defined $options->{'showscheduleddowntime'}; $options->{'timeformat'} = '%s' unless defined $options->{'timeformat'}; $options->{'breakdown'} = BREAK_NONE unless defined $options->{'breakdown'}; return $options; } ######################################## sub _verify_options { my $self = shift; my $options = shift; # set default backtrack to 4 days if(defined $options->{'backtrack'}) { if($options->{'backtrack'} < 0) { croak('backtrack has to be a positive integer'); } } # our yes no options for my $yes_no (qw/assumeinitialstates assumestateretention assumestatesduringnotrunning includesoftstates showscheduleddowntime /) { if(defined $options->{$yes_no}) { if(lc $options->{$yes_no} eq 'yes') { $options->{$yes_no} = TRUE; } elsif(lc $options->{$yes_no} eq 'no') { $options->{$yes_no} = FALSE; } else { croak($yes_no.' unknown, please use \'yes\' or \'no\'. Got: '.$options->{$yes_no}); } } } # set initial assumed host state if(defined $options->{'initialassumedhoststate'}) { if(lc $options->{'initialassumedhoststate'} eq 'unspecified') { $options->{'initialassumedhoststate'} = STATE_UNSPECIFIED; } elsif(lc $options->{'initialassumedhoststate'} eq 'current') { $options->{'initialassumedhoststate'} = STATE_CURRENT; } elsif(lc $options->{'initialassumedhoststate'} eq 'up') { $options->{'initialassumedhoststate'} = STATE_UP; } elsif(lc $options->{'initialassumedhoststate'} eq 'down') { $options->{'initialassumedhoststate'} = STATE_DOWN; } elsif(lc $options->{'initialassumedhoststate'} eq 'unreachable') { $options->{'initialassumedhoststate'} = STATE_UNREACHABLE; } else { croak('initialassumedhoststate unknown, please use one of: unspecified, current, up, down or unreachable. Got: '.$options->{'initialassumedhoststate'}); } } # set initial assumed service state if(defined $options->{'initialassumedservicestate'}) { if(lc $options->{'initialassumedservicestate'} eq 'unspecified') { $options->{'initialassumedservicestate'} = STATE_UNSPECIFIED; } elsif(lc $options->{'initialassumedservicestate'} eq 'current') { $options->{'initialassumedservicestate'} = STATE_CURRENT; } elsif(lc $options->{'initialassumedservicestate'} eq 'ok') { $options->{'initialassumedservicestate'} = STATE_OK; } elsif(lc $options->{'initialassumedservicestate'} eq 'warning') { $options->{'initialassumedservicestate'} = STATE_WARNING; } elsif(lc $options->{'initialassumedservicestate'} eq 'unknown') { $options->{'initialassumedservicestate'} = STATE_UNKNOWN; } elsif(lc $options->{'initialassumedservicestate'} eq 'critical') { $options->{'initialassumedservicestate'} = STATE_CRITICAL; } else { croak('initialassumedservicestate unknown, please use one of: unspecified, current, ok, warning, unknown or critical. Got: '.$options->{'initialassumedservicestate'}); } } # set breakdown if(defined $options->{'breakdown'}) { if(lc $options->{'breakdown'} eq '') { $options->{'breakdown'} = BREAK_NONE; } elsif(lc $options->{'breakdown'} eq 'months') { $options->{'breakdown'} = BREAK_MONTHS; } elsif(lc $options->{'breakdown'} eq 'weeks') { $options->{'breakdown'} = BREAK_WEEKS; } elsif(lc $options->{'breakdown'} eq 'days') { $options->{'breakdown'} = BREAK_DAYS; } elsif(lc $options->{'breakdown'} eq 'none') { $options->{'breakdown'} = BREAK_NONE; } elsif( $options->{'breakdown'} == BREAK_NONE or $options->{'breakdown'} == BREAK_DAYS or $options->{'breakdown'} == BREAK_WEEKS or $options->{'breakdown'} == BREAK_MONTHS) { # ok } else { croak('breakdown unknown, please use one of: months, weeks, days or none. Got: '.$options->{'breakdown'}); } } return $options; } ######################################## sub _add_log_entry { my($self, %opts) = @_; $self->_log('_add_log_entry()') if $verbose; # do we build up a log? return if $self->{'report_options'}->{'build_log'} == FALSE; push @{$self->{'full_log_store'}}, \%opts; return 1; } ######################################## sub _calculate_log { my($self) = @_; $self->_log('_calculate_log()') if $verbose; # combine outside report range log events my $changed = FALSE; if(defined $self->{'first_known_state_before_report'}) { push @{$self->{'full_log_store'}}, $self->{'first_known_state_before_report'}; $changed = TRUE; } if(defined $self->{'first_known_proc_before_report'}) { push @{$self->{'full_log_store'}}, $self->{'first_known_proc_before_report'}; $changed = TRUE; } # sort once more if changed if($changed) { @{$self->{'full_log_store'}} = sort { $a->{'log'}->{'start'} <=> $b->{'log'}->{'start'} } @{$self->{'full_log_store'}}; } # insert fakelog service entry when initial state is fixed if($self->{'report_options'}->{'initialassumedservicestate'} != STATE_UNSPECIFIED and scalar @{$self->{'report_options'}->{'services'}} == 1 ) { my $type; my $first_state = $self->{'report_options'}->{'initialassumedservicestate'}; if($first_state == STATE_CURRENT) { $first_state = $self->{'report_options'}->{'first_state'}; } if($first_state == STATE_OK) { $type = 'OK'; } elsif($first_state == STATE_WARNING) { $type = 'WARNING'; } elsif($first_state == STATE_UNKNOWN) { $type = 'UNKNOWN'; } elsif($first_state == STATE_CRITICAL) { $type = 'CRITICAL'; } my $fake_start = $self->{'report_options'}->{'start'}; if(defined $self->{'full_log_store'}->[0]) { if($fake_start >= $self->{'full_log_store'}->[0]->{'log'}->{'start'}) { $fake_start = $self->{'full_log_store'}->[0]->{'log'}->{'start'} - 1; } } my $fakelog = { 'log' => { 'type' => 'SERVICE '.$type.' (HARD)', 'class' => $type, 'start' => $fake_start, 'plugin_output' => 'First Service State Assumed (Faked Log Entry)', } }; unshift @{$self->{'full_log_store'}}, $fakelog; } # insert fakelog host entry when initial state is fixed if($self->{'report_options'}->{'initialassumedhoststate'} != STATE_UNSPECIFIED and scalar @{$self->{'report_options'}->{'hosts'}} == 1 ) { my $type; my $first_state = $self->{'report_options'}->{'initialassumedhoststate'}; if($first_state == STATE_CURRENT) { $first_state = $self->{'report_options'}->{'first_state'}; } if($first_state == STATE_UP) { $type = 'UP'; } elsif($first_state == STATE_DOWN) { $type = 'DOWN'; } elsif($first_state == STATE_UNREACHABLE) { $type = 'UNREACHABLE'; } my $fake_start = $self->{'report_options'}->{'start'}; if(defined $self->{'full_log_store'}->[0] and $fake_start >= $self->{'full_log_store'}->[0]->{'log'}->{'start'}) { $fake_start = $self->{'full_log_store'}->[0]->{'log'}->{'start'} - 1; } my $fakelog = { 'log' => { 'type' => 'HOST '.$type.' (HARD)', 'class' => $type, 'start' => $fake_start, 'plugin_output' => 'First Host State Assumed (Faked Log Entry)', } }; unshift @{$self->{'full_log_store'}}, $fakelog; } if($verbose) { $self->_log("#################################"); $self->_log("LOG STORE:"); $self->_log(\@{$self->{'full_log_store'}}); $self->_log("#################################"); } for(my $x = 0; $x < scalar @{$self->{'full_log_store'}}; $x++) { my $log_entry = $self->{'full_log_store'}->[$x]; my $next_log_entry = $self->{'full_log_store'}->[$x+1]; my $log = $log_entry->{'log'}; # set end date of current log entry if(defined $next_log_entry->{'log'}->{'start'}) { $log->{'end'} = $next_log_entry->{'log'}->{'start'}; $log->{'duration'} = $self->_duration($log->{'start'} - $log->{'end'}); } else { $log->{'end'} = $self->{'report_options'}->{'end'}; $log->{'duration'} = $self->_duration($log->{'start'} - $log->{'end'}).'+'; } # convert time format if($self->{'report_options'}->{'timeformat'} ne '%s') { $log->{'end'} = strftime $self->{'report_options'}->{'timeformat'}, localtime($log->{'end'}); $log->{'start'} = strftime $self->{'report_options'}->{'timeformat'}, localtime($log->{'start'}); } push @{$self->{'log_output'}}, $log unless defined $log_entry->{'full_only'}; push @{$self->{'full_log_output'}}, $log; } $self->{'log_output_calculated'} = TRUE; return 1; } ######################################## sub _state_to_int { my($self, $string) = @_; return unless defined $string; if(defined $self->{'state_string_2_int'}->{$string}) { return $self->{'state_string_2_int'}->{$string}; } croak("valid values for services are: ok, warning, unknown and critical\nvalues for host: up, down and unreachable"); } ######################################## sub _new_service_data { my($self, $breakdown, $timestamp) = @_; my $data = { time_ok => 0, time_warning => 0, time_unknown => 0, time_critical => 0, scheduled_time_ok => 0, scheduled_time_warning => 0, scheduled_time_unknown => 0, scheduled_time_critical => 0, scheduled_time_indeterminate => 0, time_indeterminate_nodata => 0, time_indeterminate_notrunning => 0, time_indeterminate_outside_timeperiod => 0, }; $data->{'timestamp'} = $timestamp if $timestamp; if($breakdown != BREAK_NONE) { $data->{'breakdown'} = {}; for my $cur (@{$self->{'breakpoints'}}) { my $timestr = $self->_get_break_timestr($cur); next if defined $data->{'breakdown'}->{$timestr}; $data->{'breakdown'}->{$timestr} = $self->_new_service_data(BREAK_NONE, $cur); } } return $data; } ######################################## sub _new_host_data { my($self, $breakdown, $timestamp) = @_; my $data = { time_up => 0, time_down => 0, time_unreachable => 0, scheduled_time_up => 0, scheduled_time_down => 0, scheduled_time_unreachable => 0, scheduled_time_indeterminate => 0, time_indeterminate_nodata => 0, time_indeterminate_notrunning => 0, time_indeterminate_outside_timeperiod => 0, }; $data->{'timestamp'} = $timestamp if $timestamp; if($breakdown != BREAK_NONE) { $data->{'breakdown'} = {}; for my $cur (@{$self->{'breakpoints'}}) { my $timestr = $self->_get_break_timestr($cur); next if defined $data->{'breakdown'}->{$timestr}; $data->{'breakdown'}->{$timestr} = $self->_new_host_data(BREAK_NONE, $cur); } } return $data; } ######################################## sub _get_break_timestr { my($self, $timestamp) = @_; my @localtime = localtime($timestamp); if($self->{'report_options'}->{'breakdown'} == BREAK_DAYS) { return strftime('%Y-%m-%d', @localtime); } elsif($self->{'report_options'}->{'breakdown'} == BREAK_WEEKS) { return strftime('%G-WK%V', @localtime); } elsif($self->{'report_options'}->{'breakdown'} == BREAK_MONTHS) { return strftime('%Y-%m', @localtime); } die('huh?'); return; } ######################################## sub _set_breakpoints { my($self) = @_; $self->{'breakpoints'} = []; return if $self->{'report_options'}->{'breakdown'} == BREAK_NONE; my $cur = $self->{'report_options'}->{'start'}; # round to next 0:00 my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($cur); $cur = mktime(0, 0, 0, $mday, $mon, $year, $wday, $yday, $isdst); while($cur < $self->{'report_options'}->{'end'}) { push @{$self->{'breakpoints'}}, $cur; $cur = $cur + 86400; } return; } ######################################## 1; =head1 BUGS Please report any bugs or feature requests to L. =head1 DEBUGING You may enable the debug mode by setting MONITORING_AVAILABILITY_DEBUG environment variable. This will create a logfile: /tmp/Monitoring-Availability-Debug.log which gets overwritten with every calculation. You will need the Log4Perl module to create this logfile. =head1 SEE ALSO You can also look for information at: =over 4 =item * Search CPAN L =item * Github L =back =head1 AUTHOR Sven Nierlein, Enierlein@cpan.orgE =head1 COPYRIGHT AND LICENSE Copyright (C) 2010 by Sven Nierlein This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut __END__ libmonitoring-availability-perl-0.46/lib/Monitoring/Availability/000077500000000000000000000000001242301703500252315ustar00rootroot00000000000000libmonitoring-availability-perl-0.46/lib/Monitoring/Availability/Logs.pm000066400000000000000000000202211242301703500264700ustar00rootroot00000000000000package Monitoring::Availability::Logs; use 5.008; use strict; use warnings; use Data::Dumper; use Carp; use POSIX qw(strftime); use constant { STATE_UP => 0, STATE_DOWN => 1, STATE_UNREACHABLE => 2, STATE_OK => 0, STATE_WARNING => 1, STATE_CRITICAL => 2, STATE_UNKNOWN => 3, START_NORMAL => 1, START_RESTART => 2, STOP_NORMAL => 0, STOP_ERROR => -1, }; $Monitoring::Availability::Logs::host_states = { 'OK' => 0, 'UP' => 0, 'DOWN' => 1, 'UNREACHABLE' => 2, 'RECOVERY' => 0, 'PENDING' => 0, }; $Monitoring::Availability::Logs::service_states = { 'OK' => 0, 'WARNING' => 1, 'CRITICAL' => 2, 'UNKNOWN' => 3, 'RECOVERY' => 0, 'PENDING' => 0, }; =head1 NAME Monitoring::Availability::Logs - Load/Store/Access Logfiles =head1 DESCRIPTION Store for logfiles =head2 new ( [ARGS] ) Creates an C object. =cut sub new { my $class = shift; my(%options) = @_; my $self = { 'verbose' => 0, # enable verbose output 'logger' => undef, # logger object used for verbose output 'log_string' => undef, # logs from string 'log_livestatus' => undef, # logs from a livestatus query 'log_file' => undef, # logs from a file 'log_dir' => undef, # logs from a dir }; bless $self, $class; for my $opt_key (keys %options) { if(exists $self->{$opt_key}) { $self->{$opt_key} = $options{$opt_key}; } else { croak("unknown option: $opt_key"); } } # create an empty log store $self->{'logs'} = []; # which source do we use? if(defined $self->{'log_string'}) { $self->_store_logs_from_string($self->{'log_string'}); } if(defined $self->{'log_file'}) { $self->_store_logs_from_file($self->{'log_file'}); } if(defined $self->{'log_dir'}) { $self->_store_logs_from_dir($self->{'log_dir'}); } if(defined $self->{'log_livestatus'}) { $self->_store_logs_from_livestatus($self->{'log_livestatus'}); } return $self; } ######################################## =head1 METHODS =head2 get_logs get_logs() returns all read logs as array of hashrefs =cut sub get_logs { my $self = shift; return($self->{'logs'}); } ######################################## =head2 parse_line parse_line($line) return parsed logfile line =cut sub parse_line { return if substr($_[0], 0, 1, '') ne '['; my $return = { 'time' => substr($_[0], 0, 10, '') }; substr($_[0], 0, 2, ''); ($return->{'type'},$_[0]) = split(/:\ /mxo, $_[0], 2); if(!$_[0]) { # extract starts/stops &_set_from_type($return); return $return; } # extract more information from our options &_set_from_options($return->{'type'}, $return, $_[0]); return $return; } ######################################## # INTERNAL SUBS ######################################## sub _store_logs_from_string { my $self = shift; my $string = shift; return unless defined $string; for my $line (split/\n/mxo, $string) { my $data = &parse_line($line); push @{$self->{'logs'}}, $data if defined $data; } return 1; } ######################################## sub _store_logs_from_file { my $self = shift; my $file = shift; return unless defined $file; open(my $FH, '<', $file) or croak('cannot read file '.$file.': '.$!); while(my $line = <$FH>) { chomp($line); my $data = &parse_line($line); push @{$self->{'logs'}}, $data if defined $data; } close($FH); return 1; } ######################################## sub _store_logs_from_dir { my $self = shift; my $dir = shift; return unless defined $dir; opendir(my $dh, $dir) or croak('cannot open directory '.$dir.': '.$!); while(my $file = readdir($dh)) { if($file =~ m/\.log$/mxo) { $self->_store_logs_from_file($dir.'/'.$file); } } closedir $dh; return 1; } ######################################## sub _store_logs_from_livestatus { my $self = shift; my $log_array = shift; return unless defined $log_array; for my $entry (@{$log_array}) { my $data = $self->_parse_livestatus_entry($entry); push @{$self->{'logs'}}, $data if defined $data; } return 1; } ######################################## sub _parse_livestatus_entry { my($self, $entry) = @_; my $string = $entry->{'message'} || $entry->{'options'} || ''; if($string eq '') { # extract starts/stops &_set_from_type($entry, $string); return $entry; } # extract more information from our options if($entry->{'message'}) { return &parse_line($string); } else { &_set_from_options($entry->{'type'}, $entry, $string); } return $entry; } ######################################## sub _set_from_options { my($type, $data, $string) = @_; # Service States if( $type eq 'SERVICE ALERT' or $type eq 'CURRENT SERVICE STATE' or $type eq 'INITIAL SERVICE STATE' ) { my @tmp = split(/;/mxo, $string,6); # regex is faster than strtok here $data->{'host_name'} = $tmp[0]; $data->{'service_description'} = $tmp[1]; $data->{'state'} = $Monitoring::Availability::Logs::service_states->{$tmp[2]}; return unless defined $data->{'state'}; $data->{'hard'} = $tmp[3] eq 'HARD' ? 1 : 0; $data->{'plugin_output'} = $tmp[5]; } # Host States elsif( $type eq 'HOST ALERT' or $type eq 'CURRENT HOST STATE' or $type eq 'INITIAL HOST STATE' ) { my @tmp = split(/;/mxo, $string,5); # regex is faster than strtok here $data->{'host_name'} = $tmp[0]; $data->{'state'} = $Monitoring::Availability::Logs::host_states->{$tmp[1]}; return unless defined $data->{'state'}; $data->{'hard'} = $tmp[2] eq 'HARD' ? 1 : 0; $data->{'plugin_output'} = $tmp[4]; } # Host Downtimes elsif($type eq 'HOST DOWNTIME ALERT') { my @tmp = split(/;/mxo, $string,3); # regex is faster than strtok here $data->{'host_name'} = $tmp[0]; $data->{'start'} = $tmp[1] eq 'STARTED' ? 1 : 0; } # Service Downtimes elsif($type eq 'SERVICE DOWNTIME ALERT') { my @tmp = split(/;/mxo, $string,4); # regex is faster than strtok here $data->{'host_name'} = $tmp[0]; $data->{'service_description'} = $tmp[1]; $data->{'start'} = $tmp[2] eq 'STARTED' ? 1 : 0; } # Timeperiod Transitions # livestatus does not parse this correct, so we have to use regex elsif($type =~ m/^TIMEPERIOD\ TRANSITION/mxo) { my @tmp = split(/;/mxo, $string,3); # regex is faster than strtok here $data->{'type'} = 'TIMEPERIOD TRANSITION'; $data->{'timeperiod'} = $tmp[0]; $data->{'from'} = $tmp[1]; $data->{'to'} = $tmp[2]; } return 1; } ######################################## sub _set_from_type { my($data) = @_; # program starts if($data->{'type'} =~ m/\ starting\.\.\./mxo) { $data->{'proc_start'} = START_NORMAL; } elsif($data->{'type'} =~ m/\ restarting\.\.\./mxo) { $data->{'proc_start'} = START_RESTART; } # program stops elsif($data->{'type'} =~ m/shutting\ down\.\.\./mxo) { $data->{'proc_start'} = STOP_NORMAL; } elsif($data->{'type'} =~ m/Bailing\ out/mxo) { $data->{'proc_start'} = STOP_ERROR; } return 1; } ######################################## 1; =head1 AUTHOR Sven Nierlein, Enierlein@cpan.orgE =head1 COPYRIGHT AND LICENSE Copyright (C) 2010 by Sven Nierlein This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut __END__ libmonitoring-availability-perl-0.46/t/000077500000000000000000000000001242301703500201675ustar00rootroot00000000000000libmonitoring-availability-perl-0.46/t/00_test_utils.pm000066400000000000000000000033071242301703500232260ustar00rootroot00000000000000#!/usr/bin/env perl package TestUtils; ######################### # Test Utils ######################### use strict; use Exporter; use Data::Dumper; use Test::More; use vars qw(@ISA @EXPORT); @ISA = qw(Exporter); @EXPORT = qw ($logger); ######################### # create a logger object if we have log4perl installed our $logger; eval { if(defined $ENV{'TEST_LOG'}) { require Log::Log4perl; Log::Log4perl->import(qw(:easy)); Log::Log4perl->init(\ q{ log4perl.logger = DEBUG, Screen log4perl.appender.Screen = Log::Log4perl::Appender::ScreenColoredLevels log4perl.appender.Screen.stderr = 1 log4perl.appender.Screen.Threshold = DEBUG log4perl.appender.Screen.layout = Log::Log4perl::Layout::PatternLayout log4perl.appender.Screen.layout.ConversionPattern = [%d] %m%n }); $logger = get_logger(); } }; ######################### sub check_array_one_by_one { my $exp = shift; my $got = shift; my $name = shift; for(my $x = 0; $x <= scalar @{$exp}; $x++) { Test::More::is_deeply($got->[$x], $exp->[$x], $name.' '.$x) or Test::More::diag("got:\n".Dumper($got->[$x])."\nbut expected:\n".Dumper($exp->[$x])); } return 1; } ######################### sub parse_logs { my $text = shift; print "my \$expected_log = [\n"; for my $line (split/\n/, $text) { my($start,$end,$duration,$type,$plugin_output) = split/\t/, $line; print " { 'start' => '".$start."', 'end' => '".$end."', 'duration' => '".$duration."', 'type' => '".$type."', 'plugin_output' => '".$plugin_output."' }, \n"; } print "];\n"; } 1; __END__ libmonitoring-availability-perl-0.46/t/01-availability-basic_tests.t000066400000000000000000000004521242301703500255460ustar00rootroot00000000000000#!/usr/bin/env perl ######################### use strict; use Test::More tests => 2; use Data::Dumper; use_ok('Monitoring::Availability'); my $ma = Monitoring::Availability->new(); isa_ok($ma, 'Monitoring::Availability', 'create new Monitoring::Availability object'); ######################### libmonitoring-availability-perl-0.46/t/10-availability-load_logs.t000066400000000000000000000160121242301703500252050ustar00rootroot00000000000000#!/usr/bin/env perl ######################### use strict; use Test::More tests => 60; use Data::Dumper; use File::Temp qw/ tempfile tempdir /; use_ok('Monitoring::Availability::Logs'); ######################### my $expected = [ { 'time' => '1260711580', 'type' => 'Local time is Sun Dec 13 14:39:40 CET 2009' }, { 'time' => '1260711580', 'type' => 'Nagios 3.0.6 starting... (PID=12480)', 'proc_start' => 1 }, { 'time' => '1260711581', 'type' => 'Finished daemonizing... (New PID=12484)' }, { 'time' => '1260715790', 'type' => 'Error' }, { 'time' => '1260715801', 'type' => 'Successfully shutdown... (PID=12502)' }, { 'time' => '1260716221', 'type' => 'Lockfile \'/opt/projects/nagios/n1/var/nagios3.pid\' looks like its already held by another instance of Nagios (PID 13226). Bailing out...', 'proc_start' => -1 }, { 'time' => '1260722815', 'type' => 'Warning' }, { 'time' => '1260725492', 'type' => 'Warning' }, { 'time' => '1260725492', 'type' => 'Warning' }, { 'time' => '1260971246', 'type' => 'PROGRAM_RESTART event encountered, restarting...', 'proc_start' => 2 }, { 'time' => '1261050819', 'type' => 'PASSIVE HOST CHECK' }, { 'time' => '1261685289', 'type' => 'SERVICE NOTIFICATION' }, { 'time' => '1261686379', 'type' => 'SERVICE FLAPPING ALERT' }, { 'time' => '1261686484', 'type' => 'SERVICE ALERT', 'host_name' => 'i0test_host_132', 'service_description' => 'i0test_random_18', 'state' => 2, 'hard' => 1, 'plugin_output' => 'mo CRITICAL: random servicecheck critical' }, { 'time' => '1261687372', 'type' => 'HOST ALERT', 'host_name' => 'i0test_host_198', 'state' => 1, 'hard' => 1, 'plugin_output' => 'mo DOWN: random hostcheck: parent host down' }, { 'time' => '1261687372', 'type' => 'HOST NOTIFICATION' }, { 'time' => '1261687373', 'type' => 'HOST FLAPPING ALERT' }, { 'time' => '1262850812', 'type' => 'Caught SIGSEGV, shutting down...', 'proc_start' => 0 }, { 'time' => '1262850822', 'type' => 'HOST DOWNTIME ALERT', 'host_name' => 'localhost', 'start' => 1 }, { 'time' => '1262850822', 'type' => 'SERVICE DOWNTIME ALERT', 'host_name' => 'localhost', 'service_description' => 'test', 'start' => 1 }, { 'time' => '1263042133', 'type' => 'EXTERNAL COMMAND' }, { 'time' => '1263423600', 'type' => 'CURRENT HOST STATE', 'host_name' => 'i0test_router_19', 'state' => 0, 'hard' => 1, 'plugin_output' => 'mo OK: random hostcheck ok' }, { 'time' => '1263423600', 'type' => 'CURRENT SERVICE STATE', 'host_name' => 'i0test_host_199', 'service_description' => 'i0test_warning_18', 'state' => 1, 'hard' => 1, 'plugin_output' => 'mo WARNING: warning servicecheck' }, { 'time' => '1263423600', 'type' => 'LOG ROTATION' }, { 'time' => '1263457861', 'type' => 'Auto-save of retention data completed successfully.' }, { 'time' => '1263458022', 'type' => 'Caught SIGTERM, shutting down...', 'proc_start' => 0 }, { 'time' => '1263648166', 'type' => 'LOG VERSION' }, ]; my $mal = Monitoring::Availability::Logs->new(); isa_ok($mal, 'Monitoring::Availability::Logs', 'create new Monitoring::Availability::Logs object'); #################################### # try logs, line by line my $x = 0; my $logs; while(my $line = ) { $logs .= $line; $mal->{'logs'} = []; my $rt = $mal->_store_logs_from_string($line); is($rt, 1, '_store_logs_from_string rc') or fail_out($x, $line, $mal); is_deeply($mal->{'logs'}->[0], $expected->[$x], 'reading logs from string') or fail_out($x, $line, $mal); $x++; } #################################### # write logs to temp file and load it my($fh,$filename) = tempfile(CLEANUP => 1); print $fh $logs; close($fh); $mal->{'logs'} = []; my $rt = $mal->_store_logs_from_file($filename); is($rt, 1, '_store_logs_from_file rc'); is_deeply($mal->{'logs'}, $expected, 'reading logs from file'); #################################### # write logs to temp dir and load it my $dir = tempdir( CLEANUP => 1 ); open(my $logfile, '>', $dir.'/monitoring.log') or die('cannot write to '.$dir.'/monitoring.log: '.$!); print $logfile $logs; close($logfile); $mal->{'logs'} = []; $rt = $mal->_store_logs_from_dir($dir); is($rt, 1, '_store_logs_from_dir rc'); is_deeply($mal->{'logs'}, $expected, 'reading logs from dir'); #################################### # fail and die with debug output sub fail_out { my $x = shift; my $line = shift; my $mal = shift; diag('line: '.Dumper($line)); diag('got : '.Dumper($mal->{'logs'}->[0])); diag('exp : '.Dumper($expected->[$x])); BAIL_OUT('failed'); } __DATA__ [1260711580] Local time is Sun Dec 13 14:39:40 CET 2009: 39:40 CET 2009 [1260711580] Nagios 3.0.6 starting... (PID=12480) [1260711581] Finished daemonizing... (New PID=12484) [1260715790] Error: Unable to create temp file for writing status data! [1260715801] Successfully shutdown... (PID=12502) [1260716221] Lockfile '/opt/projects/nagios/n1/var/nagios3.pid' looks like its already held by another instance of Nagios (PID 13226). Bailing out... [1260722815] Warning: The check of host 'test_host_020' looks like it was orphaned (results never came back). I'm scheduling an immediate check of the host... [1260725492] Warning: Check result queue contained results for host 'test_host_105', but the host could not be found! Perhaps you forgot to define the host in your config files? [1260725492] Warning: Check result queue contained results for service 'test_ok_04' on host 'test_host_131', but the service could not be found! Perhaps you forgot to define the service in your config files? [1260971246] PROGRAM_RESTART event encountered, restarting... [1261050819] PASSIVE HOST CHECK: n1_test_router_00;0;blah blah blah [1261685289] SERVICE NOTIFICATION: test_contact;i0test_host_180;i0test_random_18;OK;notify-service;mo REVOVERED: random servicecheck recovered [1261686379] SERVICE FLAPPING ALERT: i0test_host_135;i0test_flap_01;STARTED; Service appears to have started flapping (24.2% change >= 20.0% threshold) [1261686484] SERVICE ALERT: i0test_host_132;i0test_random_18;CRITICAL;HARD;1;mo CRITICAL: random servicecheck critical [1261687372] HOST ALERT: i0test_host_198;DOWN;HARD;1;mo DOWN: random hostcheck: parent host down [1261687372] HOST NOTIFICATION: test_contact;i0test_host_198;DOWN;notify-host;mo DOWN: random hostcheck: parent host down [1261687373] HOST FLAPPING ALERT: i0test_host_198;STARTED; Host appears to have started flapping (20.3% change > 20.0% threshold) [1262850812] Caught SIGSEGV, shutting down... [1262850822] HOST DOWNTIME ALERT: localhost;STARTED; Host has entered a period of scheduled downtime [1262850822] SERVICE DOWNTIME ALERT: localhost;test;STARTED; Service has entered a period of scheduled downtime [1263042133] EXTERNAL COMMAND: ENABLE_NOTIFICATIONS; [1263423600] CURRENT HOST STATE: i0test_router_19;UP;HARD;1;mo OK: random hostcheck ok [1263423600] CURRENT SERVICE STATE: i0test_host_199;i0test_warning_18;WARNING;HARD;3;mo WARNING: warning servicecheck [1263423600] LOG ROTATION: DAILY: DAILY [1263457861] Auto-save of retention data completed successfully. [1263458022] Caught SIGTERM, shutting down... [1263648166] LOG VERSION: 2.0 libmonitoring-availability-perl-0.46/t/11-availability-load_logs_livestatus.t000066400000000000000000000137521242301703500275010ustar00rootroot00000000000000#!/usr/bin/env perl ######################### use strict; use Test::More tests => 4; use Data::Dumper; use_ok('Monitoring::Availability::Logs'); ######################### my $livestatus_logs= [ { 'time' => '1263423600', 'type' => 'CURRENT HOST STATE', 'options' => 'i0test_router_19;UP;HARD;1;mo OK: random hostcheck ok', 'host_name' => 'i0test_router_19', 'service_description' => '', 'plugin_output' => 'mo OK: random hostcheck ok', 'state' => '0', 'class' => '6', }, { 'time' => '1263423600', 'type' => 'CURRENT SERVICE STATE', 'service_description' => 'i0test_warning_18', 'plugin_output' => 'mo WARNING: warning servicecheck', 'options' => 'i0test_host_199;i0test_warning_18;WARNING;HARD;3;mo WARNING: warning servicecheck', 'state' => '1', 'host_name' => 'i0test_host_199', 'class' => '6', }, { 'time' => '1261184172', 'type' => 'Caught SIGHUP, restarting...', 'options' => '', 'class' => '2', 'state' => '0' }, { 'time' => '1263650899', 'type' => 'Caught SIGTERM, shutting down...', 'options' => '', 'class' => '2', 'state' => '0' }, { 'time' => '1261687372', 'type' => 'HOST ALERT', 'options' => 'i0test_host_198;DOWN;HARD;1;mo DOWN: random hostcheck: parent host down', 'service_description' => '', 'plugin_output' => 'mo DOWN: random hostcheck: parent host down', 'state' => '1', 'host_name' => 'i0test_host_198', 'class' => '1', }, { 'time' => '1262850822', 'type' => 'HOST DOWNTIME ALERT', 'options' => 'localhost;STARTED; Host has entered a period of scheduled downtime', 'host_name' => 'localhost', 'class' => '1', 'state' => '0' }, { 'time' => '1261386470', 'type' => 'Nagios 3.0.6 starting... (PID=10056)', 'options' => '', 'class' => '2', 'state' => '0' }, { 'time' => '1261686484', 'type' => 'SERVICE ALERT', 'options' => 'i0test_host_132;i0test_random_18;CRITICAL;HARD;1;mo CRITICAL: random servicecheck critical', 'service_description' => 'i0test_random_18', 'plugin_output' => 'mo CRITICAL: random servicecheck critical', 'state' => '2', 'host_name' => 'i0test_host_132', 'class' => '1', }, { 'time' => '1262850822', 'type' => 'SERVICE DOWNTIME ALERT', 'options' => 'localhost;test;STARTED; Service has entered a period of scheduled downtime', 'service_description' => 'test', 'host_name' => 'localhost', 'class' => '1', 'state' => '0' }, { 'time' => '1261686379', 'type' => 'SERVICE FLAPPING ALERT', 'options' => 'i0test_host_135;i0test_flap_01;STARTED; Service appears to have started flapping (24.2% change >= 20.0% threshold)', 'service_description' => 'i0test_flap_01', 'host_name' => 'i0test_host_135', 'class' => '1', 'state' => '0' }, { 'time' => '1261685289', 'type' => 'SERVICE NOTIFICATION', 'options' => 'test_contact;i0test_host_180;i0test_random_18;OK;notify-service;mo REVOVERED: random servicecheck recovered', 'service_description' => 'i0test_random_18', 'plugin_output' => 'mo REVOVERED: random servicecheck recovered', 'state' => '0', 'host_name' => 'i0test_host_180', 'class' => '3', }, ]; my $expected = [ {'plugin_output' => 'mo OK: random hostcheck ok','service_description' => '','options' => 'i0test_router_19;UP;HARD;1;mo OK: random hostcheck ok','time' => '1263423600','state' => 0,'host_name' => 'i0test_router_19','type' => 'CURRENT HOST STATE','class' => '6','hard' => 1}, {'plugin_output' => 'mo WARNING: warning servicecheck','service_description' => 'i0test_warning_18','options' => 'i0test_host_199;i0test_warning_18;WARNING;HARD;3;mo WARNING: warning servicecheck','time' => '1263423600','state' => 1,'host_name' => 'i0test_host_199','type' => 'CURRENT SERVICE STATE','class' => '6','hard' => 1}, {'options' => '','time' => '1261184172','class' => '2','type' => 'Caught SIGHUP, restarting...','proc_start' => 2,'state' => '0'}, {'options' => '','time' => '1263650899','class' => '2','type' => 'Caught SIGTERM, shutting down...','proc_start' => 0,'state' => '0'}, {'plugin_output' => 'mo DOWN: random hostcheck: parent host down','service_description' => '','options' => 'i0test_host_198;DOWN;HARD;1;mo DOWN: random hostcheck: parent host down','time' => '1261687372','state' => 1,'host_name' => 'i0test_host_198','type' => 'HOST ALERT','class' => '1','hard' => 1}, {'options' => 'localhost;STARTED; Host has entered a period of scheduled downtime','time' => '1262850822','host_name' => 'localhost','class' => '1','type' => 'HOST DOWNTIME ALERT','start' => 1,'state' => '0'}, {'options' => '','time' => '1261386470','class' => '2','type' => 'Nagios 3.0.6 starting... (PID=10056)','proc_start' => 1,'state' => '0'}, {'plugin_output' => 'mo CRITICAL: random servicecheck critical','service_description' => 'i0test_random_18','options' => 'i0test_host_132;i0test_random_18;CRITICAL;HARD;1;mo CRITICAL: random servicecheck critical','time' => '1261686484','state' => 2,'host_name' => 'i0test_host_132','type' => 'SERVICE ALERT','class' => '1','hard' => 1}, {'service_description' => 'test','options' => 'localhost;test;STARTED; Service has entered a period of scheduled downtime','time' => '1262850822','state' => '0','host_name' => 'localhost','type' => 'SERVICE DOWNTIME ALERT','class' => '1','start' => 1}, {'service_description' => 'i0test_flap_01','options' => 'i0test_host_135;i0test_flap_01;STARTED; Service appears to have started flapping (24.2% change >= 20.0% threshold)','time' => '1261686379','host_name' => 'i0test_host_135','class' => '1','type' => 'SERVICE FLAPPING ALERT','state' => '0'}, {'plugin_output' => 'mo REVOVERED: random servicecheck recovered','service_description' => 'i0test_random_18','options' => 'test_contact;i0test_host_180;i0test_random_18;OK;notify-service;mo REVOVERED: random servicecheck recovered','time' => '1261685289','state' => '0','host_name' => 'i0test_host_180','type' => 'SERVICE NOTIFICATION','class' => '3'} ]; my $mal = Monitoring::Availability::Logs->new(); isa_ok($mal, 'Monitoring::Availability::Logs', 'create new Monitoring::Availability::Logs object'); my $rc = $mal->_store_logs_from_livestatus($livestatus_logs); is($rc, 1, '_store_logs_from_livestatus rc'); is_deeply($mal->{'logs'}, $expected, 'sample 1 result'); libmonitoring-availability-perl-0.46/t/20-availability-host_up.t000066400000000000000000000035371242301703500247340ustar00rootroot00000000000000#!/usr/bin/env perl ######################### use strict; use Test::More tests => 3; use Data::Dumper; BEGIN { require 't/00_test_utils.pm'; import TestUtils; } use_ok('Monitoring::Availability'); ######################### # read logs from data my $logs; while(my $line = ) { $logs .= $line; } my $expected = { 'services' => {}, 'hosts' => { 'n0_test_host_000' => { 'time_up' => 507250, 'time_down' => 0, 'time_unreachable' => 0, 'scheduled_time_up' => 0, 'scheduled_time_down' => 0, 'scheduled_time_unreachable' => 0, 'scheduled_time_indeterminate' => 0, 'time_indeterminate_nodata' => 97550, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_outside_timeperiod' => 0, } } }; ######################### my $ma = Monitoring::Availability->new( 'verbose' => 0, 'backtrack' => 4, 'assumestateretention' => 'yes', 'assumeinitialstates' => 'yes', 'assumestatesduringnotrunning' => 'yes', 'initialassumedhoststate' => 'unspecified', 'initialassumedservicestate' => 'unspecified', ); isa_ok($ma, 'Monitoring::Availability', 'create new Monitoring::Availability object'); my $result = $ma->calculate( 'log_string' => $logs, 'hosts' => ['n0_test_host_000'], 'start' => 1262894050, 'end' => 1263498850, ); is_deeply($result, $expected, 'up host') or diag("got:\n".Dumper($result)."\nbut expected:\n".Dumper($expected)); __DATA__ [1262962252] Nagios 3.2.0 starting... (PID=7873) [1262991600] CURRENT HOST STATE: n0_test_host_000;UP;HARD;1;n0_test_host_000 ... libmonitoring-availability-perl-0.46/t/21-availability-host_down.t000066400000000000000000000035421242301703500252540ustar00rootroot00000000000000#!/usr/bin/env perl ######################### use strict; use Test::More tests => 3; use Data::Dumper; BEGIN { require 't/00_test_utils.pm'; import TestUtils; } use_ok('Monitoring::Availability'); ######################### # read logs from data my $logs; while(my $line = ) { $logs .= $line; } my $expected = { 'services' => {}, 'hosts' => { 'n0_test_host_000' => { 'time_up' => 0, 'time_down' => 507250, 'time_unreachable' => 0, 'scheduled_time_up' => 0, 'scheduled_time_down' => 0, 'scheduled_time_unreachable' => 0, 'scheduled_time_indeterminate' => 0, 'time_indeterminate_nodata' => 97550, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_outside_timeperiod' => 0, } } }; ######################### my $ma = Monitoring::Availability->new( 'verbose' => 0, 'backtrack' => 4, 'assumestateretention' => 'yes', 'assumeinitialstates' => 'yes', 'assumestatesduringnotrunning' => 'no', 'initialassumedhoststate' => 'unspecified', 'initialassumedservicestate' => 'unspecified', ); isa_ok($ma, 'Monitoring::Availability', 'create new Monitoring::Availability object'); my $result = $ma->calculate( 'log_string' => $logs, 'hosts' => ['n0_test_host_000'], 'start' => 1262894050, 'end' => 1263498850, ); is_deeply($result, $expected, 'down host') or diag("got:\n".Dumper($result)."\nbut expected:\n".Dumper($expected)); __DATA__ [1262962252] Nagios 3.2.0 starting... (PID=7873) [1262991600] CURRENT HOST STATE: n0_test_host_000;DOWN;HARD;1;n0_test_host_000 ... libmonitoring-availability-perl-0.46/t/22-availability-host_unreachable.t000066400000000000000000000035601242301703500265570ustar00rootroot00000000000000#!/usr/bin/env perl ######################### use strict; use Test::More tests => 3; use Data::Dumper; BEGIN { require 't/00_test_utils.pm'; import TestUtils; } use_ok('Monitoring::Availability'); ######################### # read logs from data my $logs; while(my $line = ) { $logs .= $line; } my $expected = { 'services' => {}, 'hosts' => { 'n0_test_host_000' => { 'time_up' => 0, 'time_down' => 0, 'time_unreachable' => 507250, 'scheduled_time_up' => 0, 'scheduled_time_down' => 0, 'scheduled_time_unreachable' => 0, 'scheduled_time_indeterminate' => 0, 'time_indeterminate_nodata' => 97550, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_outside_timeperiod' => 0, } } }; ######################### my $ma = Monitoring::Availability->new( 'verbose' => 0, 'backtrack' => 4, 'assumestateretention' => 'yes', 'assumeinitialstates' => 'yes', 'assumestatesduringnotrunning' => 'no', 'initialassumedhoststate' => 'unspecified', 'initialassumedservicestate' => 'unspecified', ); isa_ok($ma, 'Monitoring::Availability', 'create new Monitoring::Availability object'); my $result = $ma->calculate( 'log_string' => $logs, 'hosts' => ['n0_test_host_000'], 'start' => 1262894050, 'end' => 1263498850, ); is_deeply($result, $expected, 'unreachable host') or diag("got:\n".Dumper($result)."\nbut expected:\n".Dumper($expected)); __DATA__ [1262962252] Nagios 3.2.0 starting... (PID=7873) [1262991600] CURRENT HOST STATE: n0_test_host_000;UNREACHABLE;HARD;1;n0_test_host_000 ... libmonitoring-availability-perl-0.46/t/23-availability-service_ok.t000066400000000000000000000042341242301703500254020ustar00rootroot00000000000000#!/usr/bin/env perl ######################### use strict; use Test::More tests => 3; use Data::Dumper; BEGIN { require 't/00_test_utils.pm'; import TestUtils; } use_ok('Monitoring::Availability'); ######################### # read logs from data my $logs; while(my $line = ) { $logs .= $line; } my $expected = { 'hosts' => {}, 'services' => { 'n0_test_host_000' => { 'n0_test_random_04' => { 'time_ok' => 507250, 'time_warning' => 0, 'time_unknown' => 0, 'time_critical' => 0, 'scheduled_time_ok' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_critical' => 0, 'scheduled_time_indeterminate' => 0, 'time_indeterminate_nodata' => 97550, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_outside_timeperiod' => 0, } } } }; ######################### my $ma = Monitoring::Availability->new( 'verbose' => 0, 'backtrack' => 4, 'assumestateretention' => 'yes', 'assumeinitialstates' => 'yes', 'assumestatesduringnotrunning' => 'no', 'initialassumedhoststate' => 'unspecified', 'initialassumedservicestate' => 'unspecified', ); isa_ok($ma, 'Monitoring::Availability', 'create new Monitoring::Availability object'); my $result = $ma->calculate( 'log_string' => $logs, 'services' => [{'host' => 'n0_test_host_000', 'service' => 'n0_test_random_04'}], 'start' => 1262894050, 'end' => 1263498850, ); is_deeply($result, $expected, 'ok service') or diag("got:\n".Dumper($result)."\nbut expected:\n".Dumper($expected)); __DATA__ [1262962252] Nagios 3.2.0 starting... (PID=7873) [1262991600] CURRENT SERVICE STATE: n0_test_host_000;n0_test_random_04;OK;HARD;1;n0_test_host_000 (checked by mo) REVOVERED: random n0_test_random_04 recovered libmonitoring-availability-perl-0.46/t/24-availability-service_warning.t000066400000000000000000000041541242301703500264400ustar00rootroot00000000000000#!/usr/bin/env perl ######################### use strict; use Test::More tests => 3; use Data::Dumper; BEGIN { require 't/00_test_utils.pm'; import TestUtils; } use_ok('Monitoring::Availability'); ######################### # read logs from data my $logs; while(my $line = ) { $logs .= $line; } my $expected = { 'hosts' => {}, 'services' => { 'n0_test_host_000' => { 'n0_test_random_04' => { 'time_ok' => 0, 'time_warning' => 507250, 'time_unknown' => 0, 'time_critical' => 0, 'scheduled_time_ok' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_critical' => 0, 'scheduled_time_indeterminate' => 0, 'time_indeterminate_nodata' => 97550, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_outside_timeperiod' => 0, } } } }; ######################### my $ma = Monitoring::Availability->new( 'verbose' => 0, 'backtrack' => 4, 'assumestateretention' => 'yes', 'assumeinitialstates' => 'yes', 'assumestatesduringnotrunning' => 'no', 'initialassumedhoststate' => 'unspecified', 'initialassumedservicestate' => 'unspecified', ); isa_ok($ma, 'Monitoring::Availability', 'create new Monitoring::Availability object'); my $result = $ma->calculate( 'log_string' => $logs, 'services' => [{'host' => 'n0_test_host_000', 'service' => 'n0_test_random_04'}], 'start' => 1262894050, 'end' => 1263498850, ); is_deeply($result, $expected, 'warning service') or diag("got:\n".Dumper($result)."\nbut expected:\n".Dumper($expected)); __DATA__ [1262962252] Nagios 3.2.0 starting... (PID=7873) [1262991600] CURRENT SERVICE STATE: n0_test_host_000;n0_test_random_04;WARNING;HARD;1;n0_test_host_000 ... libmonitoring-availability-perl-0.46/t/25-availability-service_critical.t000066400000000000000000000041561242301703500265700ustar00rootroot00000000000000#!/usr/bin/env perl ######################### use strict; use Test::More tests => 3; use Data::Dumper; BEGIN { require 't/00_test_utils.pm'; import TestUtils; } use_ok('Monitoring::Availability'); ######################### # read logs from data my $logs; while(my $line = ) { $logs .= $line; } my $expected = { 'hosts' => {}, 'services' => { 'n0_test_host_000' => { 'n0_test_random_04' => { 'time_ok' => 0, 'time_warning' => 0, 'time_unknown' => 0, 'time_critical' => 507250, 'scheduled_time_ok' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_critical' => 0, 'scheduled_time_indeterminate' => 0, 'time_indeterminate_nodata' => 97550, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_outside_timeperiod' => 0, } } } }; ######################### my $ma = Monitoring::Availability->new( 'verbose' => 0, 'backtrack' => 4, 'assumestateretention' => 'yes', 'assumeinitialstates' => 'yes', 'assumestatesduringnotrunning' => 'no', 'initialassumedhoststate' => 'unspecified', 'initialassumedservicestate' => 'unspecified', ); isa_ok($ma, 'Monitoring::Availability', 'create new Monitoring::Availability object'); my $result = $ma->calculate( 'log_string' => $logs, 'services' => [{'host' => 'n0_test_host_000', 'service' => 'n0_test_random_04'}], 'start' => 1262894050, 'end' => 1263498850, ); is_deeply($result, $expected, 'critical service') or diag("got:\n".Dumper($result)."\nbut expected:\n".Dumper($expected)); __DATA__ [1262962252] Nagios 3.2.0 starting... (PID=7873) [1262991600] CURRENT SERVICE STATE: n0_test_host_000;n0_test_random_04;CRITICAL;HARD;1;n0_test_host_000 ... libmonitoring-availability-perl-0.46/t/26-availability-service_unknown.t000066400000000000000000000041541242301703500264740ustar00rootroot00000000000000#!/usr/bin/env perl ######################### use strict; use Test::More tests => 3; use Data::Dumper; BEGIN { require 't/00_test_utils.pm'; import TestUtils; } use_ok('Monitoring::Availability'); ######################### # read logs from data my $logs; while(my $line = ) { $logs .= $line; } my $expected = { 'hosts' => {}, 'services' => { 'n0_test_host_000' => { 'n0_test_random_04' => { 'time_ok' => 0, 'time_warning' => 0, 'time_unknown' => 507250, 'time_critical' => 0, 'scheduled_time_ok' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_critical' => 0, 'scheduled_time_indeterminate' => 0, 'time_indeterminate_nodata' => 97550, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_outside_timeperiod' => 0, } } } }; ######################### my $ma = Monitoring::Availability->new( 'verbose' => 0, 'backtrack' => 4, 'assumestateretention' => 'yes', 'assumeinitialstates' => 'yes', 'assumestatesduringnotrunning' => 'no', 'initialassumedhoststate' => 'unspecified', 'initialassumedservicestate' => 'unspecified', ); isa_ok($ma, 'Monitoring::Availability', 'create new Monitoring::Availability object'); my $result = $ma->calculate( 'log_string' => $logs, 'services' => [{'host' => 'n0_test_host_000', 'service' => 'n0_test_random_04'}], 'start' => 1262894050, 'end' => 1263498850, ); is_deeply($result, $expected, 'unknown service') or diag("got:\n".Dumper($result)."\nbut expected:\n".Dumper($expected)); __DATA__ [1262962252] Nagios 3.2.0 starting... (PID=7873) [1262991600] CURRENT SERVICE STATE: n0_test_host_000;n0_test_random_04;UNKNOWN;HARD;1;n0_test_host_000 ... libmonitoring-availability-perl-0.46/t/30-availability-host_with_downtime.t000066400000000000000000000115131242301703500271630ustar00rootroot00000000000000#!/usr/bin/env perl ######################### use strict; use Test::More; use Data::Dumper; # checks against localtime will fail otherwise use POSIX qw(tzset); $ENV{'TZ'} = "CET"; POSIX::tzset(); BEGIN { if( $^O eq 'MSWin32' ) { plan skip_all => 'windows is not supported'; } else { plan tests => 14; } require 't/00_test_utils.pm'; import TestUtils; } use_ok('Monitoring::Availability'); ######################### # read logs from data my $logs; while(my $line = ) { $logs .= $line; } my $expected = { 'services' => {}, 'hosts' => { 'n0_test_host_000' => { 'time_up' => 507245, 'time_down' => 0, 'time_unreachable' => 0, 'scheduled_time_up' => 680, 'scheduled_time_down' => 0, 'scheduled_time_unreachable' => 0, 'scheduled_time_indeterminate' => 0, 'time_indeterminate_nodata' => 97550, 'time_indeterminate_notrunning' => 5, 'time_indeterminate_outside_timeperiod' => 0, } } }; my $expected_condensed_log = [ { 'start' => '2010-01-09 00:00:00', end => '2010-01-09 14:11:33', 'duration' => '0d 14h 11m 33s', 'type' => 'HOST UP (HARD)', plugin_output => 'n0_test_host_000 ...', 'class' => 'UP', 'in_downtime' => 0 }, { 'start' => '2010-01-09 14:11:33', end => '2010-01-09 14:22:53', 'duration' => '0d 0h 11m 20s', 'type' => 'HOST DOWNTIME START', plugin_output => 'Start of scheduled downtime', 'class' => 'INDETERMINATE', 'in_downtime' => 1 }, { 'start' => '2010-01-09 14:22:53', end => '2010-01-09 14:25:55', 'duration' => '0d 0h 3m 2s', 'type' => 'HOST DOWNTIME STOP', plugin_output => 'End of scheduled downtime', 'class' => 'INDETERMINATE', 'in_downtime' => 0 }, ]; my $expected_full_log = [ { 'start' => '2010-01-08 15:50:52', end => '2010-01-09 00:00:00', 'duration' => '0d 8h 9m 8s', 'type' => 'PROGRAM (RE)START', plugin_output => 'Program start', 'class' => 'INDETERMINATE' }, { 'start' => '2010-01-09 00:00:00', end => '2010-01-09 14:11:33', 'duration' => '0d 14h 11m 33s', 'type' => 'HOST UP (HARD)', plugin_output => 'n0_test_host_000 ...', 'class' => 'UP', 'in_downtime' => 0 }, { 'start' => '2010-01-09 14:11:33', end => '2010-01-09 14:22:53', 'duration' => '0d 0h 11m 20s', 'type' => 'HOST DOWNTIME START', plugin_output => 'Start of scheduled downtime', 'class' => 'INDETERMINATE', 'in_downtime' => 1 }, { 'start' => '2010-01-09 14:22:53', end => '2010-01-09 14:25:55', 'duration' => '0d 0h 3m 2s', 'type' => 'HOST DOWNTIME STOP', plugin_output => 'End of scheduled downtime', 'class' => 'INDETERMINATE', 'in_downtime' => 0 }, { 'start' => '2010-01-09 14:25:55', end => '2010-01-09 14:26:00', 'duration' => '0d 0h 0m 5s', 'type' => 'PROGRAM END', plugin_output => 'Normal program termination', 'class' => 'INDETERMINATE' }, { 'start' => '2010-01-09 14:26:00', end => '2010-01-14 20:54:10', 'duration' => '5d 6h 28m 10s+', 'type' => 'PROGRAM (RE)START', plugin_output => 'Program start', 'class' => 'INDETERMINATE' }, ]; ######################### my $ma = Monitoring::Availability->new( 'verbose' => 0, 'backtrack' => 4, 'assumestateretention' => 'yes', 'assumeinitialstates' => 'yes', 'assumestatesduringnotrunning' => 'no', 'initialassumedhoststate' => 'unspecified', 'initialassumedservicestate' => 'unspecified', ); isa_ok($ma, 'Monitoring::Availability', 'create new Monitoring::Availability object'); my $result = $ma->calculate( 'log_string' => $logs, 'hosts' => ['n0_test_host_000'], 'start' => 1262894050, 'end' => 1263498850, 'timeformat' => '%Y-%m-%d %H:%M:%S', ); is_deeply($result, $expected, 'host with downtime') or diag("got:\n".Dumper($result)."\nbut expected:\n".Dumper($expected)); my $condensed_logs = $ma->get_condensed_logs(); # test will fail on windows because of a different used timezone TestUtils::check_array_one_by_one($expected_condensed_log, $condensed_logs, 'condensed logs'); my $full_logs = $ma->get_full_logs(); # test will fail on windows because of a different used timezone TestUtils::check_array_one_by_one($expected_full_log, $full_logs, 'full logs'); __DATA__ [1262962252] Nagios 3.2.0 starting... (PID=7873) [1262991600] CURRENT HOST STATE: n0_test_host_000;OK;HARD;1;n0_test_host_000 ... [1263042693] HOST DOWNTIME ALERT: n0_test_host_000;STARTED; Host has entered a period of scheduled downtime [1263043373] HOST DOWNTIME ALERT: n0_test_host_000;STOPPED; Host has exited from a period of scheduled downtime [1263043555] Caught SIGSEGV, shutting down... [1263043560] Nagios 3.2.0 starting... (PID=22865) libmonitoring-availability-perl-0.46/t/30-availability-service_with_hostdowntimes.t000066400000000000000000000051271242301703500307330ustar00rootroot00000000000000#!/usr/bin/env perl ######################### use strict; use Test::More; use Data::Dumper; BEGIN { if( $^O eq 'MSWin32' ) { plan skip_all => 'windows is not supported'; } else { plan tests => 3; } require 't/00_test_utils.pm'; import TestUtils; } use_ok('Monitoring::Availability'); ######################### # read logs from data my $logs; while(my $line = ) { $logs .= $line; } my $expected = { 'hosts' => {}, 'services' => { 'n0_test_host_000' => { 'n0_test_random_04' => { 'time_ok' => 507245, 'time_warning' => 0, 'time_unknown' => 0, 'time_critical' => 0, 'scheduled_time_ok' => 680, 'scheduled_time_warning' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_critical' => 0, 'scheduled_time_indeterminate' => 0, 'time_indeterminate_nodata' => 97550, 'time_indeterminate_notrunning' => 5, 'time_indeterminate_outside_timeperiod' => 0, } } } }; ######################### my $ma = Monitoring::Availability->new( 'verbose' => 0, 'backtrack' => 4, 'assumestateretention' => 'yes', 'assumeinitialstates' => 'yes', 'assumestatesduringnotrunning' => 'no', 'initialassumedhoststate' => 'unspecified', 'initialassumedservicestate' => 'unspecified', ); isa_ok($ma, 'Monitoring::Availability', 'create new Monitoring::Availability object'); my $result = $ma->calculate( 'log_string' => $logs, 'services' => [{'host' => 'n0_test_host_000', 'service' => 'n0_test_random_04'}], 'start' => 1262894050, 'end' => 1263498850, ); is_deeply($result, $expected, 'sample 1 result') or diag("got:\n".Dumper($result)."\nbut expected:\n".Dumper($expected)); __DATA__ [1262962252] Nagios 3.2.0 starting... (PID=7873) [1262991600] CURRENT SERVICE STATE: n0_test_host_000;n0_test_random_04;OK;HARD;1;n0_test_host_000 (checked by mo) REVOVERED: random n0_test_random_04 recovered [1263042693] HOST DOWNTIME ALERT: n0_test_host_000;STARTED; Host has entered a period of scheduled downtime [1263043373] HOST DOWNTIME ALERT: n0_test_host_000;STOPPED; Host has exited from a period of scheduled downtime [1263043555] Caught SIGSEGV, shutting down... [1263043560] Nagios 3.2.0 starting... (PID=22865) libmonitoring-availability-perl-0.46/t/31-availability-host_with_services.t000066400000000000000000000451061242301703500271660ustar00rootroot00000000000000#!/usr/bin/env perl ######################### use strict; use Test::More; use Data::Dumper; # checks against localtime will fail otherwise use POSIX qw(tzset); $ENV{'TZ'} = "CET"; POSIX::tzset(); BEGIN { if( $^O eq 'MSWin32' ) { plan skip_all => 'windows is not supported'; } else { plan tests => 19; } require 't/00_test_utils.pm'; import TestUtils; } use_ok('Monitoring::Availability'); ######################### # read logs from data my $logs; while(my $line = ) { $logs .= $line; } my $expected = { 'hosts' => { 'n0_test_host_001' => { 'time_down' => 0, 'time_indeterminate_notrunning' => 0, 'scheduled_time_down' => 0, 'scheduled_time_up' => 0, 'time_unreachable' => 0, 'time_indeterminate_nodata' => 396597, 'time_indeterminate_outside_timeperiod' => 0, 'time_up' => 208203, 'scheduled_time_unreachable' => 0, 'scheduled_time_indeterminate' => 0 } }, 'services' => { 'n0_test_host_001' => { 'n0_test_flap_19' => { 'time_ok' => 208203, 'scheduled_time_critical' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_ok' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_nodata' => 396597, 'time_indeterminate_outside_timeperiod' => 0, 'time_warning' => 0, 'time_critical' => 0, 'time_unknown' => 0, 'scheduled_time_indeterminate' => 0 }, 'n0_test_pending_06' => { 'time_ok' => 208203, 'scheduled_time_critical' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_ok' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_nodata' => 396597, 'time_indeterminate_outside_timeperiod' => 0, 'time_warning' => 0, 'time_critical' => 0, 'time_unknown' => 0, 'scheduled_time_indeterminate' => 0 }, 'n0_test_random_03' => { 'time_ok' => 208203, 'scheduled_time_critical' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_ok' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_nodata' => 396597, 'time_indeterminate_outside_timeperiod' => 0, 'time_warning' => 0, 'time_critical' => 0, 'time_unknown' => 0, 'scheduled_time_indeterminate' => 0 }, 'n0_test_ok_05' => { 'time_ok' => 208203, 'scheduled_time_critical' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_ok' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_nodata' => 396597, 'time_indeterminate_outside_timeperiod' => 0, 'time_warning' => 0, 'time_critical' => 0, 'time_unknown' => 0, 'scheduled_time_indeterminate' => 0 }, 'n0_test_unknown_04' => { 'time_ok' => 0, 'scheduled_time_critical' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_ok' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_nodata' => 396597, 'time_indeterminate_outside_timeperiod' => 0, 'time_warning' => 0, 'time_critical' => 0, 'time_unknown' => 208203, 'scheduled_time_indeterminate' => 0 }, 'n0_test_random_13' => { 'time_ok' => 208203, 'scheduled_time_critical' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_ok' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_nodata' => 396597, 'time_indeterminate_outside_timeperiod' => 0, 'time_warning' => 0, 'time_critical' => 0, 'time_unknown' => 0, 'scheduled_time_indeterminate' => 0 }, 'n0_test_ok_14' => { 'time_ok' => 208203, 'scheduled_time_critical' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_ok' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_nodata' => 396597, 'time_indeterminate_outside_timeperiod' => 0, 'time_warning' => 0, 'time_critical' => 0, 'time_unknown' => 0, 'scheduled_time_indeterminate' => 0 }, 'n0_test_ok_17' => { 'time_ok' => 208203, 'scheduled_time_critical' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_ok' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_nodata' => 396597, 'time_indeterminate_outside_timeperiod' => 0, 'time_warning' => 0, 'time_critical' => 0, 'time_unknown' => 0, 'scheduled_time_indeterminate' => 0 }, 'n0_test_random_02' => { 'time_ok' => 208203, 'scheduled_time_critical' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_ok' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_nodata' => 396597, 'time_indeterminate_outside_timeperiod' => 0, 'time_warning' => 0, 'time_critical' => 0, 'time_unknown' => 0, 'scheduled_time_indeterminate' => 0 }, 'n0_test_ok_12' => { 'time_ok' => 208203, 'scheduled_time_critical' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_ok' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_nodata' => 396597, 'time_indeterminate_outside_timeperiod' => 0, 'time_warning' => 0, 'time_critical' => 0, 'time_unknown' => 0, 'scheduled_time_indeterminate' => 0 }, 'n0_test_ok_08' => { 'time_ok' => 208203, 'scheduled_time_critical' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_ok' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_nodata' => 396597, 'time_indeterminate_outside_timeperiod' => 0, 'time_warning' => 0, 'time_critical' => 0, 'time_unknown' => 0, 'scheduled_time_indeterminate' => 0 }, 'n0_test_warning_18' => { 'time_ok' => 0, 'scheduled_time_critical' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_ok' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_nodata' => 396597, 'time_indeterminate_outside_timeperiod' => 0, 'time_warning' => 208203, 'time_critical' => 0, 'time_unknown' => 0, 'scheduled_time_indeterminate' => 0 }, 'n0_test_ok_11' => { 'time_ok' => 208203, 'scheduled_time_critical' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_ok' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_nodata' => 396597, 'time_indeterminate_outside_timeperiod' => 0, 'time_warning' => 0, 'time_critical' => 0, 'time_unknown' => 0, 'scheduled_time_indeterminate' => 0 }, 'n0_test_ok_07' => { 'time_ok' => 208203, 'scheduled_time_critical' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_ok' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_nodata' => 396597, 'time_indeterminate_outside_timeperiod' => 0, 'time_warning' => 0, 'time_critical' => 0, 'time_unknown' => 0, 'scheduled_time_indeterminate' => 0 }, 'n0_test_flap_00' => { 'time_ok' => 208203, 'scheduled_time_critical' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_ok' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_nodata' => 396597, 'time_indeterminate_outside_timeperiod' => 0, 'time_warning' => 0, 'time_critical' => 0, 'time_unknown' => 0, 'scheduled_time_indeterminate' => 0 }, 'n0_test_ok_10' => { 'time_ok' => 208203, 'scheduled_time_critical' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_ok' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_nodata' => 396597, 'time_indeterminate_outside_timeperiod' => 0, 'time_warning' => 0, 'time_critical' => 0, 'time_unknown' => 0, 'scheduled_time_indeterminate' => 0 }, 'n0_test_ok_09' => { 'time_ok' => 208203, 'scheduled_time_critical' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_ok' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_nodata' => 396597, 'time_indeterminate_outside_timeperiod' => 0, 'time_warning' => 0, 'time_critical' => 0, 'time_unknown' => 0, 'scheduled_time_indeterminate' => 0 }, 'n0_test_ok_01' => { 'time_ok' => 208203, 'scheduled_time_critical' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_ok' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_nodata' => 396597, 'time_indeterminate_outside_timeperiod' => 0, 'time_warning' => 0, 'time_critical' => 0, 'time_unknown' => 0, 'scheduled_time_indeterminate' => 0 }, 'n0_test_warning_16' => { 'time_ok' => 0, 'scheduled_time_critical' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_ok' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_nodata' => 396597, 'time_indeterminate_outside_timeperiod' => 0, 'time_warning' => 208203, 'time_critical' => 0, 'time_unknown' => 0, 'scheduled_time_indeterminate' => 0 }, 'n0_test_random_15' => { 'time_ok' => 208203, 'scheduled_time_critical' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_ok' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_nodata' => 396597, 'time_indeterminate_outside_timeperiod' => 0, 'time_warning' => 0, 'time_critical' => 0, 'time_unknown' => 0, 'scheduled_time_indeterminate' => 0 } } } }; my $expected_condensed_log = [ { 'start' => '2010-01-22 00:00:00', 'end' => '2010-01-22 22:11:09', 'duration' => '0d 22h 11m 9s', 'type' => 'HOST UP (HARD)', 'plugin_output' => 'n0_test_host_001 (checked by mo) OK: ok hostcheck', 'class' => 'UP', 'in_downtime' => 0 }, ]; my $expected_full_log = [ { 'start' => '2010-01-08 15:50:52', 'end' => '2010-01-17 14:58:55', 'duration' => '8d 23h 8m 3s', 'type' => 'PROGRAM (RE)START', 'plugin_output' => 'Program start', 'class' => 'INDETERMINATE' }, { 'start' => '2010-01-17 14:58:55', 'end' => '2010-01-17 17:02:26', 'duration' => '0d 2h 3m 31s', 'type' => 'PROGRAM (RE)START', 'plugin_output' => 'Program start', 'class' => 'INDETERMINATE' }, { 'start' => '2010-01-17 17:02:26', 'end' => '2010-01-17 17:02:28', 'duration' => '0d 0h 0m 2s', 'type' => 'PROGRAM END', 'plugin_output' => 'Normal program termination', 'class' => 'INDETERMINATE' }, { 'start' => '2010-01-17 17:02:28', 'end' => '2010-01-17 17:03:55', 'duration' => '0d 0h 1m 27s', 'type' => 'PROGRAM (RE)START', 'plugin_output' => 'Program start', 'class' => 'INDETERMINATE' }, { 'start' => '2010-01-17 17:03:55', 'end' => '2010-01-17 17:03:58', 'duration' => '0d 0h 0m 3s', 'type' => 'PROGRAM END', 'plugin_output' => 'Normal program termination', 'class' => 'INDETERMINATE' }, { 'start' => '2010-01-17 17:03:58', 'end' => '2010-01-17 17:04:57', 'duration' => '0d 0h 0m 59s', 'type' => 'PROGRAM (RE)START', 'plugin_output' => 'Program start', 'class' => 'INDETERMINATE' }, { 'start' => '2010-01-17 17:04:57', 'end' => '2010-01-17 17:05:00', 'duration' => '0d 0h 0m 3s', 'type' => 'PROGRAM END', 'plugin_output' => 'Normal program termination', 'class' => 'INDETERMINATE' }, { 'start' => '2010-01-17 17:05:00', 'end' => '2010-01-22 00:00:00', 'duration' => '4d 6h 55m 0s', 'type' => 'PROGRAM (RE)START', 'plugin_output' => 'Program start', 'class' => 'INDETERMINATE' }, { 'start' => '2010-01-22 00:00:00', 'end' => '2010-01-22 22:11:09', 'duration' => '0d 22h 11m 9s', 'type' => 'HOST UP (HARD)', 'plugin_output' => 'n0_test_host_001 (checked by mo) OK: ok hostcheck', 'class' => 'UP', 'in_downtime' => 0 }, { 'start' => '2010-01-22 22:11:09', 'end' => '2010-01-22 22:12:22', 'duration' => '0d 0h 1m 13s', 'type' => 'PROGRAM END', 'plugin_output' => 'Normal program termination', 'class' => 'INDETERMINATE' }, { 'start' => '2010-01-22 22:12:22', 'end' => '2010-01-23 23:03:54', 'duration' => '1d 0h 51m 32s', 'type' => 'PROGRAM (RE)START', 'plugin_output' => 'Program start', 'class' => 'INDETERMINATE' }, { 'start' => '2010-01-23 23:03:54', 'end' => '2010-01-23 23:03:57', 'duration' => '0d 0h 0m 3s', 'type' => 'PROGRAM END', 'plugin_output' => 'Normal program termination', 'class' => 'INDETERMINATE' }, { 'start' => '2010-01-23 23:03:57', 'end' => '2010-01-24 09:50:03', 'duration' => '0d 10h 46m 6s+', 'type' => 'PROGRAM (RE)START', 'plugin_output' => 'Program start', 'class' => 'INDETERMINATE' }, ]; ######################### # avail.cgi?t1=1263718203&t2=1264323003&show_log_entries=&full_log_entries=&host=n0_test_host_001&assumeinitialstates=yes&assumestateretention=yes&assumestatesduringnotrunning=yes&includesoftstates=no&initialassumedhoststate=0&initialassumedservicestate=0&timeperiod=[+Current+time+range+]&backtrack=4 my $ma = Monitoring::Availability->new( 'verbose' => 0, 'backtrack' => 4, 'assumestateretention' => 'yes', 'assumeinitialstates' => 'yes', 'assumestatesduringnotrunning' => 'yes', 'initialassumedhoststate' => 'unspecified', 'initialassumedservicestate' => 'unspecified', ); isa_ok($ma, 'Monitoring::Availability', 'create new Monitoring::Availability object'); my $result = $ma->calculate( 'log_string' => $logs, 'hosts' => ['n0_test_host_001'], 'services' => [ { 'service' => 'n0_test_flap_19', 'host' => 'n0_test_host_001' }, { 'service' => 'n0_test_random_03', 'host' => 'n0_test_host_001' }, { 'service' => 'n0_test_pending_06', 'host' => 'n0_test_host_001' }, { 'service' => 'n0_test_ok_05', 'host' => 'n0_test_host_001' }, { 'service' => 'n0_test_unknown_04', 'host' => 'n0_test_host_001' }, { 'service' => 'n0_test_random_13', 'host' => 'n0_test_host_001' }, { 'service' => 'n0_test_ok_14', 'host' => 'n0_test_host_001' }, { 'service' => 'n0_test_ok_17', 'host' => 'n0_test_host_001' }, { 'service' => 'n0_test_random_02', 'host' => 'n0_test_host_001' }, { 'service' => 'n0_test_ok_12', 'host' => 'n0_test_host_001' }, { 'service' => 'n0_test_ok_08', 'host' => 'n0_test_host_001' }, { 'service' => 'n0_test_warning_18', 'host' => 'n0_test_host_001' }, { 'service' => 'n0_test_ok_11', 'host' => 'n0_test_host_001' }, { 'service' => 'n0_test_ok_07', 'host' => 'n0_test_host_001' }, { 'service' => 'n0_test_flap_00', 'host' => 'n0_test_host_001' }, { 'service' => 'n0_test_ok_10', 'host' => 'n0_test_host_001' }, { 'service' => 'n0_test_ok_09', 'host' => 'n0_test_host_001' }, { 'service' => 'n0_test_warning_16', 'host' => 'n0_test_host_001' }, { 'service' => 'n0_test_ok_01', 'host' => 'n0_test_host_001' }, { 'service' => 'n0_test_random_15', 'host' => 'n0_test_host_001' } ], 'start' => 1263718203, 'end' => 1264323003, 'timeformat' => '%Y-%m-%d %H:%M:%S', ); is_deeply($result, $expected, 'host with services') or diag("got:\n".Dumper($result)."\nbut expected:\n".Dumper($expected)); my $condensed_logs = $ma->get_condensed_logs(); # test will fail on windows because of a different used timezone TestUtils::check_array_one_by_one($expected_condensed_log, $condensed_logs, 'condensed logs'); my $full_logs = $ma->get_full_logs(); # test will fail on windows because of a different used timezone TestUtils::check_array_one_by_one($expected_full_log, $full_logs, 'full logs'); __DATA__ [1262962252] Nagios 3.2.0 starting... (PID=7873) [1263736735] Nagios 3.2.0 starting... (PID=528) [1263744146] Caught SIGTERM, shutting down... [1263744148] Nagios 3.2.0 starting... (PID=21311) [1263744235] Caught SIGTERM, shutting down... [1263744238] Nagios 3.2.0 starting... (PID=21471) [1263744297] Caught SIGTERM, shutting down... [1263744300] Nagios 3.2.0 starting... (PID=21647) [1264114800] CURRENT HOST STATE: n0_test_host_001;UP;HARD;1;n0_test_host_001 (checked by mo) OK: ok hostcheck [1264114800] CURRENT SERVICE STATE: n0_test_host_001;n0_test_flap_00;OK;HARD;1;n0_test_host_001 (checked by mo) FLAP: up n0_test_flap_00 up [1264114800] CURRENT SERVICE STATE: n0_test_host_001;n0_test_flap_19;OK;HARD;1;n0_test_host_001 (checked by mo) FLAP: up n0_test_flap_19 up [1264114800] CURRENT SERVICE STATE: n0_test_host_001;n0_test_ok_01;OK;HARD;1;n0_test_host_001 (checked by mo) OK: ok n0_test_ok_01 [1264114800] CURRENT SERVICE STATE: n0_test_host_001;n0_test_ok_05;OK;HARD;1;n0_test_host_001 (checked by mo) OK: ok n0_test_ok_05 [1264114800] CURRENT SERVICE STATE: n0_test_host_001;n0_test_ok_07;OK;HARD;1;n0_test_host_001 (checked by mo) OK: ok n0_test_ok_07 [1264114800] CURRENT SERVICE STATE: n0_test_host_001;n0_test_ok_08;OK;HARD;1;n0_test_host_001 (checked by mo) OK: ok n0_test_ok_08 [1264114800] CURRENT SERVICE STATE: n0_test_host_001;n0_test_ok_09;OK;HARD;1;n0_test_host_001 (checked by mo) OK: ok n0_test_ok_09 [1264114800] CURRENT SERVICE STATE: n0_test_host_001;n0_test_ok_10;OK;HARD;1;n0_test_host_001 (checked by mo) OK: ok n0_test_ok_10 [1264114800] CURRENT SERVICE STATE: n0_test_host_001;n0_test_ok_11;OK;HARD;1;n0_test_host_001 (checked by mo) OK: ok n0_test_ok_11 [1264114800] CURRENT SERVICE STATE: n0_test_host_001;n0_test_ok_12;OK;HARD;1;n0_test_host_001 (checked by mo) OK: ok n0_test_ok_12 [1264114800] CURRENT SERVICE STATE: n0_test_host_001;n0_test_ok_14;OK;HARD;1;n0_test_host_001 (checked by mo) OK: ok n0_test_ok_14 [1264114800] CURRENT SERVICE STATE: n0_test_host_001;n0_test_ok_17;OK;HARD;1;n0_test_host_001 (checked by mo) OK: ok n0_test_ok_17 [1264114800] CURRENT SERVICE STATE: n0_test_host_001;n0_test_pending_06;OK;HARD;1; [1264114800] CURRENT SERVICE STATE: n0_test_host_001;n0_test_random_02;OK;HARD;1;n0_test_host_001 (checked by mo) OK: random n0_test_random_02 ok [1264114800] CURRENT SERVICE STATE: n0_test_host_001;n0_test_random_03;OK;HARD;1;n0_test_host_001 (checked by mo) OK: random n0_test_random_03 ok [1264114800] CURRENT SERVICE STATE: n0_test_host_001;n0_test_random_13;OK;HARD;1;n0_test_host_001 (checked by mo) OK: random n0_test_random_13 ok [1264114800] CURRENT SERVICE STATE: n0_test_host_001;n0_test_random_15;OK;HARD;1;n0_test_host_001 (checked by mo) OK: random n0_test_random_15 ok [1264114800] CURRENT SERVICE STATE: n0_test_host_001;n0_test_unknown_04;UNKNOWN;HARD;3;n0_test_host_001 (checked by mo) UNKNOWN: unknown n0_test_unknown_04 [1264114800] CURRENT SERVICE STATE: n0_test_host_001;n0_test_warning_16;WARNING;HARD;3;n0_test_host_001 (checked by mo) WARNING: warning n0_test_warning_16 [1264114800] CURRENT SERVICE STATE: n0_test_host_001;n0_test_warning_18;WARNING;HARD;3;n0_test_host_001 (checked by mo) WARNING: warning n0_test_warning_18 [1264194669] Caught SIGTERM, shutting down... [1264194742] Nagios 3.2.0 starting... (PID=10418) [1264284234] Caught SIGTERM, shutting down... [1264284237] Nagios 3.2.0 starting... (PID=22961) libmonitoring-availability-perl-0.46/t/32-availability-service.t000066400000000000000000000245001242301703500247070ustar00rootroot00000000000000#!/usr/bin/env perl ######################### use strict; use Test::More; use Data::Dumper; # checks against localtime will fail otherwise use POSIX qw(tzset); $ENV{'TZ'} = "CET"; POSIX::tzset(); BEGIN { if( $^O eq 'MSWin32' ) { plan skip_all => 'windows is not supported'; } else { plan tests => 18; } require 't/00_test_utils.pm'; import TestUtils; } use_ok('Monitoring::Availability'); ######################### # read logs from data my $logs; while(my $line = ) { $logs .= $line; } my $expected = { 'hosts' => {}, 'services' => { 'n0_test_host_000' => { 'n0_test_pending_01' => { 'time_ok' => 0, 'time_warning' => 0, 'time_unknown' => 20, 'time_critical' => 647, 'scheduled_time_ok' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_critical' => 633, 'scheduled_time_indeterminate' => 55, 'time_indeterminate_nodata' => 85733, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_outside_timeperiod' => 0, } } } }; my $expected_condensed_log = [ { 'start' => '2010-01-21 23:12:10', end => '2010-01-21 23:13:05', 'duration' => '0d 0h 0m 55s', 'type' => 'SERVICE DOWNTIME START', plugin_output => 'Start of scheduled downtime', 'class' => 'INDETERMINATE', 'in_downtime' => 1 }, { 'start' => '2010-01-21 23:13:05', end => '2010-01-21 23:13:37', 'duration' => '0d 0h 0m 32s', 'type' => 'SERVICE DOWNTIME END', plugin_output => 'End of scheduled downtime', 'class' => 'INDETERMINATE', 'in_downtime' => 0 }, { 'start' => '2010-01-21 23:14:00', end => '2010-01-21 23:14:20', 'duration' => '0d 0h 0m 20s', 'type' => 'SERVICE UNKNOWN (HARD)', plugin_output => 'unknown', 'class' => 'UNKNOWN', 'in_downtime' => 0 }, { 'start' => '2010-01-21 23:14:20', end => '2010-01-21 23:14:34', 'duration' => '0d 0h 0m 14s', 'type' => 'SERVICE CRITICAL (HARD)', plugin_output => 'critical', 'class' => 'CRITICAL', 'in_downtime' => 0 }, { 'start' => '2010-01-21 23:14:34', end => '2010-01-21 23:25:07', 'duration' => '0d 0h 10m 33s+','type' => 'HOST DOWNTIME START', plugin_output => 'Start of scheduled downtime', 'class' => 'INDETERMINATE', 'in_downtime' => 1 }, ]; my $expected_full_log = [ { 'start' => '2010-01-21 23:05:15', end => '2010-01-21 23:12:10', 'duration' => '0d 0h 6m 55s', 'type' => 'PROGRAM (RE)START', plugin_output => 'Program start', 'class' => 'INDETERMINATE' }, { 'start' => '2010-01-21 23:12:10', end => '2010-01-21 23:13:05', 'duration' => '0d 0h 0m 55s', 'type' => 'SERVICE DOWNTIME START', plugin_output => 'Start of scheduled downtime', 'class' => 'INDETERMINATE', 'in_downtime' => 1 }, { 'start' => '2010-01-21 23:13:05', end => '2010-01-21 23:13:37', 'duration' => '0d 0h 0m 32s', 'type' => 'SERVICE DOWNTIME END', plugin_output => 'End of scheduled downtime', 'class' => 'INDETERMINATE', 'in_downtime' => 0}, { 'start' => '2010-01-21 23:13:37', end => '2010-01-21 23:13:38', 'duration' => '0d 0h 0m 1s', 'type' => 'PROGRAM (RE)START', plugin_output => 'Program restart', 'class' => 'INDETERMINATE' }, { 'start' => '2010-01-21 23:13:38', end => '2010-01-21 23:14:00', 'duration' => '0d 0h 0m 22s', 'type' => 'PROGRAM (RE)START', plugin_output => 'Program start', 'class' => 'INDETERMINATE' }, { 'start' => '2010-01-21 23:14:00', end => '2010-01-21 23:14:20', 'duration' => '0d 0h 0m 20s', 'type' => 'SERVICE UNKNOWN (HARD)', plugin_output => 'unknown', 'class' => 'UNKNOWN', 'in_downtime' => 0 }, { 'start' => '2010-01-21 23:14:20', end => '2010-01-21 23:14:34', 'duration' => '0d 0h 0m 14s', 'type' => 'SERVICE CRITICAL (HARD)', plugin_output => 'critical', 'class' => 'CRITICAL', 'in_downtime' => 0 }, { 'start' => '2010-01-21 23:14:34', end => '2010-01-21 23:25:07', 'duration' => '0d 0h 10m 33s+','type' => 'HOST DOWNTIME START', plugin_output => 'Start of scheduled downtime', 'class' => 'INDETERMINATE', 'in_downtime' => 1 }, ]; ######################### # avail.cgi?host=n0_test_host_000&service=n0_test_pending_01&t1=1264026307&t2=1264112707&backtrack=4&assumestateretention=yes&assumeinitialstates=yes&assumestatesduringnotrunning=yes&initialassumedhoststate=0&initialassumedservicestate=0&show_log_entries&showscheduleddowntime=yes my $ma = Monitoring::Availability->new( 'verbose' => 0, 'backtrack' => 4, 'assumestateretention' => 'yes', 'assumeinitialstates' => 'yes', 'assumestatesduringnotrunning' => 'yes', 'initialassumedhoststate' => 'unspecified', 'initialassumedservicestate' => 'unspecified', 'showscheduleddowntime' => 'yes', 'timeformat' => '%Y-%m-%d %H:%M:%S', ); isa_ok($ma, 'Monitoring::Availability', 'create new Monitoring::Availability object'); my $result = $ma->calculate( 'log_string' => $logs, 'services' => [{'host' => 'n0_test_host_000', 'service' => 'n0_test_pending_01'}], 'start' => 1264026307, 'end' => 1264112707, ); is_deeply($result, $expected, 'service availability') or diag("got:\n".Dumper($result)."\nbut expected:\n".Dumper($expected)); my $condensed_logs = $ma->get_condensed_logs(); # test will fail on windows because of a different used timezone TestUtils::check_array_one_by_one($expected_condensed_log, $condensed_logs, 'condensed logs'); my $full_logs = $ma->get_full_logs(); # test will fail on windows because of a different used timezone TestUtils::check_array_one_by_one($expected_full_log, $full_logs, 'full logs'); __DATA__ [1264111515] Nagios 3.2.0 starting... (PID=31189) [1264111515] Local time is Thu Jan 21 23:05:15 CET 2010 [1264111515] LOG VERSION: 2.0 [1264111515] livestatus: Setting max number of cached log messages to 0 [1264111515] livestatus: Version 1.1.2rc1 initializing. Socket path: '/tmp/live.sock' [1264111515] livestatus: Created UNIX control socket at /tmp/live.sock [1264111515] livestatus: Opened UNIX socket /tmp/live.sock [1264111515] livestatus: successfully finished initialization [1264111515] Event broker module '/opt/projects/git/check_mk/livestatus/src/livestatus.o' initialized successfully. [1264111516] Finished daemonizing... (New PID=31195) [1264111516] livestatus: Entering main loop, listening on UNIX socket. PID is 31195 [1264111516] livestatus: Starting 10 client threads [1264111516] SERVICE DOWNTIME ALERT: n0_test_host_004;n0_test_critical_18;STARTED; Service has entered a period of scheduled downtime [1264111555] EXTERNAL COMMAND: PROCESS_SERVICE_CHECK_RESULT;n0_test_host_000;n0_test_pending_01;0;ok| [1264111556] PASSIVE SERVICE CHECK: n0_test_host_000;n0_test_pending_01;0;ok [1264111929] EXTERNAL COMMAND: SCHEDULE_SVC_DOWNTIME;n0_test_host_000;n0_test_pending_01;1264111923;1264119123;1;0;0;thrukadmin;downtime [1264111930] SERVICE DOWNTIME ALERT: n0_test_host_000;n0_test_pending_01;STARTED; Service has entered a period of scheduled downtime [1264111944] EXTERNAL COMMAND: PROCESS_SERVICE_CHECK_RESULT;n0_test_host_000;n0_test_pending_01;1;warn| [1264111946] PASSIVE SERVICE CHECK: n0_test_host_000;n0_test_pending_01;1;warn [1264111946] SERVICE ALERT: n0_test_host_000;n0_test_pending_01;WARNING;SOFT;1;warn [1264111967] EXTERNAL COMMAND: DEL_SVC_COMMENT;730 [1264111985] EXTERNAL COMMAND: DEL_SVC_DOWNTIME;551 [1264111985] SERVICE DOWNTIME ALERT: n0_test_host_000;n0_test_pending_01;CANCELLED; Scheduled downtime for service has been cancelled. [1264112005] EXTERNAL COMMAND: PROCESS_SERVICE_CHECK_RESULT;n0_test_host_000;n0_test_pending_01;3;unknown| [1264112006] PASSIVE SERVICE CHECK: n0_test_host_000;n0_test_pending_01;3;unknown [1264112006] SERVICE ALERT: n0_test_host_000;n0_test_pending_01;UNKNOWN;SOFT;2;unknown [1264112016] EXTERNAL COMMAND: RESTART_PROCESS; [1264112017] PROGRAM_RESTART event encountered, restarting... [1264112017] livestatus: deinitializing [1264112017] livestatus: Waiting for main to terminate... [1264112018] livestatus: Socket thread has terminated [1264112018] livestatus: error: Client connection terminated while request still incomplete [1264112018] livestatus: Waiting for client threads to terminate... [1264112018] livestatus: Main thread + 10 client threads have finished [1264112018] Event broker module '/opt/projects/git/check_mk/livestatus/src/livestatus.o' deinitialized successfully. [1264112018] Nagios 3.2.0 starting... (PID=31195) [1264112018] Local time is Thu Jan 21 23:13:38 CET 2010 [1264112018] LOG VERSION: 2.0 [1264112018] livestatus: Setting max number of cached log messages to 0 [1264112018] livestatus: Version 1.1.2rc1 initializing. Socket path: '/tmp/live.sock' [1264112018] livestatus: Created UNIX control socket at /tmp/live.sock [1264112018] livestatus: Opened UNIX socket /tmp/live.sock [1264112018] livestatus: successfully finished initialization [1264112018] Event broker module '/opt/projects/git/check_mk/livestatus/src/livestatus.o' initialized successfully. [1264112019] livestatus: Starting 10 client threads [1264112019] livestatus: Entering main loop, listening on UNIX socket. PID is 31195 [1264112020] SERVICE DOWNTIME ALERT: n0_test_host_004;n0_test_critical_18;STARTED; Service has entered a period of scheduled downtime [1264112036] EXTERNAL COMMAND: PROCESS_SERVICE_CHECK_RESULT;n0_test_host_000;n0_test_pending_01;3;unknown| [1264112040] PASSIVE SERVICE CHECK: n0_test_host_000;n0_test_pending_01;3;unknown [1264112040] SERVICE ALERT: n0_test_host_000;n0_test_pending_01;UNKNOWN;HARD;3;unknown [1264112040] SERVICE NOTIFICATION: test_contact;n0_test_host_000;n0_test_pending_01;UNKNOWN;notify-service;unknown [1264112053] EXTERNAL COMMAND: PROCESS_SERVICE_CHECK_RESULT;n0_test_host_000;n0_test_pending_01;2;critical| [1264112060] PASSIVE SERVICE CHECK: n0_test_host_000;n0_test_pending_01;2;critical [1264112060] SERVICE ALERT: n0_test_host_000;n0_test_pending_01;CRITICAL;HARD;3;critical [1264112060] SERVICE NOTIFICATION: test_contact;n0_test_host_000;n0_test_pending_01;CRITICAL;notify-service;critical [1264112074] EXTERNAL COMMAND: SCHEDULE_HOST_DOWNTIME;n0_test_host_000;1264112067;1264119267;1;0;0;thrukadmin;downtime [1264112074] HOST DOWNTIME ALERT: n0_test_host_000;STARTED; Host has entered a period of scheduled downtime libmonitoring-availability-perl-0.46/t/33-availability-service_ok_logs.t000066400000000000000000000245431242301703500264340ustar00rootroot00000000000000#!/usr/bin/env perl ######################### use strict; use Test::More; use Data::Dumper; # checks against localtime will fail otherwise use POSIX qw(tzset); $ENV{'TZ'} = "CET"; POSIX::tzset(); BEGIN { if( $^O eq 'MSWin32' ) { plan skip_all => 'windows is not supported'; } else { plan tests => 63; } require 't/00_test_utils.pm'; import TestUtils; } use_ok('Monitoring::Availability'); ######################### # read logs from data my $logs; while(my $line = ) { $logs .= $line; } my $expected = { 'hosts' => {}, 'services' => { 'n0_test_host_000' => { 'n0_test_random_04' => { 'time_ok' => 604800, 'time_warning' => 0, 'time_unknown' => 0, 'time_critical' => 0, 'scheduled_time_ok' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_critical' => 0, 'scheduled_time_indeterminate' => 0, 'time_indeterminate_nodata' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_outside_timeperiod' => 0, } } } }; my $expected_log = [ { 'start' => '2010-01-09 00:00:00', end => '2010-01-17 14:58:55', 'duration' => '8d 14h 58m 55s', 'type' => 'SERVICE OK (HARD)', plugin_output => 'n0_test_host_000 (checked by mo) REVOVERED: random n0_test_random_04 recovered', 'class' => 'OK', 'in_downtime' => 0 }, { 'start' => '2010-01-18 00:00:00', end => '2010-01-19 00:00:00', 'duration' => '1d 0h 0m 0s', 'type' => 'SERVICE OK (HARD)', plugin_output => 'n0_test_host_000 (checked by mo) REVOVERED: random n0_test_random_04 recovered', 'class' => 'OK', 'in_downtime' => 0 }, { 'start' => '2010-01-19 00:00:00', end => '2010-01-20 00:00:00', 'duration' => '1d 0h 0m 0s', 'type' => 'SERVICE OK (HARD)', plugin_output => 'n0_test_host_000 (checked by mo) REVOVERED: random n0_test_random_04 recovered', 'class' => 'OK', 'in_downtime' => 0 }, { 'start' => '2010-01-20 00:00:00', end => '2010-01-20 22:16:24', 'duration' => '0d 22h 16m 24s+', 'type' => 'SERVICE OK (HARD)', plugin_output => 'n0_test_host_000 (checked by mo) REVOVERED: random n0_test_random_04 recovered', 'class' => 'OK', 'in_downtime' => 0 }, ]; my $expected_full_log = [ { 'start' => '2010-01-08 15:50:52', 'end' => '2010-01-09 00:00:00', 'duration' => '0d 8h 9m 8s', 'type' => 'PROGRAM (RE)START', 'plugin_output' => 'Program start', 'class' => 'INDETERMINATE' }, { 'start' => '2010-01-09 00:00:00', 'end' => '2010-01-17 14:58:55', 'duration' => '8d 14h 58m 55s', 'type' => 'SERVICE OK (HARD)', 'plugin_output' => 'n0_test_host_000 (checked by mo) REVOVERED: random n0_test_random_04 recovered', 'class' => 'OK', 'in_downtime' => 0 }, { 'start' => '2010-01-17 14:58:55', 'end' => '2010-01-17 17:02:26', 'duration' => '0d 2h 3m 31s', 'type' => 'PROGRAM (RE)START', 'plugin_output' => 'Program start', 'class' => 'INDETERMINATE' }, { 'start' => '2010-01-17 17:02:26', 'end' => '2010-01-17 17:02:28', 'duration' => '0d 0h 0m 2s', 'type' => 'PROGRAM END', 'plugin_output' => 'Normal program termination', 'class' => 'INDETERMINATE' }, { 'start' => '2010-01-17 17:02:28', 'end' => '2010-01-17 17:03:55', 'duration' => '0d 0h 1m 27s', 'type' => 'PROGRAM (RE)START', 'plugin_output' => 'Program start', 'class' => 'INDETERMINATE' }, { 'start' => '2010-01-17 17:03:55', 'end' => '2010-01-17 17:03:58', 'duration' => '0d 0h 0m 3s', 'type' => 'PROGRAM END', 'plugin_output' => 'Normal program termination', 'class' => 'INDETERMINATE' }, { 'start' => '2010-01-17 17:03:58', 'end' => '2010-01-17 17:04:57', 'duration' => '0d 0h 0m 59s', 'type' => 'PROGRAM (RE)START', 'plugin_output' => 'Program start', 'class' => 'INDETERMINATE' }, { 'start' => '2010-01-17 17:04:57', 'end' => '2010-01-17 17:05:00', 'duration' => '0d 0h 0m 3s', 'type' => 'PROGRAM END', 'plugin_output' => 'Normal program termination', 'class' => 'INDETERMINATE' }, { 'start' => '2010-01-17 17:05:00', 'end' => '2010-01-18 00:00:00', 'duration' => '0d 6h 55m 0s', 'type' => 'PROGRAM (RE)START', 'plugin_output' => 'Program start', 'class' => 'INDETERMINATE' }, { 'start' => '2010-01-18 00:00:00', 'end' => '2010-01-19 00:00:00', 'duration' => '1d 0h 0m 0s', 'type' => 'SERVICE OK (HARD)', 'plugin_output' => 'n0_test_host_000 (checked by mo) REVOVERED: random n0_test_random_04 recovered', 'class' => 'OK', 'in_downtime' => 0 }, { 'start' => '2010-01-19 00:00:00', 'end' => '2010-01-20 00:00:00', 'duration' => '1d 0h 0m 0s', 'type' => 'SERVICE OK (HARD)', 'plugin_output' => 'n0_test_host_000 (checked by mo) REVOVERED: random n0_test_random_04 recovered', 'class' => 'OK', 'in_downtime' => 0 }, { 'start' => '2010-01-20 00:00:00', 'end' => '2010-01-20 22:16:24', 'duration' => '0d 22h 16m 24s+', 'type' => 'SERVICE OK (HARD)', 'plugin_output' => 'n0_test_host_000 (checked by mo) REVOVERED: random n0_test_random_04 recovered', 'class' => 'OK', 'in_downtime' => 0 }, ]; ######################### # avail.cgi?host=n0_test_host_000&service=n0_test_random_04&t1=1263417384&t2=1264022184&backtrack=4&assumestateretention=yes&assumeinitialstates=yes&assumestatesduringnotrunning=yes&initialassumedhoststate=0&initialassumedservicestate=0&show_log_entries&full_log_entries&showscheduleddowntime=yes my $ma = Monitoring::Availability->new( 'verbose' => 0, 'backtrack' => 4, 'assumestateretention' => 'yes', 'assumeinitialstates' => 'yes', 'assumestatesduringnotrunning' => 'yes', 'initialassumedhoststate' => 'unspecified', 'initialassumedservicestate' => 'unspecified', 'timeformat' => '%Y-%m-%d %H:%M:%S', ); isa_ok($ma, 'Monitoring::Availability', 'create new Monitoring::Availability object'); my $result = $ma->calculate( 'log_string' => $logs, 'services' => [{'host' => 'n0_test_host_000', 'service' => 'n0_test_random_04'}], 'start' => 1263417384, 'end' => 1264022184, ); is_deeply($result, $expected, 'ok service') or diag("got:\n".Dumper($result)."\nbut expected:\n".Dumper($expected)); my $condensed_logs = $ma->get_condensed_logs(); # test will fail on windows because of a different used timezone TestUtils::check_array_one_by_one($expected_log, $condensed_logs, 'condensed logs'); my $full_logs = $ma->get_full_logs(); # test will fail on windows because of a different used timezone TestUtils::check_array_one_by_one($expected_full_log, $full_logs, 'full logs'); ################################# # now check with initial assumed state "unknown" $result = $ma->calculate( 'log_string' => $logs, 'services' => [{'host' => 'n0_test_host_000', 'service' => 'n0_test_random_04'}], 'start' => 1263417384, 'end' => 1264022184, 'initialassumedservicestate' => 'unknown', ); is_deeply($result, $expected, 'ok service with initial unknown') or diag("got:\n".Dumper($result)."\nbut expected:\n".Dumper($expected)); my $additional_logs = [ { 'start' => '2010-01-08 15:50:51', 'end' => '2010-01-08 15:50:52', 'duration' => '0d 0h 0m 1s', 'type' => 'SERVICE UNKNOWN (HARD)', 'plugin_output' => 'First Service State Assumed (Faked Log Entry)', 'class' => 'UNKNOWN' }, ]; $condensed_logs = $ma->get_condensed_logs(); # test will fail on windows because of a different used timezone TestUtils::check_array_one_by_one([@{$additional_logs}, @{$expected_log}], $condensed_logs, 'condensed logs with initial unknown'); $full_logs = $ma->get_full_logs(); # test will fail on windows because of a different used timezone TestUtils::check_array_one_by_one([@{$additional_logs}, @{$expected_full_log}], $full_logs, 'full logs with initial unknown'); ################################# # now check with initial state "current" $result = $ma->calculate( 'log_string' => $logs, 'services' => [{'host' => 'n0_test_host_000', 'service' => 'n0_test_random_04'}], 'start' => 1263417384, 'end' => 1264022184, 'initialassumedservicestate' => 'current', 'initial_states' => { 'services' => { 'n0_test_host_000' => { 'n0_test_random_04' => 'warning' }}}, ); is_deeply($result, $expected, 'ok service with initial current') or diag("got:\n".Dumper($result)."\nbut expected:\n".Dumper($expected)); $additional_logs = [ { 'start' => '2010-01-08 15:50:51', 'end' => '2010-01-08 15:50:52', 'duration' => '0d 0h 0m 1s', 'type' => 'SERVICE WARNING (HARD)', 'plugin_output' => 'First Service State Assumed (Faked Log Entry)', 'class' => 'WARNING' }, ]; $condensed_logs = $ma->get_condensed_logs(); # test will fail on windows because of a different used timezone TestUtils::check_array_one_by_one([@{$additional_logs}, @{$expected_log}], $condensed_logs, 'condensed logs with initial unknown'); $full_logs = $ma->get_full_logs(); # test will fail on windows because of a different used timezone TestUtils::check_array_one_by_one([@{$additional_logs}, @{$expected_full_log}], $full_logs, 'full logs with initial unknown'); ################################# __DATA__ [1262962252] Nagios 3.2.0 starting... (PID=7873) [1262991600] CURRENT SERVICE STATE: n0_test_host_000;n0_test_random_04;OK;HARD;1;n0_test_host_000 (checked by mo) REVOVERED: random n0_test_random_04 recovered [1263736735] Nagios 3.2.0 starting... (PID=528) [1263744146] Caught SIGTERM, shutting down... [1263744148] Nagios 3.2.0 starting... (PID=21311) [1263744235] Caught SIGTERM, shutting down... [1263744238] Nagios 3.2.0 starting... (PID=21471) [1263744297] Caught SIGTERM, shutting down... [1263744300] Nagios 3.2.0 starting... (PID=21647) [1263769200] CURRENT SERVICE STATE: n0_test_host_000;n0_test_random_04;OK;HARD;1;n0_test_host_000 (checked by mo) REVOVERED: random n0_test_random_04 recovered [1263855600] CURRENT SERVICE STATE: n0_test_host_000;n0_test_random_04;OK;HARD;1;n0_test_host_000 (checked by mo) REVOVERED: random n0_test_random_04 recovered [1263942000] CURRENT SERVICE STATE: n0_test_host_000;n0_test_random_04;OK;HARD;1;n0_test_host_000 (checked by mo) REVOVERED: random n0_test_random_04 recovered libmonitoring-availability-perl-0.46/t/34-availability-breakdown.t000066400000000000000000000120701242301703500252240ustar00rootroot00000000000000#!/usr/bin/env perl ######################### use strict; use Test::More; use Data::Dumper; # checks against localtime will fail otherwise use POSIX qw(tzset); $ENV{'TZ'} = "CET"; POSIX::tzset(); BEGIN { if( $^O eq 'MSWin32' ) { plan skip_all => 'windows is not supported'; } else { plan tests => 4; } require 't/00_test_utils.pm'; import TestUtils; } use_ok('Monitoring::Availability'); ######################### # read logs from data my $logs; while(my $line = ) { $logs .= $line; } my $expected = { 'services' => {}, 'hosts' => { 'mo' => { 'time_up' => 172218, 'time_down' => 582, 'time_unreachable' => 0, 'scheduled_time_up' => 0, 'scheduled_time_down' => 0, 'scheduled_time_unreachable' => 0, 'scheduled_time_indeterminate' => 0, 'time_indeterminate_nodata' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_outside_timeperiod' => 0, 'breakdown' => { '2012-04-22' => { 'time_down' => 582, 'time_indeterminate_notrunning' => 0, 'scheduled_time_down' => 0, 'scheduled_time_up' => 0, 'time_unreachable' => 0, 'time_indeterminate_nodata' => 0, 'time_up' => 85818, 'scheduled_time_unreachable' => 0, 'time_indeterminate_outside_timeperiod' => 0, 'scheduled_time_indeterminate' => 0, 'timestamp' => 1335045600 }, '2012-04-21' => { 'time_down' => 0, 'time_indeterminate_notrunning' => 0, 'scheduled_time_down' => 0, 'scheduled_time_up' => 0, 'time_unreachable' => 0, 'time_indeterminate_nodata' => 0, 'time_up' => 86400, 'scheduled_time_unreachable' => 0, 'time_indeterminate_outside_timeperiod' => 0, 'scheduled_time_indeterminate' => 0, 'timestamp' => 1334959200 } }, } } }; ######################### my $ma = Monitoring::Availability->new( 'verbose' => 0, 'backtrack' => 4, 'assumestateretention' => 'yes', 'assumeinitialstates' => 'yes', 'assumestatesduringnotrunning' => 'no', 'initialassumedhoststate' => 'unspecified', 'initialassumedservicestate' => 'unspecified', 'breakdown' => 'days', ); isa_ok($ma, 'Monitoring::Availability', 'create new Monitoring::Availability object'); my $result = $ma->calculate( 'log_string' => $logs, 'hosts' => ['mo'], 'start' => 1334959200, 'end' => 1335132000, ); is_deeply($result, $expected, 'breakdown host') or diag("got:\n".Dumper($result)."\nbut expected:\n".Dumper($expected)); ######################### $result = $ma->calculate( 'log_string' => $logs, 'hosts' => ['mo'], 'start' => 1334959200, 'end' => 1335132100, ); $expected->{'hosts'}->{'mo'}->{'time_up'} += 100; $expected->{'hosts'}->{'mo'}->{'breakdown'}->{'2012-04-23'} = { 'time_down' => 0, 'time_indeterminate_notrunning' => 0, 'scheduled_time_down' => 0, 'scheduled_time_up' => 0, 'time_unreachable' => 0, 'time_indeterminate_nodata' => 0, 'time_up' => 100, 'scheduled_time_unreachable' => 0, 'time_indeterminate_outside_timeperiod' => 0, 'scheduled_time_indeterminate' => 0, 'timestamp' => 1335132000 }; is_deeply($result, $expected, 'breakdown host') or diag("got:\n".Dumper($result)."\nbut expected:\n".Dumper($expected)); __DATA__ [1334959200] CURRENT HOST STATE: mo;UP;HARD;1;OK - 172.16.0.1: rta 25.610ms, lost 0% [1335066684] HOST ALERT: mo;DOWN;HARD;5;CRITICAL - 172.16.0.1: Host unreachable @ 172.16.0.3. rta nan, lost 100% [1335067266] HOST ALERT: mo;UP;HARD;1;OK - 172.16.0.1: rta 24.712ms, lost 0% libmonitoring-availability-perl-0.46/t/35-availability-timeperiods.t000066400000000000000000000216371242301703500256060ustar00rootroot00000000000000#!/usr/bin/env perl ######################### use strict; use Test::More; use Data::Dumper; # checks against localtime will fail otherwise use POSIX qw(tzset); $ENV{'TZ'} = "CET"; POSIX::tzset(); BEGIN { if( $^O eq 'MSWin32' ) { plan skip_all => 'windows is not supported'; } else { plan tests => 30; } require 't/00_test_utils.pm'; import TestUtils; } use_ok('Monitoring::Availability'); ######################### # read logs from data my $logs; while(my $line = ) { $logs .= $line; } my $options = { 'verbose' => 0, 'backtrack' => 4, 'assumestateretention' => 'yes', 'assumeinitialstates' => 'yes', 'assumestatesduringnotrunning' => 'yes', 'initialassumedhoststate' => 'unspecified', 'initialassumedservicestate' => 'unspecified', 'timeformat' => '%Y-%m-%d %H:%M:%S', 'rpttimeperiod' => '', }; my $expected = { 'hosts' => {}, 'services' => { 'testhost' => { 'testservice' => { 'time_ok' => 230, 'time_warning' => 0, 'time_unknown' => 0, 'time_critical' => 70, 'scheduled_time_ok' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_critical' => 0, 'scheduled_time_indeterminate' => 0, 'time_indeterminate_nodata' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_outside_timeperiod' => 0, } } } }; my $expected_log = [ { 'plugin_output' => 'service is ok', 'duration' => '0d 0h 0m 40s', 'class' => 'OK', 'type' => 'SERVICE OK (HARD)', 'end' => '2010-01-09 00:00:40', 'start' => '2010-01-09 00:00:00', 'in_downtime' => 0 }, { 'plugin_output' => 'service is down', 'duration' => '0d 0h 1m 10s', 'class' => 'CRITICAL', 'type' => 'SERVICE CRITICAL (HARD)', 'end' => '2010-01-09 00:01:50', 'start' => '2010-01-09 00:00:40', 'in_downtime' => 0 }, { 'plugin_output' => 'service is ok', 'duration' => '0d 0h 3m 10s', 'class' => 'OK', 'type' => 'SERVICE OK (HARD)', 'end' => '2010-01-09 00:05:00', 'start' => '2010-01-09 00:01:50', 'in_downtime' => 0 }, ]; my $expected_full_log = [ { 'plugin_output' => 'Program start', 'duration' => '0d 0h 0m 0s', 'class' => 'INDETERMINATE', 'type' => 'PROGRAM (RE)START', 'end' => '2010-01-09 00:00:00', 'start' => '2010-01-09 00:00:00' }, { 'plugin_output' => 'service is ok', 'duration' => '0d 0h 0m 40s', 'class' => 'OK', 'type' => 'SERVICE OK (HARD)', 'end' => '2010-01-09 00:00:40', 'start' => '2010-01-09 00:00:00', 'in_downtime' => 0 }, { 'plugin_output' => 'service is down', 'duration' => '0d 0h 1m 10s', 'class' => 'CRITICAL', 'type' => 'SERVICE CRITICAL (HARD)', 'end' => '2010-01-09 00:01:50', 'start' => '2010-01-09 00:00:40', 'in_downtime' => 0 }, { 'plugin_output' => 'service is ok', 'duration' => '0d 0h 3m 10s', 'class' => 'OK', 'type' => 'SERVICE OK (HARD)', 'end' => '2010-01-09 00:05:00', 'start' => '2010-01-09 00:01:50', 'in_downtime' => 0 }, { 'duration' => '0d 0h 0m 0s', 'end' => '2010-01-09 00:05:00', 'start' => '2010-01-09 00:05:00' }, { 'plugin_output' => 'Normal program termination', 'duration' => '0d 0h 0m 0s+', 'class' => 'INDETERMINATE', 'type' => 'PROGRAM END', 'end' => '2010-01-09 00:05:00', 'start' => '2010-01-09 00:05:00' }, ]; ######################### my $ma = Monitoring::Availability->new(%{$options}); isa_ok($ma, 'Monitoring::Availability', 'create new Monitoring::Availability object'); my $result = $ma->calculate( 'log_string' => $logs, 'services' => [{'host' => 'testhost', 'service' => 'testservice'}], 'start' => 1262991600, 'end' => 1262991900, ); is_deeply($result, $expected, 'ok service') or diag("got:\n".Dumper($result)."\nbut expected:\n".Dumper($expected)); my $condensed_logs = $ma->get_condensed_logs(); TestUtils::check_array_one_by_one($expected_log, $condensed_logs, 'condensed logs'); my $full_logs = $ma->get_full_logs(); TestUtils::check_array_one_by_one($expected_full_log, $full_logs, 'full logs'); ######################### # now with timeperiod $expected_log = [ { 'plugin_output' => 'service is ok', 'duration' => '0d 0h 0m 0s', 'class' => 'OK', 'type' => 'SERVICE OK (HARD)', 'end' => '2010-01-09 00:00:00', 'start' => '2010-01-09 00:00:00', 'in_downtime' => 0 }, { 'plugin_output' => 'service is down', 'duration' => '0d 0h 1m 0s', 'class' => 'CRITICAL', 'type' => 'SERVICE CRITICAL (HARD)', 'end' => '2010-01-09 00:01:40', 'start' => '2010-01-09 00:00:40', 'in_downtime' => 0 }, { 'plugin_output' => 'service is ok', 'duration' => '0d 0h 3m 10s', 'class' => 'OK', 'type' => 'SERVICE OK (HARD)', 'end' => '2010-01-09 00:05:00', 'start' => '2010-01-09 00:01:50', 'in_downtime' => 0 }, ]; $expected_full_log = [ { 'plugin_output' => 'Program start', 'duration' => '0d 0h 0m 0s', 'class' => 'INDETERMINATE', 'type' => 'PROGRAM (RE)START', 'end' => '2010-01-09 00:00:00', 'start' => '2010-01-09 00:00:00' }, { 'plugin_output' => 'service is ok', 'duration' => '0d 0h 0m 0s', 'class' => 'OK', 'type' => 'SERVICE OK (HARD)', 'end' => '2010-01-09 00:00:00', 'start' => '2010-01-09 00:00:00', 'in_downtime' => 0 }, { 'plugin_output' => 'entering timeperiod: workhours', 'duration' => '0d 0h 0m 30s', 'class' => 'INDETERMINATE', 'type' => 'TIMEPERIOD START', 'end' => '2010-01-09 00:00:30', 'start' => '2010-01-09 00:00:00' }, { 'plugin_output' => 'leaving timeperiod: workhours', 'duration' => '0d 0h 0m 10s', 'class' => 'INDETERMINATE', 'type' => 'TIMEPERIOD STOP', 'end' => '2010-01-09 00:00:40', 'start' => '2010-01-09 00:00:30' }, { 'plugin_output' => 'service is down', 'duration' => '0d 0h 1m 0s', 'class' => 'CRITICAL', 'type' => 'SERVICE CRITICAL (HARD)', 'end' => '2010-01-09 00:01:40', 'start' => '2010-01-09 00:00:40', 'in_downtime' => 0 }, { 'plugin_output' => 'entering timeperiod: workhours', 'duration' => '0d 0h 0m 10s', 'class' => 'INDETERMINATE', 'type' => 'TIMEPERIOD START', 'end' => '2010-01-09 00:01:50', 'start' => '2010-01-09 00:01:40' }, { 'plugin_output' => 'service is ok', 'duration' => '0d 0h 3m 10s', 'class' => 'OK', 'type' => 'SERVICE OK (HARD)', 'end' => '2010-01-09 00:05:00', 'start' => '2010-01-09 00:01:50', 'in_downtime' => 0 }, { 'duration' => '0d 0h 0m 0s', 'end' => '2010-01-09 00:05:00', 'start' => '2010-01-09 00:05:00' }, { 'plugin_output' => 'Normal program termination', 'duration' => '0d 0h 0m 0s+', 'class' => 'INDETERMINATE', 'type' => 'PROGRAM END', 'end' => '2010-01-09 00:05:00', 'start' => '2010-01-09 00:05:00' } ]; $expected->{'services'}->{'testhost'}->{'testservice'}->{'time_ok'} = 220; $expected->{'services'}->{'testhost'}->{'testservice'}->{'time_critical'} = 10; $expected->{'services'}->{'testhost'}->{'testservice'}->{'time_indeterminate_outside_timeperiod'} = 70; $options->{'rpttimeperiod'} = 'workhours'; $ma = Monitoring::Availability->new(%{$options}); isa_ok($ma, 'Monitoring::Availability', 'create new Monitoring::Availability object'); $result = $ma->calculate( 'log_string' => $logs, 'services' => [{'host' => 'testhost', 'service' => 'testservice'}], 'start' => 1262991600, 'end' => 1262991900, ); is_deeply($result, $expected, 'ok service') or diag("got:\n".Dumper($result)."\nbut expected:\n".Dumper($expected)); $condensed_logs = $ma->get_condensed_logs(); TestUtils::check_array_one_by_one($expected_log, $condensed_logs, 'condensed logs'); $full_logs = $ma->get_full_logs(); TestUtils::check_array_one_by_one($expected_full_log, $full_logs, 'full logs'); ################################# __DATA__ [1262991600] Nagios 3.2.0 starting... (PID=7873) [1262991600] CURRENT SERVICE STATE: testhost;testservice;OK;HARD;1;service is ok [1262991600] TIMEPERIOD TRANSITION: workhours;-1;1 [1262991630] TIMEPERIOD TRANSITION: workhours;1;0 [1262991640] SERVICE ALERT: testhost;testservice;CRITICAL;HARD;1;service is down [1262991700] TIMEPERIOD TRANSITION: workhours;0;1 [1262991710] SERVICE ALERT: testhost;testservice;OK;HARD;1;service is ok [1262991900] Caught SIGTERM, shutting down... libmonitoring-availability-perl-0.46/t/36-availability-nologs.t000066400000000000000000000041511242301703500245540ustar00rootroot00000000000000#!/usr/bin/env perl ######################### use strict; use Test::More; use Data::Dumper; # checks against localtime will fail otherwise use POSIX qw(tzset); $ENV{'TZ'} = "CET"; POSIX::tzset(); BEGIN { if( $^O eq 'MSWin32' ) { plan skip_all => 'windows is not supported'; } else { plan tests => 4; } require 't/00_test_utils.pm'; import TestUtils; } use_ok('Monitoring::Availability'); ######################### my $expected = { 'services' => {}, 'hosts' => { 'mo' => { 'time_up' => 172800, 'time_down' => 0, 'time_unreachable' => 0, 'scheduled_time_up' => 0, 'scheduled_time_down' => 0, 'scheduled_time_unreachable' => 0, 'scheduled_time_indeterminate' => 0, 'time_indeterminate_nodata' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_outside_timeperiod' => 0, } } }; ######################### my $ma = Monitoring::Availability->new( 'verbose' => 0, 'assumeinitialstates' => 'yes', 'initialassumedhoststate' => 'up', 'initialassumedservicestate' => 'ok', ); isa_ok($ma, 'Monitoring::Availability', 'create new Monitoring::Availability object'); my $result = $ma->calculate( 'log_livestatus' => [], 'hosts' => ['mo'], 'start' => 1334959200, 'end' => 1335132000, ); is_deeply($result, $expected, 'nologs host') or diag("got:\n".Dumper($result)."\nbut expected:\n".Dumper($expected)); my $logs = $ma->get_full_logs(); my $explogs = [{ 'plugin_output' => 'First Host State Assumed (Faked Log Entry)', 'duration' => '2d 0h 0m 0s+', 'class' => 'UP', 'type' => 'HOST UP (HARD)', 'end' => 1335132000, 'start' => 1334959200 }]; is_deeply($logs, $explogs, 'nologs host logs') or diag("got:\n".Dumper($logs)."\nbut expected:\n".Dumper($explogs)); libmonitoring-availability-perl-0.46/t/37-availability-no_initial_log.t000066400000000000000000000037531242301703500262510ustar00rootroot00000000000000#!/usr/bin/env perl ######################### use strict; use Test::More tests => 3; use Data::Dumper; BEGIN { require 't/00_test_utils.pm'; import TestUtils; } use_ok('Monitoring::Availability'); ######################### # read logs from data my $logs; while(my $line = ) { $logs .= $line; } my $expected = { 'hosts' => {}, 'services' => { 'n0_test_host_000' => { 'n0_test_random_04' => { 'time_ok' => 1000, 'time_warning' => 0, 'time_unknown' => 0, 'time_critical' => 0, 'scheduled_time_ok' => 0, 'scheduled_time_warning' => 0, 'scheduled_time_unknown' => 0, 'scheduled_time_critical' => 0, 'scheduled_time_indeterminate' => 0, 'time_indeterminate_nodata' => 0, 'time_indeterminate_notrunning' => 0, 'time_indeterminate_outside_timeperiod' => 0, } } } }; ######################### my $ma = Monitoring::Availability->new( 'verbose' => 0, 'backtrack' => 4, 'assumestateretention' => 'yes', 'assumeinitialstates' => 'yes', 'assumestatesduringnotrunning' => 'yes', 'initialassumedhoststate' => 'up', 'initialassumedservicestate' => 'ok', ); isa_ok($ma, 'Monitoring::Availability', 'create new Monitoring::Availability object'); my $result = $ma->calculate( 'log_string' => $logs, 'services' => [{'host' => 'n0_test_host_000', 'service' => 'n0_test_random_04'}], 'start' => 1262991000, 'end' => 1262992000, ); is_deeply($result, $expected, 'critical service') or diag("got:\n".Dumper($result)."\nbut expected:\n".Dumper($expected)); __DATA__ [1262991000] Nagios 3.2.0 starting... (PID=7873) libmonitoring-availability-perl-0.46/t/92_clean_debug.t000066400000000000000000000007471242301703500231260ustar00rootroot00000000000000use strict; use warnings; use Test::More; use Data::Dumper; plan skip_all => 'Author test. Set $ENV{TEST_AUTHOR} to a true value to run.' unless $ENV{TEST_AUTHOR}; my $cmds = [ "grep -nr 'print STDERR Dumper' lib/", ]; # find all missed debug outputs for my $cmd (@{$cmds}) { open(my $ph, '-|', $cmd.' 2>&1') or die('cmd '.$cmd.' failed: '.$!); ok($ph, 'cmd started'); while(<$ph>) { my $line = $_; chomp($line); fail($line); } close($ph); } done_testing(); libmonitoring-availability-perl-0.46/t/92_todo.t000066400000000000000000000007701242301703500216370ustar00rootroot00000000000000use strict; use warnings; use Test::More; use Data::Dumper; plan skip_all => 'Author test. Set $ENV{TEST_AUTHOR} to a true value to run.' unless $ENV{TEST_AUTHOR}; my $cmds = [ "grep -nr 'TODO' lib/.", ]; # find all TODOs for my $cmd (@{$cmds}) { open(my $ph, '-|', $cmd.' 2>&1') or die('cmd '.$cmd.' failed: '.$!); ok($ph, 'cmd started'); while(<$ph>) { my $line = $_; chomp($line); TODO: { local $TODO = ' '; fail($line); }; } close($ph); } done_testing(); libmonitoring-availability-perl-0.46/t/93-manifest.t000066400000000000000000000015771242301703500224250ustar00rootroot00000000000000use strict; use warnings; use Test::More; use Data::Dumper; plan skip_all => 'Author test. Set $ENV{TEST_AUTHOR} to a true value to run.' unless $ENV{TEST_AUTHOR}; # first do a make distcheck open(my $ph, '-|', 'make distcheck 2>&1') or die('make failed: '.$!); while(<$ph>) { my $line = $_; chomp($line); if( $line =~ m/\/bin\/perl/ or $line =~ m/: Entering directory/ or $line =~ m/: Leaving directory/ ) { pass($line); next; } fail($line); } close($ph); ok($? == 0, 'make exited with: '.$?); # read our manifest file my $manifest = {}; open(my $fh, '<', 'MANIFEST') or die('open MANIFEST failed: '.$!); while(<$fh>) { my $line = $_; chomp($line); next if $line =~ m/^#/; $manifest->{$line} = 1; } close($fh); ok(scalar keys %{$manifest} > 0, 'read entrys from MANIFEST: '.(scalar keys %{$manifest})); done_testing(); libmonitoring-availability-perl-0.46/t/97-Pod.t000066400000000000000000000003661242301703500213400ustar00rootroot00000000000000use strict; use warnings; use Test::More; eval "use Test::Pod 1.14"; plan skip_all => 'Test::Pod 1.14 required' if $@; plan skip_all => 'Author test. Set $ENV{TEST_AUTHOR} to a true value to run.' unless $ENV{TEST_AUTHOR}; all_pod_files_ok(); libmonitoring-availability-perl-0.46/t/98-Pod-Coverage.t000066400000000000000000000006651242301703500230740ustar00rootroot00000000000000#!/usr/bin/env perl # # $Id$ # use strict; use warnings; use File::Spec; use Test::More; if ( not $ENV{TEST_AUTHOR} ) { my $msg = 'Author test. Set $ENV{TEST_AUTHOR} to a true value to run.'; plan( skip_all => $msg ); } eval { require Test::Pod::Coverage; }; if ( $@ ) { my $msg = 'Test::Pod::Coverage required to criticise pod'; plan( skip_all => $msg ); } eval "use Test::Pod::Coverage 1.00"; all_pod_coverage_ok(); libmonitoring-availability-perl-0.46/t/99-Perl-Critic.t000066400000000000000000000007651242301703500227400ustar00rootroot00000000000000#!/usr/bin/env perl # # $Id$ # use strict; use warnings; use File::Spec; use Test::More; if ( not $ENV{TEST_AUTHOR} ) { my $msg = 'Author test. Set $ENV{TEST_AUTHOR} to a true value to run.'; plan( skip_all => $msg ); } eval { require Test::Perl::Critic; }; if ( $@ ) { my $msg = 'Test::Perl::Critic required to criticise code'; plan( skip_all => $msg ); } my $rcfile = File::Spec->catfile( 't', 'perlcriticrc' ); Test::Perl::Critic->import( -profile => $rcfile ); all_critic_ok(); libmonitoring-availability-perl-0.46/t/perlcriticrc000066400000000000000000000171151242301703500226040ustar00rootroot00000000000000############################################################################## # This Perl::Critic configuration file sets the Policy severity levels # according to Damian Conway's own personal recommendations. Feel free to # use this as your own, or make modifications. ############################################################################## [Perl::Critic::Policy::ValuesAndExpressions::ProhibitAccessOfPrivateData] severity = 3 [Perl::Critic::Policy::BuiltinFunctions::ProhibitLvalueSubstr] severity = 3 [Perl::Critic::Policy::BuiltinFunctions::ProhibitReverseSortBlock] severity = 1 [Perl::Critic::Policy::BuiltinFunctions::ProhibitSleepViaSelect] severity = 5 [Perl::Critic::Policy::BuiltinFunctions::ProhibitStringyEval] severity = 5 [Perl::Critic::Policy::BuiltinFunctions::ProhibitStringySplit] severity = 2 [Perl::Critic::Policy::BuiltinFunctions::ProhibitUniversalCan] severity = 4 [Perl::Critic::Policy::BuiltinFunctions::ProhibitUniversalIsa] severity = 4 [Perl::Critic::Policy::BuiltinFunctions::ProhibitVoidGrep] severity = 3 [Perl::Critic::Policy::BuiltinFunctions::ProhibitVoidMap] severity = 3 [Perl::Critic::Policy::BuiltinFunctions::RequireBlockGrep] severity = 4 [Perl::Critic::Policy::BuiltinFunctions::RequireBlockMap] severity = 4 [Perl::Critic::Policy::BuiltinFunctions::RequireGlobFunction] severity = 5 [Perl::Critic::Policy::BuiltinFunctions::RequireSimpleSortBlock] severity = 3 [Perl::Critic::Policy::ClassHierarchies::ProhibitAutoloading] severity = 3 [Perl::Critic::Policy::ClassHierarchies::ProhibitExplicitISA] severity = 4 [Perl::Critic::Policy::ClassHierarchies::ProhibitOneArgBless] severity = 5 [Perl::Critic::Policy::CodeLayout::ProhibitHardTabs] severity = 3 [Perl::Critic::Policy::CodeLayout::ProhibitParensWithBuiltins] severity = 1 [Perl::Critic::Policy::CodeLayout::ProhibitQuotedWordLists] severity = 2 [Perl::Critic::Policy::CodeLayout::RequireConsistentNewlines] severity = 4 [Perl::Critic::Policy::CodeLayout::RequireTidyCode] severity = 1 [Perl::Critic::Policy::CodeLayout::RequireTrailingCommas] severity = 3 [Perl::Critic::Policy::ControlStructures::ProhibitCStyleForLoops] severity = 3 [Perl::Critic::Policy::ControlStructures::ProhibitCascadingIfElse] severity = 3 [Perl::Critic::Policy::ControlStructures::ProhibitDeepNests] severity = 3 [Perl::Critic::Policy::ControlStructures::ProhibitMutatingListFunctions] severity = 5 [Perl::Critic::Policy::ControlStructures::ProhibitPostfixControls] severity = 4 [Perl::Critic::Policy::ControlStructures::ProhibitUnlessBlocks] severity = 4 [Perl::Critic::Policy::ControlStructures::ProhibitUnreachableCode] severity = 4 [Perl::Critic::Policy::ControlStructures::ProhibitUntilBlocks] severity = 4 [Perl::Critic::Policy::Documentation::RequirePodAtEnd] severity = 2 [Perl::Critic::Policy::Documentation::RequirePodSections] severity = 2 [Perl::Critic::Policy::ErrorHandling::RequireCarping] severity = 4 [Perl::Critic::Policy::InputOutput::ProhibitBacktickOperators] severity = 3 [Perl::Critic::Policy::InputOutput::ProhibitBarewordFileHandles] severity = 5 [Perl::Critic::Policy::InputOutput::ProhibitInteractiveTest] severity = 4 [Perl::Critic::Policy::InputOutput::ProhibitOneArgSelect] severity = 4 [Perl::Critic::Policy::InputOutput::ProhibitReadlineInForLoop] severity = 5 [Perl::Critic::Policy::InputOutput::ProhibitTwoArgOpen] severity = 4 [Perl::Critic::Policy::InputOutput::RequireBracedFileHandleWithPrint] severity = 3 [Perl::Critic::Policy::Miscellanea::ProhibitFormats] severity = 3 [Perl::Critic::Policy::Miscellanea::ProhibitTies] severity = 4 [-Perl::Critic::Policy::Miscellanea::RequireRcsKeywords] [Perl::Critic::Policy::Modules::ProhibitAutomaticExportation] severity = 4 [Perl::Critic::Policy::Modules::ProhibitEvilModules] severity = 5 [Perl::Critic::Policy::Modules::ProhibitMultiplePackages] severity = 4 [Perl::Critic::Policy::Modules::RequireBarewordIncludes] severity = 5 [Perl::Critic::Policy::Modules::RequireEndWithOne] severity = 4 [Perl::Critic::Policy::Modules::RequireExplicitPackage] severity = 4 [Perl::Critic::Policy::Modules::RequireFilenameMatchesPackage] severity = 5 [Perl::Critic::Policy::Modules::RequireVersionVar] severity = 4 [Perl::Critic::Policy::NamingConventions::ProhibitAmbiguousNames] severity = 3 [Perl::Critic::Policy::NamingConventions::ProhibitMixedCaseSubs] severity = 1 [Perl::Critic::Policy::NamingConventions::ProhibitMixedCaseVars] severity = 1 [Perl::Critic::Policy::References::ProhibitDoubleSigils] severity = 4 [Perl::Critic::Policy::RegularExpressions::ProhibitCaptureWithoutTest] severity = 4 [Perl::Critic::Policy::RegularExpressions::RequireExtendedFormatting] severity = 5 [Perl::Critic::Policy::RegularExpressions::RequireLineBoundaryMatching] severity = 5 [Perl::Critic::Policy::Subroutines::ProhibitAmpersandSigils] severity = 2 [Perl::Critic::Policy::Subroutines::ProhibitBuiltinHomonyms] severity = 4 [Perl::Critic::Policy::Subroutines::ProhibitExcessComplexity] severity = 3 [Perl::Critic::Policy::Subroutines::ProhibitExplicitReturnUndef] severity = 5 [Perl::Critic::Policy::Subroutines::ProhibitSubroutinePrototypes] severity = 4 [Perl::Critic::Policy::Subroutines::ProtectPrivateSubs] severity = 3 [Perl::Critic::Policy::Subroutines::RequireFinalReturn] severity = 5 [Perl::Critic::Policy::TestingAndDebugging::ProhibitNoStrict] severity = 5 [Perl::Critic::Policy::TestingAndDebugging::ProhibitNoWarnings] severity = 4 [Perl::Critic::Policy::TestingAndDebugging::ProhibitProlongedStrictureOverride] severity = 4 [Perl::Critic::Policy::TestingAndDebugging::RequireTestLabels] severity = 3 [Perl::Critic::Policy::TestingAndDebugging::RequireUseStrict] severity = 5 [Perl::Critic::Policy::TestingAndDebugging::RequireUseWarnings] severity = 4 [Perl::Critic::Policy::ValuesAndExpressions::ProhibitConstantPragma] severity = 4 [Perl::Critic::Policy::ValuesAndExpressions::ProhibitEmptyQuotes] severity = 2 [Perl::Critic::Policy::ValuesAndExpressions::ProhibitEscapedCharacters] severity = 2 [Perl::Critic::Policy::ValuesAndExpressions::ProhibitInterpolationOfLiterals] severity = 1 [Perl::Critic::Policy::ValuesAndExpressions::ProhibitLeadingZeros] severity = 5 [Perl::Critic::Policy::ValuesAndExpressions::ProhibitMismatchedOperators] severity = 2 [Perl::Critic::Policy::ValuesAndExpressions::ProhibitMixedBooleanOperators] severity = 4 [Perl::Critic::Policy::ValuesAndExpressions::ProhibitNoisyQuotes] severity = 2 [Perl::Critic::Policy::ValuesAndExpressions::ProhibitVersionStrings] severity = 3 [Perl::Critic::Policy::ValuesAndExpressions::RequireInterpolationOfMetachars] severity = 1 [Perl::Critic::Policy::ValuesAndExpressions::RequireNumberSeparators] severity = 2 [Perl::Critic::Policy::ValuesAndExpressions::RequireQuotedHeredocTerminator] severity = 4 [Perl::Critic::Policy::ValuesAndExpressions::RequireUpperCaseHeredocTerminator] severity = 4 [Perl::Critic::Policy::Variables::ProhibitConditionalDeclarations] severity = 5 [Perl::Critic::Policy::Variables::ProhibitLocalVars] severity = 2 [Perl::Critic::Policy::Variables::ProhibitMatchVars] severity = 4 [Perl::Critic::Policy::Variables::ProhibitPackageVars] severity = 3 [Perl::Critic::Policy::Variables::ProhibitPunctuationVars] severity = 2 [Perl::Critic::Policy::Variables::ProtectPrivateVars] severity = 3 [Perl::Critic::Policy::Variables::RequireInitializationForLocalVars] severity = 5 [Perl::Critic::Policy::Variables::RequireLexicalLoopIterators] severity = 5 [Perl::Critic::Policy::Variables::RequireNegativeIndices] severity = 4