diff --git a/pandora_server/ChangeLog b/pandora_server/ChangeLog index e33bc8435f..73a31b6324 100644 --- a/pandora_server/ChangeLog +++ b/pandora_server/ChangeLog @@ -1,3 +1,9 @@ +2012-10-23 Ramon Novoa + + * lib/PandoraFMS/Core.pm, + lib/PandoraFMS/Tools.pm: Added support for remote cron modules. Small + fixes. + 2012-10-23 Dario Rodriguez * util/recon_scripts/snmpdevices.pl: Fixed an error in snmpdevices.pl diff --git a/pandora_server/lib/PandoraFMS/Core.pm b/pandora_server/lib/PandoraFMS/Core.pm index 80a11cf703..1101e18b48 100644 --- a/pandora_server/lib/PandoraFMS/Core.pm +++ b/pandora_server/lib/PandoraFMS/Core.pm @@ -974,7 +974,16 @@ sub pandora_process_module ($$$$$$$$$;$) { my $new_status = get_module_status ($processed_data, $module, $module_type); # Calculate the current interval - my $current_interval = ($module->{'module_interval'} == 0 ? $agent->{'intervalo'} : $module->{'module_interval'}); + my $current_interval; + if ($module->{'cron_interval'} ne '' && $module->{'cron_interval'} ne '* * * * *') { + $current_interval = cron_next_execution ($module->{'cron_interval'}); + } + elsif ($module->{'module_interval'} == 0) { + $current_interval = 300; + } + else { + $current_interval = $module->{'module_interval'}; + } #Update module status my $current_utimestamp = time (); @@ -2297,7 +2306,16 @@ sub pandora_update_module_on_error ($$$) { my ($pa_config, $module, $dbh) = @_; # Set tagente_estado.current_interval to make sure it is not 0 - my $current_interval = ($module->{'module_interval'} == 0 ? 300 : $module->{'module_interval'}); + my $current_interval; + if ($module->{'cron_interval'} ne '' && $module->{'cron_interval'} ne '* * * * *') { + $current_interval = cron_next_execution ($module->{'cron_interval'}); + } + elsif ($module->{'module_interval'} == 0) { + $current_interval = 300; + } + else { + $current_interval = $module->{'module_interval'}; + } logger($pa_config, "Updating module " . safe_output($module->{'nombre'}) . " (ID " . $module->{'id_agente_modulo'} . ") on error.", 10); @@ -3457,8 +3475,8 @@ sub pandora_module_unknown ($$) { AND tagente_modulo.disabled = 0 AND tagente_estado.estado <> 3 AND tagente_modulo.id_tipo_modulo NOT IN (21, 22, 23, 100) - AND (tagente_estado.current_interval = 0 - OR (tagente_estado.current_interval * 2) + tagente_estado.utimestamp < UNIX_TIMESTAMP())'); + AND tagente_estado.utimestamp != 0 + AND (tagente_estado.current_interval * 2) + tagente_estado.utimestamp < UNIX_TIMESTAMP()'); foreach my $module (@modules) { diff --git a/pandora_server/lib/PandoraFMS/Tools.pm b/pandora_server/lib/PandoraFMS/Tools.pm index 6236f19745..4e8bde8e8c 100644 --- a/pandora_server/lib/PandoraFMS/Tools.pm +++ b/pandora_server/lib/PandoraFMS/Tools.pm @@ -41,6 +41,8 @@ our @ISA = ("Exporter"); our %EXPORT_TAGS = ( 'all' => [ qw( ) ] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw( + cron_next_execution + cron_next_execution_date pandora_daemonize logger limpia_cadena @@ -1038,6 +1040,139 @@ sub translate_obj ($$$) { return $oid; } +############################################################################### +# Get the number of seconds left to the next execution of the given cron entry. +############################################################################### +sub cron_next_execution ($) { + my ($cron) = @_; + + # Check cron conf format + if ($cron !~ /^((\*|(\d+(-\d+){0,1}))\s*){5}$/) { + return 300; + } + + # Get day of the week and month from cron config + my ($mday, $wday) = (split (/\s/, $cron))[2, 4]; + + # Get current time + my $cur_time = time(); + + # Any day of the way + if ($wday eq '*') { + my $nex_time = cron_next_execution_date ($cron, $cur_time); + return $nex_time - time(); + } + + # A specific day of the week + my $count = 0; + my $nex_time = $cur_time; + do { + $nex_time = cron_next_execution_date ($cron, $nex_time); + my $nex_time_wd = $nex_time; + my ($nex_mon, $nex_wday) = (localtime ($nex_time_wd))[4, 6]; + my $nex_mon_wd; + do { + # Check the day of the week + if ($nex_wday == $wday) { + return $nex_time_wd - time(); + } + + # Move to the next day of the month + $nex_time_wd += 86400; + ($nex_mon_wd, $nex_wday) = (localtime ($nex_time_wd))[4, 6]; + } while ($mday eq '*' && $nex_mon_wd == $nex_mon); + $count++; + } while ($count < 60); + + # Something went wrong, default to 5 minutes + return 300; +} + +############################################################################### +# Get the next execution date for the given cron entry in seconds since epoch. +############################################################################### +sub cron_next_execution_date ($$) { + my ($cron, $cur_time) = @_; + + # Get cron configuration + my ($min, $hour, $mday, $mon, $wday) = split (/\s/, $cron); + + # Months start from 0 + if($mon ne '*') { + $mon -= 1; + } + + # Get current time + if (! defined ($cur_time)) { + $cur_time = time(); + } + my ($cur_min, $cur_hour, $cur_mday, $cur_mon, $cur_year) = (localtime ($cur_time))[1, 2, 3, 4, 5]; + + # Get first next date candidate from cron configuration + my ($nex_min, $nex_hour, $nex_mday, $nex_mon, $nex_year) = ($min, $hour, $mday, $mon, $cur_year); + + # Replace wildcards + if ($min eq '*') { + if ($hour ne '*' || $mday ne '*' || $wday ne '*' || $mon ne '*') { + $nex_min = 0; + } + else { + $nex_min = $cur_min; + } + } + if ($hour eq '*') { + if ($mday ne '*' || $wday ne '*' ||$mon ne '*') { + $nex_hour = 0; + } + else { + $nex_hour = $cur_hour; + } + } + if ($mday eq '*') { + if ($mon ne '*') { + $nex_mday = 1; + } + else { + $nex_mday = $cur_mday; + } + } + if ($mon eq '*') { + $nex_mon = $cur_mon; + } + + # Find the next execution date + my $count = 0; + do { + my $next_time = timelocal(0, $nex_min, $nex_hour, $nex_mday, $nex_mon, $nex_year); + if ($next_time > $cur_time) { + return $next_time; + } + if ($min eq '*' && $hour eq '*' && $wday eq '*' && $mday eq '*' && $mon eq '*') { + ($nex_min, $nex_hour, $nex_mday, $nex_mon, $nex_year) = (localtime ($next_time + 60))[1, 2, 3, 4, 5]; + } + elsif ($hour eq '*' && $wday eq '*' && $mday eq '*' && $mon eq '*') { + ($nex_min, $nex_hour, $nex_mday, $nex_mon, $nex_year) = (localtime ($next_time + 3600))[1, 2, 3, 4, 5]; + } + elsif ($mday eq '*' && $mon eq '*') { + ($nex_min, $nex_hour, $nex_mday, $nex_mon, $nex_year) = (localtime ($next_time + 86400))[1, 2, 3, 4, 5]; + } + elsif ($mon eq '*') { + $nex_mon = $nex_mon + 1; + if ($nex_mon > 11) { + $nex_mon = 0; + $nex_year++; + } + } + else { + $nex_year++; + } + $count++; + } while ($count < 60); + + # Something went wrong, default to 5 minutes + return $cur_time + 300; +} + # End of function declaration # End of defined Code