2009-04-22 Ramon Novoa <rnovoa@artica.es>

* lib/PandoraFMS/Server.pm: Enabled thread status detection when
          available.

        * lib/PandoraFMS/Core.pm: Fixed module status calculation. Moved and
          rewrote the old pandora_ping* functions. Small aesthetic fixes.

        * lib/PandoraFMS/ReconServer.pm, lib/PandoraFMS/NetworkServer.pm: Use
          the new pandora_ping* functions. The old functions were not thread
          safe and had to lock.

        * bin/pandora_server: Properly shutdown on error.




git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@1643 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f
This commit is contained in:
ramonn 2009-04-22 09:36:32 +00:00
parent c57cecc318
commit 6e3273bb0f
6 changed files with 106 additions and 157 deletions

View File

@ -1,3 +1,17 @@
2009-04-22 Ramon Novoa <rnovoa@artica.es>
* lib/PandoraFMS/Server.pm: Enabled thread status detection when
available.
* lib/PandoraFMS/Core.pm: Fixed module status calculation. Moved and
rewrote the old pandora_ping* functions. Small aesthetic fixes.
* lib/PandoraFMS/ReconServer.pm, lib/PandoraFMS/NetworkServer.pm: Use
the new pandora_ping* functions. The old functions were not thread
safe and had to lock.
* bin/pandora_server: Properly shutdown on error.
2009-04-21 Jorge Gonzalez <jorgegonz@artica.es>
* util/pandora_dbstress.README: fixed many typos and width, now fits

View File

