Merge branch 'ent-1718-module_crontab-Agente-software' into 'develop'
Ent 1718 module crontab agente software See merge request artica/pandorafms!1311
This commit is contained in:
commit
ccc17c79ac
|
@ -510,8 +510,6 @@ sub parse_conf_modules($) {
|
|||
}
|
||||
} elsif ($line =~ /^\s*module_crontab\s+(((\*|(\d+(-\d+){0,1}))\s*){5}).*$/) {
|
||||
$module->{'cron'} = $1;
|
||||
} elsif ($line =~ /^\s*module_cron_interval\s+(\d+).*$/) {
|
||||
$module->{'cron_interval'} = $1;
|
||||
} elsif ($line =~ /^\s*module_end\s*$/) {
|
||||
next unless ($module->{'name'} ne '') and ($module->{'func'} != 0);
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ use File::Basename;
|
|||
use File::Copy;
|
||||
use IO::Socket;
|
||||
use Sys::Syslog;
|
||||
use Time::Local;
|
||||
|
||||
# Agent XML data
|
||||
my $Xml;
|
||||
|
@ -515,10 +516,11 @@ sub parse_conf_modules($) {
|
|||
}
|
||||
}
|
||||
} elsif ($line =~ /^\s*module_crontab\s+(((\*|(\d+(-\d+){0,1}))\s*){5}).*$/) {
|
||||
$module->{'cron'} = $1;
|
||||
chomp ($module->{'cron'});
|
||||
} elsif ($line =~ /^\s*module_cron_interval\s+(\d+).*$/) {
|
||||
$module->{'cron_interval'} = $1;
|
||||
my $cron_text = $1;
|
||||
chomp ($cron_text);
|
||||
if (cron_check_syntax($cron_text)) {
|
||||
$module->{'cron'} = $cron_text;
|
||||
}
|
||||
} elsif ($line =~ /^\s*module_end\s*$/) {
|
||||
|
||||
$module_begin = 0;
|
||||
|
@ -1632,8 +1634,8 @@ sub guess_os_version ($) {
|
|||
################################################################################
|
||||
# Execute the given module.
|
||||
################################################################################
|
||||
sub exec_module ($) {
|
||||
my $module = shift;
|
||||
sub exec_module {
|
||||
my ($module, $interval) = @_;
|
||||
|
||||
# Need something to execute
|
||||
if ($module->{'func'} == 0) {
|
||||
|
@ -1648,7 +1650,7 @@ sub exec_module ($) {
|
|||
}
|
||||
|
||||
# Check module cron
|
||||
if (check_module_cron ($module) != 1) {
|
||||
if (check_module_cron ($module, $interval) != 1) {
|
||||
$ThreadSem->up () if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1);
|
||||
return;
|
||||
}
|
||||
|
@ -2044,85 +2046,339 @@ sub evaluate_module_intensive_conditions ($$) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Get the number of seconds left to the next execution of the given cron entry.
|
||||
###############################################################################
|
||||
sub cron_next_execution {
|
||||
my ($cron, $interval) = @_;
|
||||
|
||||
# Check cron conf format
|
||||
if ($cron !~ /^((\*|(\d+(-\d+){0,1}))\s*){5}$/) {
|
||||
return $interval;
|
||||
}
|
||||
|
||||
# Get day of the week and month from cron config
|
||||
my ($mday, $wday) = (split (/\s/, $cron))[2, 4];
|
||||
|
||||
# Get current time and day of the week
|
||||
my $cur_time = time();
|
||||
my $cur_wday = (localtime ($cur_time))[6];
|
||||
|
||||
# Any day of the week
|
||||
if ($wday eq '*') {
|
||||
my $nex_time = cron_next_execution_date ($cron, $cur_time, $interval);
|
||||
return $nex_time - time();
|
||||
}
|
||||
# A range?
|
||||
else {
|
||||
$wday = cron_get_closest_in_range ($cur_wday, $wday);
|
||||
}
|
||||
|
||||
# A specific day of the week
|
||||
my $count = 0;
|
||||
my $nex_time = $cur_time;
|
||||
do {
|
||||
$nex_time = cron_next_execution_date ($cron, $nex_time, $interval);
|
||||
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 $interval;
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Get the number of seconds left to the next execution of the given cron entry.
|
||||
###############################################################################
|
||||
sub cron_check_syntax ($) {
|
||||
my ($cron) = @_;
|
||||
|
||||
return 0 if !defined ($cron);
|
||||
return ($cron =~ m/^(\d|\*|-)+ (\d|\*|-)+ (\d|\*|-)+ (\d|\*|-)+ (\d|\*|-)+$/);
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Get the next execution date for the given cron entry in seconds since epoch.
|
||||
###############################################################################
|
||||
sub cron_next_execution_date {
|
||||
my ($cron, $cur_time, $interval) = @_;
|
||||
|
||||
# Get cron configuration
|
||||
my ($min, $hour, $mday, $mon, $wday) = split (/\s/, $cron);
|
||||
|
||||
# Months start from 0
|
||||
if($mon ne '*') {
|
||||
my ($mon_down, $mon_up) = cron_get_interval ($mon);
|
||||
if (defined($mon_up)) {
|
||||
$mon = ($mon_down - 1) . "-" . ($mon_up - 1);
|
||||
} else {
|
||||
$mon = $mon_down - 1;
|
||||
}
|
||||
}
|
||||
|
||||
# Get current time
|
||||
if (! defined ($cur_time)) {
|
||||
$cur_time = time();
|
||||
}
|
||||
# Check if current time + interval is on cron too
|
||||
my $nex_time = $cur_time + $interval;
|
||||
my ($cur_min, $cur_hour, $cur_mday, $cur_mon, $cur_year)
|
||||
= (localtime ($nex_time))[1, 2, 3, 4, 5];
|
||||
|
||||
my @cron_array = ($min, $hour, $mday, $mon);
|
||||
my @curr_time_array = ($cur_min, $cur_hour, $cur_mday, $cur_mon);
|
||||
return ($nex_time) if cron_is_in_cron(\@cron_array, \@curr_time_array) == 1;
|
||||
|
||||
# Get first next date candidate from next cron configuration
|
||||
# Initialize some vars
|
||||
my @nex_time_array = @curr_time_array;
|
||||
|
||||
# Update minutes
|
||||
my ($min_down, undef) = cron_get_interval ($min);
|
||||
$nex_time_array[0] = ($min_down eq '*') ? 0 : $min_down;
|
||||
|
||||
$nex_time = cron_valid_date(@nex_time_array, $cur_year);
|
||||
if ($nex_time >= $cur_time) {
|
||||
return $nex_time if cron_is_in_cron(\@cron_array, \@nex_time_array);
|
||||
}
|
||||
|
||||
# Check if next hour is in cron
|
||||
$nex_time_array[1]++;
|
||||
$nex_time = cron_valid_date(@nex_time_array, $cur_year);
|
||||
|
||||
if ($nex_time == 0) {
|
||||
#Update the month day if overflow
|
||||
$nex_time_array[1] = 0;
|
||||
$nex_time_array[2]++;
|
||||
$nex_time = cron_valid_date(@nex_time_array, $cur_year);
|
||||
if ($nex_time == 0) {
|
||||
#Update the month if overflow
|
||||
$nex_time_array[2] = 1;
|
||||
$nex_time_array[3]++;
|
||||
$nex_time = cron_valid_date(@nex_time_array, $cur_year);
|
||||
if ($nex_time == 0) {
|
||||
#Update the year if overflow
|
||||
$cur_year++;
|
||||
$nex_time_array[3] = 0;
|
||||
$nex_time = cron_valid_date(@nex_time_array, $cur_year);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Check the hour
|
||||
return $nex_time if cron_is_in_cron(\@cron_array, \@nex_time_array);
|
||||
|
||||
#Update the hour if fails
|
||||
my ($hour_down, undef) = cron_get_interval ($hour);
|
||||
$nex_time_array[1] = ($hour_down eq '*') ? 0 : $hour_down;
|
||||
|
||||
# When an overflow is passed check the hour update again
|
||||
$nex_time = cron_valid_date(@nex_time_array, $cur_year);
|
||||
if ($nex_time >= $cur_time) {
|
||||
return $nex_time if cron_is_in_cron(\@cron_array, \@nex_time_array);
|
||||
}
|
||||
|
||||
# Check if next day is in cron
|
||||
$nex_time_array[2]++;
|
||||
$nex_time = cron_valid_date(@nex_time_array, $cur_year);
|
||||
if ($nex_time == 0) {
|
||||
#Update the month if overflow
|
||||
$nex_time_array[2] = 1;
|
||||
$nex_time_array[3]++;
|
||||
$nex_time = cron_valid_date(@nex_time_array, $cur_year);
|
||||
if ($nex_time == 0) {
|
||||
#Update the year if overflow
|
||||
$nex_time_array[3] = 0;
|
||||
$cur_year++;
|
||||
$nex_time = cron_valid_date(@nex_time_array, $cur_year);
|
||||
}
|
||||
}
|
||||
|
||||
#Check the day
|
||||
return $nex_time if cron_is_in_cron(\@cron_array, \@nex_time_array);
|
||||
|
||||
#Update the day if fails
|
||||
my ($mday_down, undef) = cron_get_interval ($mday);
|
||||
$nex_time_array[2] = ($mday_down eq '*') ? 1 : $mday_down;
|
||||
|
||||
# When an overflow is passed check the day update in the next execution
|
||||
$nex_time = cron_valid_date(@nex_time_array, $cur_year);
|
||||
if ($nex_time >= $cur_time) {
|
||||
return $nex_time if cron_is_in_cron(\@cron_array, \@nex_time_array);
|
||||
}
|
||||
|
||||
# Check if next month is in cron
|
||||
$nex_time_array[3]++;
|
||||
$nex_time = cron_valid_date(@nex_time_array, $cur_year);
|
||||
if ($nex_time == 0) {
|
||||
#Update the year if overflow
|
||||
$nex_time_array[3] = 0;
|
||||
$cur_year++;
|
||||
$nex_time = cron_valid_date(@nex_time_array, $cur_year);
|
||||
}
|
||||
|
||||
#Check the month
|
||||
return $nex_time if cron_is_in_cron(\@cron_array, \@nex_time_array);
|
||||
|
||||
#Update the month if fails
|
||||
my ($mon_down, undef) = cron_get_interval ($mon);
|
||||
$nex_time_array[3] = ($mon_down eq '*') ? 0 : $mon_down;
|
||||
|
||||
# When an overflow is passed check the month update in the next execution
|
||||
$nex_time = cron_valid_date(@nex_time_array, $cur_year);
|
||||
if ($nex_time >= $cur_time) {
|
||||
return $nex_time if cron_is_in_cron(\@cron_array, \@nex_time_array);
|
||||
}
|
||||
|
||||
#Update the year if fails
|
||||
$nex_time = cron_valid_date(@nex_time_array, $cur_year + 1);
|
||||
|
||||
return $nex_time;
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Returns if a date is in a cron. Recursive.
|
||||
# Needs the cron like an array reference and
|
||||
# current time in cron format to works properly
|
||||
###############################################################################
|
||||
sub cron_is_in_cron {
|
||||
my ($elems_cron, $elems_curr_time) = @_;
|
||||
|
||||
my @deref_elems_cron = @$elems_cron;
|
||||
my @deref_elems_curr_time = @$elems_curr_time;
|
||||
|
||||
my $elem_cron = shift(@deref_elems_cron);
|
||||
my $elem_curr_time = shift (@deref_elems_curr_time);
|
||||
|
||||
#If there is no elements means that is in cron
|
||||
return 1 unless (defined($elem_cron) || defined($elem_curr_time));
|
||||
|
||||
# Go to last element if current is a wild card
|
||||
if ($elem_cron ne '*') {
|
||||
my ($down, $up) = cron_get_interval($elem_cron);
|
||||
# Check if there is no a range
|
||||
return 0 if (!defined($up) && ($down != $elem_curr_time));
|
||||
# Check if there is on the range
|
||||
if (defined($up)) {
|
||||
if ($down < $up) {
|
||||
return 0 if ($elem_curr_time < $down || $elem_curr_time > $up);
|
||||
} else {
|
||||
return 0 if ($elem_curr_time > $down || $elem_curr_time < $up);
|
||||
}
|
||||
}
|
||||
}
|
||||
return cron_is_in_cron(\@deref_elems_cron, \@deref_elems_curr_time);
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Returns the interval of a cron element. If there is not a range,
|
||||
# returns an array with the first element in the first place of array
|
||||
# and the second place undefined.
|
||||
###############################################################################
|
||||
sub cron_get_interval {
|
||||
my ($element) = @_;
|
||||
|
||||
# Not a range
|
||||
if ($element !~ /(\d+)\-(\d+)/) {
|
||||
return ($element, undef);
|
||||
}
|
||||
|
||||
return ($1, $2);
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Returns the closest number to the target inside the given range (including
|
||||
# the target itself).
|
||||
###############################################################################
|
||||
sub cron_get_closest_in_range ($$) {
|
||||
my ($target, $range) = @_;
|
||||
|
||||
# Not a range
|
||||
if ($range !~ /(\d+)\-(\d+)/) {
|
||||
return $range;
|
||||
}
|
||||
|
||||
# Search the closes number to the target in the given range
|
||||
my $range_start = $1;
|
||||
my $range_end = $2;
|
||||
|
||||
# Outside the range
|
||||
if ($target <= $range_start || $target > $range_end) {
|
||||
return $range_start;
|
||||
}
|
||||
|
||||
# Inside the range
|
||||
return $target;
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Check if a date is valid to get timelocal
|
||||
###############################################################################
|
||||
sub cron_valid_date {
|
||||
my ($min, $hour, $mday, $month, $year) = @_;
|
||||
my $utime;
|
||||
eval {
|
||||
local $SIG{__DIE__} = sub {};
|
||||
$utime = timelocal(0, $min, $hour, $mday, $month, $year);
|
||||
};
|
||||
if ($@) {
|
||||
return 0;
|
||||
}
|
||||
return $utime;
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Checks the module's cron string. Returns 1 if the module should be run, 0 if
|
||||
# not.
|
||||
################################################################################
|
||||
sub check_module_cron ($) {
|
||||
my $module = shift;
|
||||
sub check_module_cron {
|
||||
my ($module, $main_interval) = @_;
|
||||
|
||||
# No cron string defined
|
||||
return 1 unless ($module->{'cron'} ne '');
|
||||
|
||||
my $now = time();
|
||||
|
||||
# Check if the module was already executed
|
||||
return 0 unless (time() >= $module->{'cron_utimestamp'});
|
||||
return 0 unless ($now >= $module->{'cron_utimestamp'});
|
||||
|
||||
# Get cron configuration
|
||||
my @cron_params = split (/\s/, $module->{'cron'});
|
||||
my $interval = $main_interval * $module->{'interval'};
|
||||
|
||||
# Get current time
|
||||
my $current_time = time();
|
||||
my @time = localtime($current_time);
|
||||
my $time_to_next_execution = cron_next_execution(
|
||||
$module->{'cron'},
|
||||
$interval
|
||||
);
|
||||
|
||||
# Minutes, hours, day of the month, month and day of the week
|
||||
my @time_params = @time[1, 2, 3, 4, 6];
|
||||
$module->{'cron_utimestamp'} = $now + $time_to_next_execution;
|
||||
$module->{'cron_interval'} = $time_to_next_execution;
|
||||
|
||||
# Fix month (localtime retuns 0..11 and we need 1..12)
|
||||
$time_params[3] += 1;
|
||||
|
||||
# Check cron parameters
|
||||
for (my $i = 0; $i < 5; $i++) {
|
||||
|
||||
# Wildcard
|
||||
next if ($cron_params[$i] eq '*');
|
||||
|
||||
# Get interval
|
||||
my ($bottom, $top) = split (/-/, $cron_params[$i]);
|
||||
$top = $bottom unless defined ($top);
|
||||
|
||||
# Check if next execution will overflow the cron (only minutes overflow)
|
||||
# If overflow, execute the module
|
||||
my $overflow_cron = 0;
|
||||
if ($i == 0) {
|
||||
my $start_cron_seconds = $bottom*60;
|
||||
my $current_exec_seconds = $time_params[$i]*60;
|
||||
my $next_exec_seconds = $time_params[$i]*60 + $module->{'interval'}*$Conf{'interval'};
|
||||
if ($current_exec_seconds > $start_cron_seconds && $current_exec_seconds > $next_exec_seconds) {
|
||||
$start_cron_seconds += 3600;
|
||||
}
|
||||
if (($current_exec_seconds <= $start_cron_seconds) && ($start_cron_seconds <= $next_exec_seconds)) {
|
||||
$overflow_cron = 1
|
||||
}
|
||||
}
|
||||
|
||||
# Check interval
|
||||
if ($bottom <= $top) {
|
||||
return 0 if (($time_params[$i] < $bottom || $time_params[$i] > $top) && !$overflow_cron);
|
||||
} else {
|
||||
return 0 if (($time_params[$i] < $bottom && $time_params[$i] > $top) && !$overflow_cron);
|
||||
}
|
||||
if ($Conf{'debug'} eq '1') {
|
||||
log_message ('debug', "Cron for module $module->{'name'} will be executed next time at timestamp: $module->{'cron_utimestamp'}.");
|
||||
}
|
||||
|
||||
# Do not check in the next minute, hour, day or month.
|
||||
my $offset = 0;
|
||||
if ($module->{'cron_interval'} >= 0) {
|
||||
$offset = $module->{'cron_interval'};
|
||||
} elsif($cron_params[0] ne '*') {
|
||||
# 1 minute
|
||||
$offset = 60;
|
||||
} elsif($cron_params[1] ne '*') {
|
||||
# 1 hour
|
||||
$offset = 3600;
|
||||
} elsif($cron_params[2] ne '*' || $cron_params[4] ne '*') {
|
||||
# 1 day
|
||||
$offset = 86400;
|
||||
} elsif($cron_params[3] ne '*') {
|
||||
# 31 days
|
||||
$offset = 2678400;
|
||||
}
|
||||
# On first execution checking if cron is valid is required
|
||||
return 1 unless ($module->{'cron_utimestamp'} == 0);
|
||||
|
||||
$module->{'cron_utimestamp'} = $current_time + $offset;
|
||||
return 1;
|
||||
# Check if current timestamp is a valid cron date
|
||||
my $next_execution = cron_next_execution_date(
|
||||
$module->{'cron'},
|
||||
$now - $interval,
|
||||
$interval
|
||||
);
|
||||
return 1 if ($next_execution == $now);
|
||||
return 0;
|
||||
}
|
||||
|
||||
################################################################################
|
||||
|
@ -2222,8 +2478,9 @@ sub write_module_xml ($@) {
|
|||
# Module Alert template
|
||||
$Xml .= " <alert_template>" . $module->{'alert_template'} . "</alert_template>\n" if (defined ($module->{'alert_template'}));
|
||||
|
||||
# Module Alert template
|
||||
# Module Crontab
|
||||
$Xml .= " <crontab>" . $module->{'cron'} . "</crontab>\n" if (defined ($module->{'cron'}) and ($module->{'cron'} ne ""));
|
||||
$Xml .= " <cron_interval>" . $module->{'cron_interval'} . "</cron_interval>\n" if (defined ($module->{'cron'}) and (defined ($module->{'cron_interval'})));
|
||||
|
||||
# FF threshold configuration
|
||||
$Xml .= " <min_ff_event_normal>" . $module->{'min_ff_event_normal'} . "</min_ff_event_normal>\n" if (defined ($module->{'min_ff_event_normal'}));
|
||||
|
@ -2461,7 +2718,6 @@ sub init_module ($) {
|
|||
$module->{'conditions'} = [];
|
||||
$module->{'cron'} = '';
|
||||
$module->{'cron_utimestamp'} = 0;
|
||||
$module->{'cron_interval'} = -1;
|
||||
$module->{'precondition'} = [];
|
||||
$module->{'is_intensive'} = 0;
|
||||
$module->{'intensive_conditions'} = [];
|
||||
|
@ -2770,7 +3026,7 @@ while (1) {
|
|||
# Execute the module in a separate thread
|
||||
if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1) {
|
||||
$ThreadSem->down ();
|
||||
my $thr = threads->create (\&exec_module, $module);
|
||||
my $thr = threads->create (\&exec_module, $module, $Conf{'interval'});
|
||||
if (! defined ($thr)) {
|
||||
$ThreadSem->up ();
|
||||
} else {
|
||||
|
@ -2778,7 +3034,7 @@ while (1) {
|
|||
}
|
||||
# Execute the module
|
||||
} else {
|
||||
exec_module($module);
|
||||
exec_module($module, $Conf{'interval'});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
bin_PROGRAMS = PandoraAgent
|
||||
if DEBUG
|
||||
PandoraAgent_SOURCES = misc/pandora_file.cc modules/pandora_data.cc modules/pandora_module_factory.cc modules/pandora_module.cc modules/pandora_module_list.cc modules/pandora_module_plugin.cc modules/pandora_module_inventory.cc modules/pandora_module_freememory.cc modules/pandora_module_exec.cc modules/pandora_module_perfcounter.cc modules/pandora_module_proc.cc modules/pandora_module_tcpcheck.cc modules/pandora_module_freememory_percent.cc modules/pandora_module_freedisk.cc modules/pandora_module_freedisk_percent.cc modules/pandora_module_logevent.cc modules/pandora_module_service.cc modules/pandora_module_cpuusage.cc modules/pandora_module_wmiquery.cc modules/pandora_module_regexp.cc modules/pandora_module_ping.cc modules/pandora_module_snmpget.cc udp_server/udp_server.cc main.cc pandora_strutils.cc pandora.cc windows_service.cc pandora_agent_conf.cc windows/pandora_windows_info.cc windows/pandora_wmi.cc pandora_windows_service.cc misc/md5.c misc/sha256.cc windows/wmi/disphelper.c ssh/libssh2/channel.c ssh/libssh2/mac.c ssh/libssh2/session.c ssh/libssh2/comp.c ssh/libssh2/misc.c ssh/libssh2/sftp.c ssh/libssh2/crypt.c ssh/libssh2/packet.c ssh/libssh2/userauth.c ssh/libssh2/hostkey.c ssh/libssh2/publickey.c ssh/libssh2/kex.c ssh/libssh2/scp.c ssh/pandora_ssh_client.cc ssh/pandora_ssh_test.cc ftp/pandora_ftp_client.cc ftp/pandora_ftp_test.cc debug_new.cpp
|
||||
PandoraAgent_SOURCES = misc/cron.cc misc/pandora_file.cc modules/pandora_data.cc modules/pandora_module_factory.cc modules/pandora_module.cc modules/pandora_module_list.cc modules/pandora_module_plugin.cc modules/pandora_module_inventory.cc modules/pandora_module_freememory.cc modules/pandora_module_exec.cc modules/pandora_module_perfcounter.cc modules/pandora_module_proc.cc modules/pandora_module_tcpcheck.cc modules/pandora_module_freememory_percent.cc modules/pandora_module_freedisk.cc modules/pandora_module_freedisk_percent.cc modules/pandora_module_logevent.cc modules/pandora_module_service.cc modules/pandora_module_cpuusage.cc modules/pandora_module_wmiquery.cc modules/pandora_module_regexp.cc modules/pandora_module_ping.cc modules/pandora_module_snmpget.cc udp_server/udp_server.cc main.cc pandora_strutils.cc pandora.cc windows_service.cc pandora_agent_conf.cc windows/pandora_windows_info.cc windows/pandora_wmi.cc pandora_windows_service.cc misc/md5.c misc/sha256.cc windows/wmi/disphelper.c ssh/libssh2/channel.c ssh/libssh2/mac.c ssh/libssh2/session.c ssh/libssh2/comp.c ssh/libssh2/misc.c ssh/libssh2/sftp.c ssh/libssh2/crypt.c ssh/libssh2/packet.c ssh/libssh2/userauth.c ssh/libssh2/hostkey.c ssh/libssh2/publickey.c ssh/libssh2/kex.c ssh/libssh2/scp.c ssh/pandora_ssh_client.cc ssh/pandora_ssh_test.cc ftp/pandora_ftp_client.cc ftp/pandora_ftp_test.cc debug_new.cpp
|
||||
PandoraAgent_CXXFLAGS=-g -O0
|
||||
else
|
||||
PandoraAgent_SOURCES = misc/pandora_file.cc modules/pandora_data.cc modules/pandora_module_factory.cc modules/pandora_module.cc modules/pandora_module_list.cc modules/pandora_module_plugin.cc modules/pandora_module_inventory.cc modules/pandora_module_freememory.cc modules/pandora_module_exec.cc modules/pandora_module_perfcounter.cc modules/pandora_module_proc.cc modules/pandora_module_tcpcheck.cc modules/pandora_module_freememory_percent.cc modules/pandora_module_freedisk.cc modules/pandora_module_freedisk_percent.cc modules/pandora_module_logevent.cc modules/pandora_module_logchannel.cc modules/pandora_module_service.cc modules/pandora_module_cpuusage.cc modules/pandora_module_wmiquery.cc modules/pandora_module_regexp.cc modules/pandora_module_ping.cc modules/pandora_module_snmpget.cc udp_server/udp_server.cc main.cc pandora_strutils.cc pandora.cc windows_service.cc pandora_agent_conf.cc windows/pandora_windows_info.cc windows/pandora_wmi.cc pandora_windows_service.cc misc/md5.c misc/sha256.cc windows/wmi/disphelper.c ssh/libssh2/channel.c ssh/libssh2/mac.c ssh/libssh2/session.c ssh/libssh2/comp.c ssh/libssh2/misc.c ssh/libssh2/sftp.c ssh/libssh2/crypt.c ssh/libssh2/packet.c ssh/libssh2/userauth.c ssh/libssh2/hostkey.c ssh/libssh2/publickey.c ssh/libssh2/kex.c ssh/libssh2/scp.c ssh/pandora_ssh_client.cc ssh/pandora_ssh_test.cc ftp/pandora_ftp_client.cc ftp/pandora_ftp_test.cc
|
||||
PandoraAgent_SOURCES = misc/cron.cc misc/pandora_file.cc modules/pandora_data.cc modules/pandora_module_factory.cc modules/pandora_module.cc modules/pandora_module_list.cc modules/pandora_module_plugin.cc modules/pandora_module_inventory.cc modules/pandora_module_freememory.cc modules/pandora_module_exec.cc modules/pandora_module_perfcounter.cc modules/pandora_module_proc.cc modules/pandora_module_tcpcheck.cc modules/pandora_module_freememory_percent.cc modules/pandora_module_freedisk.cc modules/pandora_module_freedisk_percent.cc modules/pandora_module_logevent.cc modules/pandora_module_logchannel.cc modules/pandora_module_service.cc modules/pandora_module_cpuusage.cc modules/pandora_module_wmiquery.cc modules/pandora_module_regexp.cc modules/pandora_module_ping.cc modules/pandora_module_snmpget.cc udp_server/udp_server.cc main.cc pandora_strutils.cc pandora.cc windows_service.cc pandora_agent_conf.cc windows/pandora_windows_info.cc windows/pandora_wmi.cc pandora_windows_service.cc misc/md5.c misc/sha256.cc windows/wmi/disphelper.c ssh/libssh2/channel.c ssh/libssh2/mac.c ssh/libssh2/session.c ssh/libssh2/comp.c ssh/libssh2/misc.c ssh/libssh2/sftp.c ssh/libssh2/crypt.c ssh/libssh2/packet.c ssh/libssh2/userauth.c ssh/libssh2/hostkey.c ssh/libssh2/publickey.c ssh/libssh2/kex.c ssh/libssh2/scp.c ssh/pandora_ssh_client.cc ssh/pandora_ssh_test.cc ftp/pandora_ftp_client.cc ftp/pandora_ftp_test.cc
|
||||
PandoraAgent_CXXFLAGS=-O2
|
||||
endif
|
||||
|
||||
|
|
|
@ -0,0 +1,414 @@
|
|||
/* Pandora cron manager for Win32.
|
||||
|
||||
Copyright (C) 2018 Artica ST.
|
||||
Written by Fermin Hernandez.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sstream>
|
||||
#include "cron.h"
|
||||
#include "../pandora.h"
|
||||
|
||||
/**
|
||||
* @brief Constructor of cron class
|
||||
*
|
||||
* @param cron_string String with cron format (https://en.wikipedia.org/wiki/Cron)
|
||||
*/
|
||||
Cron::Cron (string cron_string) {
|
||||
char cron_params[5][256], bottom[256], top[256];
|
||||
|
||||
// Check if cron string is the default or empty
|
||||
if (
|
||||
cron_string.compare(CRON_DEFAULT_STRING) == 0 ||
|
||||
cron_string.compare("") == 0
|
||||
) {
|
||||
this->isSet = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse the cron string
|
||||
if (sscanf (cron_string.c_str (), "%255s %255s %255s %255s %255s", cron_params[0], cron_params[1], cron_params[2], cron_params[3], cron_params[4]) != 5) {
|
||||
Pandora::pandoraDebug ("Invalid cron string: %s", cron_string.c_str ());
|
||||
this->isSet = false;
|
||||
this->cronString = CRON_DEFAULT_STRING;
|
||||
return;
|
||||
}
|
||||
|
||||
this->cronString = cron_string;
|
||||
|
||||
// Fill the cron structure
|
||||
this->utimestamp = 0;
|
||||
this->cronInterval = 0;
|
||||
this->isSet = true;
|
||||
// Months in cron are from 1 to 12. For date, are required from 0 to 11.
|
||||
for (int i = 0; i < 5; i++) {
|
||||
|
||||
// Wildcard
|
||||
if (cron_params[i][0] == '*') {
|
||||
this->params[i][CRDOWN] = CR_WILDCARD_VALUE;
|
||||
this->params[i][1] = CR_WILDCARD_VALUE;
|
||||
|
||||
// Interval
|
||||
} else if (sscanf (cron_params[i], "%255[^-]-%255s", bottom, top) == 2) {
|
||||
// Check if there is an interval with two equal values
|
||||
if (strcmp(bottom, top) == 0) {
|
||||
this->params[i][CRDOWN] = (i != 3)
|
||||
? atoi (cron_params[i])
|
||||
: atoi (cron_params[i]) - 1;
|
||||
this->params[i][CRUP] = CR_WILDCARD_VALUE;
|
||||
} else {
|
||||
this->params[i][CRDOWN] = (i != 3) ? atoi (bottom) : atoi (bottom) - 1;
|
||||
this->params[i][CRUP] = (i != 3) ? atoi (top) : atoi (top) -1;
|
||||
}
|
||||
|
||||
// Single value
|
||||
} else {
|
||||
this->params[i][CRDOWN] = (i != 3)
|
||||
? atoi (cron_params[i])
|
||||
: atoi (cron_params[i]) - 1;
|
||||
this->params[i][CRUP] = CR_WILDCARD_VALUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Getter of isSet property
|
||||
*
|
||||
*/
|
||||
bool Cron::getIsSet () { return this->isSet; }
|
||||
|
||||
/**
|
||||
* @brief Getter of cronString property
|
||||
*
|
||||
*/
|
||||
string Cron::getCronString() { return this->cronString; }
|
||||
|
||||
/**
|
||||
* @brief Getter of cronInterval property casting in string
|
||||
*
|
||||
*/
|
||||
string Cron::getCronIntervalStr() {
|
||||
stringstream ss;
|
||||
ss << this->cronInterval;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Given a date, return if is inside a cron string or not
|
||||
*
|
||||
* @param date Date to check
|
||||
* @return true If is inside cron
|
||||
* @return false If is outside cron
|
||||
*/
|
||||
bool Cron::isInCron(time_t date) {
|
||||
struct tm * timeinfo = localtime(&date);
|
||||
|
||||
// Convert the tm struct to an array
|
||||
int date_array[4] = {
|
||||
timeinfo->tm_min,
|
||||
timeinfo->tm_hour,
|
||||
timeinfo->tm_mday,
|
||||
timeinfo->tm_mon
|
||||
};
|
||||
|
||||
// Check all positions faliures
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!isBetweenParams(date_array[i], i)) return false;
|
||||
}
|
||||
|
||||
// If no failures, date is inside cron.
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if a value is in a position of cron
|
||||
*
|
||||
* @param value Value to check
|
||||
* @param position Position in cron to make the check
|
||||
* @return If position is in cron
|
||||
*/
|
||||
bool Cron::isBetweenParams(int value, int position) {
|
||||
if (!isWildCard(position)) {
|
||||
if (isSingleValue(position)) {
|
||||
if (this->params[position][CRDOWN] != value) return false;
|
||||
} else {
|
||||
if (isNormalInterval(position)) {
|
||||
if (
|
||||
value < this->params[position][CRDOWN] ||
|
||||
value > this->params[position][CRUP]
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
value < this->params[position][CRDOWN] &&
|
||||
value > this->params[position][CRUP]
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if a cron position is a wildcard
|
||||
*
|
||||
* @param position Position inside the param array
|
||||
* @return true if is a wildcard
|
||||
*/
|
||||
bool Cron::isWildCard(int position) {
|
||||
return this->params[position][CRDOWN] == CR_WILDCARD_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if a cron position is a single value
|
||||
*
|
||||
* @param position Position inside the param array
|
||||
* @return true if is a single value
|
||||
*/
|
||||
bool Cron::isSingleValue(int position) {
|
||||
return this->params[position][CRUP] == CR_WILDCARD_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if a cron position is an interval with down lower than up
|
||||
*
|
||||
* @param position Position inside the param array
|
||||
* @return true if is a normal interval
|
||||
* @return false if is an inverse interval
|
||||
*/
|
||||
bool Cron::isNormalInterval (int position) {
|
||||
// Wildcard and single value will be treated like normal interval
|
||||
if (
|
||||
this->params[position][CRDOWN] == CR_WILDCARD_VALUE ||
|
||||
this->params[position][CRUP] == CR_WILDCARD_VALUE
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return (this->params[position][CRUP] >= this->params[position][CRDOWN]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the reset value on a cron position
|
||||
*
|
||||
* @param position
|
||||
* @return int Reset value
|
||||
*/
|
||||
int Cron::getResetValue (int position) {
|
||||
int default_value = 0;
|
||||
// Days start in 1
|
||||
if (position == 2) default_value = 1;
|
||||
return isWildCard(position)
|
||||
? default_value
|
||||
: this->params[position][CRDOWN];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if cron module should be executed at a given time
|
||||
*
|
||||
* @param date
|
||||
* @return true if should execute
|
||||
* @return false if should not execute
|
||||
*/
|
||||
bool Cron::shouldExecuteAt (time_t date) {
|
||||
return this->utimestamp < date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if a module should be executed when utimestamp is not calculated yet
|
||||
*
|
||||
* @param date Current date
|
||||
* @return true It is not first time and current date fit in cron
|
||||
* @return false Don't execute first time
|
||||
*/
|
||||
bool Cron::shouldExecuteAtFirst (time_t date) {
|
||||
|
||||
// Return true if it is not first
|
||||
if (this->utimestamp != 0) return true;
|
||||
|
||||
// Check current date in cron
|
||||
return isInCron(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update the cron utimestamp
|
||||
*
|
||||
* @param date Timestamp "from" to update cron utimestamp
|
||||
* @param interval Module interval
|
||||
*/
|
||||
void Cron::update (time_t date, int interval) {
|
||||
time_t next_time = getNextExecutionFrom(date, interval);
|
||||
|
||||
// Check the day of the week
|
||||
struct tm * timeinfo = localtime(&next_time);
|
||||
int count = 0; // Avoid infinite loops
|
||||
while ((!isBetweenParams(timeinfo->tm_wday, 4)) && (count++ < CR_MAX_ITERS)){
|
||||
next_time = getNextExecutionFrom(next_time + CR_SECONDS_ONE_DAY, 0);
|
||||
timeinfo = localtime(&next_time);
|
||||
}
|
||||
if (count >= CR_MAX_ITERS) {
|
||||
Pandora::pandoraLog(
|
||||
"Module with cron %s will be executed at timestamp: %d, but it can be incorrect",
|
||||
this->cronString.c_str(),
|
||||
this->utimestamp
|
||||
);
|
||||
}
|
||||
|
||||
// Security about values
|
||||
if (next_time < date) {
|
||||
this->utimestamp = date + interval;
|
||||
this->cronInterval = interval;
|
||||
Pandora::pandoraLog("Cron update fails in Module with cron %s", this->cronString.c_str());
|
||||
}
|
||||
|
||||
// Save the data
|
||||
this->utimestamp = next_time;
|
||||
this->cronInterval = next_time - date;
|
||||
Pandora::pandoraDebug(
|
||||
"Module with cron %s will be executed at timestamp: %d.",
|
||||
this->cronString.c_str(),
|
||||
this->utimestamp
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get next execution date given a certain date.
|
||||
*
|
||||
* @param date Date when start the search for a new date
|
||||
* @param interval Module interval
|
||||
* @return time_t Timestamp when module should be executed next time
|
||||
* @remarks It does not look for day of the week
|
||||
*/
|
||||
time_t Cron::getNextExecutionFrom(time_t date, int interval) {
|
||||
time_t nex_time = date + interval;
|
||||
if (isInCron(nex_time)) {
|
||||
return nex_time;
|
||||
}
|
||||
|
||||
// Copy tm struct values to an empty struct to avoid conflicts
|
||||
struct tm * timeinfo_first = localtime(&nex_time);
|
||||
struct tm * timeinfo = new tm();
|
||||
timeinfo->tm_sec = 0;
|
||||
timeinfo->tm_min = timeinfo_first->tm_min;
|
||||
timeinfo->tm_hour = timeinfo_first->tm_hour;
|
||||
timeinfo->tm_mday = timeinfo_first->tm_mday;
|
||||
timeinfo->tm_mon = timeinfo_first->tm_mon;
|
||||
timeinfo->tm_year = timeinfo_first->tm_year;
|
||||
|
||||
// Update minutes
|
||||
timeinfo->tm_min = getResetValue(0);
|
||||
nex_time = mktime(timeinfo);
|
||||
if (nex_time >= date && isInCron(nex_time)) {
|
||||
return nex_time;
|
||||
}
|
||||
|
||||
if (nex_time == CRINVALID_DATE) {
|
||||
// Update the month day if overflow
|
||||
timeinfo->tm_hour = 0;
|
||||
timeinfo->tm_mday++;
|
||||
nex_time = mktime(timeinfo);
|
||||
if (nex_time == CRINVALID_DATE) {
|
||||
// Update the month if overflow
|
||||
timeinfo->tm_mday = 1;
|
||||
timeinfo->tm_mon++;
|
||||
nex_time = mktime(timeinfo);
|
||||
if (nex_time == CRINVALID_DATE) {
|
||||
// Update the year if overflow
|
||||
timeinfo->tm_mon = 0;
|
||||
timeinfo->tm_year++;
|
||||
nex_time = mktime(timeinfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check the hour
|
||||
if (isInCron(nex_time)) {
|
||||
return nex_time;
|
||||
}
|
||||
|
||||
// Update hour if fails
|
||||
timeinfo->tm_hour = getResetValue(1);
|
||||
|
||||
// When an overflow is passed check the hour update again
|
||||
nex_time = mktime(timeinfo);
|
||||
if (nex_time >= date && isInCron(nex_time)) {
|
||||
return nex_time;
|
||||
}
|
||||
|
||||
// Check if next day is in cron
|
||||
timeinfo->tm_mday++;
|
||||
nex_time = mktime(timeinfo);
|
||||
if (nex_time == CRINVALID_DATE) {
|
||||
// Update the month if overflow
|
||||
timeinfo->tm_mday = 1;
|
||||
timeinfo->tm_mon++;
|
||||
nex_time = mktime(timeinfo);
|
||||
if (nex_time == CRINVALID_DATE) {
|
||||
// Update the year if overflow
|
||||
timeinfo->tm_mon = 0;
|
||||
timeinfo->tm_year++;
|
||||
nex_time = mktime(timeinfo);
|
||||
}
|
||||
}
|
||||
|
||||
// Check the day
|
||||
if (isInCron(nex_time)){
|
||||
return nex_time;
|
||||
}
|
||||
|
||||
// Update the day if fails
|
||||
timeinfo->tm_mday = getResetValue(2);
|
||||
|
||||
// When an overflow is passed check the day update in the next execution
|
||||
nex_time = mktime(timeinfo);
|
||||
if (nex_time >= date && isInCron(nex_time)) {
|
||||
return nex_time;
|
||||
}
|
||||
|
||||
// Check if next month is in cron
|
||||
timeinfo->tm_mon++;
|
||||
nex_time = mktime(timeinfo);
|
||||
if (nex_time == CRINVALID_DATE) {
|
||||
// Update the year if overflow
|
||||
timeinfo->tm_mon = 0;
|
||||
timeinfo->tm_year++;
|
||||
nex_time = mktime(timeinfo);
|
||||
}
|
||||
|
||||
// Check the month
|
||||
if (isInCron(nex_time)) {
|
||||
return nex_time;
|
||||
}
|
||||
|
||||
// Update the month if fails
|
||||
timeinfo->tm_mon = getResetValue(3);
|
||||
|
||||
// When an overflow is passed check the month update in the next execution
|
||||
nex_time = mktime(timeinfo);
|
||||
if (nex_time >= date) {
|
||||
return nex_time;
|
||||
}
|
||||
|
||||
// Update the year if fails
|
||||
timeinfo->tm_year++;
|
||||
nex_time = mktime(timeinfo);
|
||||
|
||||
return nex_time;
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/* Pandora cron manager for Win32.
|
||||
|
||||
Copyright (C) 2018 Artica ST.
|
||||
Written by Fermin Hernandez.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _CRON_PANDORA_H_
|
||||
#define _CRON_PANDORA_H_
|
||||
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
const string CRON_DEFAULT_STRING = "* * * * *";
|
||||
const int CR_WILDCARD_VALUE = -1;
|
||||
const int CRDOWN = 0;
|
||||
const int CRUP = 1;
|
||||
const int CRINVALID_DATE = -1;
|
||||
const int CR_SECONDS_ONE_DAY = 86400;
|
||||
const int CR_MAX_ITERS = 60;
|
||||
|
||||
class Cron {
|
||||
private:
|
||||
// Properties
|
||||
time_t utimestamp;
|
||||
/**
|
||||
* @brief Stored cron values array
|
||||
*
|
||||
* First index: minutes, hours, months, days, month
|
||||
* Second index: bottom, top
|
||||
*
|
||||
* Wildcard (*): Bottom and top are -1
|
||||
* Single value: Bottom is set and top is -1
|
||||
* Interval: Bottom and top are set
|
||||
*/
|
||||
int params[5][2];
|
||||
bool isSet;
|
||||
string cronString;
|
||||
time_t cronInterval;
|
||||
|
||||
// Methods
|
||||
time_t getNextExecutionFrom(time_t date, int interval);
|
||||
bool isInCron(time_t date);
|
||||
bool isBetweenParams(int value, int position);
|
||||
bool isWildCard(int position);
|
||||
bool isSingleValue(int position);
|
||||
bool isNormalInterval(int position);
|
||||
int getResetValue(int position);
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
Cron(string cron_string);
|
||||
// Getter & setters
|
||||
bool getIsSet();
|
||||
string getCronString();
|
||||
string getCronIntervalStr();
|
||||
|
||||
// Other methods
|
||||
void update(time_t date, int interval);
|
||||
bool shouldExecuteAt(time_t date);
|
||||
bool shouldExecuteAtFirst(time_t date);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -740,10 +740,14 @@ Pandora_Module::getXml () {
|
|||
}
|
||||
|
||||
/* Module Crontab */
|
||||
if (this->module_crontab != "") {
|
||||
if (this->cron->getIsSet()) {
|
||||
module_xml += "\t<crontab>";
|
||||
module_xml += this->module_crontab;
|
||||
module_xml += this->cron->getCronString();
|
||||
module_xml += "</crontab>\n";
|
||||
|
||||
module_xml += "\t<cron_interval><![CDATA[";
|
||||
module_xml += this->cron->getCronIntervalStr();
|
||||
module_xml += "]]></cron_interval>\n";
|
||||
}
|
||||
|
||||
/* Write module data */
|
||||
|
@ -1565,156 +1569,29 @@ Pandora_Module::evaluateIntensiveConditions () {
|
|||
*
|
||||
* @return 1 if the module should run, 0 if not.
|
||||
*/
|
||||
int
|
||||
Pandora_Module::checkCron (int module_interval, int agent_interval) {
|
||||
int i, time_params[5];
|
||||
time_t current_time, offset;
|
||||
struct tm *time_struct;
|
||||
Cron *cron = this->cron;
|
||||
bool
|
||||
Pandora_Module::checkCron (int interval) {
|
||||
|
||||
// No cron
|
||||
if (cron == NULL) {
|
||||
return 1;
|
||||
}
|
||||
// Execute always if cron is not configured
|
||||
if (!this->cron->getIsSet()) return true;
|
||||
|
||||
// Get current time
|
||||
current_time = time (NULL);
|
||||
time_t now = time(NULL);
|
||||
if (!this->cron->shouldExecuteAt(now)) return false;
|
||||
|
||||
// Check if the module was already executed
|
||||
if (current_time <= cron->utimestamp) {
|
||||
return 0;
|
||||
}
|
||||
// Check if should execute this module at first before update cron params
|
||||
bool execute = this->cron->shouldExecuteAtFirst(now);
|
||||
|
||||
// Break current time
|
||||
time_struct = localtime(¤t_time);
|
||||
if (time_struct == NULL) {
|
||||
return 1;
|
||||
}
|
||||
this->cron->update(now, interval);
|
||||
|
||||
time_params[0] = time_struct->tm_min;
|
||||
time_params[1] = time_struct->tm_hour;
|
||||
time_params[2] = time_struct->tm_mday;
|
||||
time_params[3] = time_struct->tm_mon;
|
||||
time_params[4] = time_struct->tm_wday;
|
||||
|
||||
// Fix month (localtime retuns 0..11 and we need 1..12)
|
||||
time_params[3] += 1;
|
||||
|
||||
// Check cron parameters
|
||||
for (i = 0; i < 5; i++) {
|
||||
|
||||
// Wildcard
|
||||
if (cron->params[i][0] < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if next execution will overflow the cron (only minutes overflow)
|
||||
// If overflow, execute the module
|
||||
bool overflow_cron = false;
|
||||
if (i == 0) {
|
||||
int start_cron_seconds = cron->params[i][0]*60;
|
||||
int current_exec_seconds = time_params[i]*60;
|
||||
int next_exec_seconds = time_params[i]*60 + module_interval*agent_interval;
|
||||
if (current_exec_seconds > start_cron_seconds && current_exec_seconds > next_exec_seconds) {
|
||||
start_cron_seconds += 3600;
|
||||
}
|
||||
if ((current_exec_seconds <= start_cron_seconds) && (start_cron_seconds <= next_exec_seconds)) {
|
||||
overflow_cron = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check interval
|
||||
if (cron->params[i][0] <= cron->params[i][1]) {
|
||||
if ((time_params[i] < cron->params[i][0] || time_params[i] > cron->params[i][1]) && !overflow_cron) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if ((time_params[i] < cron->params[i][0] && time_params[i] > cron->params[i][1]) && !overflow_cron) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do not check in the next minute, hour, day or month.
|
||||
offset = 0;
|
||||
if (cron->interval >= 0) {
|
||||
offset = cron->interval;
|
||||
} else if(cron->params[0][0] >= 0) {
|
||||
// 1 minute
|
||||
offset = 60;
|
||||
} else if(cron->params[1][0] >= 0) {
|
||||
// 1 hour
|
||||
offset = 3600;
|
||||
} else if(cron->params[2][0] >=0 || cron->params[4][0] >= 0) {
|
||||
// 1 day
|
||||
offset = 86400;
|
||||
} else if(cron->params[3][0] >= 0) {
|
||||
// 31 days
|
||||
offset = 2678400;
|
||||
}
|
||||
|
||||
cron->utimestamp = current_time + offset;
|
||||
return 1;
|
||||
return execute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the module cron from a string.
|
||||
*
|
||||
* @return 1 if the module should run, 0 if not.
|
||||
*/
|
||||
void
|
||||
Pandora_Module::setCron (string cron_string) {
|
||||
int i, value;
|
||||
char cron_params[5][256], bottom[256], top[256];
|
||||
|
||||
/* Create the new cron if necessary */
|
||||
if (this->cron == NULL) {
|
||||
this->cron = new Cron ();
|
||||
}
|
||||
|
||||
/* Parse the cron string */
|
||||
if (sscanf (cron_string.c_str (), "%255s %255s %255s %255s %255s", cron_params[0], cron_params[1], cron_params[2], cron_params[3], cron_params[4]) != 5) {
|
||||
pandoraDebug ("Invalid cron string: %s", cron_string.c_str ());
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fill the cron structure */
|
||||
this->cron->utimestamp = 0;
|
||||
this->cron->interval = -1;
|
||||
for (i = 0; i < 5; i++) {
|
||||
|
||||
/* Wildcard */
|
||||
if (cron_params[i][0] == '*') {
|
||||
this->cron->params[i][0] = -1;
|
||||
|
||||
/* Interval */
|
||||
} else if (sscanf (cron_params[i], "%255[^-]-%255s", bottom, top) == 2) {
|
||||
value = atoi (bottom);
|
||||
this->cron->params[i][0] = value;
|
||||
value = atoi (top);
|
||||
this->cron->params[i][1] = value;
|
||||
|
||||
/* Single value */
|
||||
} else {
|
||||
value = atoi (cron_params[i]);
|
||||
this->cron->params[i][0] = value;
|
||||
this->cron->params[i][1] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the interval of the module cron.
|
||||
*
|
||||
* @param interval Module cron interval in seconds.
|
||||
*/
|
||||
void
|
||||
Pandora_Module::setCronInterval (int interval) {
|
||||
if (this->cron == NULL) {
|
||||
this->cron = new Cron ();
|
||||
}
|
||||
|
||||
this->cron->interval = interval;
|
||||
this->cron = new Cron(cron_string);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#define __PANDORA_MODULE_H__
|
||||
|
||||
#include "../pandora.h"
|
||||
#include "../misc/cron.h"
|
||||
#include "pandora_data.h"
|
||||
#include "boost/regex.h"
|
||||
#include <list>
|
||||
|
@ -108,15 +109,6 @@ namespace Pandora_Modules {
|
|||
regex_t regexp;
|
||||
} Condition;
|
||||
|
||||
/**
|
||||
* Defines the structure that holds the module cron.
|
||||
*/
|
||||
typedef struct {
|
||||
time_t utimestamp;
|
||||
int interval;
|
||||
int params[5][2];
|
||||
} Cron;
|
||||
|
||||
const string module_exec_str = "module_exec";
|
||||
const string module_proc_str = "module_proc";
|
||||
const string module_service_str = "module_service";
|
||||
|
@ -298,9 +290,8 @@ namespace Pandora_Modules {
|
|||
void addIntensiveCondition (string intensivecondition);
|
||||
int evaluatePreconditions ();
|
||||
void evaluateConditions ();
|
||||
int checkCron (int module_interval, int agent_interval);
|
||||
bool checkCron (int interval);
|
||||
void setCron (string cron_string);
|
||||
void setCronInterval (int interval);
|
||||
int evaluateCondition (string string_value, double double_value, Condition *condition);
|
||||
int evaluateIntensiveConditions ();
|
||||
int hasOutput ();
|
||||
|
|
|
@ -94,7 +94,6 @@ using namespace Pandora_Strutils;
|
|||
#define TOKEN_SAVE ("module_save ")
|
||||
#define TOKEN_CONDITION ("module_condition ")
|
||||
#define TOKEN_CRONTAB ("module_crontab ")
|
||||
#define TOKEN_CRONINTERVAL ("module_cron_interval ")
|
||||
#define TOKEN_PRECONDITION ("module_precondition ")
|
||||
#define TOKEN_NOSEEKEOF ("module_noseekeof ")
|
||||
#define TOKEN_PING ("module_ping ")
|
||||
|
@ -168,7 +167,7 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) {
|
|||
string module_perfcounter, module_tcpcheck;
|
||||
string module_port, module_timeout, module_regexp;
|
||||
string module_plugin, module_save, module_condition, module_precondition;
|
||||
string module_crontab, module_cron_interval, module_post_process;
|
||||
string module_crontab, module_post_process;
|
||||
string module_min_critical, module_max_critical, module_min_warning, module_max_warning;
|
||||
string module_disabled, module_min_ff_event, module_noseekeof;
|
||||
string module_ping, module_ping_count, module_ping_timeout;
|
||||
|
@ -222,7 +221,6 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) {
|
|||
module_save = "";
|
||||
module_condition = "";
|
||||
module_crontab = "";
|
||||
module_cron_interval = "";
|
||||
module_post_process = "";
|
||||
module_precondition = "";
|
||||
module_min_critical = "";
|
||||
|
@ -423,9 +421,6 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) {
|
|||
if (module_crontab == "") {
|
||||
module_crontab = parseLine (line, TOKEN_CRONTAB);
|
||||
}
|
||||
if (module_cron_interval == "") {
|
||||
module_cron_interval = parseLine (line, TOKEN_CRONINTERVAL);
|
||||
}
|
||||
if (module_noseekeof == "") {
|
||||
module_noseekeof = parseLine (line, TOKEN_NOSEEKEOF);
|
||||
}
|
||||
|
@ -904,13 +899,6 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) {
|
|||
}
|
||||
}
|
||||
|
||||
if (module_cron_interval != "") {
|
||||
pos_macro = module_cron_interval.find(macro_name);
|
||||
if (pos_macro != string::npos){
|
||||
module_cron_interval.replace(pos_macro, macro_name.size(), macro_value);
|
||||
}
|
||||
}
|
||||
|
||||
if (module_noseekeof != "") {
|
||||
pos_macro = module_noseekeof.find(macro_name);
|
||||
if (pos_macro != string::npos){
|
||||
|
@ -1319,14 +1307,7 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) {
|
|||
}
|
||||
|
||||
/* Module cron */
|
||||
if (module_crontab != "") {
|
||||
module->setCron (module_crontab);
|
||||
|
||||
/* Set the cron interval */
|
||||
if (module_cron_interval != "") {
|
||||
module->setCronInterval (atoi (module_cron_interval.c_str ()));
|
||||
}
|
||||
}
|
||||
module->setCron (module_crontab);
|
||||
|
||||
/* Plugins do not have a module type */
|
||||
if (module_plugin == "") {
|
||||
|
|
|
@ -1884,8 +1884,8 @@ Pandora_Windows_Service::pandora_run_broker (string config) {
|
|||
continue;
|
||||
}
|
||||
|
||||
/* Check preconditions */
|
||||
if (module->checkCron (module->getInterval (), atoi (conf->getValue ("interval").c_str())) == 0) {
|
||||
/* Check cron */
|
||||
if (!module->checkCron (module->getInterval () * atoi (conf->getValue ("interval").c_str()))) {
|
||||
pandoraDebug ("Cron not matched for module %s", module->getName ().c_str ());
|
||||
module->setNoOutput ();
|
||||
this->broker_modules->goNext ();
|
||||
|
@ -2012,8 +2012,8 @@ Pandora_Windows_Service::pandora_run (int forced_run) {
|
|||
continue;
|
||||
}
|
||||
|
||||
/* Check preconditions */
|
||||
if (module->checkCron (module->getInterval (), atoi (conf->getValue ("interval").c_str())) == 0) {
|
||||
/* Check cron */
|
||||
if (!module->checkCron (module->getInterval () * atoi (conf->getValue ("interval").c_str()))) {
|
||||
pandoraDebug ("Cron not matched for module %s", module->getName ().c_str ());
|
||||
module->setNoOutput ();
|
||||
this->modules->goNext ();
|
||||
|
|
|
@ -611,7 +611,7 @@ sub process_module_data ($$$$$$$$$$) {
|
|||
'unknown_instructions' => '', 'tags' => '', 'critical_inverse' => 0, 'warning_inverse' => 0, 'quiet' => 0,
|
||||
'module_ff_interval' => 0, 'alert_template' => '', 'crontab' => '', 'min_ff_event_normal' => 0,
|
||||
'min_ff_event_warning' => 0, 'min_ff_event_critical' => 0, 'ff_timeout' => 0, 'each_ff' => 0, 'module_parent' => 0,
|
||||
'module_parent_unlink' => 0};
|
||||
'module_parent_unlink' => 0, 'cron_interval' => 0};
|
||||
|
||||
# Other tags will be saved here
|
||||
$module_conf->{'extended_info'} = '';
|
||||
|
@ -644,8 +644,12 @@ sub process_module_data ($$$$$$$$$$) {
|
|||
delete $module_conf->{'name'};
|
||||
|
||||
# Calculate the module interval in seconds
|
||||
$module_conf->{'module_interval'} = 1 unless defined ($module_conf->{'module_interval'});
|
||||
$module_conf->{'module_interval'} *= $interval if (defined ($module_conf->{'module_interval'}));
|
||||
if (defined($module_conf->{'cron_interval'})) {
|
||||
$module_conf->{'module_interval'} = 1 unless defined ($module_conf->{'module_interval'});
|
||||
$module_conf->{'module_interval'} *= $interval if (defined ($module_conf->{'module_interval'}));
|
||||
} else {
|
||||
$module_conf->{'module_interval'} = $module_conf->{'cron_interval'};
|
||||
}
|
||||
|
||||
# Allow , as a decimal separator
|
||||
$module_conf->{'post_process'} =~ s/,/./ if (defined ($module_conf->{'post_process'}));
|
||||
|
|
Loading…
Reference in New Issue