diff --git a/pandora_server/ChangeLog b/pandora_server/ChangeLog index 2f491a9c37..29414d838c 100644 --- a/pandora_server/ChangeLog +++ b/pandora_server/ChangeLog @@ -1,3 +1,28 @@ +2008-06-13 Sancho Lerena + + * conf/pandora_server.conf: Added new internal MTA feature config tokens . + + * pandora_server_installer: Copy default plugins to /usr/share/pandora/util + + * Config.pm: New MTA feature tokens, and added event when starting server. + + * DB.pm: Changes in execute_alert function (now passes several hash refs). + Alerts and events now use new format of events. Add support for new inter- + nal MTA/SMTP alert feature. Discovered and FIXED a very annoying bug on + need_update usage in write_state function that was making a HUGE + degradation when too many non-init modules in network server. + + * Tools.pm: Added pandora_sendmail() function. Needs Mail::Sendmail dep. + + * All servers: Support for pandora_shutdown notify on event database. + + * pandora_snmpconsole: Updated SNMP alert mechanism. Need to be tested!. + + * pandora_recon: Now generate an event when discover a new host. + + * util/pandora_db.pl: Added support to automatically delete events. + + 2008-06-12 Manuel Arostegui * pandora_snmpconsole: Removed "/var/run/pandora" we are diff --git a/pandora_server/bin/pandora_network b/pandora_server/bin/pandora_network index 82527ee111..e0fde5635c 100755 --- a/pandora_server/bin/pandora_network +++ b/pandora_server/bin/pandora_network @@ -116,15 +116,6 @@ while (1) { #------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------ -######################################################################################## -# pandora_shutdown () -# Close system -######################################################################################## -sub pandora_shutdown { - logger (\%pa_config,"Pandora FMS Network Server Shutdown by signal ",0); - print " [*] Shutting down Pandora FMS Network Server (received signal)...\n"; - exit; -} ########################################################################## # SUB pandora_network_subsystem @@ -226,16 +217,16 @@ sub pandora_network_producer ($) { AND tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo AND ( - (tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP() + ((tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP()) OR tagente_modulo.flag = 1 ) ORDER BY - last_execution_try ASC "; + last_execution_try ASC "; } else { # Query for MASTER SERVER ! $query1 = "SELECT - DISTINCT(tagente_modulo.id_agente_modulo), tagente_modulo.flag + DISTINCT(tagente_modulo.id_agente_modulo), tagente_modulo.flag, tagente_estado.last_execution_try FROM tagente, tagente_modulo, tagente_estado, tserver WHERE @@ -251,9 +242,13 @@ sub pandora_network_producer ($) { tagente_modulo.id_tipo_modulo < 19 AND tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo - AND - ((tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP() OR tagente_modulo.flag = 1 ) - ORDER BY last_execution_try ASC"; + AND ( + ((tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP() ) + OR + tagente_modulo.flag = 1 + ) + ORDER BY + last_execution_try ASC"; } $exec_sql1 = $dbh->prepare($query1); $exec_sql1 ->execute; @@ -457,9 +452,9 @@ sub pandora_query_snmp (%$$$$) { my $snmp_target = $_[3]; # $_[4] contains error var. - my $output =""; - my $snmp_timeout = 1000 * 1000 * $pa_config->{"snmp_timeout"}; - my $snmp_retries = $pa_config->{'snmp_checks'}; + my $output =""; + my $snmp_timeout = 1000 * 1000 * $pa_config->{"snmp_timeout"}; + my $snmp_retries = $pa_config->{'snmp_checks'}; my $SESSION; # Locking for SNMP call. SNMP is not thread safe !! { @@ -467,13 +462,16 @@ sub pandora_query_snmp (%$$$$) { $SESSION = new SNMP::Session (DestHost => $snmp_target, Timeout => $snmp_timeout, Retries => $snmp_retries, - Community => $snmp_community, - Version => 1); + Community => $snmp_community, + Version => 1); } - if ($SESSION->{ErrorStr}) { - logger($pa_config, "SNMP ERROR SESSION for Target $snmp_target ".$SESSION->{ErrorStr}, 2); + + if ((!defined($SESSION)) || ($SESSION->{ErrorStr})) { + logger($pa_config, "SNMP ERROR SESSION for Target $snmp_target ".$SESSION->{ErrorStr}, 2); $_[4] = "1"; - undef ($SESSION); + if (defined($SESSION)){ + undef ($SESSION); + } return 0; } my $oid = SNMP::translateObj($snmp_oid); @@ -482,10 +480,10 @@ sub pandora_query_snmp (%$$$$) { lock $snmp_lock; $output = $SESSION->get($oid); } - if ((!defined($SESSION)) || (!defined($output)) || ($output eq "") || ($SESSION->{ErrorStr})) { + if ((!defined($output)) || ($output eq "")) { logger($pa_config, "SNMP ERROR SNMPGET for Target $snmp_target ".$SESSION->{ErrorStr}, 2); $_[4] = "1"; - undef ($SESSION); + undef ($SESSION); return 0; } $_[4] = "0"; @@ -628,7 +626,6 @@ sub exec_network_module { } } - # Write data section my $timestamp = &UnixDate("today","%Y-%m-%d %H:%M:%S"); my $utimestamp = &UnixDate("today","%s"); @@ -642,7 +639,7 @@ sub exec_network_module { $part{'max'}[0] = $max; $part{'min'}[0] = $min; my $tipo_modulo = dame_nombretipomodulo_idagentemodulo ($pa_config, $id_tipo_modulo, $dbh); - if (($tipo_modulo eq 'remote_snmp') || ($tipo_modulo eq 'remote_icmp') || ($tipo_modulo eq 'remote_tcp') || ($tipo_modulo eq 'remote_udp')) { + if (($tipo_modulo eq 'remote_snmp') || ($tipo_modulo eq 'remote_icmp') || ($tipo_modulo eq 'remote_tcp')) { module_generic_data ($pa_config, \%part, $timestamp, $agent_name, $tipo_modulo, $dbh); } elsif ($tipo_modulo =~ /\_inc/ ) { @@ -661,19 +658,31 @@ sub exec_network_module { # Update agent last contact # Insert Pandora version as agent version pandora_lastagentcontact ($pa_config, $timestamp, $agent_name, $pa_config->{'servername'}.$pa_config->{"servermode"}, $pa_config->{'version'}, -1, $dbh); - } - - if ($module_result != 0) { + + } else { if ($module_interval == 0){ $module_interval = dame_intervalo ($pa_config, $id_agente, $dbh); } # Modules who cannot connect or something go bad, update last_execution_try field - logger ($pa_config, "Cannot obtain exec Network Module $nombre from agent $agent_name", 4); - my $query_act = "UPDATE tagente_estado SET current_interval = $module_interval, last_execution_try = $utimestamp WHERE id_agente_modulo = $id_agente_modulo "; + logger ($pa_config, "Cannot obtain exec Network Module $nombre from agent $agent_name", 3); + my $query_act = "UPDATE tagente_estado SET current_interval = ($module_interval*5), last_execution_try = $utimestamp WHERE id_agente_modulo = $id_agente_modulo "; my $a_idages = $dbh->prepare($query_act); $a_idages->execute; $a_idages->finish(); } } + +######################################################################################## +# pandora_shutdown () +# Close system +######################################################################################## +sub pandora_shutdown { + logger (\%pa_config,"Pandora FMS Server '".$pa_config{'servername'}.$pa_config{"servermode"}."' Shutdown by signal ",0); + print " [*] Shutting down ".$pa_config{'servername'}.$pa_config{"servermode"} ."(received signal)...\n"; + pandora_event (\%pa_config, $pa_config{'servername'}.$pa_config{"servermode"}." going Down", 0, + 0, 4, 0, 0, "system", $dbh); + exit; +} + diff --git a/pandora_server/bin/pandora_plugin b/pandora_server/bin/pandora_plugin index 014b874dc9..c3c0e3fca8 100755 --- a/pandora_server/bin/pandora_plugin +++ b/pandora_server/bin/pandora_plugin @@ -106,12 +106,14 @@ while (1) { ######################################################################################## # pandora_shutdown () -# Close system on a received signal +# Close system ######################################################################################## sub pandora_shutdown { - logger (\%pa_config,"Pandora FMS Plugin Server Shutdown by signal ",0); - print " [*] Shutting down Pandora FMS Plugin Server (received signal)...\n"; - exit; + logger (\%pa_config,"Pandora FMS Server '".$pa_config{'servername'}.$pa_config{"servermode"}."' Shutdown by signal ",0); + print " [*] Shutting down ".$pa_config{'servername'}.$pa_config{"servermode"} ."(received signal)...\n"; + pandora_event (\%pa_config, $pa_config{'servername'}.$pa_config{"servermode"}." going Down", 0, + 0, 4, 0, 0, "system", $dbh); + exit; } ########################################################################## diff --git a/pandora_server/bin/pandora_prediction b/pandora_server/bin/pandora_prediction index e5a183fdcd..206ed44b21 100755 --- a/pandora_server/bin/pandora_prediction +++ b/pandora_server/bin/pandora_prediction @@ -106,15 +106,18 @@ while (1) { ######################################################################################## # pandora_shutdown () -# Close system on a received signal +# Close system ######################################################################################## sub pandora_shutdown { - logger (\%pa_config,"Pandora FMS Prediction Server Shutdown by signal ",0); - print " [*] Shutting down Pandora FMS Prediction Server (received signal)...\n"; - exit; + logger (\%pa_config,"Pandora FMS Server '".$pa_config{'servername'}.$pa_config{"servermode"}."' Shutdown by signal ",0); + print " [*] Shutting down ".$pa_config{'servername'}.$pa_config{"servermode"} ."(received signal)...\n"; + pandora_event (\%pa_config, $pa_config{'servername'}.$pa_config{"servermode"}." going Down", 0, + 0, 4, 0, 0, "system", $dbh); + exit; } + sub pandora_prediction_consumer ($$) { my $pa_config = $_[0]; my $thread_id = $_[1]; diff --git a/pandora_server/bin/pandora_recon b/pandora_server/bin/pandora_recon index 1bf4280289..1d17fb9fb5 100755 --- a/pandora_server/bin/pandora_recon +++ b/pandora_server/bin/pandora_recon @@ -43,6 +43,10 @@ $| = 0; my %pa_config; +$SIG{'TERM'} = 'pandora_shutdown'; +$SIG{'INT'} = 'pandora_shutdown'; + + # Inicio del bucle principal de programa pandora_init(\%pa_config, "Pandora FMS Recon server"); @@ -190,15 +194,16 @@ sub pandora_exec_task { $list_ip = $list_ip." ".$target_ip; $list_host = $list_host." ".resolv_ip2name($target_ip_resolved); # If has a network profile, create agent and modules + my $agent_id; if ($task_ncprofile > 0){ # Create address, agent and more... my $target_ip_id = pandora_task_create_address ($pa_config, $dbh, $id_task, $target_ip); - my $agent_id = pandora_task_create_agent($pa_config, $dbh, $target_ip, $target_ip_id, $task_group, $network_server_assigned, $target_ip_resolved); + $agent_id = pandora_task_create_agent($pa_config, $dbh, $target_ip, $target_ip_id, $task_group, $network_server_assigned, $target_ip_resolved); pandora_task_create_agentmodules($pa_config, $dbh, $agent_id, $task_ncprofile, $target_ip); } my $title = "[RECON] New host [$target_ip_resolved] detected on network [$target_network]"; # Always create event about this detected IP - pandora_event ($pa_config, $title, $task_group, 0, $dbh); + pandora_event ($pa_config, $title,$task_group, $agent_id, 2, 0, 0, 'recon_host_detected', $dbh); } } my $progress = ceil($position / ($total_hosts / 100)); @@ -360,7 +365,7 @@ sub pandora_task_create_agent { my $name = $_[6]; logger($pa_config,"Recon Server: Creating agent for ip $target_ip ",2); - my $query_sql2 = "INSERT INTO tagente (nombre, direccion, comentarios, id_grupo, id_os, agent_type, id_server, intervalo) VALUES ('$name', '$target_ip', 'Autogenerated by Pandora FMS Recon Server', $id_group, 11, 1, $id_server, 300)"; + my $query_sql2 = "INSERT INTO tagente (nombre, direccion, comentarios, id_grupo, id_os, id_network_server, intervalo) VALUES ('$name', '$target_ip', 'Autogenerated by Pandora FMS Recon Server', $id_group, 11, $id_server, 300)"; $dbh->do ($query_sql2); my $lastid = $dbh->{'mysql_insertid'}; my $query_sql3 = "INSERT INTO taddress_agent (id_a, id_agent) values ($target_ip_id, $lastid)"; @@ -435,3 +440,14 @@ sub pandora_task_create_agentmodules { $exec_sql->finish(); } +######################################################################################## +# pandora_shutdown () +# Close system +######################################################################################## +sub pandora_shutdown { + logger (\%pa_config,"Pandora FMS Server '".$pa_config{'servername'}.$pa_config{"servermode"}."' Shutdown by signal ",0); + print " [*] Shutting down ".$pa_config{'servername'}.$pa_config{"servermode"} ."(received signal)...\n"; + pandora_event (\%pa_config, $pa_config{'servername'}.$pa_config{"servermode"}." going Down", 0, + 0, 4, 0, 0, "system", $dbh); + exit; +} \ No newline at end of file diff --git a/pandora_server/bin/pandora_server b/pandora_server/bin/pandora_server index 9d305e89b4..bd06621fe7 100755 --- a/pandora_server/bin/pandora_server +++ b/pandora_server/bin/pandora_server @@ -100,12 +100,14 @@ while (1) { ######################################################################################## # pandora_shutdown () -# Close system on a received signal +# Close system ######################################################################################## sub pandora_shutdown { - logger (\%pa_config,"Pandora FMS Data Server Shutdown by signal ",0); - print " [*] Shutting down Pandora FMS Data Server (received signal)...\n"; - exit; + logger (\%pa_config,"Pandora FMS Server '".$pa_config{'servername'}.$pa_config{"servermode"}."' Shutdown by signal ",0); + print " [*] Shutting down ".$pa_config{'servername'}.$pa_config{"servermode"} ."(received signal)...\n"; + pandora_event (\%pa_config, $pa_config{'servername'}.$pa_config{"servermode"}." going Down", 0, + 0, 4, 0, 0, "system", $dbh); + exit; } ############################################################################### diff --git a/pandora_server/bin/pandora_snmpconsole b/pandora_server/bin/pandora_snmpconsole index 1a3a720c16..e1b476588d 100755 --- a/pandora_server/bin/pandora_snmpconsole +++ b/pandora_server/bin/pandora_snmpconsole @@ -38,6 +38,9 @@ $| = 0; my %pa_config; +$SIG{'TERM'} = 'pandora_shutdown'; +$SIG{'INT'} = 'pandora_shutdown'; + # Inicio del bucle principal de programa pandora_init(\%pa_config,"Pandora SNMP Console"); # Read config file for Global variables @@ -255,10 +258,21 @@ sub calcula_alerta_snmp { # The new alert is between last valid time + threshold and between max/min limit to alerts in this gap of time. $times_fired++; $internal_counter++; - # ---------> EXECUTE ALERT <--------------- logger($pa_config,"Executing SNMP Trap alert for $agent - $alert_data",2); - execute_alert ($pa_config, $id_alert, $field1, $field2, $field3, -$trap_agente, $timestamp, $alert_data, "", "", "", 1, $dbh); + + # Create a hash for passing to execute_alert + my %data_alert; + $data_alert{'id_aam'} = 0; + $data_alert{'id_agente_modulo'} = 0; + $data_alert{'id_alerta'} = $id_alert; + $data_alert{'al_campo1'} = $field1; + $data_alert{'al_campo2'} = $field2; + $data_alert{'al_campo3'} = $field3; + $data_alert{'descripcion'} = $description; + + # Execute alert + execute_alert ($pa_config, \%data_alert, $agent, $id_group, $agent, $trap_agente, 1, $dbh); + # Now update the new value for times_fired, alert_fired, internal_counter and last_fired for this alert. my $query_idag2 = "update talert_snmp set times_fired = $times_fired, last_fired = '$ahora_mysql', internal_counter = $internal_counter where id_as = $id_as "; $dbh->do($query_idag2); @@ -288,3 +302,15 @@ $trap_agente, $timestamp, $alert_data, "", "", "", 1, $dbh); } # if $s_idag->finish(); } + +######################################################################################## +# pandora_shutdown () +# Close system +######################################################################################## +sub pandora_shutdown { + logger (\%pa_config,"Pandora FMS Server '".$pa_config{'servername'}.$pa_config{"servermode"}."' Shutdown by signal ",0); + print " [*] Shutting down ".$pa_config{'servername'}.$pa_config{"servermode"} ."(received signal)...\n"; + pandora_event (\%pa_config, $pa_config{'servername'}.$pa_config{"servermode"}." going Down", 0, + 0, 4, 0, 0, "system", $dbh); + exit; +} diff --git a/pandora_server/bin/pandora_wmi b/pandora_server/bin/pandora_wmi index 14888a3073..ec5b6290ad 100755 --- a/pandora_server/bin/pandora_wmi +++ b/pandora_server/bin/pandora_wmi @@ -79,10 +79,66 @@ my $wmiwebloc = Win32::OLE->new('WbemScripting.SWbemLocator') || my $wmi = $wmiwebloc->ConnectServer($computer,$wmipath,$user,$pwd); + +# New samples + +# Process executing (return PID) +# SELECT ProcessId FROM Win32_Process WHERE Caption = "spoolsv.exe" + +# Service State of a service (Running or Stopped) +# SELECT State FROM Win32_Service WHERE Name = "Eventlog" + +# CPU de CPU0 +# SELECT LoadPercentage from Win32_Processor WHERE DeviceID = "CPU0" + +# Available memory (bytes) +# SELECT AvailableBytes from Win32_PerfRawData_PerfOS_Memory + +# Available cache memory (bytes) +# SELECT CacheBytes from Win32_PerfRawData_PerfOS_Memory + +# AvgDiskBytesPerTransfer +# DiskReadsPersec +# DiskTransfersPersec +# FreeMegabytes +# SELECT * from Win32_PerfRawData_PerfDisk_LogicalDisk WHERE Name = "F:" + + +# FragmentedDatagramsPersec +# FragmentationFailures +# DatagramsReceivedPersec +# DatagramsSentPersec +# SELECT * from Win32_PerfFormattedData_Tcpip_IP + +my $colItems = $wmi->ExecQuery ("SELECT State FROM Win32_Service WHERE Name = 'Eventlog'"); +foreach my $objItem (in $colItems){ + print $objItem->{State}; + print "\n"; +} # get all the service objects my @services = in $wmi->InstancesOf("Win32_Service"); # Take 10 first services for (my $a=0;$a<10;$a++){ print "Service ", $services[$a]->Name, " is ", $services[$a]->Status, "\n"; -} \ No newline at end of file +} + +#------------------------------------------------------------------------------------ +#------------------------------------------------------------------------------------ +#------------------------------------------------------------------------------------ +#--------------------- Main Perl Code below this line----------------------- +#------------------------------------------------------------------------------------ +#------------------------------------------------------------------------------------ +#------------------------------------------------------------------------------------ + +######################################################################################## +# pandora_shutdown () +# Close system +######################################################################################## +sub pandora_shutdown { + logger (\%pa_config,"Pandora FMS Server '".$pa_config{'servername'}.$pa_config{"servermode"}."' Shutdown by signal ",0); + print " [*] Shutting down ".$pa_config{'servername'}.$pa_config{"servermode"} ."(received signal)...\n"; + pandora_event (\%pa_config, $pa_config{'servername'}.$pa_config{"servermode"}." going Down", 0, + 0, 4, 0, 0, "system", $dbh); + exit; +} diff --git a/pandora_server/conf/pandora_server.conf b/pandora_server/conf/pandora_server.conf index cdf411000b..e9e41c9d27 100755 --- a/pandora_server/conf/pandora_server.conf +++ b/pandora_server/conf/pandora_server.conf @@ -151,3 +151,16 @@ wmi_timeout 10 # wmi_threads: Specify number of WMI server threads for processing WMI remote calls wmi_threads 3 + +# mta_address: External Mailer (MTA) IP Address to be used by Pandora FMS internal email capabilities +# mta_address 192.168.50.1 + +mta_address localhost + +# mta_port: MTA port (default 25) +# mta_port 25 + +# mta_user: MTA User (if needed for auth) +# mta_pass: MTA Pass (if needed for auth) +# mta_auth: MTA Auth system (if needed, support: LOGIN PLAIN CRAM-MD5 DIGEST-MD) + diff --git a/pandora_server/lib/PandoraFMS/Config.pm b/pandora_server/lib/PandoraFMS/Config.pm index 606fec0793..87822cbf22 100644 --- a/pandora_server/lib/PandoraFMS/Config.pm +++ b/pandora_server/lib/PandoraFMS/Config.pm @@ -182,6 +182,14 @@ sub pandora_loadconfig { $pa_config->{"compound_max_depth"} = 5; # Maximum nested compound alert depth. Not in config file. $pa_config->{"dataserver_threads"} = 3; # Introduced on 2.0 + # Internal MTA for alerts, each server need its own config. + $pa_config->{"mta_address"} = '127.0.0.1'; # Introduced on 2.0 + $pa_config->{"mta_port"} = '25'; # Introduced on 2.0 + $pa_config->{"mta_user"} = ''; # Introduced on 2.0 + $pa_config->{"mta_pass"} = ''; # Introduced on 2.0 + $pa_config->{"mta_auth"} = 'none'; # Introduced on 2.0 (Support LOGIN PLAIN CRAM-MD5 DIGEST-MD) + $pa_config->{"mta_from"} = 'pandora@localhost'; # Introduced on 2.0 + # Check for UID0 if ($pa_config->{"quiet"} != 0){ if ($> == 0){ @@ -249,6 +257,27 @@ sub pandora_loadconfig { $pa_config->{"errorlogfile"} = $tbuf; } } + + # MTA setup (2.0) + elsif ($parametro =~ m/^mta_user\s(.*)/i) { + $pa_config->{'mta_user'}= clean_blank($1); + } + elsif ($parametro =~ m/^mta_pass\s(.*)/i) { + $pa_config->{'mta_pass'}= clean_blank($1); + } + elsif ($parametro =~ m/^mta_address\s(.*)/i) { + $pa_config->{'mta_address'}= clean_blank($1); + } + elsif ($parametro =~ m/^mta_port\s(.*)/i) { + $pa_config->{'mta_port'}= clean_blank($1); + } + elsif ($parametro =~ m/^mta_auth\s(.*)/i) { + $pa_config->{'mta_auth'}= clean_blank($1); + } + elsif ($parametro =~ m/^mta_from\s(.*)/i) { + $pa_config->{'mta_from'}= clean_blank($1); + } + elsif ($parametro =~ m/^snmp_logfile\s(.*)/i) { $pa_config->{'snmp_logfile'}= clean_blank($1); } @@ -474,6 +503,8 @@ sub pandora_loadconfig { print " [*] Pandora FMS Server [".$pa_config->{'servername'}.$pa_config->{"servermode"}."] is running and operative \n"; } $pa_config->{'server_id'} = dame_server_id ($pa_config, $pa_config->{'servername'}.$pa_config->{"servermode"}, $dbh); + pandora_event ($pa_config, $pa_config->{'servername'}.$pa_config->{"servermode"}." going UP", 0, + 0, 3, 0, 0, "system", $dbh); } diff --git a/pandora_server/lib/PandoraFMS/DB.pm b/pandora_server/lib/PandoraFMS/DB.pm index 2868da84c6..5b88af671e 100644 --- a/pandora_server/lib/PandoraFMS/DB.pm +++ b/pandora_server/lib/PandoraFMS/DB.pm @@ -257,7 +257,8 @@ sub pandora_process_alert (%$$$$$%$$) { # Generate an event pandora_event ($pa_config, "Alert ceased (" . $alert_data->{'descripcion'} . ")", $id_group, - $id_agent, $dbh); + $id_agent, $alert_data->{'priority'}, $alert_data->{'id_aam'}, $alert_data->{'id_agente_modulo'}, + "alert_recovered", $dbh); return; } @@ -269,12 +270,8 @@ sub pandora_process_alert (%$$$$$%$$) { internal_counter = 0 WHERE id_aam = " . $alert_data->{'id_aam'}); - execute_alert ($pa_config, $timestamp, $alert_data->{'id_alerta'}, - $id_agent, $id_group, $alert_data->{'al_campo1'}, - $alert_data->{'al_f2_recovery'}, - $alert_data->{'al_f3_recovery'}, $agent_name, - $module_data, '', '', $alert_data->{'descripcion'}, 1, - $dbh); + execute_alert ($pa_config, $alert_data, $id_agent, $id_group, $agent_name, + $module_data, 0, $dbh); return; } @@ -308,11 +305,8 @@ sub pandora_process_alert (%$$$$$%$$) { $alert_data->{'internal_counter'} . " WHERE id_aam = " . $alert_data->{'id_aam'}); - execute_alert ($pa_config, $timestamp, $alert_data->{'id_alerta'}, - $id_agent, $id_group, $alert_data->{'al_campo1'}, - $alert_data->{'al_campo2'}, $alert_data->{'al_campo3'}, - $agent_name, $module_data, '', '', - $alert_data->{'descripcion'}, 1, $dbh); + execute_alert ($pa_config, $alert_data, $id_agent, $id_group, $agent_name, + $module_data, 1, $dbh); return; } } @@ -459,55 +453,67 @@ sub pandora_generate_compound_alerts (%$$$$$$$) { } ########################################################################## -## SUB execute_alert (pa_config, timestamp, id_alert, id_agent, id_group, -## field1, field2, field3, agent, data, command, alert_name, alert_description, -## create_event, dbh) +## SUB execute_alert ## Do a execution of given alert with this parameters ########################################################################## sub execute_alert (%$$$$$$$$$$$$$$$) { my $pa_config = $_[0]; - my $timestamp = $_[1]; - my $id_alert = $_[2]; - my $id_agent = $_[3]; - my $id_group = $_[4]; - my $field1 = $_[5]; - my $field2 = $_[6]; - my $field3 = $_[7]; - my $agent = $_[8]; - my $data = $_[9]; - my $command = $_[10]; - my $alert_name = $_[11]; - my $alert_description = $_[12]; - my $create_event = $_[13]; - my $dbh = $_[14]; + my $data_alert = $_[1]; + my $id_agent = $_[2]; + my $id_group = $_[3]; + my $agent = $_[4]; + my $data = $_[5]; + my $alert_mode = $_[6]; # 0 is recovery, 1 is normal + my $dbh = $_[7]; + # Some variable init + + my $create_event = 1; + my $command = ""; + my $alert_name = ""; + my $field1; + my $field2; + my $field3; + my $id_alert = $data_alert->{'id_alerta'}; + my $id_agent_module = $data_alert->{'id_agente_modulo'}; + my $timestamp = &UnixDate ("today", "%Y-%m-%d %H:%M:%S"); # string timestamp + my $alert_description = $data_alert->{'descripcion'}; + # Compound only if ($id_alert == 1){ return; } + + if ($alert_mode == 1){ + $field1 = $data_alert->{'al_campo1'}; + $field2 = $data_alert->{'al_campo2'}; + $field3 = $data_alert->{'al_campo3'}; + } else { + $field1 = $data_alert->{'al_campo1'}; + $field2 = $data_alert->{'al_f2_recovery'}; + $field3 = $data_alert->{'al_f3_recovery'}; + } - if (($command eq "") && ($alert_name eq "")){ - # Get values for commandline, reading from talerta. - my $query_idag = "SELECT * FROM talerta WHERE id_alerta = '$id_alert'"; - my $idag = $dbh->prepare($query_idag); - $idag ->execute; - my @datarow; - if ($idag->rows != 0) { - while (@datarow = $idag->fetchrow_array()) { - $command = $datarow[2]; - $alert_name = $datarow[1]; - } + # Get values for commandline, reading from talerta. + my $query_idag = "SELECT * FROM talerta WHERE id_alerta = '$id_alert'"; + my $idag = $dbh->prepare($query_idag); + $idag ->execute; + my @datarow; + if ($idag->rows != 0) { + while (@datarow = $idag->fetchrow_array()) { + $command = $datarow[2]; + $alert_name = $datarow[1]; } - $idag->finish(); } - + $idag->finish(); + logger($pa_config, "Alert ($alert_name) TRIGGERED for $agent",2); - if ($id_alert != 3){ # id_alerta 3 is reserved for internal audit system + if ($id_alert > 4) { # Skip internal alerts $command =~ s/_field1_/"$field1"/ig; $command =~ s/_field2_/"$field2"/ig; $command =~ s/_field3_/"$field3"/ig; - $command=~ s/_agent_/$agent/ig; + $command =~ s/_agent_/$agent/ig; $command =~ s/_timestamp_/$timestamp/ig; $command =~ s/_data_/$data/ig; # Clean up some "tricky" characters @@ -522,19 +528,34 @@ sub execute_alert (%$$$$$$$$$$$$$$$) { } }; if ($@){ - logger($pa_config, "WARNING: Alert command don't retun from execution. ( $command )", 0 ); - logger($pa_config, "ERROR Code: $@",1); + logger($pa_config, "WARNING: Alert command don't return from execution. ( $command )", 0 ); + logger($pa_config, "ERROR Code: $@",2); } - } else { # id_alerta = 3, is a internal system audit + } elsif ($id_alert == 3) { # id_alerta = 3, is a internal system audit logger($pa_config, "Internal audit lauch for agent name $agent",3); $field1 =~ s/_agent_/$agent/ig; $field1 =~ s/_timestamp_/$timestamp/ig; $field1 =~ s/_data_/$data/ig; pandora_audit ($pa_config, $field1, $agent, "Alert ($alert_description)", $dbh); - } + $create_event = 0; + } elsif ($id_alert == 2) { # email + $field3 =~ s/_agent_/$agent/ig; + $field3 =~ s/_timestamp_/$timestamp/ig; + $field3 =~ s/_data_/$data/ig; + pandora_sendmail ( $pa_config, $field1, $field2, $field3); + } elsif ($id_alert == 4) { # internal event + $create_event = 1; + } + if ($create_event == 1){ my $evt_descripcion = "Alert fired ($alert_description)"; - pandora_event ($pa_config, $evt_descripcion, $id_group, $id_agent, $dbh); + if ($alert_mode == 0){ # recovery + pandora_event ($pa_config, $evt_descripcion, $id_group, $id_agent, $data_alert->{'priority'}, $data_alert->{'id_aam'}, + $data_alert->{'id_agente_modulo'}, 'alert_recovered', $dbh); + } else { + pandora_event ($pa_config, $evt_descripcion, $id_group, $id_agent, $data_alert->{'priority'}, $data_alert->{'id_aam'}, + $data_alert->{'id_agente_modulo'}, 'alert_fired', $dbh); + } } } @@ -552,7 +573,7 @@ sub pandora_writestate (%$$$$$$$) { my $nombre_agente = $_[1]; my $tipo_modulo = $_[2]; # passed as string my $nombre_modulo = $_[3]; - my $datos = $_[4]; # Careful: Dont pass a hash, only a single value + my $datos = $_[4]; # Careful: This don't reference a hash, only a single value my $estado = $_[5]; my $dbh = $_[6]; my $needs_update = $_[7]; @@ -562,7 +583,7 @@ sub pandora_writestate (%$$$$$$$) { # Get current timestamp / unix numeric time my $timestamp = &UnixDate ("today", "%Y-%m-%d %H:%M:%S"); # string timestamp - my $utimestamp = &UnixDate($timestamp,"%s"); # convert from human to integer + my $utimestamp = &UnixDate($timestamp, "%s"); # convert from human to integer # Get server id my $server_name = $pa_config->{'servername'}.$pa_config->{"servermode"}; @@ -574,15 +595,15 @@ sub pandora_writestate (%$$$$$$$) { my $id_agente = dame_agente_id ($pa_config, $nombre_agente, $dbh); my $id_modulo = dame_modulo_id ($pa_config, $tipo_modulo, $dbh); my $id_agente_modulo = dame_agente_modulo_id($pa_config, $id_agente, $id_modulo, $nombre_modulo, $dbh); - if (($id_agente == -1) || ($id_agente_modulo == -1)) { return 0; } - my $id_grupo = dame_grupo_agente($pa_config, $id_agente,$dbh); + + my $id_grupo = dame_grupo_agente($pa_config, $id_agente,$dbh); # Seek for agent_interval or module_interval - my $query_idag = "SELECT * FROM tagente_modulo WHERE id_agente = $id_agente AND id_agente_modulo = " . $id_agente_modulo;; + my $query_idag = "SELECT * FROM tagente_modulo WHERE id_agente = $id_agente AND id_agente_modulo = " . $id_agente_modulo; my $s_idag = $dbh->prepare($query_idag); $s_idag ->execute; if ($s_idag->rows == 0) { @@ -591,6 +612,7 @@ sub pandora_writestate (%$$$$$$$) { } else { @data = $s_idag->fetchrow_array(); } + my $id_module_type = $data[2]; my $module_interval = $data[7]; if ($module_interval == 0){ @@ -612,28 +634,42 @@ sub pandora_writestate (%$$$$$$$) { my $s_idages = $dbh->prepare($idages); $s_idages ->execute; $datos = $dbh->quote($datos); # Parse data entry for adecuate SQL representation. + my $query_act; # OJO que dentro de una llave solo tiene existencia en esa llave !! if ($s_idages->rows == 0) { # Doesnt exist entry in table, lets make the first entry logger($pa_config, "Create entry in tagente_estado for module $nombre_modulo",4); $query_act = "INSERT INTO tagente_estado (id_agente_modulo, datos, timestamp, estado, cambio, id_agente, last_try, utimestamp, current_interval, running_by, last_execution_try) VALUES ($id_agente_modulo,$datos,'$timestamp','$estado','1',$id_agente,'$timestamp',$utimestamp, $module_interval, $id_server, $utimestamp)"; # Cuando se hace un insert, siempre hay un cambio de estado + } else { # There are an entry in table already @data = $s_idages->fetchrow_array(); + if ( $data[11] == 0){ + $needs_update = 1; + } + # Se supone que $data[5](estado) ( nos daria el estado ANTERIOR - # For xxxx_PROC type (boolean / monitor), create an event if state has changed + # For xxxx_PROC type (boolean / monitor), create an event if state has changed if (( $data[5] != $estado) && ( ($tipo_modulo =~/keep_alive/) || ($tipo_modulo =~ /proc/)) ) { # Cambio de estado detectado ! $cambio = 1; + $needs_update = 1; # Este seria el momento oportuno de probar a saltar la alerta si estuviera definida - # Makes an event entry, only if previous state changes, if new state, doesnt give any alert - my $descripcion; - if ( $estado == 0) { - $descripcion = "Monitor ($nombre_modulo) goes up "; - } - if ( $estado == 1) { - $descripcion = "Monitor ($nombre_modulo) goes down"; - } - pandora_event ($pa_config, $descripcion, $id_grupo, $id_agente, $dbh); + # Makes an event entry, only if previous state changes, if new state, doesnt give any alert + my $descripcion; + my $event_type; + if ( $estado == 0) { + $descripcion = "Monitor ($nombre_modulo) goes up "; + $event_type = "monitor_up"; + } + if ( $estado == 1) { + $descripcion = "Monitor ($nombre_modulo) goes down"; + $event_type = "monitor_down"; + } + + pandora_event ($pa_config, $descripcion, $id_grupo, + $id_agente, 2, 0, $id_agente_modulo, + $event_type, $dbh); } + if ($needs_update == 1) { $query_act = "UPDATE tagente_estado SET utimestamp = $utimestamp, datos = $datos, cambio = '$cambio', timestamp = '$timestamp', estado = '$estado', id_agente = $id_agente, last_try = '$timestamp', current_interval = '$module_interval', running_by = $id_server, last_execution_try = $utimestamp WHERE id_agente_modulo = $id_agente_modulo"; } else { # dont update last_try field, that it's the field @@ -759,7 +795,8 @@ sub module_generic_proc (%$$$$$) { if (ref($a_min) eq "HASH") { $a_min = ""; } - pandora_writedata($pa_config, $a_timestamp,$agent_name,$module_type,$a_name,$a_datos,$a_max,$a_min,$a_desc,$dbh, \$bUpdateDatos); + pandora_writedata ($pa_config, $a_timestamp, $agent_name, $module_type, $a_name, + $a_datos, $a_max, $a_min, $a_desc, $dbh, \$bUpdateDatos); # Check for status: <1 state 1 (Bad), >= 1 state 0 (Good) # Calculamos su estado @@ -1126,7 +1163,7 @@ sub pandora_writedata (%$$$$$$$$$$){ $datos = $dbh->quote($datos); $timestamp = $dbh->quote($timestamp); # Parse data entry for adecuate SQL representation. - $query = "INSERT INTO tagente_datos (id_agente_modulo, datos, timestamp, utimestamp, id_agente) VALUES ($id_agente_modulo, $datos, $timestamp, $utimestamp, $id_agente)"; + $query = "INSERT INTO tagente_datos (id_agente_modulo, datos, timestamp, utimestamp, id_agente) VALUES ($id_agente_modulo, $datos, $timestamp, $utimestamp, $id_agente)"; } # If data is out of limits, do not insert into database if ($outlimit == 0){ logger($pa_config, "DEBUG: pandora_insertdata Calculado id_agente_modulo a $id_agente_modulo",6); @@ -1170,7 +1207,11 @@ sub pandora_serverkeepaliver (%$$) { $version_data = $pa_config->{"version"}." (P) ".$pa_config->{"build"}; my $sql_update = "UPDATE tserver SET status = 0, version = '".$version_data."' WHERE id_server = $data[0]"; $dbh->do($sql_update); - pandora_event($pa_config, "Server ".$data[1]." going Down", 0, 0, $dbh); + + + pandora_event ($pa_config, "Server ".$data[1]." going Down", 0, + 0, 4, 0, 0, "system", $dbh); + logger( $pa_config, "Server ".$data[1]." going Down ",1); } } @@ -1235,7 +1276,6 @@ sub pandora_updateserver (%$$$) { if ($s_idag->rows != 0) { if (@data = $s_idag->fetchrow_array()){ if ($data[3] == 0){ # If down, update to get up the server - pandora_event($pa_config, "Server ".$data[1]." going UP", 0, 0, $dbh); logger( $pa_config, "Server ".$data[1]." going UP ",1); } # Update server data @@ -1293,25 +1333,31 @@ sub pandora_lastagentcontact (%$$$$$$) { } ########################################################################## -## SUB pandora_event (pa_config, evento, id_grupo, id_agente, dbh) +## SUB pandora_event ## Write in internal audit system an entry. +## Params: config_hash, event_title, group, agent_id, severity, id_alertam +## id_agentmodule, event_type (from a set, as string), db_handle ########################################################################## -sub pandora_event (%$$$$) { - my $pa_config = $_[0]; - my $evento = $_[1]; - my $id_grupo = $_[2]; - my $id_agente = $_[3]; - my $dbh = $_[4]; - my $timestamp = &UnixDate("today","%Y-%m-%d %H:%M:%S"); +sub pandora_event (%$$$$$$$$) { + my $pa_config = $_[0]; + my $evento = $_[1]; + my $id_grupo = $_[2]; + my $id_agente = $_[3]; + my $severity = $_[4]; # new in 2.0 + my $id_alert_am = $_[5]; # new in 2.0 + my $id_agentmodule = $_[6]; # new in 2.0 + my $event_type = $_[7]; # new in 2.0 + my $dbh = $_[8]; + my $timestamp = &UnixDate("today","%Y-%m-%d %H:%M:%S"); my $utimestamp; # integer version of timestamp $utimestamp = &UnixDate($timestamp,"%s"); # convert from human to integer - $evento = $dbh->quote($evento); - $timestamp = $dbh->quote($timestamp); - my $query = "INSERT INTO tevento (id_agente, id_grupo, evento, timestamp, estado, utimestamp) VALUES ($id_agente, $id_grupo, $evento, $timestamp, 0, $utimestamp)"; - logger ($pa_config,"EVENT Insertion: $query", 5); - $dbh->do($query); + $evento = $dbh->quote($evento); + $event_type = $dbh->quote($event_type); + $timestamp = $dbh->quote($timestamp); + my $query = "INSERT INTO tevento (id_agente, id_grupo, evento, timestamp, estado, utimestamp, event_type, id_agentmodule, id_alert_am, criticity) VALUES ($id_agente, $id_grupo, $evento, $timestamp, 0, $utimestamp, $event_type, $id_agentmodule, $id_alert_am, $severity)"; + $dbh->do($query); } ########################################################################## diff --git a/pandora_server/lib/PandoraFMS/Tools.pm b/pandora_server/lib/PandoraFMS/Tools.pm index 28411b0f3c..7eead7b709 100644 --- a/pandora_server/lib/PandoraFMS/Tools.pm +++ b/pandora_server/lib/PandoraFMS/Tools.pm @@ -21,6 +21,7 @@ use warnings; use Time::Local; use Date::Manip; # Needed to manipulate DateTime formats of input, output and compare use POSIX qw(setsid); +use Mail::Sendmail; # New in 2.0. Used to sendmail internally, without external scripts require Exporter; @@ -36,6 +37,7 @@ our @EXPORT = qw( sqlWrap is_numeric clean_blank + pandora_sendmail ); @@ -68,6 +70,41 @@ sub pandora_daemonize { # Pandora other General functions | # -------------------------------------------+ +########################################################################## +# SUB pandora_sendmail +# Send a mail, connecting directly to MTA +# param1 - config hash +# param2 - Destination email addres +# param3 - Email subject +# param4 - Email Message body +########################################################################## + +sub pandora_sendmail { # added in 2.0 version + my $pa_config = $_[0]; + my $to_address = $_[1]; + my $subject = $_[2]; + my $message = $_[3]; + + my %mail = ( To => $to_address, + Message => $message, + Subject => $subject, + Smtp => $pa_config->{"mta_address"}, + Port => $pa_config->{"mta_port"}, + From => $pa_config->{"mta_from"}, + ); + + if ($pa_config->{"mta_user"} ne ""){ + $mail{auth} = {user=>$config->{"mta_user"}, password=>$config->{"mta_pass"}, method=>$config->{"mta_auth"}, required=>0 } + } + eval { + sendmail(%mail); + }; + if ($@){ + logger ($pa_config, "[ERROR] Sending email to $to_address with subject $subject", 1); + logger ($pa_config, "ERROR Code: $@", 4); + } +} + ########################################################################## # SUB is_numeric # Return TRUE if given argument is numeric diff --git a/pandora_server/pandora_server_installer b/pandora_server/pandora_server_installer index 6c692499ac..25694c7e6c 100755 --- a/pandora_server/pandora_server_installer +++ b/pandora_server/pandora_server_installer @@ -60,6 +60,7 @@ else ln -s /usr/local/bin/pandora_export /usr/bin/pandora_export mkdir /usr/share/pandora cp -R util /usr/share/pandora + cp -R plugin /usr/share/pandora echo "perl /usr/share/pandora/util/pandora_db /etc/pandora/pandora_server.conf" > /etc/cron.daily/pandora_purge_db chmod +x /etc/cron.daily/pandora_purge_db rm output diff --git a/pandora_server/util/pandora_db.pl b/pandora_server/util/pandora_db.pl index a3419fb905..f6c3980f8c 100755 --- a/pandora_server/util/pandora_db.pl +++ b/pandora_server/util/pandora_db.pl @@ -84,9 +84,15 @@ sub pandora_purgedb { my $timestamp = &UnixDate("today","%Y-%m-%d %H:%M:%S"); my $limit_access = DateCalc("today","-24 hours",\$err); $limit_access = &UnixDate($limit_access,"%Y-%m-%d %H:%M:%S"); - print "[PURGE] Deleting old access data... \n"; + print "[PURGE] Deleting old access data (More than 24hr) \n"; $dbh->do("DELETE FROM tagent_access WHERE timestamp < '$limit_access'"); + + my $limit_event = DateCalc("today","-$config_days_purge days",\$err); + $limit_event = &UnixDate($limit_event,"%Y-%m-%d %H:%M:%S"); + print "[PURGE] Deleting old event data (More than $config_days_purge days)... \n"; + $dbh->do("DELETE FROM tevent WHERE timestamp < '$limit_event'"); + print "[PURGE] Deleting old data... \n"; # Lets insert the last value on $limit_timestamp + 1 minute for each id_agente_modulo my $query_idag = "select count(distinct(id_agente_modulo)) from tagente_datos where timestamp < '$limit_timestamp'";