@ -106,7 +106,7 @@ while (1) {
# Update server status
foreach my $server (@Servers) {
exit (1) unless ($server->checkThreads () == 1);
pandora_shutdown () unless ($server->checkThreads () == 1);
$server->update ();
}
@ -115,6 +115,10 @@ while (1) {
pandora_exec_forced_alerts (\%Config, $DBH);
pandora_module_keep_alive_nd (\%Config, $DBH);
};
if ($@) {
pandora_shutdown ();
}
threads->yield;
sleep ($Config{'server_threshold'});

View File

@ -42,6 +42,7 @@ our @EXPORT = qw(
pandora_create_module
pandora_evaluate_alert
pandora_evaluate_compound_alert
pandora_evaluate_snmp_alerts
pandora_event
pandora_event_status
pandora_execute_alert
@ -51,6 +52,8 @@ our @EXPORT = qw(
pandora_generate_compound_alerts
pandora_module_keep_alive
pandora_module_keep_alive_nd
pandora_ping
pandora_ping_latency
pandora_planned_downtime
pandora_process_alert
pandora_process_module
@ -58,21 +61,16 @@ our @EXPORT = qw(
pandora_update_agent
pandora_update_module_on_error
pandora_update_server
pandora_evaluate_snmp_alerts
@ServerTypes
@ServerSuffixes
@ServerColumns
);
# Some global variables
our @DayNames = qw(monday tuesday wednesday thursday friday saturday sunday);
our @ServerTypes = qw (dataserver networkserver snmpconsole reconserver pluginserver predictionserver wmiserver exportserver inventoryserver webserver);
our @ServerSuffixes = qw (_Data _Net _SNMP _Recon _Plugin _Prediction _WMI _Export _Inventory _Web);
our @ServerColumns = qw (data_server network_server snmp_server recon_server plugin_server prediction_server wmi_server export_server inventory_server web_server);
##########################################################################
#Generate alerts for a given module.
# Generate alerts for a given module.
##########################################################################
sub pandora_generate_alerts ($$$$$$$) {
my ($pa_config, $data, $status, $agent, $module, $utimestamp, $dbh) = @_;
@ -104,7 +102,7 @@ sub pandora_generate_alerts ($$$$$$$) {
}
##########################################################################
#Evaluate trigger conditions for a given alert. Returns:
# Evaluate trigger conditions for a given alert. Returns:
# 0 Execute the alert.
# 1 Do not execute the alert.
# 2 Do not execute the alert, but increment its internal counter.
@ -191,7 +189,7 @@ sub pandora_evaluate_alert ($$$$$$) {
}
##########################################################################
#Process an alert given the status returned by pandora_evaluate_alert.
# Process an alert given the status returned by pandora_evaluate_alert.
##########################################################################
sub pandora_process_alert ($$$$$$$) {
my ($pa_config, $data, $agent, $module, $alert, $rc, $dbh) = @_;
@ -271,8 +269,8 @@ sub pandora_process_alert ($$$$$$$) {
}
##########################################################################
#Evaluate the given compound alert. Returns 1 if the alert should be
#fired, 0 if not.
# Evaluate the given compound alert. Returns 1 if the alert should be
# fired, 0 if not.
##########################################################################
sub pandora_evaluate_compound_alert ($$$) {
my ($pa_config, $id, $dbh) = @_;
@ -323,7 +321,7 @@ sub pandora_evaluate_compound_alert ($$$) {
}
##########################################################################
#Generate compound alerts that depend on a given alert.
# Generate compound alerts that depend on a given alert.
##########################################################################
sub pandora_generate_compound_alerts ($$$$$$$) {
my ($pa_config, $data, $agent, $module, $alert, $utimestamp, $dbh) = @_;
@ -481,7 +479,7 @@ sub pandora_execute_action ($$$$$$$) {
}
##########################################################################
#Update agent access table.
# Update agent access table.
##########################################################################
sub pandora_access_update ($$$) {
my ($pa_config, $agent_id, $dbh) = @_;
@ -492,7 +490,7 @@ sub pandora_access_update ($$$) {
}
##########################################################################
#Process Pandora module.
# Process Pandora module.
##########################################################################
sub pandora_process_module ($$$$$$$$) {
my ($pa_config, $data, $agent, $module, $module_type,
@ -541,7 +539,7 @@ sub pandora_process_module ($$$$$$$$) {
($agent_status->{'status_changes'} + 1, $agent_status->{'last_status'});
# Generate events
if ($agent_status->{'status_changes'} == $module->{'min_ff_event'}) {
if ($status_changes == $module->{'min_ff_event'}) {
generate_status_event ($pa_config, $data, $agent, $module, $status, $last_status, $dbh);
}
@ -563,7 +561,7 @@ sub pandora_process_module ($$$$$$$$) {
}
##########################################################################
#Update planned downtimes.
# Update planned downtimes.
##########################################################################
sub pandora_planned_downtime ($$) {
my ($pa_config, $dbh) = @_;
@ -601,8 +599,8 @@ sub pandora_planned_downtime ($$) {
}
##########################################################################
#Update server status: 0 dataserver, 1 network server, 2 snmp console,
#3 recon, 4 plugin, 5 prediction, 6 wmi.
# Update server status: 0 dataserver, 1 network server, 2 snmp console,
# 3 recon, 4 plugin, 5 prediction, 6 wmi.
##########################################################################
sub pandora_update_server ($$$$$;$$) {
my ($pa_config, $dbh, $server_name, $status,
@ -640,7 +638,7 @@ sub pandora_update_server ($$$$$;$$) {
}
##########################################################################
#Update last contact field in agent table
# Update last contact field in agent table
##########################################################################
sub pandora_update_agent ($$$$$$$) {
my ($pa_config, $agent_timestamp, $agent_id, $os_version,
@ -662,7 +660,7 @@ sub pandora_update_agent ($$$$$$$) {
}
##########################################################################
#Updates the keep_alive module for the given agent.
# Updates the keep_alive module for the given agent.
##########################################################################
sub pandora_module_keep_alive ($$$$) {
my ($pa_config, $id_agent, $agent_name, $dbh) = @_;
@ -675,7 +673,7 @@ sub pandora_module_keep_alive ($$$$) {
}
##########################################################################
#Create an internal Pandora incident.
# Create an internal Pandora incident.
##########################################################################
sub pandora_create_incident ($$$$$$$$) {
my ($pa_config, $dbh, $title, $text,
@ -687,7 +685,7 @@ sub pandora_create_incident ($$$$$$$$) {
##########################################################################
#Create an internal audit entry.
# Create an internal audit entry.
##########################################################################
sub pandora_audit ($$$$$) {
my ($pa_config, $description, $name, $action, $dbh) = @_;
@ -704,8 +702,8 @@ sub pandora_audit ($$$$$) {
}
##########################################################################
#Create a new entry in tagente_modulo and the corresponding entry in
#tagente_estado.
# Create a new entry in tagente_modulo and the corresponding entry in
# tagente_estado.
##########################################################################
sub pandora_create_module ($$$$$$$$) {
my ($agent_id, $module_type_id, $module_name, $max,
@ -739,7 +737,7 @@ sub pandora_create_agent ($$$$$$$$$) {
}
##########################################################################
#Generate an event.
# Generate an event.
##########################################################################
sub pandora_event (%$$$$$$$$) {
my ($pa_config, $evento, $id_grupo, $id_agente, $severity,
@ -753,7 +751,7 @@ sub pandora_event (%$$$$$$$$) {
}
##########################################################################
#Generate an event with the given status. TODO: Merge with pandora_event
# Generate an event with the given status. TODO: Merge with pandora_event
##########################################################################
sub pandora_event_status ($$$$$$$$$$) {
my ($pa_config, $evento, $id_grupo, $id_agente, $severity,
@ -778,7 +776,7 @@ sub pandora_update_module_on_error ($$$) {
}
##########################################################################
#Execute forced alerts.
# Execute forced alerts.
##########################################################################
sub pandora_exec_forced_alerts {
my ($pa_config, $dbh) = @_;
@ -802,7 +800,7 @@ sub pandora_exec_forced_alerts {
}
##########################################################################
#Update keep_alive modules for agents without data.
# Update keep_alive modules for agents without data.
##########################################################################
sub pandora_module_keep_alive_nd {
my ($pa_config, $dbh) = @_;
@ -865,7 +863,7 @@ sub pandora_evaluate_snmp_alerts {
my $utimestamp = time ();
my $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime($utimestamp));
# Out limits, start a new interval
# Out of limits, start a new interval
($times_fired, $internal_counter) = (0, 0) if ($utimestamp >= ($last_fired + $alert->{'time_threshold'}));
# Execute the alert
@ -913,13 +911,43 @@ sub pandora_evaluate_snmp_alerts {
db_do ($dbh, 'UPDATE talert_snmp SET internal_counter = ?, times_fired = ?, last_fired = ? WHERE id_as = ?',
$internal_counter, $times_fired, $timestamp, $alert->{'id_as'});
} else {
db_do ($dbh, 'UPDATE talert_snmp SET times_fired=, internal_counter = ? WHERE id_as = ?',
db_do ($dbh, 'UPDATE talert_snmp SET times_fired = ?, internal_counter = ? WHERE id_as = ?',
$times_fired, $internal_counter, $alert->{'id_as'});
}
}
}
}
##############################################################################
# Ping the given host. Returns 1 if the host is alive, 0 otherwise.
##############################################################################
sub pandora_ping ($$) {
my ($pa_config, $host) = @_;
# Ping the host
`ping -q -W $pa_config->{'networktimeout'} -n -c $pa_config->{'icmp_checks'} $host >/dev/null 2>&1`;
return ($? == 0) ? 1 : 0;
}
##############################################################################
# Ping the given host. Returns the average round-trip time.
##############################################################################
sub pandora_ping_latency ($$) {
my ($pa_config, $host) = @_;
# Ping the host
my @output = `ping -q -W $pa_config->{'networktimeout'} -n -c $pa_config->{'icmp_checks'} $host 2>/dev/null`;
# Something went wrong
return 0 if ($? != 0);
# Parse the output
my $stats = pop (@output);
return 0 unless ($stats =~ m/([\d\.]+)\/([\d\.]+)\/([\d\.]+)\/([\d\.]+) +ms/);
return $2;
}
##########################################################################
# Utility functions, not to be exported.
##########################################################################
@ -1007,20 +1035,26 @@ sub process_inc_data ($$$$) {
##########################################################################
sub get_module_status ($$) {
my ($data, $module, $module_type) = @_;
# Critical
if (($module->{'min_critical'} ne $module->{'max_critical'})) {
return 1 if ($data >= $module->{'min_critical'} && $data <= $module->{'max_critical'});
my ($critical_min, $critical_max, $warning_min, $warning_max) =
($module->{'min_critical'}, $module->{'max_critical'}, $module->{'min_warning'}, $module->{'max_warning'});
# Proc modules default to critical if data is 0 and no max/min was specified
} elsif ($module_type =~ m/_proc$/ && $data == 0) {
return 1;
# Set default critical max/min for *proc modules
if ($module_type =~ m/_proc$/ && ($critical_min eq $critical_max)) {
($critical_min, $critical_max) = (0, 1);
}
# Critical
if ($critical_min ne $critical_max) {
return 1 if ($data >= $critical_min && $data < $critical_max);
return 1 if ($data >= $critical_min && $critical_max < $critical_min);
}
# Warning
return 2 if (($module->{'min_warning'} ne $module->{'max_warning'}) &&
($data >= $module->{'min_warning'} && $data <= $module->{'max_warning'}));
if ($warning_min ne $warning_max) {
return 2 if ($data >= $warning_min && $data < $warning_max);
return 2 if ($data >= $warning_min && $warning_max < $warning_min);
}
# Normal
return 0;
}

View File

@ -41,7 +41,6 @@ my @TaskQueue :shared;
my %PendingTasks :shared;
my $Sem :shared = new Thread::Semaphore;
my $TaskSem :shared = new Thread::Semaphore (0);
my $ICMPLock :shared;
########################################################################################
# Network Server class constructor.
@ -133,76 +132,6 @@ sub data_consumer ($$) {
exec_network_module ($self->getConfig (), $task, $self->getDBH ());
}
##############################################################################
# pandora_ping_icmp (config, destination, timeout)
# Do a ICMP scan, return 1 if alive, 0 if not
##############################################################################
sub pandora_ping_icmp {
my $pa_config = $_[0];
my $dest = $_[1];
my $l_timeout = $_[2];
# temporal vars.
my $result = 0;
my $result2 = 0;
my $temp;
if ($pa_config->{'icmp_checks'} eq ""){
$pa_config->{'icmp_checks'} = 1;
}
# Make more than a single ping (as defined in icmp_checks
for ($temp =0; $temp < $pa_config->{'icmp_checks'}; $temp++){
my $p;
# Some hosts don't accept ICMP with too small payload. Use 16 Bytes min
{
lock $ICMPLock;
$p = Net::Ping->new("icmp", $l_timeout, 32);
$result = $p->ping($dest);
}
if (defined ($result)){
$p->close();
if ($result == 1){
$result2 = 1;
$temp = $pa_config->{'icmp_checks'}; # Exit for
}
}
undef ($p);
}
return $result2;
}
##############################################################################
# pandora_ping_latency (destination, timeout, data, result) - Do a ICMP latency check
##############################################################################
sub pandora_ping_latency {
my $dest = $_[0];
my $l_timeout = $_[1];
my $module_data = $_[2];
my $module_result = $_[3];
my $icmp_return;
my $icmp_reply;
my $icmp_ip;
my $nm;
# Locking for use ICMP call safety
{
lock $ICMPLock;
$nm = Net::Ping->new("icmp", $l_timeout, 32);
$nm->hires();
($icmp_return, $icmp_reply, $icmp_ip) = $nm->ping ($dest,$l_timeout);
}
if ($icmp_return) {
$$module_data = $icmp_reply * 1000; # milliseconds
$$module_result = 0; # Successful
} else {
$$module_result = 1; # Error.
$$module_data = 0;
}
$nm->close();
undef($nm);
}
##########################################################################
# SUB pandora_query_tcp (pa_config, tcp_port. ip_target, result, data, tcp_send,
# tcp_rcv, id_tipo_module, dbh)
@ -358,7 +287,7 @@ sub exec_network_module {
return 0;
}
my $module = get_db_single_row ($dbh, 'SELECT * FROM tagente_modulo WHERE id_agente_modulo = ?', $id_agente_modulo);
if ($module == -1) {
if (! defined ($module)) {
logger ($pa_config,"[ERROR] Processing data for invalid module", 0);
return 0;
}
@ -383,22 +312,11 @@ sub exec_network_module {
# ICMP Modules
# ------------
if ($id_tipo_modulo == 6){ # ICMP (Connectivity only: Boolean)
$temp = pandora_ping_icmp ($pa_config, $ip_target, $pa_config->{'networktimeout'});
if ($temp == 1 ){
$module_result = 0; # Successful
$module_data = 1;
} else {
$module_result = 0; # If cannot connect, its down.
$module_data = 0;
}
$module_data = pandora_ping ($pa_config, $ip_target);
$module_result = 0; # Successful
} elsif ($id_tipo_modulo == 7){ # ICMP (data for latency in ms)
# This module only could be executed if executed as root
if ($> == 0){
pandora_ping_latency ($ip_target, $pa_config->{"networktimeout"}, \$module_data, \$module_result);
} else {
$module_result = 0; # Done but, with zero value
$module_data = 0; # This should don't happen
}
$module_data = pandora_ping_latency ($pa_config, $ip_target);
$module_result = 0; # Successful
# SNMP Modules (Proc=18, inc, data, string)
# ------------
} elsif (($id_tipo_modulo == 15) || ($id_tipo_modulo == 18) || ($id_tipo_modulo == 16) || ($id_tipo_modulo == 17)) { # SNMP module

View File

@ -42,7 +42,6 @@ my @TaskQueue :shared;
my %PendingTasks :shared;
my $Sem :shared = Thread::Semaphore->new;
my $TaskSem :shared = Thread::Semaphore->new (0);
my $ICMPLock :shared;
my $TracerouteAvailable = (eval 'use Net::Traceroute::PurePerl; 1') ? 1 : 0;
########################################################################################
@ -129,7 +128,7 @@ sub data_consumer ($$) {
# Is the host alive? (thanks to Evi for the TCP scans)
my $alive = 0;
if (icmp_scan ($addr, $pa_config->{'networktimeout'}) == 1) {
if (pandora_ping ($pa_config, $addr) == 1) {
$alive = 1;
#Check for Remote Desktop & VNC (Desktop & Server machines)
#} elsif (tcp_scan ($addr, $pa_config->{'networktimeout'}, 3389) == 1 ||
@ -199,28 +198,6 @@ sub data_consumer ($$) {
update_recon_task ($dbh, $task_id, -1);
}
##############################################################################
# ICMP scan the given host. Returns 1 if successful, 0 otherwise.
##############################################################################
sub icmp_scan ($$) {
my ($host, $timeout) = @_;
# Ping the host
my $ping;
{
lock $ICMPLock;
$ping = Net::Ping->new ();
}
# Host is alive
if ($ping->ping($host)){
$ping->close();
return 1;
}
return 0;
}
##############################################################################
# TCP scan the given host/port. Returns 1 if successful, 0 otherwise.
##############################################################################

View File

@ -153,8 +153,8 @@ sub checkThreads ($) {
foreach my $tid (@{$self->{'_threads'}}) {
my $thr = threads->object ($tid);
return 0 unless defined ($thr);
#return 0 unless $thr->is_running ();
return 1 unless $thr->can ('is_running');
return 0 unless $thr->is_running ();
}
return 1;
@ -202,12 +202,14 @@ sub update ($) {
sub stop ($) {
my $self = shift;
# Update server status
pandora_update_server ($self->{'_pa_config'}, $self->{'_dbh'}, $self->{'_pa_config'}->{'servername'},
eval {
# Update server status
pandora_update_server ($self->{'_pa_config'}, $self->{'_dbh'}, $self->{'_pa_config'}->{'servername'},
0, $self->{'_server_type'});
# Generate an event
$self->downEvent ();
# Generate an event
$self->downEvent ();
};
# Kill server threads
foreach my $tid (@{$self->{'_threads'}}) {