2009-04-14 Ramon Novoa <rnovoa@artica.es>
* pandora_ctl, pandora_network, pandora_wmi, pandora_plugin, pandora_prediction, bin/pandora_wmi, bin/pandora_plugin, bin/pandora_prediction, bin/pandora_snmpconsole, bin/pandora_recon, bin/pandora_network, pandora_recon, pandora_snmpconsole: Deleted from repository. Old server code and startup scripts. * Makefile.PL, pandora_server_installer, lib/PandoraFMS/Config.pm lib/PandoraFMS/DB.pm, lib/PandoraFMS/Tools.pm, bin/pandora_server, pandora_package_installer, pandora_server: Updated to work with the new code, removed unneeded dependencies, fixed some bugs etc. * lib/PandoraFMS/SNMPServer.pm, lib/PandoraFMS/PluginServer.pm, lib/PandoraFMS/ProducerConsumerServer.pm, lib/PandoraFMS/Server.pm, lib/PandoraFMS/PredictionServer.pm, lib/PandoraFMS/Core.pm, lib/PandoraFMS/ReconServer.pm, lib/PandoraFMS/DataServer.pm, lib/PandoraFMS/NetworkServer.pm, lib/PandoraFMS/WMIServer.pm: Added to repository. New server code. git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@1620 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f
This commit is contained in:
parent
a1a5cd216b
commit
894ab9a30a
|
@ -1,3 +1,23 @@
|
|||
2009-04-14 Ramon Novoa <rnovoa@artica.es>
|
||||
|
||||
* pandora_ctl, pandora_network, pandora_wmi, pandora_plugin,
|
||||
pandora_prediction, bin/pandora_wmi, bin/pandora_plugin,
|
||||
bin/pandora_prediction, bin/pandora_snmpconsole, bin/pandora_recon,
|
||||
bin/pandora_network, pandora_recon, pandora_snmpconsole: Deleted
|
||||
from repository. Old server code and startup scripts.
|
||||
|
||||
* Makefile.PL, pandora_server_installer, lib/PandoraFMS/Config.pm
|
||||
lib/PandoraFMS/DB.pm, lib/PandoraFMS/Tools.pm, bin/pandora_server,
|
||||
pandora_package_installer, pandora_server: Updated to work with the
|
||||
new code, removed unneeded dependencies, fixed some bugs etc.
|
||||
|
||||
* lib/PandoraFMS/SNMPServer.pm, lib/PandoraFMS/PluginServer.pm,
|
||||
lib/PandoraFMS/ProducerConsumerServer.pm, lib/PandoraFMS/Server.pm,
|
||||
lib/PandoraFMS/PredictionServer.pm, lib/PandoraFMS/Core.pm,
|
||||
lib/PandoraFMS/ReconServer.pm, lib/PandoraFMS/DataServer.pm,
|
||||
lib/PandoraFMS/NetworkServer.pm, lib/PandoraFMS/WMIServer.pm: Added
|
||||
to repository. New server code.
|
||||
|
||||
2009-04-02 Sancho Lerena <slerena@artica.es>
|
||||
|
||||
* DB.pm: Function to process SNMP Alerts was not properly exported, so
|
||||
|
|
|
@ -22,7 +22,7 @@ WriteMakefile(
|
|||
HTML::Entities => 0,
|
||||
SNMP => 0
|
||||
},
|
||||
EXE_FILES => [ 'bin/pandora_server', 'bin/pandora_network', 'bin/pandora_wmi', 'bin/pandora_recon', 'bin/pandora_snmpconsole' , 'bin/pandora_plugin', 'bin/pandora_prediction', 'util/pandora_exec'],
|
||||
EXE_FILES => [ 'bin/pandora_server', 'util/pandora_exec'],
|
||||
PMLIBDIRS => [ 'lib' ],
|
||||
'dist' => { 'TAR' => 'tar', 'TARFLAGS' => 'cvfz', 'SUFFIX'
|
||||
=> '.gz', 'COMPRESS' => 'gzip'}
|
||||
|
|
|
@ -1,696 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
##########################################################################
|
||||
# Pandora FMS Network Server
|
||||
# http://www.pandorafms.com
|
||||
##########################################################################
|
||||
# Copyright (c) 2006-2008 Sancho Lerena, slerena@gmail.com
|
||||
# (c) 2006-2008 Artica Soluciones Tecnologicas S.L
|
||||
#
|
||||
# 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; version 2
|
||||
#
|
||||
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
##########################################################################
|
||||
|
||||
# Includes list
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Date::Manip; # Needed to manipulate DateTime formats of input, output and compare
|
||||
use Time::Local; # DateTime basic manipulation
|
||||
use Net::Ping; # For ICMP latency
|
||||
use Time::HiRes; # For high precission timedate functions (Net::Ping)
|
||||
use IO::Socket; # For TCP/UDP access
|
||||
use threads;
|
||||
use threads::shared;
|
||||
|
||||
# Pandora Modules
|
||||
use PandoraFMS::Config;
|
||||
use PandoraFMS::Tools;
|
||||
use PandoraFMS::DB;
|
||||
enterprise_load ();
|
||||
|
||||
# FLUSH in each IO (only for debug, very slooow)
|
||||
# ENABLED in DEBUGMODE
|
||||
# DISABLE FOR PRODUCTION
|
||||
$| = 0;
|
||||
|
||||
my %pa_config;
|
||||
my @pending_task : shared;
|
||||
my %pending_task_hash : shared;
|
||||
my %current_task_hash : shared;
|
||||
my $icmp_lock : shared;
|
||||
my $queue_lock : shared;
|
||||
|
||||
$SIG{'TERM'} = 'pandora_shutdown';
|
||||
$SIG{'INT'} = 'pandora_shutdown';
|
||||
|
||||
# Inicio del bucle principal de programa
|
||||
pandora_init(\%pa_config, "Pandora FMS Network Server");
|
||||
|
||||
# Read config file for Global variables
|
||||
pandora_loadconfig (\%pa_config,1);
|
||||
|
||||
# Audit server starting
|
||||
pandora_audit (\%pa_config, "Pandora FMS Network Daemon starting", "SYSTEM", "System");
|
||||
|
||||
# Check for snmpget
|
||||
|
||||
if (! -e $pa_config{"snmpget"}) {
|
||||
print " [E] ".$pa_config{"snmpget"}." not found. Pandora FMS Network cannot run without it.\n\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
# Thread startup
|
||||
|
||||
if ($pa_config{"verbosity"} > 4){
|
||||
print " [*] Starting up network threads\n";
|
||||
}
|
||||
|
||||
# Daemonize and put in background
|
||||
if ( $pa_config{"daemon"} eq "1" ){
|
||||
if ($pa_config{"verbosity"} > 0){
|
||||
print " [*] Backgrounding Pandora FMS Network Server process.\n\n";
|
||||
}
|
||||
&pandora_daemonize ( \%pa_config);
|
||||
}
|
||||
|
||||
|
||||
# Launch now all network threads
|
||||
# $ax is local thread id for this server
|
||||
for (my $ax=0; $ax < $pa_config{'network_threads'}; $ax++){
|
||||
threads->new( \&pandora_network_consumer, \%pa_config, $ax);
|
||||
}
|
||||
|
||||
# Launch now the network producer thread
|
||||
threads->new( \&pandora_network_producer, \%pa_config);
|
||||
|
||||
|
||||
if ($pa_config{"verbosity"} > 4){
|
||||
print " [*] All threads loaded and running \n\n";
|
||||
}
|
||||
|
||||
# Start Pandora FMS loggin
|
||||
pandora_startlog (\%pa_config);
|
||||
|
||||
# Last thread is the main process (this process)
|
||||
my $dbhost = $pa_config{'dbhost'};
|
||||
my $dbname = $pa_config{'dbname'};
|
||||
my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost:3306",
|
||||
$pa_config{'dbuser'},
|
||||
$pa_config{'dbpass'},
|
||||
{ RaiseError => 1, AutoCommit => 1 });
|
||||
|
||||
my $counter_status_report = 0;
|
||||
my $counter_status_loops = (30 / $pa_config{"server_threshold"}) + 1;
|
||||
|
||||
while (1) {
|
||||
pandora_serverkeepaliver (\%pa_config, 1, $dbh);
|
||||
|
||||
# Only call this each 30 loops
|
||||
if ($counter_status_report > $counter_status_loops ){
|
||||
enterprise_hook('mcast_status_report', [\%pa_config, $dbh]);
|
||||
$counter_status_report = 0;
|
||||
} else {
|
||||
$counter_status_report++;
|
||||
}
|
||||
|
||||
threads->yield;
|
||||
sleep ($pa_config{"server_threshold"});
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------------
|
||||
#------------------------------------------------------------------------------------
|
||||
#------------------------------------------------------------------------------------
|
||||
#--------------------- Main Perl Code below this line-----------------------
|
||||
#------------------------------------------------------------------------------------
|
||||
#------------------------------------------------------------------------------------
|
||||
#------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
##########################################################################
|
||||
# SUB pandora_network_subsystem
|
||||
# Subsystem to process network modules
|
||||
# This module runs each X seconds (server threshold) checking for network modules status
|
||||
##########################################################################
|
||||
sub pandora_network_consumer ($$) {
|
||||
my $pa_config = $_[0];
|
||||
my $thread_id = $_[1];
|
||||
|
||||
if ($pa_config->{"verbosity"} > 4){
|
||||
print " [*] Starting up Network Consumer Thread # $thread_id \n";
|
||||
}
|
||||
|
||||
my $data_id_agent_module;
|
||||
# Create Database handler
|
||||
my $dbh = DBI->connect("DBI:mysql:$pa_config->{'dbname'}:$pa_config->{'dbhost'}:3306", $pa_config->{'dbuser'}, $pa_config->{'dbpass'}, { RaiseError => 1, AutoCommit => 1 });
|
||||
my $counter =0;
|
||||
|
||||
LOOP: while (1) {
|
||||
if ($counter > 10) {
|
||||
threads->yield;
|
||||
sleep (1);
|
||||
$counter = 0;
|
||||
}
|
||||
|
||||
# Take the first element on the shared queue
|
||||
# Insert this element on the current task hash
|
||||
{
|
||||
lock $queue_lock;
|
||||
if (scalar(@pending_task) == 0){
|
||||
$counter++;
|
||||
next LOOP;
|
||||
}
|
||||
|
||||
$data_id_agent_module = shift(@pending_task);
|
||||
delete($pending_task_hash{$data_id_agent_module});
|
||||
$current_task_hash{$data_id_agent_module}=1;
|
||||
}
|
||||
|
||||
# Executing network task with unmanaged error trapping
|
||||
eval {
|
||||
# Call network execution process
|
||||
exec_network_module ( $pa_config, $data_id_agent_module, $dbh);
|
||||
};
|
||||
if ($@){
|
||||
logger ($pa_config, "[ERROR] Network Task for module $data_id_agent_module causes a system exception", 0);
|
||||
logger ($pa_config, "ERROR Code: $@", 1);
|
||||
}
|
||||
|
||||
# Remove from queue. If catch an error, probably data is
|
||||
# not been processed, but has been freed from task queue
|
||||
{
|
||||
lock $queue_lock;
|
||||
delete($current_task_hash{$data_id_agent_module});
|
||||
}
|
||||
$counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
sub pandora_network_producer ($) {
|
||||
my $pa_config = $_[0];
|
||||
|
||||
if ($pa_config->{"verbosity"} > 4){
|
||||
print " [*] Starting up Network Producer Thread ...\n";
|
||||
}
|
||||
|
||||
my $dbh = DBI->connect("DBI:mysql:$pa_config->{'dbname'}:$pa_config->{'dbhost'}:3306", $pa_config->{'dbuser'}, $pa_config->{'dbpass'}, { RaiseError => 1, AutoCommit => 1 });
|
||||
|
||||
my $server_id = $pa_config->{'server_id'};
|
||||
|
||||
# Initialize variables for posterior usage
|
||||
my $query1;
|
||||
my @sql_data1;
|
||||
my $data_id_agente_modulo;
|
||||
my $data_flag;
|
||||
my $exec_sql1;
|
||||
|
||||
while (1) {
|
||||
if ($pa_config->{"pandora_master"} != 1) {
|
||||
# Query for normal server, not MASTER server
|
||||
$query1 = "SELECT tagente_modulo.id_agente_modulo, tagente_modulo.flag, UNIX_TIMESTAMP() - tagente_estado.current_interval - tagente_estado.last_execution_try AS time_left
|
||||
FROM
|
||||
tagente, tagente_modulo, tagente_estado
|
||||
WHERE
|
||||
id_network_server = $server_id
|
||||
AND
|
||||
tagente_modulo.id_agente = tagente.id_agente
|
||||
AND
|
||||
tagente.disabled = 0
|
||||
AND
|
||||
tagente_modulo.id_tipo_modulo > 4
|
||||
AND
|
||||
tagente_modulo.id_tipo_modulo < 19
|
||||
AND
|
||||
tagente_modulo.disabled = 0
|
||||
AND
|
||||
tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo
|
||||
AND (
|
||||
tagente_modulo.flag = 1
|
||||
OR
|
||||
((tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP())
|
||||
)
|
||||
ORDER BY
|
||||
tagente_modulo.flag DESC, time_left DESC, last_execution_try ASC ";
|
||||
} else {
|
||||
# Query for MASTER SERVER !
|
||||
# Apparently the MASTER SERVER takes over a SLAVE SERVER tasks' when it's down. Made a subquery of it so it doesn't do 3-4 joins
|
||||
$query1 = "SELECT DISTINCT(tagente_modulo.id_agente_modulo), tagente_modulo.flag, tagente_estado.last_execution_try, UNIX_TIMESTAMP() - tagente_estado.current_interval - tagente_estado.last_execution_try AS time_left
|
||||
FROM
|
||||
tagente, tagente_modulo, tagente_estado
|
||||
WHERE
|
||||
(
|
||||
(tagente.id_network_server = $server_id)
|
||||
OR
|
||||
(tagente.id_network_server = ANY(SELECT id_server FROM tserver WHERE status = 0 AND id_server != $server_id AND network_server = 1))
|
||||
)
|
||||
AND
|
||||
tagente_modulo.id_agente = tagente.id_agente
|
||||
AND
|
||||
tagente.disabled = 0
|
||||
AND
|
||||
tagente_modulo.disabled = 0
|
||||
AND
|
||||
tagente_modulo.id_tipo_modulo > 4
|
||||
AND
|
||||
tagente_modulo.id_tipo_modulo < 19
|
||||
AND
|
||||
tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo
|
||||
AND (
|
||||
tagente_modulo.flag = 1
|
||||
OR
|
||||
((tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP() )
|
||||
)
|
||||
ORDER BY tagente_modulo.flag DESC, time_left DESC, last_execution_try ASC";
|
||||
}
|
||||
$exec_sql1 = $dbh->prepare($query1);
|
||||
$exec_sql1 ->execute;
|
||||
while (@sql_data1 = $exec_sql1->fetchrow_array()) {
|
||||
$data_id_agente_modulo = $sql_data1[0];
|
||||
$data_flag = $sql_data1[1];
|
||||
# Skip modules already queued
|
||||
if ((!defined($pending_task_hash{$data_id_agente_modulo})) &&
|
||||
(!defined($current_task_hash{$data_id_agente_modulo}))) {
|
||||
if ($data_flag == 1){
|
||||
$dbh->do("UPDATE tagente_modulo SET flag = 0 WHERE id_agente_modulo = $data_id_agente_modulo")
|
||||
}
|
||||
# Locking scope, do not remove redundant { }
|
||||
{
|
||||
lock $queue_lock;
|
||||
push (@pending_task, $data_id_agente_modulo);
|
||||
$pending_task_hash {$data_id_agente_modulo}=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#logger ($pa_config, "Items in Network Pending Queue: ".scalar(@pending_task), 5);
|
||||
$exec_sql1->finish();
|
||||
sleep($pa_config->{"server_threshold"});
|
||||
} # Main loop
|
||||
}
|
||||
|
||||
##############################################################################
|
||||
# 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 $icmp_lock;
|
||||
$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 $icmp_lock;
|
||||
$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)
|
||||
# Makes a call to TCP modules to get a value.
|
||||
##########################################################################
|
||||
sub pandora_query_tcp (%$$$$$$$) {
|
||||
my $pa_config = $_[0];
|
||||
my $tcp_port = $_[1];
|
||||
my $ip_target = $_[2];
|
||||
my $module_result = $_[3];
|
||||
my $module_data = $_[4];
|
||||
my $tcp_send = $_[5];
|
||||
my $tcp_rcv = $_[6];
|
||||
my $id_tipo_modulo = $_[7];
|
||||
|
||||
my $counter;
|
||||
for ($counter =0; $counter < $pa_config->{'tcp_checks'}; $counter++){
|
||||
my $temp; my $temp2;
|
||||
my $tam;
|
||||
my $handle=IO::Socket::INET->new(
|
||||
Proto=>"tcp",
|
||||
PeerAddr=>$ip_target,
|
||||
Timeout=>$pa_config->{'tcp_timeout'},
|
||||
PeerPort=>$tcp_port,
|
||||
Blocking=>0 ); # Non blocking !!, very important !
|
||||
|
||||
if (defined($handle)){
|
||||
# Multi request patch, submitted by Glen Eustace (new zealand)
|
||||
my @tcp_send = split( /\|/, $tcp_send );
|
||||
my @tcp_rcv = split( /\|/, $tcp_rcv );
|
||||
|
||||
next_pair:
|
||||
$tcp_send = shift( @tcp_send );
|
||||
$tcp_rcv = shift( @tcp_rcv );
|
||||
|
||||
if ((defined($tcp_send)) && ($tcp_send ne "")){ # its Expected to sending data ?
|
||||
# Send data
|
||||
$handle->autoflush(1);
|
||||
$tcp_send =~ s/\^M/\r\n/g;
|
||||
# Replace Carriage rerturn and line feed
|
||||
$handle->send($tcp_send);
|
||||
}
|
||||
# we expect to receive data ? (non proc types)
|
||||
if ((defined($tcp_rcv)) && (($tcp_rcv ne "") || ($id_tipo_modulo == 10) || ($id_tipo_modulo ==8) || ($id_tipo_modulo == 11))) {
|
||||
# Receive data, non-blocking !!!! (VERY IMPORTANT!)
|
||||
$temp2 = "";
|
||||
for ($tam=0; $tam<($pa_config->{'tcp_timeout'}); $tam++){
|
||||
$handle->recv($temp,16000,0x40);
|
||||
$temp2 = $temp2.$temp;
|
||||
if ($temp ne ""){
|
||||
$tam++; # If doesnt receive data, increase counter
|
||||
}
|
||||
sleep(1);
|
||||
}
|
||||
if ($id_tipo_modulo == 9){ # only for TCP Proc
|
||||
if ($temp2 =~ /$tcp_rcv/i){ # String match !
|
||||
if ( @tcp_send ) { # still more pairs
|
||||
goto next_pair;
|
||||
}
|
||||
$$module_data = 1;
|
||||
$$module_result = 0;
|
||||
$counter = $pa_config->{'tcp_checks'};
|
||||
} else {
|
||||
$$module_data = 0;
|
||||
$$module_result = 0;
|
||||
$counter = $pa_config->{'tcp_checks'};
|
||||
}
|
||||
} elsif ($id_tipo_modulo == 10 ){ # TCP String (no int conversion)!
|
||||
$$module_data = $temp2;
|
||||
$$module_result =0;
|
||||
} else { # TCP Data numeric (inc or data)
|
||||
if ($temp2 ne ""){
|
||||
if ($temp2 =~ /[A-Za-z\.\,\-\/\\\(\)\[\]]/){
|
||||
$$module_result = 1;
|
||||
$$module_data = 0; # invalid data
|
||||
$counter = $pa_config->{'tcp_checks'};
|
||||
} else {
|
||||
$$module_data = int($temp2);
|
||||
$$module_result = 0; # Successful
|
||||
$counter = $pa_config->{'tcp_checks'};
|
||||
}
|
||||
} else {
|
||||
$$module_result = 1;
|
||||
$$module_data = 0; # invalid data
|
||||
$counter = $pa_config->{'tcp_checks'};
|
||||
}
|
||||
}
|
||||
} else { # No expected data to receive, if connected and tcp_proc type successful
|
||||
if ($id_tipo_modulo == 9){ # TCP Proc
|
||||
$$module_result = 0;
|
||||
$$module_data = 1;
|
||||
$counter = $pa_config->{'tcp_checks'};
|
||||
}
|
||||
}
|
||||
$handle->close();
|
||||
undef ($handle);
|
||||
} else { # Cannot connect (open sock failed)
|
||||
$$module_result = 1; # Fail
|
||||
if ($id_tipo_modulo == 9){ # TCP Proc
|
||||
$$module_result = 0;
|
||||
$$module_data = 0; # Failed, but data exists
|
||||
$counter = $pa_config->{'tcp_checks'};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# SUB pandora_query_snmp (pa_config, oid, community, target, version, error, dbh)
|
||||
# Makes a call to SNMP modules to get a value,
|
||||
##########################################################################
|
||||
sub pandora_query_snmp (%$$$$$) {
|
||||
my $pa_config = $_[0];
|
||||
my $snmp_oid = $_[1];
|
||||
my $snmp_community =$_[2];
|
||||
my $snmp_target = $_[3];
|
||||
my $snmp_version = $_[4];
|
||||
# $_[5] contains error var.
|
||||
|
||||
if ($snmp_version ne '1' && $snmp_version ne '2'
|
||||
&& $snmp_version ne '2c' && $snmp_version ne '3') {
|
||||
$snmp_version = '1';
|
||||
}
|
||||
|
||||
my $snmp_timeout = $pa_config->{"snmp_timeout"};
|
||||
my $snmp_retries = $pa_config->{'snmp_checks'};
|
||||
|
||||
# TODO: Alternative version if command is not available or user select a new switch
|
||||
# with "use internal SNMP" option. At this moment, due to locks() external snmp is much faster
|
||||
|
||||
$_[5] = 0;
|
||||
my $snmpget_cmd = $pa_config->{"snmpget"};
|
||||
my $output = `$snmpget_cmd -v $snmp_version -r $snmp_retries -t $snmp_timeout -OUevqt -c $snmp_community $snmp_target $snmp_oid`;
|
||||
if ($output eq ""){
|
||||
$_[5] = 1;
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# SUB exec_network_module (paconfig, id_agente_modulo, dbh )
|
||||
# Execute network module task
|
||||
##########################################################################
|
||||
sub exec_network_module {
|
||||
my $pa_config = $_[0];
|
||||
my $id_agente_modulo = $_[1];
|
||||
my $dbh = $_[2];
|
||||
# Init variables
|
||||
my $id_agente;
|
||||
my $id_tipo_modulo;
|
||||
my $nombre;
|
||||
my $min;
|
||||
my $max;
|
||||
my $module_interval;
|
||||
my $tcp_port;
|
||||
my $tcp_send;
|
||||
my $tcp_rcv;
|
||||
my $snmp_community;
|
||||
my $snmp_oid;
|
||||
my $ip_target;
|
||||
my $id_module_group;
|
||||
my $flag;
|
||||
my @sql_data;
|
||||
if ((!defined($id_agente_modulo)) || ($id_agente_modulo eq "")){
|
||||
return 0;
|
||||
}
|
||||
my $query_sql = "SELECT * FROM tagente_modulo WHERE id_agente_modulo = $id_agente_modulo";
|
||||
my $exec_sql = $dbh->prepare($query_sql);
|
||||
$exec_sql ->execute;
|
||||
if (@sql_data = $exec_sql->fetchrow_array()){
|
||||
$id_agente= $sql_data[1];
|
||||
$id_tipo_modulo = $sql_data[2];
|
||||
$nombre = $sql_data[4];
|
||||
$min = $sql_data[6];
|
||||
$max = $sql_data[5];
|
||||
$module_interval = $sql_data[7];
|
||||
$tcp_port = $sql_data[8];
|
||||
$tcp_send = $sql_data[9];
|
||||
$tcp_rcv = $sql_data[10];
|
||||
$snmp_community = $sql_data[11];
|
||||
$snmp_oid = $sql_data[12];
|
||||
$ip_target = $sql_data[13];
|
||||
$id_module_group = $sql_data[14];
|
||||
$flag = $sql_data[15];
|
||||
$exec_sql->finish();
|
||||
} else {
|
||||
$exec_sql->finish();
|
||||
logger (\%pa_config,"[ERROR] Processing data for invalid module", 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
my $agent_name = dame_agente_nombre ($pa_config, $id_agente, $dbh);
|
||||
my $error = "1";
|
||||
my $query_sql2;
|
||||
my $temp=0; my $tam; my $temp2;
|
||||
my $module_result = 1; # Fail by default
|
||||
my $module_data = 0;
|
||||
|
||||
if ((defined($ip_target)) && ($ip_target ne "")) {
|
||||
|
||||
# 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;
|
||||
}
|
||||
} 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
|
||||
}
|
||||
# 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
|
||||
if ((defined($snmp_oid)) && ($snmp_oid ne "") && (defined($snmp_community)) && ($snmp_community ne "")) { # Port check
|
||||
$temp2 = pandora_query_snmp ($pa_config, $snmp_oid, $snmp_community, $ip_target, $tcp_send, $error);
|
||||
} else {
|
||||
$error = 1
|
||||
}
|
||||
if ($error == 0) { # A correct SNMP Query
|
||||
$module_result = 0;
|
||||
# SNMP_DATA_PROC
|
||||
if ($id_tipo_modulo == 18){ #snmp_data_proc
|
||||
# RFC1213-MIB where it says that: SYNTAX INTEGER { up(1), down(2), testing(3),
|
||||
# unknown(4), dormant(5), notPresent(6), lowerLayerDown(7) }
|
||||
if ($temp2 != 1){ # up state is 1, down state in SNMP is 2 ....
|
||||
$temp2 = 0;
|
||||
}
|
||||
$module_data = $temp2;
|
||||
}
|
||||
# SNMP_DATA and SNMP_DATA_INC
|
||||
elsif (($id_tipo_modulo == 15) || ($id_tipo_modulo == 16) ){
|
||||
if (!is_numeric($temp2)){
|
||||
$module_result = 1;
|
||||
} else {
|
||||
$module_data = $temp2;
|
||||
}
|
||||
} else { # String SNMP
|
||||
$module_data = $temp2;
|
||||
}
|
||||
} else { # Failed SNMP-GET
|
||||
$module_data = 0;
|
||||
if ($id_tipo_modulo == 18){ # snmp_proc
|
||||
# Feature from 10Feb08. If snmp_proc_deadresponse = 1 and cannot contact by an error
|
||||
# this is a fail monitor
|
||||
if ($pa_config->{"snmp_proc_deadresponse"} eq "1"){
|
||||
$module_result = 0;
|
||||
} else {
|
||||
$module_result = 1;
|
||||
}
|
||||
} else {
|
||||
$module_result = 1; # No data, cannot connect
|
||||
}
|
||||
}
|
||||
# TCP Module
|
||||
# ----------
|
||||
} elsif (($id_tipo_modulo == 8) || ($id_tipo_modulo == 9) || ($id_tipo_modulo == 10) || ($id_tipo_modulo == 11)) { # TCP Module
|
||||
if ((defined($tcp_port)) && ($tcp_port < 65536) && ($tcp_port > 0)) { # Port check
|
||||
pandora_query_tcp ($pa_config, $tcp_port, $ip_target, \$module_result, \$module_data, $tcp_send, $tcp_rcv, $id_tipo_modulo);
|
||||
} else {
|
||||
# Invalid port, get no check
|
||||
$module_result = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Write data section
|
||||
my $timestamp = &UnixDate("today","%Y-%m-%d %H:%M:%S");
|
||||
my $utimestamp = &UnixDate("today","%s");
|
||||
|
||||
# Is everything goes ok
|
||||
if ($module_result == 0) {
|
||||
my %part;
|
||||
$part{'name'}[0]=$nombre;
|
||||
$part{'description'}[0]="";
|
||||
$part{'data'}[0] = $module_data;
|
||||
$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')) {
|
||||
module_generic_data ($pa_config, \%part, $timestamp, $agent_name, $tipo_modulo, $dbh);
|
||||
}
|
||||
elsif ($tipo_modulo =~ /\_inc/ ) {
|
||||
module_generic_data_inc ($pa_config, \%part, $timestamp, $agent_name, $tipo_modulo, $dbh);
|
||||
}
|
||||
elsif ($tipo_modulo =~ /\_string/) {
|
||||
module_generic_data_string ($pa_config, \%part, $timestamp, $agent_name, $tipo_modulo, $dbh);
|
||||
}
|
||||
elsif ($tipo_modulo =~ /\_proc/){
|
||||
module_generic_proc ($pa_config, \%part, $timestamp, $agent_name, $tipo_modulo, $dbh);
|
||||
}
|
||||
else {
|
||||
logger ($pa_config, "Problem with unknown module type '$tipo_modulo'", 0);
|
||||
$module_result = 1;
|
||||
}
|
||||
# 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);
|
||||
|
||||
} else {
|
||||
# Modules who cannot connect or something go bad, update last_execution_try field
|
||||
update_on_error ($pa_config, $id_agente_modulo, $dbh);
|
||||
}
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# pandora_shutdown ()
|
||||
# Close system
|
||||
########################################################################################
|
||||
sub pandora_shutdown {
|
||||
logger (\%pa_config,"Pandora FMS Server '".$pa_config{'servername'}.$pa_config{"servermode"}."' Shutdown by signal ",0);
|
||||
pandora_updateserver (\%pa_config, $pa_config{'servername'}, 0, 1, $dbh);
|
||||
if ($pa_config{"quiet"} == 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;
|
||||
}
|
||||
|
|
@ -1,402 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
##########################################################################
|
||||
# Pandora FMS Plugin Server
|
||||
# http://www.pandorafms.com
|
||||
##########################################################################
|
||||
# Copyright (c) 2008-2009 Sancho Lerena, slerena@gmail.com
|
||||
# (c) 2008-2009 Artica Soluciones Tecnologicas S.L
|
||||
#
|
||||
# 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; version 2.
|
||||
#
|
||||
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
##########################################################################
|
||||
|
||||
# Includes list
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Date::Manip; # Needed to manipulate DateTime formats of input, output and compare
|
||||
use Time::Local; # DateTime basic manipulation
|
||||
use threads;
|
||||
use threads::shared;
|
||||
use HTML::Entities;
|
||||
|
||||
# Pandora Modules
|
||||
use PandoraFMS::Config;
|
||||
use PandoraFMS::Tools;
|
||||
use PandoraFMS::DB;
|
||||
|
||||
# Queue management
|
||||
my @pending_task : shared;
|
||||
my %pending_task_hash : shared;
|
||||
my %current_task_hash : shared;
|
||||
my $queue_lock : shared;
|
||||
|
||||
|
||||
# FLUSH in each IO (only for debug, very slooow)
|
||||
# ENABLED in DEBUGMODE
|
||||
# DISABLE FOR PRODUCTION
|
||||
$| = 0;
|
||||
|
||||
my %pa_config;
|
||||
|
||||
$SIG{'TERM'} = 'pandora_shutdown';
|
||||
$SIG{'INT'} = 'pandora_shutdown';
|
||||
|
||||
# Inicio del bucle principal de programa
|
||||
pandora_init(\%pa_config, "Pandora FMS Plugin Server");
|
||||
|
||||
# Check for pandora_exec
|
||||
my $pandora_exec = "pandora_exec";
|
||||
if (system("$pandora_exec > /dev/null 2>&1") != 256) {
|
||||
print " [E] $pandora_exec not found.\n\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
# Read config file for Global variables
|
||||
pandora_loadconfig (\%pa_config, 4);
|
||||
|
||||
# Audit server starting
|
||||
pandora_audit (\%pa_config, "Pandora FMS Plugin server starting", "SYSTEM", "System");
|
||||
|
||||
# Daemonize and put in background
|
||||
if ( $pa_config{"daemon"} eq "1" ){
|
||||
if ($pa_config{"quiet"} eq "0"){
|
||||
print " [*] Backgrounding Pandora FMS Plugin Server process.\n\n";
|
||||
}
|
||||
&pandora_daemonize ( \%pa_config);
|
||||
}
|
||||
|
||||
# Launch now all plugin threads
|
||||
# $ax is local thread id for this server
|
||||
for (my $ax=0; $ax < $pa_config{'plugin_threads'}; $ax++){
|
||||
threads->new( \&pandora_plugin_consumer, \%pa_config, $ax);
|
||||
}
|
||||
|
||||
# Launch now the producer thread
|
||||
threads->new( \&pandora_plugin_producer, \%pa_config);
|
||||
|
||||
# Last thread is the main process (this process)
|
||||
if ($pa_config{"quiet"} == 0){
|
||||
print " [*] All threads loaded and running \n\n";
|
||||
}
|
||||
|
||||
# Start Pandora FMS loggin
|
||||
pandora_startlog (\%pa_config);
|
||||
|
||||
my $dbhost = $pa_config{'dbhost'};
|
||||
my $dbname = $pa_config{'dbname'};
|
||||
my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost:3306",
|
||||
$pa_config{'dbuser'},
|
||||
$pa_config{'dbpass'},
|
||||
{ RaiseError => 1, AutoCommit => 1 });
|
||||
|
||||
# Server keepalive thread running in main thread on a infinite loop
|
||||
while (1) {
|
||||
pandora_serverkeepaliver (\%pa_config, 4, $dbh);
|
||||
threads->yield;
|
||||
sleep ($pa_config{"server_threshold"});
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------------
|
||||
#------------------------------------------------------------------------------------
|
||||
#------------------------------------------------------------------------------------
|
||||
#--------------------- 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);
|
||||
pandora_updateserver (\%pa_config, $pa_config{'servername'}, 0, 4, $dbh);
|
||||
exit;
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# SUB pandora_plugin_consumer_subsystem
|
||||
# Subsystem to process Plugin modules
|
||||
# This module runs each X seconds (server threshold) checking for Plugin modules status
|
||||
##########################################################################
|
||||
sub pandora_plugin_consumer ($$) {
|
||||
my $pa_config = $_[0];
|
||||
my $thread_id = $_[1];
|
||||
|
||||
if ($pa_config->{"quiet"} == 0){
|
||||
print " [*] Starting up Plugin Consumer Thread # $thread_id \n";
|
||||
}
|
||||
|
||||
my $data_id_agent_module;
|
||||
# Create Database handler
|
||||
my $dbh = DBI->connect("DBI:mysql:$pa_config->{'dbname'}:$pa_config->{'dbhost'}:3306", $pa_config->{'dbuser'}, $pa_config->{'dbpass'}, { RaiseError => 1, AutoCommit => 1 });
|
||||
my $counter =0;
|
||||
|
||||
LOOP: while (1) {
|
||||
if ($counter > 10) {
|
||||
threads->yield;
|
||||
sleep (1);
|
||||
$counter = 0;
|
||||
}
|
||||
|
||||
# Take the first element on the shared queue
|
||||
# Insert this element on the current task hash
|
||||
{
|
||||
lock $queue_lock;
|
||||
if (scalar(@pending_task) == 0){
|
||||
$counter++;
|
||||
next LOOP;
|
||||
}
|
||||
|
||||
$data_id_agent_module = shift(@pending_task);
|
||||
delete($pending_task_hash{$data_id_agent_module});
|
||||
$current_task_hash{$data_id_agent_module}=1;
|
||||
}
|
||||
|
||||
# Executing network task with unmanaged error trapping
|
||||
eval {
|
||||
# Call network execution process
|
||||
# exec_network_module ( $pa_config, $data_id_agent_module, $dbh);
|
||||
exec_plugin_module ($pa_config, $data_id_agent_module, $dbh);
|
||||
};
|
||||
if ($@){
|
||||
logger ($pa_config, "[ERROR] Plugin Task for module $data_id_agent_module causes a system exception", 0);
|
||||
logger ($pa_config, "ERROR Code: $@", 1);
|
||||
}
|
||||
|
||||
# Remove from queue. If catch an error, probably data is
|
||||
# not been processed, but has been freed from task queue
|
||||
{
|
||||
lock $queue_lock;
|
||||
delete($current_task_hash{$data_id_agent_module});
|
||||
}
|
||||
$counter = 0;
|
||||
threads->yield;
|
||||
}
|
||||
}
|
||||
|
||||
sub pandora_plugin_producer ($) {
|
||||
my $pa_config = $_[0];
|
||||
print " [*] Starting up Plugin Producer Thread ...\n";
|
||||
|
||||
my $dbh = DBI->connect("DBI:mysql:$pa_config->{'dbname'}:$pa_config->{'dbhost'}:3306", $pa_config->{'dbuser'}, $pa_config->{'dbpass'}, { RaiseError => 1, AutoCommit => 1 });
|
||||
my $server_id = $pa_config->{'server_id'};
|
||||
|
||||
# Initialize variables for posterior usage
|
||||
my $query1;
|
||||
my @sql_data1;
|
||||
my $data_id_agente_modulo;
|
||||
my $data_flag;
|
||||
my $exec_sql1;
|
||||
|
||||
while (1) {
|
||||
if ($pa_config->{"pandora_master"} != 1) {
|
||||
# Query for normal server, not MASTER server
|
||||
$query1 = "SELECT
|
||||
tagente_modulo.id_agente_modulo,
|
||||
tagente_modulo.flag
|
||||
UNIX_TIMESTAMP() - tagente_estado.current_interval - tagente_estado.last_execution_try AS time_left
|
||||
FROM
|
||||
tagente, tagente_modulo, tagente_estado
|
||||
WHERE
|
||||
id_plugin_server = $server_id
|
||||
AND
|
||||
tagente_modulo.id_agente = tagente.id_agente
|
||||
AND
|
||||
tagente.disabled = 0
|
||||
AND
|
||||
tagente_modulo.id_plugin != 0
|
||||
AND
|
||||
tagente_modulo.disabled = 0
|
||||
AND
|
||||
tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo
|
||||
AND (
|
||||
tagente_modulo.flag = 1
|
||||
OR
|
||||
(tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP()
|
||||
)
|
||||
ORDER BY
|
||||
tagente_modulo.flag DESC, time_left DESC, last_execution_try ASC ";
|
||||
} else {
|
||||
# Query for MASTER SERVER !
|
||||
$query1 = "SELECT
|
||||
DISTINCT(tagente_modulo.id_agente_modulo), tagente_modulo.flag, UNIX_TIMESTAMP() - tagente_estado.current_interval - tagente_estado.last_execution_try AS time_left
|
||||
FROM
|
||||
tagente, tagente_modulo, tagente_estado
|
||||
WHERE
|
||||
( (tagente.id_plugin_server = $server_id) OR
|
||||
(tagente.id_plugin_server = ANY(SELECT id_server FROM tserver WHERE status = 0 AND id_server != $server_id AND plugin_server = 1))
|
||||
)
|
||||
AND
|
||||
tagente_modulo.id_agente = tagente.id_agente
|
||||
AND
|
||||
tagente.disabled = 0
|
||||
AND
|
||||
tagente_modulo.disabled = 0
|
||||
AND
|
||||
tagente_modulo.id_plugin != 0
|
||||
AND
|
||||
tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo
|
||||
AND
|
||||
(tagente_modulo.flag = 1 OR (tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP() )
|
||||
ORDER BY
|
||||
tagente_modulo.flag DESC, time_left DESC, last_execution_try ASC";
|
||||
}
|
||||
$exec_sql1 = $dbh->prepare($query1);
|
||||
$exec_sql1 ->execute;
|
||||
while (@sql_data1 = $exec_sql1->fetchrow_array()) {
|
||||
$data_id_agente_modulo = $sql_data1[0];
|
||||
$data_flag = $sql_data1[1];
|
||||
|
||||
# Skip modules already queued
|
||||
if ((!defined($pending_task_hash{$data_id_agente_modulo})) &&
|
||||
(!defined($current_task_hash{$data_id_agente_modulo}))) {
|
||||
if ($data_flag == 1){
|
||||
$dbh->do("UPDATE tagente_modulo SET flag = 0 WHERE id_agente_modulo = $data_id_agente_modulo")
|
||||
}
|
||||
# Locking scope, do not remove redundant { }
|
||||
{
|
||||
lock $queue_lock;
|
||||
push (@pending_task, $data_id_agente_modulo);
|
||||
$pending_task_hash {$data_id_agente_modulo}=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
$exec_sql1->finish();
|
||||
threads->yield;
|
||||
sleep($pa_config->{"server_threshold"});
|
||||
} # Main loop
|
||||
}
|
||||
|
||||
|
||||
##########################################################################
|
||||
# SUB exec_plugin_module (paconfig, id_agente_modulo, dbh )
|
||||
# Execute plugin module task
|
||||
##########################################################################
|
||||
sub exec_plugin_module {
|
||||
my $pa_config = $_[0];
|
||||
my $id_am = $_[1];
|
||||
my $dbh = $_[2];
|
||||
|
||||
# Set global variables for this sub
|
||||
my $timeout = $pa_config->{'plugin_timeout'};
|
||||
my $agent_module; # hash container for tagente_modulo record
|
||||
my $plugin; # hash container for tplugin
|
||||
|
||||
# Get a full hash for agent_plugin record reference ($agent_module)
|
||||
my $query_sql = "SELECT * FROM tagente_modulo WHERE id_agente_modulo = $id_am";
|
||||
my $exec_sql = $dbh->prepare($query_sql);
|
||||
$exec_sql ->execute;
|
||||
|
||||
# TODO: Do a check for void result ! (Gives a DBD::mysql::st execute failed: MySQL server has gone away at /usr/local/bin/pandora_plugin line 304)
|
||||
|
||||
$agent_module = $exec_sql->fetchrow_hashref;
|
||||
|
||||
# Get a full hash for plugin record reference ($plugin)
|
||||
$query_sql = "SELECT * FROM tplugin WHERE id = ".$agent_module->{'id_plugin'};
|
||||
$exec_sql = $dbh->prepare($query_sql);
|
||||
$exec_sql->execute();
|
||||
$plugin = $exec_sql->fetchrow_hashref;
|
||||
|
||||
# Calculate min timeout for this call
|
||||
if ($plugin->{'max_timeout'} < $timeout){
|
||||
$timeout = $plugin->{'max_timeout'};
|
||||
}
|
||||
|
||||
# Initialize another global sub variables.
|
||||
my $agent_name = dame_agente_nombre ($pa_config, $agent_module->{'id_agente'}, $dbh);
|
||||
my $module_data = 0; # 0 data for default
|
||||
my $module_interval = 0;
|
||||
|
||||
# Build execution command to plugin
|
||||
my $exec_output = "";
|
||||
my $plugin_command = $plugin->{"execute"};
|
||||
if ($plugin->{'net_dst_opt'} ne ""){
|
||||
$plugin_command = $plugin_command . " ". $plugin->{'net_dst_opt'} ." ". $agent_module->{'ip_target'};
|
||||
}
|
||||
if ($plugin->{'net_port_opt'} ne "") {
|
||||
$plugin_command = $plugin_command . " ". $plugin->{'net_port_opt'} ." ". $agent_module->{'tcp_port'};
|
||||
}
|
||||
if ($plugin->{'user_opt'} ne "") {
|
||||
$plugin_command = $plugin_command . " ". $plugin->{'user_opt'} ." ". $agent_module->{'plugin_user'};
|
||||
}
|
||||
if ($plugin->{'pass_opt'} ne "") {
|
||||
$plugin_command = $plugin_command . " ". $plugin->{'pass_opt'} ." ". $agent_module->{'plugin_pass'};
|
||||
}
|
||||
|
||||
# Proccess field / optional / dynamic field
|
||||
if ($agent_module->{'plugin_parameter'} ne "") {
|
||||
$plugin_command = $plugin_command . " ". $agent_module->{'plugin_parameter'};
|
||||
}
|
||||
|
||||
$plugin_command = decode_entities($plugin_command);
|
||||
|
||||
logger ($pa_config, "Executing AM # $id_am plugin command '$plugin_command'", 9);
|
||||
# Final command line execution is stored at "plugin_command"
|
||||
|
||||
$module_data = `$pandora_exec $timeout $plugin_command`;
|
||||
if ($module_data eq "") {
|
||||
update_on_error ($pa_config, $id_am, $dbh);
|
||||
undef $plugin;
|
||||
undef $agent_module;
|
||||
return;
|
||||
}
|
||||
|
||||
# Get current timestamp
|
||||
my $timestamp = &UnixDate("today","%Y-%m-%d %H:%M:%S");
|
||||
my $utimestamp = &UnixDate("today","%s");
|
||||
|
||||
my %part;
|
||||
$part{'name'}[0] = $agent_module->{'nombre'};
|
||||
$part{'description'}[0] = "";
|
||||
$part{'data'}[0] = $module_data;
|
||||
my $tipo_modulo = dame_nombretipomodulo_idagentemodulo ($pa_config, $agent_module->{'id_tipo_modulo'}, $dbh);
|
||||
|
||||
# 1 - generic_data
|
||||
# 2 - generic_proc
|
||||
# 3 - generic_data_string
|
||||
# 4 - generic_data_inc
|
||||
# 19, 20 - image
|
||||
|
||||
if (1 == $agent_module->{'id_tipo_modulo'}) {
|
||||
module_generic_data ($pa_config, \%part, $timestamp, $agent_name, $tipo_modulo, $dbh);
|
||||
}
|
||||
elsif (4 == $agent_module->{'id_tipo_modulo'}) {
|
||||
module_generic_data_inc ($pa_config, \%part, $timestamp, $agent_name, $tipo_modulo, $dbh);
|
||||
}
|
||||
elsif (3 == $agent_module->{'id_tipo_modulo'}) {
|
||||
module_generic_data_string ($pa_config, \%part, $timestamp, $agent_name, $tipo_modulo, $dbh);
|
||||
}
|
||||
# Generic_proc
|
||||
elsif (2 == $agent_module->{'id_tipo_modulo'}) {
|
||||
module_generic_proc ($pa_config, \%part, $timestamp, $agent_name, $tipo_modulo, $dbh);
|
||||
}
|
||||
elsif ( (19 == $agent_module->{'id_tipo_modulo'}) || (20 == $agent_module->{'id_tipo_modulo'}) ) {
|
||||
module_generic_image ($pa_config, \%part, $timestamp, $agent_name, $tipo_modulo, $dbh);
|
||||
}
|
||||
else { # Unknown module!, this IS a problem
|
||||
logger ($pa_config, "Plugin Server Problem with unknown module type '$tipo_modulo'", 0);
|
||||
}
|
||||
# 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);
|
||||
|
||||
$exec_sql->finish(); #close tagent_plugin hash reference
|
||||
undef $plugin;
|
||||
undef $agent_module;
|
||||
undef %part;
|
||||
}
|
|
@ -1,431 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
##########################################################################
|
||||
# Pandora FMS Prediction Server
|
||||
# http://www.pandorafms.com
|
||||
##########################################################################
|
||||
# Copyright (c) 2008 Sancho Lerena, slerena@gmail.com
|
||||
# (c) 2008 Artica Soluciones Tecnologicas S.L
|
||||
#
|
||||
# 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; version 2.
|
||||
#
|
||||
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
##########################################################################
|
||||
|
||||
# Includes list
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Date::Manip; # Needed to manipulate DateTime formats of input, output and compare
|
||||
use Time::Local; # DateTime basic manipulation
|
||||
use threads;
|
||||
use threads::shared;
|
||||
|
||||
# Pandora Modules
|
||||
use PandoraFMS::Config;
|
||||
use PandoraFMS::Tools;
|
||||
use PandoraFMS::DB;
|
||||
|
||||
# Queue management
|
||||
my @pending_task : shared;
|
||||
my %pending_task_hash : shared;
|
||||
my %current_task_hash : shared;
|
||||
my $queue_lock : shared;
|
||||
|
||||
|
||||
# FLUSH in each IO (only for debug, very slooow)
|
||||
# ENABLED in DEBUGMODE
|
||||
# DISABLE FOR PRODUCTION
|
||||
$| = 0;
|
||||
|
||||
my %pa_config;
|
||||
|
||||
$SIG{'TERM'} = 'pandora_shutdown';
|
||||
$SIG{'INT'} = 'pandora_shutdown';
|
||||
|
||||
# Inicio del bucle principal de programa
|
||||
pandora_init(\%pa_config, "Pandora FMS Prediction Server");
|
||||
|
||||
# Read config file for Global variables
|
||||
pandora_loadconfig (\%pa_config, 5);
|
||||
|
||||
# Audit server starting
|
||||
pandora_audit (\%pa_config, "Pandora FMS Prediction server starting", "SYSTEM", "System");
|
||||
|
||||
# Daemonize and put in background
|
||||
if ( $pa_config{"daemon"} eq "1" ){
|
||||
if ($pa_config{"quiet"} eq "0"){
|
||||
print " [*] Backgrounding Pandora FMS Prediction Server process.\n\n";
|
||||
}
|
||||
&pandora_daemonize ( \%pa_config);
|
||||
}
|
||||
|
||||
# Launch now all prediction threads
|
||||
# $ax is local thread id for this server
|
||||
for (my $ax=0; $ax < $pa_config{'prediction_threads'}; $ax++){
|
||||
threads->new( \&pandora_prediction_consumer, \%pa_config, $ax);
|
||||
}
|
||||
|
||||
# Launch now the producer thread
|
||||
threads->new( \&pandora_prediction_producer, \%pa_config);
|
||||
|
||||
# Last thread is the main process (this process)
|
||||
if ($pa_config{"quiet"} == 0){
|
||||
print " [*] All threads loaded and running \n";
|
||||
}
|
||||
|
||||
# Start Pandora FMS loggin
|
||||
pandora_startlog (\%pa_config);
|
||||
|
||||
my $dbhost = $pa_config{'dbhost'};
|
||||
my $dbname = $pa_config{'dbname'};
|
||||
my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost:3306",
|
||||
$pa_config{'dbuser'},
|
||||
$pa_config{'dbpass'},
|
||||
{ RaiseError => 1, AutoCommit => 1 });
|
||||
|
||||
# Server keepalive thread running in main thread on a infinite loop
|
||||
while (1) {
|
||||
pandora_serverkeepaliver (\%pa_config, 5, $dbh);
|
||||
threads->yield;
|
||||
sleep ($pa_config{"server_threshold"});
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------------
|
||||
#------------------------------------------------------------------------------------
|
||||
#------------------------------------------------------------------------------------
|
||||
#--------------------- 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);
|
||||
pandora_updateserver (\%pa_config, $pa_config{'servername'}, 0, 5, $dbh);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub pandora_prediction_consumer ($$) {
|
||||
my $pa_config = $_[0];
|
||||
my $thread_id = $_[1];
|
||||
|
||||
if ($pa_config->{"quiet"} == 0){
|
||||
print " [*] Starting up Prediction Consumer Thread # $thread_id \n";
|
||||
}
|
||||
|
||||
my $data_id_agent_module;
|
||||
# Create Database handler
|
||||
my $dbh = DBI->connect("DBI:mysql:$pa_config->{'dbname'}:$pa_config->{'dbhost'}:3306", $pa_config->{'dbuser'}, $pa_config->{'dbpass'}, { RaiseError => 1, AutoCommit => 1 });
|
||||
my $counter =0;
|
||||
|
||||
LOOP: while (1) {
|
||||
if ($counter > 10) {
|
||||
sleep (1);
|
||||
$counter = 0;
|
||||
}
|
||||
|
||||
# Take the first element on the shared queue
|
||||
# Insert this element on the current task hash
|
||||
{
|
||||
lock $queue_lock;
|
||||
if (scalar(@pending_task) == 0){
|
||||
$counter++;
|
||||
next LOOP;
|
||||
}
|
||||
|
||||
$data_id_agent_module = shift(@pending_task);
|
||||
delete($pending_task_hash{$data_id_agent_module});
|
||||
$current_task_hash{$data_id_agent_module}=1;
|
||||
}
|
||||
|
||||
# Executing network task with unmanaged error trapping
|
||||
eval {
|
||||
# Call network execution process
|
||||
# exec_network_module ( $pa_config, $data_id_agent_module, $dbh);
|
||||
exec_prediction_module ($pa_config, $data_id_agent_module, $dbh);
|
||||
};
|
||||
if ($@){
|
||||
logger ($pa_config, "[ERROR] Prediction Task for module $data_id_agent_module causes a system exception", 0);
|
||||
logger ($pa_config, "ERROR Code: $@", 1);
|
||||
}
|
||||
|
||||
# Remove from queue. If catch an error, probably data is
|
||||
# not been processed, but has been freed from task queue
|
||||
{
|
||||
lock $queue_lock;
|
||||
delete($current_task_hash{$data_id_agent_module});
|
||||
}
|
||||
$counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
sub pandora_prediction_producer ($) {
|
||||
my $pa_config = $_[0];
|
||||
|
||||
my $dbh = DBI->connect("DBI:mysql:$pa_config->{'dbname'}:$pa_config->{'dbhost'}:3306", $pa_config->{'dbuser'}, $pa_config->{'dbpass'}, { RaiseError => 1, AutoCommit => 1 });
|
||||
|
||||
my $server_id = $pa_config->{'server_id'};
|
||||
|
||||
# Initialize variables for posterior usage
|
||||
my $query1;
|
||||
my @sql_data1;
|
||||
my $data_id_agente_modulo;
|
||||
my $data_flag;
|
||||
my $exec_sql1;
|
||||
|
||||
while (1) {
|
||||
if ($pa_config->{"pandora_master"} != 1) {
|
||||
# Query for normal server, not MASTER server
|
||||
$query1 = "SELECT
|
||||
tagente_modulo.id_agente_modulo,
|
||||
tagente_modulo.flag
|
||||
FROM
|
||||
tagente, tagente_modulo, tagente_estado
|
||||
WHERE
|
||||
id_prediction_server = $server_id
|
||||
AND
|
||||
tagente_modulo.id_agente = tagente.id_agente
|
||||
AND
|
||||
tagente.disabled = 0
|
||||
AND
|
||||
tagente_modulo.prediction_module != 0
|
||||
AND
|
||||
tagente_modulo.disabled = 0
|
||||
AND
|
||||
tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo
|
||||
AND (
|
||||
tagente_modulo.flag = 1
|
||||
OR
|
||||
(tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP()
|
||||
)
|
||||
ORDER BY
|
||||
last_execution_try ASC ";
|
||||
} else {
|
||||
# Query for MASTER SERVER !
|
||||
$query1 = "SELECT
|
||||
DISTINCT(tagente_modulo.id_agente_modulo), tagente_modulo.flag
|
||||
FROM
|
||||
tagente, tagente_modulo, tagente_estado
|
||||
WHERE
|
||||
( (tagente.id_prediction_server = $server_id) OR
|
||||
(tagente.id_prediction_server = ANY(SELECT id_server FROM tserver WHERE status = 0 AND id_server != $server_id AND prediction_server = 1) )
|
||||
) AND
|
||||
tagente_modulo.id_agente = tagente.id_agente
|
||||
AND
|
||||
tagente.disabled = 0
|
||||
AND
|
||||
tagente_modulo.disabled = 0
|
||||
AND
|
||||
tagente_modulo.prediction_module != 0
|
||||
AND
|
||||
tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo
|
||||
AND
|
||||
(tagente_modulo.flag = 1 OR (tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP())
|
||||
ORDER BY last_execution_try ASC";
|
||||
}
|
||||
$exec_sql1 = $dbh->prepare($query1);
|
||||
$exec_sql1 ->execute;
|
||||
while (@sql_data1 = $exec_sql1->fetchrow_array()) {
|
||||
$data_id_agente_modulo = $sql_data1[0];
|
||||
$data_flag = $sql_data1[1];
|
||||
# Skip modules already queued
|
||||
if ((!defined($pending_task_hash{$data_id_agente_modulo})) &&
|
||||
(!defined($current_task_hash{$data_id_agente_modulo}))) {
|
||||
if ($data_flag == 1){
|
||||
$dbh->do("UPDATE tagente_modulo SET flag = 0 WHERE id_agente_modulo = $data_id_agente_modulo")
|
||||
}
|
||||
# Locking scope, do not remove redundant { }
|
||||
{
|
||||
lock $queue_lock;
|
||||
push (@pending_task, $data_id_agente_modulo);
|
||||
$pending_task_hash {$data_id_agente_modulo}=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#logger ($pa_config, "Items in Network Pending Queue: ".scalar(@pending_task), 5);
|
||||
$exec_sql1->finish();
|
||||
sleep($pa_config->{"server_threshold"});
|
||||
} # Main loop
|
||||
}
|
||||
|
||||
|
||||
##########################################################################
|
||||
# SUB exec_prediction_module (paconfig, id_agente_modulo, dbh )
|
||||
# Execute prediction module task
|
||||
##########################################################################
|
||||
sub exec_prediction_module {
|
||||
my $pa_config = $_[0];
|
||||
my $id_am = $_[1];
|
||||
my $dbh = $_[2];
|
||||
|
||||
# This function internal variables
|
||||
my $i; # Internal counter for loops
|
||||
my $n = 0; # total of real data values
|
||||
|
||||
# Set global variables for this sub
|
||||
my $agent_module; # hash reference for tagente_modulo record
|
||||
my $target_module; # hash reference for targetted tagente_modulo
|
||||
|
||||
# Get a full hash for agent_module record reference ($agent_module)
|
||||
my $query_sql = "SELECT * FROM tagente_modulo WHERE id_agente_modulo = $id_am";
|
||||
my $exec_sql = $dbh->prepare($query_sql);
|
||||
$exec_sql ->execute;
|
||||
$agent_module = $exec_sql->fetchrow_hashref;
|
||||
|
||||
# Get a full hash for target agent_module record reference ($target_module)
|
||||
$query_sql = "SELECT * FROM tagente_modulo WHERE id_agente_modulo = " . $agent_module->{'prediction_module'};
|
||||
$exec_sql = $dbh->prepare($query_sql);
|
||||
$exec_sql ->execute;
|
||||
$target_module = $exec_sql->fetchrow_hashref;
|
||||
# Prediction mode explanation
|
||||
#
|
||||
# 0 is for target type of generic_proc. It compares latest data with current data. Needs to get
|
||||
# data on a "middle" interval, so if interval is 300, get data to compare with 150 before
|
||||
# and 150 in the future. If current data is ABOVE or BELOW average +- typical_deviation
|
||||
# this is a BAD value (0), if not is ok (1) and written in target module as is.
|
||||
# more interval configured for this module, more "margin" has to compare data.
|
||||
#
|
||||
# 1 is for target type of generic_data. It get's data in the future, using the interval given in
|
||||
# module. It gets average from current timestamp to INTERVAL in the future and gets average
|
||||
# value. Typical deviation is not used here.
|
||||
|
||||
my $prediction_mode;
|
||||
if ($agent_module->{'id_tipo_modulo'} == 2){
|
||||
$prediction_mode = 0; # proc
|
||||
} else {
|
||||
$prediction_mode = 1; # data
|
||||
}
|
||||
|
||||
# Initialize another global sub variables.
|
||||
my $agent_name = dame_agente_nombre ($pa_config, $agent_module->{'id_agente'}, $dbh);
|
||||
my $module_data = 0; # 0 data for default
|
||||
|
||||
# Get current timestamp
|
||||
my $timestamp = &UnixDate("today","%Y-%m-%d %H:%M:%S");
|
||||
my $utimestamp = &UnixDate("today","%s");
|
||||
|
||||
# Get different data from each week one month ago (4 values)
|
||||
# $agent_module->{'module_interval'} uses a margin of interval to get average data from the past
|
||||
my @week_data;
|
||||
my @week_utimestamp;
|
||||
|
||||
for ($i=0; $i<4; $i++){
|
||||
$week_utimestamp[$i] = $utimestamp - (84600*7*($i+1));
|
||||
# Adjust for proc prediction
|
||||
if ($prediction_mode == 0) {
|
||||
$week_utimestamp[$i] = $week_utimestamp[$i] - ($agent_module->{'module_interval'} / 2);
|
||||
}
|
||||
}
|
||||
|
||||
# Let's calculate statistical average using past data
|
||||
my $average = 0;
|
||||
my $temp1 = 0;
|
||||
for ($i=0; $i < 4; $i++){
|
||||
my $first_data;
|
||||
my $last_data;
|
||||
my $average_interval;
|
||||
my $sum_data = 0;
|
||||
|
||||
$temp1 = $week_utimestamp[$i] + $agent_module->{'module_interval'};
|
||||
# Get data for week $i in the past
|
||||
$query_sql = 'SELECT AVG(datos) FROM tagente_datos WHERE id_agente_modulo = '. $target_module->{'id_agente_modulo'}. ' AND utimestamp > '.$week_utimestamp[$i].' AND utimestamp < '.$temp1;
|
||||
$average_interval = get_db_free_field ($query_sql, $dbh);
|
||||
|
||||
# Need to get data outside interval because no data.
|
||||
if ($average_interval == 0){
|
||||
$query_sql = 'SELECT datos FROM tagente_datos WHERE id_agente_modulo = '. $target_module->{'id_agente_modulo'}. ' AND utimestamp > '.$week_utimestamp[$i].' LIMIT 1';
|
||||
$last_data = get_db_free_field ($query_sql, $dbh);
|
||||
if ($last_data != 0){
|
||||
$sum_data++;
|
||||
}
|
||||
$query_sql = 'SELECT datos FROM tagente_datos WHERE id_agente_modulo = '. $target_module->{'id_agente_modulo'}. ' AND utimestamp < '.$temp1.' LIMIT 1';
|
||||
$first_data = get_db_free_field ($query_sql, $dbh);
|
||||
if ($first_data != 0){
|
||||
$sum_data++;
|
||||
}
|
||||
$week_data[$i] = (($last_data + $first_data) / $sum_data);
|
||||
} else {
|
||||
$week_data[$i] = $average_interval;
|
||||
}
|
||||
|
||||
# It's possible that one of the week_data[i] values was not valid (NULL)
|
||||
# so recheck it and relay on n=0 for "no data" values set to 0 in result
|
||||
# Calculate total ammount of valida data for each data sample
|
||||
if ( (is_numeric($week_data[$i])) && ($week_data[$i] > 0) ){
|
||||
$n++;
|
||||
# Average SUM
|
||||
$average = $average + $week_data[$i];
|
||||
}
|
||||
}
|
||||
|
||||
# Real average value
|
||||
if ($n > 0){
|
||||
$average = $average / $n;
|
||||
} else {
|
||||
$average = 0;
|
||||
}
|
||||
|
||||
# (PROC) Compare with current data
|
||||
if ($prediction_mode == 0){
|
||||
# Calculate typical deviation
|
||||
my $typical_deviation = 0;
|
||||
for ($i=0; $i< $n; $i++){
|
||||
if ( (is_numeric($week_data[$i])) && ($week_data[$i] > 0) ) {
|
||||
$typical_deviation = $typical_deviation + (($week_data[$i] - $average)**2);
|
||||
}
|
||||
}
|
||||
$typical_deviation = sqrt ($typical_deviation / ($n-1));
|
||||
|
||||
$query_sql = 'SELECT datos FROM tagente_estado WHERE id_agente_modulo = '.$target_module->{'id_agente_modulo'};
|
||||
my $current_value = get_db_free_field ($query_sql, $dbh);
|
||||
if ( ($current_value > ($average - $typical_deviation)) && ($current_value < ($average + $typical_deviation)) ){
|
||||
$module_data = 1; # OK !!
|
||||
} else {
|
||||
$module_data = 0; # Out of predictions
|
||||
}
|
||||
} else {
|
||||
# Prediction based on data
|
||||
$module_data = $average;
|
||||
}
|
||||
|
||||
# Build data for insertion
|
||||
my %part;
|
||||
$part{'name'}[0] = $agent_module->{'nombre'};
|
||||
$part{'description'}[0] = "";
|
||||
$part{'data'}[0] = $module_data;
|
||||
my $tipo_modulo = dame_nombretipomodulo_idagentemodulo ($pa_config, $agent_module->{'id_tipo_modulo'}, $dbh);
|
||||
|
||||
# 1 - generic_data
|
||||
# 2 - generic_proc
|
||||
if (1 == $agent_module->{'id_tipo_modulo'}) {
|
||||
module_generic_data ($pa_config, \%part, $timestamp, $agent_name, $tipo_modulo, $dbh);
|
||||
}
|
||||
elsif (2 == $agent_module->{'id_tipo_modulo'}) {
|
||||
module_generic_proc ($pa_config, \%part, $timestamp, $agent_name, $tipo_modulo, $dbh);
|
||||
}
|
||||
else { # Unknown module!, this IS a problem
|
||||
logger ($pa_config, "[FATAL] Prediction Server Problem with unknown module type '$tipo_modulo'", 0);
|
||||
print "[DEBUG] Executing Prediction UNKONWN MODULE TYPE$@\n";
|
||||
exit;
|
||||
}
|
||||
# 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);
|
||||
}
|
|
@ -1,711 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
##########################################################################
|
||||
# Pandora FMS Recon Server
|
||||
# http://www.pandorafms.com
|
||||
##########################################################################
|
||||
# Copyright (c) 2007-2008 Sancho Lerena, slerena@gmail.com
|
||||
# (c) 2007-2008 Artica Soluciones Tecnologicas S.L
|
||||
#
|
||||
# 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; version 2
|
||||
#
|
||||
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
##########################################################################
|
||||
|
||||
# Includes list
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Date::Manip; # Needed to manipulate DateTime formats
|
||||
# of input, output and compare
|
||||
use Net::Ping;
|
||||
use Time::Local; # DateTime basic manipulation
|
||||
use NetAddr::IP; # To manage IP Addresses
|
||||
|
||||
# Detect if Net:Traceroute::Pureperl is available.
|
||||
# If not, parent detection will be disabled
|
||||
my $traceroute_loaded = 1;
|
||||
# Traceroute needs traceroute command
|
||||
unless ( eval "use Net::Traceroute::PurePerl; 1" ) {
|
||||
$traceroute_loaded = 0;
|
||||
}
|
||||
|
||||
use POSIX; # to use ceil() function
|
||||
use Socket; # to resolve address
|
||||
use threads;
|
||||
use threads::shared;
|
||||
|
||||
# Pandora Modules
|
||||
use PandoraFMS::Config;
|
||||
use PandoraFMS::Tools;
|
||||
use PandoraFMS::DB;
|
||||
# Alarm signal management
|
||||
$SIG{ALRM} = sub { return 0; };
|
||||
|
||||
# Queue management
|
||||
my @pending_task : shared;
|
||||
my %pending_task_hash : shared;
|
||||
my %current_task_hash : shared;
|
||||
my $queue_lock : shared;
|
||||
my $icmp_lock : shared;
|
||||
|
||||
# FLUSH in each IO (only for debug, very slooow)
|
||||
# ENABLED in DEBUGMODE
|
||||
# DISABLE FOR PRODUCTION
|
||||
$| = 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");
|
||||
|
||||
# Read config file for Global variables
|
||||
pandora_loadconfig (\%pa_config, 3);
|
||||
|
||||
# Audit server starting
|
||||
pandora_audit (\%pa_config, "Pandora FMS Recon Daemon starting", "SYSTEM", "System");
|
||||
|
||||
# Check for traceroute
|
||||
|
||||
if ($traceroute_loaded == 0){
|
||||
print " [!] Traceroute has noot been compiled. Parent detection disabled.\n\n";
|
||||
}
|
||||
|
||||
# Check for xprobe2
|
||||
my $xprobe2 = $pa_config{"xprobe2"};
|
||||
|
||||
if (! -e $xprobe2) {
|
||||
print " [E] $xprobe2 not found. Pandora FMS Recon cannot detect OS types without it.\n\n";
|
||||
exit;
|
||||
} else {
|
||||
print " [*] $xprobe2 Detected.\n\n";
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
|
||||
# Daemonize and put in background
|
||||
if ( $pa_config{"daemon"} eq "1" ){
|
||||
if ($pa_config{"quiet"} eq "0"){
|
||||
print " [*] Backgrounding Pandora FMS Recon Server process.\n\n";
|
||||
}
|
||||
&pandora_daemonize ( \%pa_config);
|
||||
}
|
||||
|
||||
# Launch now all plugin threads
|
||||
# $ax is local thread id for this server
|
||||
|
||||
for (my $ax=0; $ax < $pa_config{'recon_threads'}; $ax++){
|
||||
threads->new( \&pandora_recon_consumer, \%pa_config, $ax);
|
||||
}
|
||||
|
||||
# Launch now the producer thread
|
||||
threads->new( \&pandora_recon_producer, \%pa_config);
|
||||
|
||||
sleep(1);
|
||||
|
||||
# Connect ONCE to Database, we cannot pass DBI handler to all subprocess because
|
||||
# cannot share DBI between threads without use method CLONE.
|
||||
|
||||
my $pa_config = \%pa_config;
|
||||
my $dbhost = $pa_config->{'dbhost'};
|
||||
my $dbuser = $pa_config->{'dbuser'};
|
||||
my $dbpass = $pa_config->{'dbpass'};
|
||||
my $dbname = $pa_config->{'dbname'};
|
||||
my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost:3306", $dbuser, $dbpass, { RaiseError => 1, AutoCommit => 1 });
|
||||
|
||||
while ( 1 ){
|
||||
pandora_serverkeepaliver ($pa_config, 3, $dbh);
|
||||
threads->yield;
|
||||
sleep($pa_config->{"server_threshold"});
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------------
|
||||
#------------------------------------------------------------------------------------
|
||||
#------------------------------------------------------------------------------------
|
||||
#--------------------- Main Perl Code below this line-----------------------
|
||||
#------------------------------------------------------------------------------------
|
||||
#------------------------------------------------------------------------------------
|
||||
#------------------------------------------------------------------------------------
|
||||
|
||||
sub pandora_recon_producer ($) {
|
||||
my $pa_config = $_[0];
|
||||
print " [*] Starting up Recon Producer Thread ...\n";
|
||||
|
||||
my $dbh = DBI->connect("DBI:mysql:$pa_config->{'dbname'}:$pa_config->{'dbhost'}:3306", $pa_config->{'dbuser'}, $pa_config->{'dbpass'}, { RaiseError => 1, AutoCommit => 1 });
|
||||
my $server_id = $pa_config->{'server_id'};
|
||||
|
||||
# Initialize variables for posterior usage
|
||||
my $query_sql;
|
||||
my @sql_data1;
|
||||
my $data_id_task;
|
||||
my $exec_sql1;
|
||||
|
||||
while (1) {
|
||||
$query_sql = "SELECT * FROM trecon_task
|
||||
WHERE
|
||||
id_recon_server = $server_id
|
||||
AND (
|
||||
status = 1
|
||||
OR
|
||||
(utimestamp + interval_sweep) < UNIX_TIMESTAMP()
|
||||
)
|
||||
";
|
||||
|
||||
$exec_sql1 = $dbh->prepare($query_sql);
|
||||
$exec_sql1 ->execute;
|
||||
while (@sql_data1 = $exec_sql1->fetchrow_array()) {
|
||||
$data_id_task = $sql_data1[0];
|
||||
|
||||
# Skip modules already queued
|
||||
if ((!defined($pending_task_hash{$data_id_task})) &&
|
||||
(!defined($current_task_hash{$data_id_task}))) {
|
||||
pandora_update_reconstatus ($pa_config, $dbh, $data_id_task, 0);
|
||||
# Locking scope, do not remove redundant { }
|
||||
{
|
||||
lock $queue_lock;
|
||||
push (@pending_task, $data_id_task);
|
||||
$pending_task_hash {$data_id_task}=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
$exec_sql1->finish();
|
||||
threads->yield;
|
||||
sleep($pa_config->{"server_threshold"});
|
||||
} # Main loop
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# SUB pandora_recon_consumer
|
||||
# This module runs each X seconds (server threshold) checking for recon task
|
||||
##########################################################################
|
||||
sub pandora_recon_consumer ($$) {
|
||||
my $pa_config = $_[0];
|
||||
my $thread_id = $_[1];
|
||||
|
||||
if ($pa_config->{"quiet"} == 0){
|
||||
print " [*] Starting up Recon Consumer Thread # $thread_id \n";
|
||||
}
|
||||
|
||||
my $data_id_task;
|
||||
# Create Database handler
|
||||
my $dbh = DBI->connect("DBI:mysql:$pa_config->{'dbname'}:$pa_config->{'dbhost'}:3306", $pa_config->{'dbuser'}, $pa_config->{'dbpass'}, { RaiseError => 1, AutoCommit => 1 });
|
||||
my $counter =0;
|
||||
|
||||
LOOP: while (1) {
|
||||
if ($counter > 10) {
|
||||
threads->yield;
|
||||
sleep($pa_config->{"server_threshold"});
|
||||
$counter = 0;
|
||||
}
|
||||
|
||||
# Take the first element on the shared queue
|
||||
# Insert this element on the current task hash
|
||||
{
|
||||
lock $queue_lock;
|
||||
if (scalar(@pending_task) == 0){
|
||||
$counter++;
|
||||
next LOOP;
|
||||
}
|
||||
|
||||
$data_id_task = shift(@pending_task);
|
||||
delete($pending_task_hash{$data_id_task});
|
||||
$current_task_hash{$data_id_task}=1;
|
||||
}
|
||||
|
||||
# Executing recon task with unmanaged error trapping
|
||||
eval {
|
||||
pandora_recon_exec_task ($pa_config, $data_id_task, $dbh);
|
||||
};
|
||||
if ($@){
|
||||
logger ($pa_config, "[ERROR] Recon Task for Task ID $data_id_task causes a system exception", 0);
|
||||
logger ($pa_config, "ERROR Code: $@", 1);
|
||||
}
|
||||
|
||||
# Remove from queue. If catch an error, probably data is
|
||||
# not been processed, but has been freed from task queue
|
||||
{
|
||||
lock $queue_lock;
|
||||
delete($current_task_hash{$data_id_task});
|
||||
}
|
||||
$counter = 0;
|
||||
threads->yield;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
##########################################################################
|
||||
# SUB pandora_detect_os (paconfig, host)
|
||||
# Detect OS using xprobe2 tool. Return tconfig_os id code.
|
||||
##########################################################################
|
||||
|
||||
sub pandora_detect_os {
|
||||
my $pa_config = $_[0];
|
||||
my $host = $_[1];
|
||||
|
||||
my $xprobe2 = $pa_config->{"xprobe2"};
|
||||
if (! -e $xprobe2){
|
||||
return 10; # other
|
||||
}
|
||||
my $command= "";
|
||||
eval {
|
||||
$command = `$xprobe2 $host 2> /dev/null | grep "Running OS" 2> /dev/null | head -1 2> /dev/null`;
|
||||
};
|
||||
if ($@){
|
||||
return 10;
|
||||
}
|
||||
return pandora_get_os ($command);
|
||||
}
|
||||
|
||||
|
||||
##########################################################################
|
||||
# SUB pandora_exec_task (pa_config, id_task)
|
||||
# Execute task
|
||||
##########################################################################
|
||||
sub pandora_recon_exec_task {
|
||||
my $pa_config = $_[0];
|
||||
my $id_task = $_[1];
|
||||
my $dbh = $_[2];
|
||||
|
||||
my $target_ip; # Real ip to check
|
||||
my @ip2; # temp array for NetAddr::IP
|
||||
my $space; # temp var to store space of ip's for netaddr::ip
|
||||
my $query_sql; # for use in SQL
|
||||
my $exec_sql; # for use in SQL
|
||||
my $sql_data; # for use in SQL
|
||||
|
||||
$query_sql = "SELECT * FROM trecon_task WHERE id_rt = $id_task";
|
||||
$exec_sql = $dbh->prepare($query_sql);
|
||||
$exec_sql ->execute;
|
||||
if ($exec_sql->rows == 0) {
|
||||
# something wrong..
|
||||
return -1;
|
||||
}
|
||||
|
||||
$sql_data = $exec_sql->fetchrow_hashref();
|
||||
my $status = $sql_data->{"status"};
|
||||
my $interval = $sql_data->{"interval"};
|
||||
my $target_network = $sql_data->{"subnet"};
|
||||
my $task_name = $sql_data->{"name"};
|
||||
my $task_ncprofile = $sql_data->{"id_network_profile"};
|
||||
my $task_group = $sql_data->{"id_group"};
|
||||
my $task_create_incident = $sql_data->{"create_incident"};
|
||||
my $task_id_os = $sql_data->{"id_os"};
|
||||
|
||||
my $position = 0;
|
||||
my $list_ip = "";
|
||||
my $list_host = "";
|
||||
my $host_found = 0;
|
||||
my $add_host = 0;
|
||||
my $id_parent = 0;
|
||||
my $id_os = 0;
|
||||
|
||||
my $detected = 0;
|
||||
|
||||
# Asign target dir to netaddr object "space"
|
||||
$space = new NetAddr::IP $target_network;
|
||||
if (!defined($space)){
|
||||
logger ($pa_config, "Bad network $target_network for task $task_name", 2);
|
||||
pandora_update_reconstatus ($pa_config, $dbh, $id_task, -1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
my $total_hosts= $space->num +1 ;
|
||||
# Begin scanning main loop
|
||||
do {
|
||||
@ip2 = split(/\//,$space);
|
||||
$target_ip = $ip2[0];
|
||||
$space++;
|
||||
$position++;
|
||||
|
||||
$add_host = 0;
|
||||
# Is this IP listed for any agent ?
|
||||
if (pandora_check_ip ($pa_config, $dbh, $target_ip) == 0){
|
||||
$detected = 0;
|
||||
# Check first for ICMP for this IP. Sometimes ICMP is blocked so check for other ports as well
|
||||
if ( scan_icmp ($target_ip, $pa_config->{'networktimeout'}) == 1) {
|
||||
$detected = 1;
|
||||
} elsif ( scan_tcp ($target_ip, $pa_config->{'networktimeout'}, 3389) == 1 || scan_tcp ($target_ip, $pa_config->{'networktimeout'}, 5900) == 1) {
|
||||
#Check for Remote Desktop & VNC (Desktop & Server machines)
|
||||
$detected = 1;
|
||||
} elsif ( scan_tcp ($target_ip, $pa_config->{'networktimeout'}, 10000) == 1 || scan_tcp ($target_ip, $pa_config->{'networktimeout'}, 161) == 1) {
|
||||
#Check for management ports 10000 = Webmin, 161 = SNMP (Most embedded devices)
|
||||
$detected = 1;
|
||||
} elsif ( scan_tcp ($target_ip, $pa_config->{'networktimeout'}, 22) == 1 || scan_tcp ($target_ip, $pa_config->{'networktimeout'}, 25) == 1) {
|
||||
#Check for SSH & Mail (Servers and Unix machines)
|
||||
$detected = 1;
|
||||
} elsif ( scan_tcp ($target_ip, $pa_config->{'networktimeout'}, 80) == 1 || scan_tcp ($target_ip, $pa_config->{'networktimeout'}, 3306) == 1) {
|
||||
#Check for WWW & MySQL (Webservers and systems in a DMZ)
|
||||
$detected = 1;
|
||||
}
|
||||
|
||||
if ($detected == 1){
|
||||
$id_os = pandora_detect_os ($pa_config, $target_ip);
|
||||
if ($task_id_os == -1){
|
||||
$add_host = 1;
|
||||
} elsif ($id_os == $task_id_os){
|
||||
$add_host = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($add_host == 1){
|
||||
$host_found ++;
|
||||
my $target_ip_resolved = resolv_ip2name($target_ip);
|
||||
$list_ip = $list_ip . " " . $target_ip;
|
||||
$list_host = $list_host . " " . $target_ip_resolved;
|
||||
$id_parent = pandora_getparent ($pa_config, $target_ip, $dbh);
|
||||
|
||||
# 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);
|
||||
$agent_id = pandora_task_create_agent ($pa_config, $dbh, $target_ip, $target_ip_id, $task_group, $target_ip_resolved, $id_parent, $id_os);
|
||||
pandora_task_create_agentmodules ($pa_config, $dbh, $agent_id, $task_ncprofile, $target_ip);
|
||||
} else {
|
||||
my $target_ip_id = pandora_task_create_address ($pa_config, $dbh, $id_task, $target_ip);
|
||||
$agent_id = pandora_task_create_agent($pa_config, $dbh, $target_ip, $target_ip_id, $task_group, $target_ip_resolved, $id_parent, $id_os);
|
||||
}
|
||||
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, $agent_id, 2, 0, 0, 'recon_host_detected', $dbh);
|
||||
}
|
||||
}
|
||||
|
||||
my $progress = ceil($position / ($total_hosts / 100));
|
||||
pandora_update_reconstatus ($pa_config, $dbh, $id_task, $progress);
|
||||
} while ($space < $space->broadcast); # fin del buclie principal de iteracion de Ips
|
||||
|
||||
# Create incident
|
||||
if (($host_found > 0) && ($task_create_incident == 1)){
|
||||
my $my_timestamp = &UnixDate("today","%Y-%m-%d %H:%M:%S");
|
||||
my $text = "At $my_timestamp a new hosts ($host_found) has been detected by Pandora FMS Recon Server running on [".$pa_config->{'servername'}."_Recon]. This incident has been automatically created following instructions for this recon task [$task_name].\n\n";
|
||||
if ($task_ncprofile > 0){
|
||||
$text = $text."Aditionally, and following instruction for this task, agent(s) has been created, with modules assigned to network component profile [".give_network_component_profile_name ($pa_config, $dbh, $task_ncprofile)."]. Please check this agent as soon as possible to verify it.";
|
||||
}
|
||||
$text = $text . "\n\nThis is the list of IP addresses found: \n\n$list_host ";
|
||||
pandora_create_incident ( $pa_config, $dbh, "[RECON] New hosts detected", $text, 0, 0, "Pandora FMS Recon Server", $task_group);
|
||||
}
|
||||
# Mark RECON TASK as done (-1)
|
||||
pandora_update_reconstatus ($pa_config, $dbh, $id_task, -1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
##############################################################################
|
||||
# pandora_ping_icmp (destination, timeout) - Do a ICMP scan, 1 if alive, 0 if not
|
||||
##############################################################################
|
||||
sub scan_icmp {
|
||||
my $dest = $_[0];
|
||||
my $l_timeout = $_[1];
|
||||
|
||||
# Temp vars.
|
||||
my $result = 0;
|
||||
my $p;
|
||||
|
||||
# Check for valid destination
|
||||
if (!defined($dest)){
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
lock $icmp_lock;
|
||||
$p = Net::Ping->new();
|
||||
}
|
||||
|
||||
if ($p->ping($dest)){
|
||||
$p->close();
|
||||
undef ($p);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
##############################################################################
|
||||
# pandora_ping_icmp (destination, timeout) - Do a ICMP scan, 1 if alive, 0 if not
|
||||
##############################################################################
|
||||
sub scan_tcp {
|
||||
my $dest = $_[0];
|
||||
my $l_timeout = $_[1];
|
||||
my $dest_port = $_[2];
|
||||
|
||||
my $opened = 0;
|
||||
|
||||
eval {
|
||||
alarm $l_timeout;
|
||||
my $handle=IO::Socket::INET->new(
|
||||
Proto=>"tcp",
|
||||
PeerAddr=>$dest,
|
||||
PeerPort=>$dest_port);
|
||||
if ($handle){
|
||||
$opened =1;
|
||||
}
|
||||
alarm 0;
|
||||
};
|
||||
if ($@){
|
||||
return 0;
|
||||
}
|
||||
return $opened;
|
||||
}
|
||||
|
||||
|
||||
##########################################################################
|
||||
# SUB resolv_ip2name (ip_address)
|
||||
# return name (if could resolve) or ip of ipaddress
|
||||
##########################################################################
|
||||
sub resolv_ip2name {
|
||||
my $ip = $_[0];
|
||||
my $addr=inet_aton($ip);
|
||||
if ($addr) {
|
||||
my $name=gethostbyaddr($addr, AF_INET);
|
||||
if ($name) {
|
||||
return $name;
|
||||
} else {
|
||||
return $ip;
|
||||
}
|
||||
} else {
|
||||
return $ip;
|
||||
}
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# SUB pandora_check_ip (pa_config, dbh, ip_address)
|
||||
# Return 1 if this IP exists, 0 if not
|
||||
##########################################################################
|
||||
sub pandora_check_ip {
|
||||
my $pa_config = $_[0];
|
||||
my $dbh = $_[1];
|
||||
my $ip_address = $_[2];
|
||||
|
||||
my $query_sql = "SELECT * FROM taddress WHERE ip = '$ip_address' ";
|
||||
my $exec_sql = $dbh->prepare($query_sql);
|
||||
$exec_sql ->execute;
|
||||
if ($exec_sql->rows != 0) {
|
||||
$exec_sql->finish();
|
||||
return 1;
|
||||
} else {
|
||||
$exec_sql->finish();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
##########################################################################
|
||||
# SUB pandora_get_agent_from_ip (pa_config, dbh, ip_address)
|
||||
# Return Id_agent for agent with IP_Address passed as parameter
|
||||
##########################################################################
|
||||
sub pandora_get_agent_from_ip {
|
||||
my $pa_config = $_[0];
|
||||
my $dbh = $_[1];
|
||||
my $ip_address = $_[2];
|
||||
if ((!defined($ip_address)) || ($ip_address eq "")){
|
||||
return 0;
|
||||
}
|
||||
|
||||
return get_db_free_field ("SELECT id_agent FROM taddress, taddress_agent WHERE taddress_agent.id_a = taddress.id_a AND ip = '$ip_address'", $dbh);
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# SUB pandora_update_reconstatus (pa_config, dbh, id_task, status)
|
||||
# Update recontask status flag
|
||||
##########################################################################
|
||||
sub pandora_update_reconstatus {
|
||||
my $pa_config = $_[0];
|
||||
my $dbh = $_[1];
|
||||
my $id_task = $_[2];
|
||||
my $status = $_[3];
|
||||
|
||||
my $my_utimestamp = &UnixDate("today", "%s");
|
||||
my $query_sql2 = "UPDATE trecon_task SET utimestamp = $my_utimestamp, status = $status WHERE id_rt = $id_task";
|
||||
$dbh->do($query_sql2);
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# SUB pandora_task_create_address (pa_config, dbh, id_task, address)
|
||||
# Add address to table taddress, return ID of created record
|
||||
##########################################################################
|
||||
sub pandora_task_create_address {
|
||||
my $pa_config = $_[0];
|
||||
my $dbh = $_[1];
|
||||
my $id_task = $_[2];
|
||||
my $ip_address = $_[3];
|
||||
my $query_sql2 = "INSERT INTO taddress (ip) VALUES ('$ip_address')";
|
||||
$dbh->do ($query_sql2);
|
||||
my $lastid = $dbh->{'mysql_insertid'};
|
||||
return $lastid;
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# SUB pandora_task_create_agent (pa_config, dbh, target_ip, target_ip_id,
|
||||
# id_group, name, id_parent)
|
||||
# Create agent, and associate address to agent in taddress_agent table.
|
||||
# it returns created id_agent.
|
||||
##########################################################################
|
||||
sub pandora_task_create_agent {
|
||||
my $pa_config = $_[0];
|
||||
my $dbh = $_[1];
|
||||
my $target_ip = $_[2];
|
||||
my $target_ip_id = $_[3];
|
||||
my $id_group = $_[4];
|
||||
my $name = $_[5];
|
||||
my $id_parent = $_[6];
|
||||
my $id_os = $_[7];
|
||||
|
||||
return pandora_create_agent ($pa_config, $dbh, $target_ip, $target_ip_id, $id_group, 0, $name, $id_parent, $id_os);
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# SUB pandora_task_create_agentmodules (pa_config, dbh, agent_id, ncprofile, ipaddress)
|
||||
# Create modules from a network component profile and associated to given agent
|
||||
##########################################################################
|
||||
sub pandora_task_create_agentmodules {
|
||||
my $pa_config = $_[0];
|
||||
my $dbh = $_[1];
|
||||
my $agent_id = $_[2];
|
||||
my $ncprofile_id = $_[3];
|
||||
my $ip_adress = $_[4];
|
||||
my $sql_data;
|
||||
|
||||
|
||||
# Search each network component that belongs to ncprofile_id
|
||||
my $query_sql = "SELECT * FROM tnetwork_profile_component WHERE id_np = $ncprofile_id ";
|
||||
|
||||
my $exec_sql = $dbh->prepare($query_sql);
|
||||
$exec_sql ->execute;
|
||||
while ($sql_data = $exec_sql->fetchrow_hashref()) {
|
||||
my $query_sql2 = "SELECT * FROM tnetwork_component wHERE id_nc = ". $sql_data->{"id_nc"};
|
||||
|
||||
my $exec_sql2 = $dbh->prepare($query_sql2);
|
||||
$exec_sql2 ->execute;
|
||||
if ($exec_sql2->rows != 0) {
|
||||
my $sql_data2 = $exec_sql2->fetchrow_hashref();
|
||||
|
||||
my $name = "";
|
||||
$name = $sql_data2->{"name"};
|
||||
my $description = "";
|
||||
$description = $sql_data2->{"description"};
|
||||
|
||||
my $type = "1";
|
||||
$type = $sql_data2->{"type"};
|
||||
|
||||
my $max = 0;
|
||||
$max = $sql_data2->{"max"};
|
||||
|
||||
my $min = 0;
|
||||
$min = $sql_data2->{"min"};
|
||||
|
||||
my $interval = 300;
|
||||
$interval = $sql_data2->{"module_interval"};
|
||||
|
||||
my $tcp_port = "";
|
||||
$tcp_port = $sql_data2->{"tcp_port"};
|
||||
|
||||
my $tcp_send = "";
|
||||
$tcp_send = $sql_data2->{"tcp_send"};
|
||||
|
||||
my $tcp_rcv = "";
|
||||
$tcp_rcv = $sql_data2->{"tcp_rcv"};
|
||||
|
||||
my $snmp_community = "public";
|
||||
$snmp_community = $sql_data2->{"snmp_community"};
|
||||
|
||||
my $snmp_oid = "";
|
||||
$snmp_oid = $sql_data2->{"snmp_oid"};
|
||||
|
||||
my $id_module_group = 0;
|
||||
$id_module_group = $sql_data2->{"id_module_group"};
|
||||
|
||||
my $id_module = 0;
|
||||
$id_module = $sql_data2->{"id_modulo"};
|
||||
|
||||
my $plugin_user = "";
|
||||
$plugin_user = $dbh->quote($sql_data2->{"plugin_user"});
|
||||
|
||||
my $plugin_pass = "";
|
||||
$plugin_pass = $dbh->quote($sql_data2->{"plugin_pass"});
|
||||
|
||||
my $plugin_parameter = "";
|
||||
$plugin_parameter = $dbh->quote($sql_data2->{"plugin_parameter"});
|
||||
|
||||
my $max_timeout = "30";
|
||||
$max_timeout = $sql_data2->{"max_timeout"};
|
||||
|
||||
my $query_sql3 = "INSERT INTO tagente_modulo (id_agente, id_tipo_modulo, descripcion, nombre, max, min, module_interval, tcp_port, tcp_send, tcp_rcv, snmp_community, snmp_oid, ip_target, id_module_group, flag, disabled, plugin_user, plugin_pass, plugin_parameter, max_timeout, id_modulo ) VALUES ( $agent_id, $type, '$description', '$name', $max, $min, $interval, $tcp_port, '$tcp_send', '$tcp_rcv', '$snmp_community', '$snmp_oid', '$ip_adress', $id_module_group, 1, 0, $plugin_user, $plugin_pass, $plugin_parameter, $max_timeout, $id_module)";
|
||||
|
||||
|
||||
$dbh->do($query_sql3);
|
||||
my $last_id_agente_modulo = $dbh->{'mysql_insertid'};
|
||||
logger($pa_config,"Recon Server: Creating module $name for agent $ip_adress",3);
|
||||
my $query_sql4;
|
||||
$query_sql4 = "INSERT INTO tagente_estado (id_agente_modulo, datos, timestamp, estado, id_agente, last_try, utimestamp, current_interval, running_by) VALUES ($last_id_agente_modulo, '', '0000-00-00 00:00:00', 1, $agent_id, '0000-00-00 00:00:00', 0, $interval, 0)";
|
||||
|
||||
$dbh->do($query_sql4);
|
||||
undef $sql_data2;
|
||||
}
|
||||
$exec_sql2->finish();
|
||||
undef $sql_data;
|
||||
}
|
||||
$exec_sql->finish();
|
||||
}
|
||||
|
||||
sub pandora_getparent ($$){
|
||||
my $pa_config = $_[0];
|
||||
my $destination = $_[1];
|
||||
my $dbh = $_[2];
|
||||
|
||||
# If don't have traceroute available, just skip
|
||||
if ($traceroute_loaded == 0){
|
||||
return 0;
|
||||
}
|
||||
|
||||
my $t = new Net::Traceroute::PurePerl(
|
||||
backend => 'PurePerl',
|
||||
host => $destination,
|
||||
debug => 0,
|
||||
max_ttl => 15,
|
||||
query_timeout => $pa_config->{"networktimeout"},
|
||||
packetlen => 40,
|
||||
protocol => 'udp', # udp or icmp
|
||||
);
|
||||
|
||||
my $success = 0;
|
||||
|
||||
eval {
|
||||
alarm($pa_config->{"networktimeout"});
|
||||
$success = $t->traceroute();
|
||||
alarm(0);
|
||||
};
|
||||
if ($@){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($t->hops > 1){
|
||||
if ($success){
|
||||
my $parent_ip = $t->hop_query_host($t->hops-1,0);
|
||||
return pandora_get_agent_from_ip ($pa_config, $dbh, $parent_ip);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# 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);
|
||||
pandora_updateserver (\%pa_config, $pa_config{'servername'}, 0, 3, $dbh);
|
||||
exit;
|
||||
}
|
|
@ -1,10 +1,9 @@
|
|||
#!/usr/bin/perl
|
||||
##########################################################################
|
||||
# Pandora Data Server
|
||||
# Pandora Server
|
||||
##########################################################################
|
||||
# Copyright (c) 2004-2008 Sancho Lerena, slerena@gmail.com
|
||||
# Copyright (c) 2008 Ramon Novoa, rnovoa@artica.es
|
||||
# Copyright (c) 2005-2008 Artica Soluciones Tecnologicas S.L
|
||||
# Copyright (c) 2009 Ramon Novoa, rnovoa@artica.es
|
||||
# Copyright (c) 2009 Artica Soluciones Tecnologicas S.L
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
|
@ -18,464 +17,102 @@
|
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
##########################################################################
|
||||
|
||||
# Includes list
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use XML::Simple; # Useful XML functions
|
||||
use Digest::MD5; # MD5 generation
|
||||
use Time::Local; # DateTime basic manipulation
|
||||
use DBI; # DB interface with MySQL
|
||||
use Date::Manip; # Needed to manipulate DateTime formats of input, output and compare
|
||||
use File::Copy; # Needed to manipulate files
|
||||
use threads;
|
||||
use threads::shared;
|
||||
|
||||
# Pandora Modules
|
||||
use PandoraFMS::DB;
|
||||
use PandoraFMS::Config;
|
||||
use PandoraFMS::Tools;
|
||||
use PandoraFMS::DB;
|
||||
enterprise_load ();
|
||||
use PandoraFMS::Core;
|
||||
use PandoraFMS::DataServer;
|
||||
use PandoraFMS::NetworkServer;
|
||||
use PandoraFMS::SNMPServer;
|
||||
use PandoraFMS::ReconServer;
|
||||
use PandoraFMS::WMIServer;
|
||||
use PandoraFMS::PluginServer;
|
||||
use PandoraFMS::PredictionServer;
|
||||
|
||||
# Queue management
|
||||
my @pending_task : shared;
|
||||
my %pending_task_hash : shared;
|
||||
my %active_task_hash : shared;
|
||||
my %incomplete_task_hash : shared;
|
||||
my $queue_lock : shared;
|
||||
# Load enterprise module
|
||||
enterprise_load () && print " [*] Pandora FMS Enterprise module loaded.\n";
|
||||
|
||||
# FLUSH in each IO, only for DEBUG, very slow !
|
||||
$| = 0;
|
||||
# Global vars
|
||||
my %Config;
|
||||
my @Servers;
|
||||
my $DBH;
|
||||
|
||||
my %pa_config;
|
||||
########################################################################################
|
||||
# Server shutdown
|
||||
########################################################################################
|
||||
sub pandora_shutdown () {
|
||||
logger (\%Config, 'Pandora FMS Server \'' . $Config{'servername'} . '\' Shutdown by signal ', 0);
|
||||
|
||||
# Stop servers
|
||||
foreach my $server (@Servers) {
|
||||
$server->stop ();
|
||||
}
|
||||
|
||||
print_message (\%Config, ' [*] Shutting down ' . $Config{'servername'} . "(received signal)...\n", 0);
|
||||
db_disconnect ($DBH);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
$SIG{'TERM'} = 'pandora_shutdown';
|
||||
$SIG{'INT'} = 'pandora_shutdown';
|
||||
|
||||
# Init main loop
|
||||
pandora_init(\%pa_config,"Pandora FMS Data Server");
|
||||
|
||||
# Read config file for Global variables
|
||||
pandora_loadconfig (\%pa_config,0);
|
||||
|
||||
# Audit server starting
|
||||
pandora_audit (\%pa_config, "Pandora FMS Data Server Daemon starting", "SYSTEM", "System");
|
||||
# Initialize
|
||||
pandora_init(\%Config, 'Pandora FMS Server');
|
||||
pandora_load_config (\%Config);
|
||||
|
||||
# Daemonize and put in background
|
||||
if ( $pa_config{"daemon"} eq "1" ){
|
||||
if ($pa_config{"verbosity"} > 0){
|
||||
print " [*] Backgrounding Pandora FMS Data Server process.\n\n";
|
||||
}
|
||||
&pandora_daemonize ( \%pa_config);
|
||||
if ($Config{'daemon'} == 1) {
|
||||
print_message (\%Config, " [*] Backgrounding Pandora FMS Server process.\n\n", 0);
|
||||
pandora_daemonize (\%Config);
|
||||
}
|
||||
|
||||
# Launch all data_consumer threads
|
||||
for (my $ax=0; $ax < $pa_config{"dataserver_threads"}; $ax++){
|
||||
threads->new( \&pandora_data_consumer, \%pa_config, $ax);
|
||||
}
|
||||
# Connect to the DB
|
||||
$DBH = db_connect ('mysql', $Config{'dbname'}, $Config{'dbhost'}, 3306,
|
||||
$Config{'dbuser'}, $Config{'dbpass'});
|
||||
|
||||
# Launch producer thread
|
||||
threads->new( \&pandora_data_producer, \%pa_config);
|
||||
|
||||
if ($pa_config{"verbosity"} > 0){
|
||||
print " [*] All threads loaded and running \n\n";
|
||||
}
|
||||
pandora_audit (\%Config, 'Pandora FMS Server Daemon starting', 'SYSTEM', 'System', $DBH);
|
||||
|
||||
# Start logging
|
||||
pandora_startlog (\%pa_config);
|
||||
pandora_start_log (\%Config);
|
||||
|
||||
my $dbhost = $pa_config{'dbhost'};
|
||||
my $dbname = $pa_config{'dbname'};
|
||||
my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost:3306",
|
||||
$pa_config{'dbuser'},
|
||||
$pa_config{'dbpass'},
|
||||
{ RaiseError => 1, AutoCommit => 1 });
|
||||
# Load servers
|
||||
push (@Servers, new PandoraFMS::DataServer (\%Config, $DBH));
|
||||
push (@Servers, new PandoraFMS::NetworkServer (\%Config, $DBH));
|
||||
push (@Servers, new PandoraFMS::ReconServer (\%Config, $DBH));
|
||||
push (@Servers, new PandoraFMS::SNMPServer (\%Config, $DBH));
|
||||
push (@Servers, new PandoraFMS::WMIServer (\%Config, $DBH));
|
||||
push (@Servers, new PandoraFMS::PluginServer (\%Config, $DBH));
|
||||
push (@Servers, new PandoraFMS::PredictionServer (\%Config, $DBH));
|
||||
enterprise_hook('load_enterprise_servers', [\@Servers, \%Config, $DBH]);
|
||||
|
||||
# Remove disabled servers
|
||||
@Servers = grep { defined ($_) } @Servers;
|
||||
|
||||
# Run
|
||||
foreach my $server (@Servers) {
|
||||
$server->run ();
|
||||
$server->upEvent ();
|
||||
}
|
||||
|
||||
# Main loop
|
||||
while (1) {
|
||||
pandora_serverkeepaliver (\%pa_config, 0, $dbh);
|
||||
# Disabled until we can finish code from editor and update server code
|
||||
pandora_planned_downtime (\%pa_config, $dbh);
|
||||
# Ececute forced alerts
|
||||
pandora_exec_forced_alerts (\%pa_config, $dbh);
|
||||
keep_alive_check (\%pa_config, $dbh);
|
||||
|
||||
# Update server status
|
||||
foreach my $server (@Servers) {
|
||||
exit (1) unless ($server->checkThreads () == 1);
|
||||
$server->update ();
|
||||
}
|
||||
|
||||
eval {
|
||||
pandora_planned_downtime (\%Config, $DBH);
|
||||
pandora_exec_forced_alerts (\%Config, $DBH);
|
||||
pandora_module_keep_alive_nd (\%Config, $DBH);
|
||||
};
|
||||
|
||||
threads->yield;
|
||||
sleep ($pa_config{"server_threshold"});
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# pandora_shutdown ()
|
||||
# Close system
|
||||
########################################################################################
|
||||
sub pandora_shutdown {
|
||||
logger (\%pa_config,"Pandora FMS Server '".$pa_config{'servername'}.$pa_config{"servermode"}."' Shutdown by signal ",0);
|
||||
pandora_updateserver (\%pa_config, $pa_config{'servername'}, 0, 0, $dbh);
|
||||
if ($pa_config{"verbosity"} > 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;
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# pandora_data_producer ()
|
||||
# Queue data files available for processing
|
||||
###############################################################################
|
||||
sub pandora_data_producer {
|
||||
my $pa_config = $_[0];
|
||||
my $file_name;
|
||||
my $file;
|
||||
|
||||
# Main loop
|
||||
while(1) {
|
||||
|
||||
# Read all files in the incoming directory
|
||||
opendir(DIR, $pa_config->{'incomingdir'} )
|
||||
|| die "[FATAL] Cannot open Incoming data directory at " .
|
||||
$pa_config->{'incomingdir'} . ": $!";
|
||||
|
||||
while (defined($file_name = readdir(DIR))){
|
||||
|
||||
# For backward compatibility
|
||||
if ($file_name =~ /^.*\.checksum$/) {
|
||||
unlink("$pa_config->{'incomingdir'}/$file_name");
|
||||
next;
|
||||
}
|
||||
|
||||
# Data files have the extension .data
|
||||
if ($file_name !~ /^.*\.data$/) {
|
||||
next;
|
||||
}
|
||||
|
||||
# Skip already queued/processed files
|
||||
if (defined($pending_task_hash{$file_name}) ||
|
||||
defined($active_task_hash{$file_name})) {
|
||||
next;
|
||||
}
|
||||
|
||||
# Queue data file
|
||||
{
|
||||
lock $queue_lock;
|
||||
push (@pending_task, $file_name);
|
||||
$pending_task_hash {$file_name} = 1;
|
||||
if (! defined($incomplete_task_hash{$file_name})) {
|
||||
$incomplete_task_hash{$file_name} = 0;
|
||||
}
|
||||
}
|
||||
threads->yield;
|
||||
}
|
||||
|
||||
closedir(DIR);
|
||||
threads->yield;
|
||||
sleep $pa_config->{"server_threshold"};
|
||||
}
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# pandora_data_consumer ()
|
||||
# Process data files
|
||||
###############################################################################
|
||||
sub pandora_data_consumer ($$) {
|
||||
my $pa_config = $_[0];
|
||||
my $thread_id = $_[1];
|
||||
my $file_name;
|
||||
my $counter =0;
|
||||
my $file;
|
||||
|
||||
if ($pa_config->{"verbosity"} > 0){
|
||||
print " [*] Starting up Data Consumer Thread # $thread_id \n";
|
||||
}
|
||||
|
||||
# Create database handler
|
||||
my $dbh = DBI->connect("DBI:mysql:" . $pa_config->{'dbname'} . ":" .
|
||||
$pa_config->{'dbhost'} . ":3306",
|
||||
$pa_config->{'dbuser'},$pa_config->{'dbpass'},
|
||||
{ RaiseError => 1, AutoCommit => 1 });
|
||||
|
||||
LOOP: while (1) {
|
||||
|
||||
if ($counter > 10) {
|
||||
$counter = 0;
|
||||
threads->yield;
|
||||
sleep (1);
|
||||
}
|
||||
|
||||
# Check for pending data files
|
||||
{
|
||||
lock $queue_lock;
|
||||
if (scalar(@pending_task) == 0) {
|
||||
$counter++;
|
||||
next LOOP;
|
||||
}
|
||||
|
||||
$file_name = shift(@pending_task);
|
||||
delete($pending_task_hash{$file_name});
|
||||
$active_task_hash{$file_name} = 1;
|
||||
}
|
||||
|
||||
$file = "$pa_config->{'incomingdir'}/$file_name";
|
||||
|
||||
# Check file really exists to avoid race conditions
|
||||
if (! -e "$file") {
|
||||
$counter++;
|
||||
delete($active_task_hash{$file_name});
|
||||
next LOOP;
|
||||
}
|
||||
|
||||
my $data; # Hash to store the XML data file
|
||||
|
||||
# Parse the XML file
|
||||
eval {
|
||||
threads->yield;
|
||||
$data = XMLin($file, forcearray=>'module');
|
||||
};
|
||||
|
||||
# Invalid MXL
|
||||
if ($@) {
|
||||
# Retry 3 times this XML
|
||||
if ($incomplete_task_hash{$file_name} < 3) {
|
||||
{
|
||||
lock $queue_lock;
|
||||
delete($active_task_hash{$file_name});
|
||||
$incomplete_task_hash{$file_name} += 1;
|
||||
}
|
||||
}
|
||||
# Discard
|
||||
else {
|
||||
{
|
||||
logger ($pa_config, "$file_name is a BAD XML. Removing", 3);
|
||||
lock $queue_lock;
|
||||
delete($active_task_hash{$file_name});
|
||||
delete($incomplete_task_hash{$file_name});
|
||||
rename($file, $file . "_BADXML");
|
||||
# Create event
|
||||
pandora_event ($pa_config, "Unable to process XML data file ($file)", 0, 0, 0, 0, 0, 'error', $dbh);
|
||||
}
|
||||
}
|
||||
|
||||
$counter = 0;
|
||||
threads->yield;
|
||||
next LOOP;
|
||||
}
|
||||
|
||||
process_datafile ($pa_config, $data, $dbh);
|
||||
{
|
||||
lock $queue_lock;
|
||||
delete($active_task_hash{$file_name});
|
||||
delete($incomplete_task_hash{$file_name});
|
||||
unlink($file);
|
||||
}
|
||||
threads->yield;
|
||||
$counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
## SUB keep_alive_check ()
|
||||
## Calculate a global keep alive check for agents without data and an alert defined
|
||||
##########################################################################
|
||||
|
||||
sub keep_alive_check {
|
||||
my $pa_config = $_[0];
|
||||
my $dbh = $_[1];
|
||||
|
||||
my $query_idag = "SELECT tagente_modulo.id_agente_modulo,
|
||||
tagente_estado.id_agente,
|
||||
tagente.nombre AS agentname,
|
||||
tagente_modulo.nombre AS modulename
|
||||
FROM tagente_modulo, tagente_estado, tagente
|
||||
WHERE tagente.id_agente = tagente_estado.id_agente
|
||||
AND tagente.disabled = 0
|
||||
AND tagente_modulo.id_tipo_modulo = 100
|
||||
AND tagente_modulo.disabled = 0
|
||||
AND tagente_estado.datos = 1
|
||||
AND tagente_estado.estado = 0
|
||||
AND tagente_modulo.id_agente_modulo = tagente_estado.id_agente_modulo
|
||||
AND ( tagente_estado.utimestamp + (tagente.intervalo * 2) < UNIX_TIMESTAMP()) ";
|
||||
|
||||
my $s_idag = $dbh->prepare($query_idag);
|
||||
$s_idag ->execute;
|
||||
|
||||
my $id_agent_module;
|
||||
my $id_agent;
|
||||
my $agent_name;
|
||||
my $module_name;
|
||||
|
||||
# data needed in loop (we'll reuse it)
|
||||
my $data;
|
||||
if ($s_idag->rows != 0) {
|
||||
while ($data = $s_idag->fetchrow_hashref()) {
|
||||
threads->yield;
|
||||
$id_agent_module = $data->{'id_agente_modulo'};
|
||||
$id_agent = $data->{'id_agente'};
|
||||
$agent_name = $data->{'agentname'};
|
||||
$module_name = $data->{'modulename'};
|
||||
pandora_writestate ($pa_config, $agent_name, "keep_alive", $module_name, 0, $dbh, 1);
|
||||
}
|
||||
}
|
||||
undef $data;
|
||||
$s_idag->finish();
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
## SUB process_datafile (param_1, param_2, param_3)
|
||||
## Process data packet (XML file)
|
||||
##########################################################################
|
||||
## param_1 : pandora_config hash
|
||||
## param_2 : XML Hash structure reference
|
||||
## param_3
|
||||
|
||||
sub process_datafile {
|
||||
my $pa_config = $_[0];
|
||||
my $datos = $_[1];
|
||||
my $dbh = $_[2];
|
||||
my $tipo_modulo;
|
||||
my $agent_name;
|
||||
my $timestamp;
|
||||
my $interval;
|
||||
my $os_version;
|
||||
my $os;
|
||||
my $agent_version;
|
||||
my $id_agente;
|
||||
my $module_name;
|
||||
|
||||
$agent_name = $datos->{'agent_name'};
|
||||
$timestamp = $datos->{'timestamp'};
|
||||
$agent_version = $datos->{'version'};
|
||||
$interval = $datos->{'interval'};
|
||||
$os_version = $datos->{'os_version'};
|
||||
|
||||
# Set default interval if not defined in agent (This is very very odd whatever!).
|
||||
if (!defined($interval)){
|
||||
$interval = 300;
|
||||
}
|
||||
|
||||
# Check for parameteres, not all version agents gives the same parameters !
|
||||
if (length($interval) == 0){
|
||||
$interval = -1; # No update for interval !
|
||||
}
|
||||
|
||||
if ((!defined ($os_version)) || (length($os_version) == 0)){
|
||||
$os_version = "N/A";
|
||||
}
|
||||
|
||||
|
||||
if ((defined $agent_name) && ($agent_name ne "")){
|
||||
$id_agente = dame_agente_id($pa_config,$agent_name,$dbh);
|
||||
|
||||
if ($id_agente == -1){
|
||||
if ($pa_config->{'autocreate'} == 1){
|
||||
$os = pandora_get_os ($datos->{'os'});
|
||||
$id_agente = pandora_create_agent ($pa_config, $dbh, "", 0, $pa_config->{'autocreate_group'}, 0, $datos->{'agent_name'}, 0, $os);
|
||||
# Always create event about this detected IP
|
||||
|
||||
} else {
|
||||
logger($pa_config, "ERROR: There is no agent defined with name $agent_name", 3);
|
||||
}
|
||||
}
|
||||
|
||||
if ($id_agente > 0) {
|
||||
pandora_lastagentcontact ($pa_config, $timestamp, $agent_name, $os_version, $agent_version, $interval, $dbh);
|
||||
update_keepalive_module ($pa_config, $id_agente, $agent_name, $dbh);
|
||||
foreach my $part(@{$datos->{module}}) {
|
||||
$tipo_modulo = $part->{type}->[0];
|
||||
$module_name = $part->{name}->[0];
|
||||
if (defined($module_name)){ # Skip modules without names
|
||||
logger($pa_config, "Processing module Name ( $module_name ) type ( $tipo_modulo ) for agent ( $agent_name )", 5);
|
||||
|
||||
# Data list
|
||||
if (defined $part->{datalist}) {
|
||||
foreach my $datalist (@{$part->{datalist}}) {
|
||||
if (! defined $datalist->{data}) {
|
||||
next;
|
||||
}
|
||||
|
||||
foreach my $data (@{$datalist->{data}}) {
|
||||
if (! defined $data->{value}) {
|
||||
next;
|
||||
}
|
||||
|
||||
$part->{data} = $data->{value};
|
||||
|
||||
# Data has its own timestamp
|
||||
if (defined $data->{timestamp}) {
|
||||
process_module_data($pa_config, $data->{timestamp}->[0], $agent_name, $tipo_modulo, $part, $dbh);
|
||||
}
|
||||
else {
|
||||
process_module_data($pa_config, $timestamp, $agent_name, $tipo_modulo, $part, $dbh);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# Single data
|
||||
else {
|
||||
# Data has its own timestamp
|
||||
if (defined $part->{timestamp}) {
|
||||
$timestamp = $part->{timestamp}->[0];
|
||||
}
|
||||
process_module_data($pa_config, $timestamp, $agent_name, $tipo_modulo, $part, $dbh);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger($pa_config, "ERROR: Received data from an unknown agent", 2);
|
||||
}
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
## SUB process_module_data ()
|
||||
## ($pa_config, $timestamp, $agent_name, $tipo_modulo, $module, $dbh)
|
||||
## Process module data according to the module type.
|
||||
##########################################################################
|
||||
|
||||
sub process_module_data {
|
||||
my $pa_config = $_[0];
|
||||
my $timestamp = $_[1];
|
||||
my $agent_name = $_[2];
|
||||
my $tipo_modulo = $_[3];
|
||||
my $module = $_[4];
|
||||
my $dbh = $_[5];
|
||||
|
||||
if (($tipo_modulo eq 'generic_data') || ($tipo_modulo eq 'async_data')) {
|
||||
module_generic_data ($pa_config, $module, $timestamp, $agent_name, $tipo_modulo, $dbh);
|
||||
}
|
||||
elsif ($tipo_modulo eq 'generic_data_inc') {
|
||||
module_generic_data_inc ($pa_config, $module, $timestamp, $agent_name,"generic_data_inc", $dbh);
|
||||
}
|
||||
elsif (($tipo_modulo eq 'generic_data_string') || ($tipo_modulo eq 'async_string')) {
|
||||
module_generic_data_string ($pa_config, $module, $timestamp, $agent_name,$tipo_modulo, $dbh);
|
||||
}
|
||||
elsif (($tipo_modulo eq 'generic_proc') || ($tipo_modulo eq 'async_proc')) {
|
||||
module_generic_proc ($pa_config, $module, $timestamp, $agent_name, $tipo_modulo, $dbh);
|
||||
}
|
||||
else {
|
||||
logger($pa_config, "ERROR: Received data from an unknown module ($tipo_modulo)", 2);
|
||||
}
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
## SUB pandora_exec_forced_alerts ($pa_config, $dbh)
|
||||
## Execute forced alerts.
|
||||
##########################################################################
|
||||
|
||||
sub pandora_exec_forced_alerts {
|
||||
my $pa_config = $_[0];
|
||||
my $dbh = $_[1];
|
||||
|
||||
# Get alerts marked for forced execution (even disabled alerts)
|
||||
my @alerts = get_db_all_rows ("SELECT talert_template_modules.id as id_template_module, talert_template_modules.*, talert_templates.*, tagente.*
|
||||
FROM talert_template_modules, talert_templates, tagente, tagente_modulo
|
||||
WHERE talert_template_modules.id_alert_template = talert_templates.id
|
||||
AND talert_template_modules.id_agent_module = tagente_modulo.id_agente_modulo
|
||||
AND tagente_modulo.id_agente = tagente.id_agente
|
||||
AND force_execution = 1", $dbh);
|
||||
|
||||
foreach my $alert (@alerts) {
|
||||
execute_alert ($pa_config, $alert, $alert->{'id_agente'}, $alert->{'id_grupo'}, $alert->{'nombre'},'', 1, 0, $dbh);
|
||||
|
||||
# Reset the force_execution flag, even if the alert could not be executed
|
||||
db_do ("UPDATE talert_template_modules SET force_execution = 0 WHERE id = " . $alert->{'id_template_module'}, $dbh);
|
||||
}
|
||||
sleep ($Config{'server_threshold'});
|
||||
}
|
||||
|
|
|
@ -1,198 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
##########################################################################
|
||||
# Pandora Server. SNMP Console
|
||||
##########################################################################
|
||||
# Copyright (c) 2004-2008 Sancho Lerena, slerena@gmail.com
|
||||
# Copyright (c) 2005-2008 Artica Soluciones Tecnologicas S.L
|
||||
#
|
||||
#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
|
||||
#of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
##########################################################################
|
||||
|
||||
# Includes list
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Date::Manip; # Needed to manipulate DateTime formats of input, output and compare
|
||||
use Time::Local; # DateTime basic manipulation
|
||||
use Time::HiRes; # For high precission timedate functions (Net::Ping)
|
||||
|
||||
# Pandora Modules
|
||||
use PandoraFMS::Config;
|
||||
use PandoraFMS::Tools;
|
||||
use PandoraFMS::DB;
|
||||
enterprise_load ();
|
||||
|
||||
# FLUSH in each IO (only for debug, very slooow)
|
||||
# ENABLED in DEBUGMODE
|
||||
# DISABLE FOR PRODUCTION
|
||||
$| = 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
|
||||
pandora_loadconfig (\%pa_config, 2);
|
||||
|
||||
# Audit server starting
|
||||
pandora_audit (\%pa_config, "Pandora Server SNMP Console Daemon starting", "SYSTEM", "System");
|
||||
|
||||
# Daemonize and put in background
|
||||
if ( $pa_config{"daemon"} eq "1" ){
|
||||
if ($pa_config{"quiet"} eq "0"){
|
||||
print " [*] Backgrounding Pandora FMS SNMP Console process.\n\n";
|
||||
}
|
||||
&pandora_daemonize ( \%pa_config);
|
||||
}
|
||||
|
||||
pandora_snmptrapd (\%pa_config);
|
||||
|
||||
##########################################################################
|
||||
## SUB pandora_snmptrapd
|
||||
## Pandora SNMP Trap console/daemon subsystem
|
||||
##########################################################################
|
||||
|
||||
sub pandora_snmptrapd {
|
||||
my $pa_config = $_[0];
|
||||
my $snmp_logfile = $pa_config->{'snmp_logfile'};
|
||||
my $logfile_size; # Size of logfile, use for calculating index file
|
||||
my @array;
|
||||
my $datos;
|
||||
my $timestamp;
|
||||
my $source;
|
||||
my $oid;
|
||||
my $type;
|
||||
my $type_desc;
|
||||
my $value;
|
||||
my $custom_oid = '';
|
||||
my $custom_type = '';
|
||||
my $custom_value = '';
|
||||
my $sql_insert;
|
||||
my @index_data;
|
||||
|
||||
# open database, only ONCE. We pass reference to DBI handler ($dbh) to all subprocess
|
||||
my $dbh = DBI->connect("DBI:mysql:$pa_config->{'dbname'}:$pa_config->{'dbhost'}:3306",$pa_config->{'dbuser'}, $pa_config->{'dbpass'}, { RaiseError => 1, AutoCommit => 1 });
|
||||
|
||||
while ( ! -e $snmp_logfile) { # Wait until a snmplogfile exists
|
||||
sleep ($pa_config{'server_threshold'});
|
||||
pandora_serverkeepaliver($pa_config,2,$dbh);
|
||||
}
|
||||
|
||||
open (SNMPLOGFILE, $snmp_logfile);
|
||||
print " [*] SNMP Console enabled \n";
|
||||
$index_data[0]=0;
|
||||
$index_data[1]=0;
|
||||
# Check for index file
|
||||
if ( -e $snmp_logfile.".index" ){
|
||||
open SNMPLOGFILE_INDEX, $snmp_logfile.".index";
|
||||
$datos = <SNMPLOGFILE_INDEX>;
|
||||
close SNMPLOGFILE_INDEX;
|
||||
@index_data = split(/\s+/,$datos);
|
||||
# $index_data[0] is the last line readed
|
||||
# $index_data[1] is the size of file (use for calculate new files or reset logfiles
|
||||
}
|
||||
$logfile_size = (stat($snmp_logfile))[7];
|
||||
|
||||
if ($logfile_size < $index_data[1]){ # Log size smaller last time we read it -> new one
|
||||
unlink ($snmp_logfile.".index");
|
||||
$index_data[0]=0;
|
||||
$index_data[1]=0;
|
||||
logger ($pa_config,"New SNMP logfile detected, resetting index",1);
|
||||
}
|
||||
|
||||
if (($index_data[1] <= $logfile_size) && ($index_data[0] > 0)){
|
||||
# Skip already processed records
|
||||
for ($value=0;$value < $index_data[0];$value++){
|
||||
$datos = readline SNMPLOGFILE;
|
||||
}
|
||||
}
|
||||
|
||||
my $trap2agent = enterprise_hook('snmp_get_trap2agent', [$dbh]);
|
||||
|
||||
# Main loop for reading file
|
||||
while ( 1 ){
|
||||
while ($datos = <SNMPLOGFILE>) {
|
||||
$index_data[0]++;
|
||||
$index_data[1]=(stat($snmp_logfile))[7];
|
||||
open SNMPLOGFILE_INDEX, ">".$snmp_logfile.".index";
|
||||
print SNMPLOGFILE_INDEX $index_data[0]," ",$index_data[1];
|
||||
close SNMPLOGFILE_INDEX;
|
||||
|
||||
#print "DEBUG $datos \n";
|
||||
if (($datos !~ m/NET-SNMP/) && ($datos =~ m/\[\*\*\]/)) { # SKIP Headers
|
||||
@array = split(/\[\*\*\]/, $datos);
|
||||
$timestamp = $array[0]." ".$array[1];
|
||||
$source = $array[2];
|
||||
$oid = $array[3];
|
||||
$type = $array[4];
|
||||
$type_desc = $array[5];
|
||||
$value = limpia_cadena($array[6]);
|
||||
if ($type == 6){ # Custom OID type
|
||||
$datos = $array[7];
|
||||
if ($datos !~ m/STRING/) { # No string datatype, marked with " chars
|
||||
$datos =~ m/([0-9\.]*)\s\=\s([A-Za-z0-9]*)\:\s(.+)/;
|
||||
$custom_oid = $1;
|
||||
$custom_type = $2;
|
||||
$custom_value = limpia_cadena($3);
|
||||
} else { # String type
|
||||
if ($datos =~ m/([0-9\.]*)\s\=\s([A-Za-z0-9]*)\:\s\"(.+)\"/){
|
||||
$custom_oid = $1;
|
||||
$custom_type = $2;
|
||||
$custom_value = limpia_cadena($3);
|
||||
}
|
||||
}
|
||||
} else { # not custom OID type, deleting old values in these vars
|
||||
$custom_oid="";
|
||||
$custom_type="";
|
||||
$custom_value=$type_desc; # Bug fixed, 080108 by anonymous
|
||||
}
|
||||
|
||||
if (! defined(enterprise_hook ('snmp_insert_trap', [$pa_config, $source, $oid, $type, $value, $custom_oid, $custom_value, $custom_type, $timestamp, $dbh]))) {
|
||||
$sql_insert = "INSERT INTO ttrap (timestamp, source, oid, type, value, oid_custom, value_custom, type_custom) VALUES ('$timestamp', '$source', '$oid', $type, '$value', '$custom_oid', '$custom_value', '$custom_type')";
|
||||
logger ($pa_config,"Received SNMP Trap from $source", 4);
|
||||
eval {
|
||||
$dbh->do($sql_insert) || logger ($pa_config, "Cannot write to database while updating SNMP Trap data (error in INSERT)",0);
|
||||
# Evaluate TRAP Alerts for this trap
|
||||
calcula_alerta_snmp ($pa_config, $source, $oid, $oid, $custom_value, $timestamp, $dbh);
|
||||
};
|
||||
if ($@) {
|
||||
logger ($pa_config, "[ERROR] Cannot access to database while updating SNMP Trap data",0);
|
||||
logger ($pa_config, "[ERROR] SQL Errorcode: $@", 2);
|
||||
}
|
||||
}
|
||||
enterprise_hook ('snmp_trap2agent', [defined($trap2agent) ? $trap2agent : 0, $pa_config, $source, $oid, $value, $custom_oid, $custom_value, $timestamp, $dbh]);
|
||||
}
|
||||
}
|
||||
sleep ($pa_config{'server_threshold'});
|
||||
pandora_serverkeepaliver($pa_config,2,$dbh);
|
||||
}
|
||||
$dbh->disconnect();
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# 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";
|
||||
my $dbh = DBI->connect("DBI:mysql:$pa_config{'dbname'}:$pa_config{'dbhost'}:3306",$pa_config{'dbuser'}, $pa_config{'dbpass'}, { RaiseError => 1, AutoCommit => 1 });
|
||||
pandora_event (\%pa_config, $pa_config{'servername'}.$pa_config{"servermode"}." going Down", 0,
|
||||
0, 4, 0, 0, "system", $dbh);
|
||||
pandora_updateserver (\%pa_config, $pa_config{'servername'}, 0, 2, $dbh);
|
||||
exit;
|
||||
}
|
|
@ -1,405 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
##########################################################################
|
||||
# Pandora FMS WMI Server
|
||||
# http://www.pandorafms.com
|
||||
##########################################################################
|
||||
# Copyright (c) 2008-2009 Artica Soluciones Tecnologicas S.L
|
||||
#
|
||||
# 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; version 2.
|
||||
#
|
||||
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
##########################################################################
|
||||
|
||||
# Includes list
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Date::Manip; # Needed to manipulate DateTime formats of input, output and compare
|
||||
use Time::Local; # DateTime basic manipulation
|
||||
use threads;
|
||||
use threads::shared;
|
||||
use HTML::Entities;
|
||||
|
||||
# Pandora Modules
|
||||
use PandoraFMS::Config;
|
||||
use PandoraFMS::Tools;
|
||||
use PandoraFMS::DB;
|
||||
# use Win32::OLE qw(in);
|
||||
|
||||
# Queue management
|
||||
my @pending_task : shared;
|
||||
my %pending_task_hash : shared;
|
||||
my %current_task_hash : shared;
|
||||
my $queue_lock : shared;
|
||||
|
||||
# FLUSH in each IO (only for debug, very slooow)
|
||||
# ENABLED in DEBUGMODE
|
||||
# DISABLE FOR PRODUCTION
|
||||
$| = 0;
|
||||
|
||||
my %pa_config;
|
||||
|
||||
$SIG{'TERM'} = 'pandora_shutdown';
|
||||
$SIG{'INT'} = 'pandora_shutdown';
|
||||
|
||||
# Inicio del bucle principal de programa
|
||||
pandora_init(\%pa_config, "Pandora FMS WMI Server");
|
||||
|
||||
# Check for wmic
|
||||
my $wmi_client = "wmic";
|
||||
if (system("$wmi_client > /dev/null 2>&1") != 256) {
|
||||
print " [E] $wmi_client not found. Pandora FMS WMI Server needs a DCOM/WMI client.\n\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
# Read config file for Global variables
|
||||
pandora_loadconfig (\%pa_config, 6);
|
||||
|
||||
# Audit server starting
|
||||
pandora_audit (\%pa_config, "Pandora FMS WMI server starting", "SYSTEM", "System");
|
||||
|
||||
# Daemonize and put in background
|
||||
if ( $pa_config{"daemon"} eq "1" ){
|
||||
if ($pa_config{"quiet"} eq "0"){
|
||||
print " [*] Backgrounding Pandora FMS WMI Server process.\n\n";
|
||||
}
|
||||
&pandora_daemonize ( \%pa_config);
|
||||
}
|
||||
|
||||
# Launch now all WMI server threads
|
||||
for (my $i=0; $i < $pa_config{'wmi_threads'}; $i++){
|
||||
threads->new( \&pandora_wmi_consumer, \%pa_config, $i);
|
||||
}
|
||||
|
||||
# Launch now the producer thread
|
||||
threads->new( \&pandora_wmi_producer, \%pa_config);
|
||||
|
||||
# Last thread is the main process (this process)
|
||||
if ($pa_config{"quiet"} == 0){
|
||||
print " [*] All threads loaded and running \n\n";
|
||||
}
|
||||
|
||||
# Start Pandora FMS loggin
|
||||
pandora_startlog (\%pa_config);
|
||||
|
||||
my $dbhost = $pa_config{'dbhost'};
|
||||
my $dbname = $pa_config{'dbname'};
|
||||
my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost:3306",
|
||||
$pa_config{'dbuser'},
|
||||
$pa_config{'dbpass'},
|
||||
{ RaiseError => 1, AutoCommit => 1 });
|
||||
|
||||
# Server keepalive thread running in main thread on a infinite loop
|
||||
while (1) {
|
||||
pandora_serverkeepaliver (\%pa_config, 6, $dbh);
|
||||
threads->yield;
|
||||
sleep ($pa_config{"server_threshold"});
|
||||
}
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------------
|
||||
#------------------------------------------------------------------------------------
|
||||
#------------------------------------------------------------------------------------
|
||||
#--------------------- 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);
|
||||
pandora_updateserver (\%pa_config, $pa_config{'servername'}, 0, 6, $dbh);
|
||||
exit;
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# SUB pandora_wmi_consumer subsystem
|
||||
# Subsystem to process WMI modules
|
||||
# This module runs each X seconds (server threshold) checking for WMI modules status
|
||||
##########################################################################
|
||||
sub pandora_wmi_consumer ($$) {
|
||||
my $pa_config = $_[0];
|
||||
my $thread_id = $_[1];
|
||||
|
||||
if ($pa_config->{"quiet"} == 0){
|
||||
print " [*] Starting up WMI Consumer Thread # $thread_id \n";
|
||||
}
|
||||
|
||||
my $data_id_agent_module;
|
||||
# Create Database handler
|
||||
my $dbh = DBI->connect("DBI:mysql:$pa_config->{'dbname'}:$pa_config->{'dbhost'}:3306", $pa_config->{'dbuser'}, $pa_config->{'dbpass'}, { RaiseError => 1, AutoCommit => 1 });
|
||||
my $counter =0;
|
||||
|
||||
LOOP: while (1) {
|
||||
if ($counter > 10) {
|
||||
threads->yield;
|
||||
sleep (1);
|
||||
$counter = 0;
|
||||
}
|
||||
|
||||
# Take the first element on the shared queue
|
||||
# Insert this element on the current task hash
|
||||
{
|
||||
lock $queue_lock;
|
||||
if (scalar(@pending_task) == 0){
|
||||
$counter++;
|
||||
next LOOP;
|
||||
}
|
||||
|
||||
$data_id_agent_module = shift(@pending_task);
|
||||
delete($pending_task_hash{$data_id_agent_module});
|
||||
$current_task_hash{$data_id_agent_module}=1;
|
||||
}
|
||||
eval {
|
||||
exec_wmi_module ($pa_config, $data_id_agent_module, $dbh);
|
||||
};
|
||||
if ($@){
|
||||
logger ($pa_config, "[ERROR] WMI Task for module $data_id_agent_module causes a system exception", 0);
|
||||
logger ($pa_config, "ERROR Code: $@", 1);
|
||||
}
|
||||
|
||||
# Remove from queue. If catch an error, probably data is
|
||||
# not been processed, but has been freed from task queue
|
||||
{
|
||||
lock $queue_lock;
|
||||
delete ($current_task_hash {$data_id_agent_module} );
|
||||
}
|
||||
$counter = 0;
|
||||
threads->yield;
|
||||
}
|
||||
}
|
||||
|
||||
sub pandora_wmi_producer ($) {
|
||||
my $pa_config = $_[0];
|
||||
print " [*] Starting up WMI Producer Thread ...\n";
|
||||
|
||||
my $dbh = DBI->connect("DBI:mysql:$pa_config->{'dbname'}:$pa_config->{'dbhost'}:3306", $pa_config->{'dbuser'}, $pa_config->{'dbpass'}, { RaiseError => 1, AutoCommit => 1 });
|
||||
my $server_id = $pa_config->{'server_id'};
|
||||
|
||||
# Initialize variables for posterior usage
|
||||
my $query1;
|
||||
my @sql_data1;
|
||||
my $data_id_agente_modulo;
|
||||
my $data_flag;
|
||||
my $exec_sql1;
|
||||
|
||||
while (1) {
|
||||
if ($pa_config->{"pandora_master"} != 1) {
|
||||
# Query for normal server, not MASTER server
|
||||
$query1 = "SELECT
|
||||
tagente_modulo.id_agente_modulo,
|
||||
tagente_modulo.flag
|
||||
UNIX_TIMESTAMP() - tagente_estado.current_interval - tagente_estado.last_execution_try AS time_left
|
||||
FROM
|
||||
tagente, tagente_modulo, tagente_estado
|
||||
WHERE
|
||||
id_wmi_server = $server_id
|
||||
AND
|
||||
tagente_modulo.id_agente = tagente.id_agente
|
||||
AND
|
||||
tagente.disabled = 0
|
||||
AND
|
||||
tagente_modulo.id_modulo = 6
|
||||
AND
|
||||
tagente_modulo.disabled = 0
|
||||
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
|
||||
tagente_modulo.flag DESC, time_left DESC, last_execution_try ASC ";
|
||||
} else {
|
||||
# Query for MASTER SERVER !
|
||||
$query1 = "SELECT
|
||||
DISTINCT(tagente_modulo.id_agente_modulo), tagente_modulo.flag, UNIX_TIMESTAMP() - tagente_estado.current_interval - tagente_estado.last_execution_try AS time_left
|
||||
FROM
|
||||
tagente, tagente_modulo, tagente_estado, tserver
|
||||
WHERE
|
||||
( (tagente.id_wmi_server = $server_id AND tagente_modulo.id_agente = tagente.id_agente) OR
|
||||
(tagente.id_wmi_server != $server_id AND tagente_modulo.id_agente = tagente.id_agente AND tagente.id_wmi_server = tserver.id_server AND tserver.status = 0)
|
||||
) AND
|
||||
tagente.disabled = 0
|
||||
AND
|
||||
tagente_modulo.disabled = 0
|
||||
AND
|
||||
tagente_modulo.id_modulo = 6
|
||||
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
|
||||
tagente_modulo.flag DESC, time_left DESC, last_execution_try ASC";
|
||||
}
|
||||
$exec_sql1 = $dbh->prepare($query1);
|
||||
$exec_sql1 ->execute;
|
||||
while (@sql_data1 = $exec_sql1->fetchrow_array()) {
|
||||
$data_id_agente_modulo = $sql_data1[0];
|
||||
$data_flag = $sql_data1[1];
|
||||
|
||||
# Skip modules already queued
|
||||
if ((!defined($pending_task_hash{$data_id_agente_modulo})) &&
|
||||
(!defined($current_task_hash{$data_id_agente_modulo}))) {
|
||||
if ($data_flag == 1){
|
||||
$dbh->do("UPDATE tagente_modulo SET flag = 0 WHERE id_agente_modulo = $data_id_agente_modulo")
|
||||
}
|
||||
# Locking scope, do not remove redundant { }
|
||||
{
|
||||
lock $queue_lock;
|
||||
push (@pending_task, $data_id_agente_modulo);
|
||||
$pending_task_hash {$data_id_agente_modulo}=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
$exec_sql1->finish();
|
||||
threads->yield;
|
||||
sleep($pa_config->{"server_threshold"});
|
||||
} # Main loop
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# SUB exec_wmi_module (paconfig, id_agente_modulo, dbh )
|
||||
# Execute WMI module task
|
||||
##########################################################################
|
||||
sub exec_wmi_module {
|
||||
my $pa_config = $_[0];
|
||||
my $id_am = $_[1];
|
||||
my $dbh = $_[2];
|
||||
|
||||
# Set global variables for this sub
|
||||
my $timeout = $pa_config->{'wmi_timeout'};
|
||||
my $agent_module; # hash container for tagente_modulo record
|
||||
|
||||
# Get a full hash for agent_plugin record reference ($agent_module)
|
||||
my $query_sql = "SELECT * FROM tagente_modulo WHERE id_agente_modulo = $id_am";
|
||||
my $exec_sql = $dbh->prepare($query_sql);
|
||||
$exec_sql ->execute;
|
||||
$agent_module = $exec_sql->fetchrow_hashref;
|
||||
|
||||
# Calculate min timeout for this call
|
||||
if ($agent_module->{'max_timeout'} < $timeout){
|
||||
$timeout = $agent_module->{'max_timeout'};
|
||||
}
|
||||
|
||||
# Initialize another global sub variables.
|
||||
my $agent_name = dame_agente_nombre ($pa_config, $agent_module->{'id_agente'}, $dbh);
|
||||
my $module_interval = $agent_module->{'module_interval'};
|
||||
|
||||
# Build execution command to plugin
|
||||
|
||||
my $wmi_query = decode_entities($agent_module->{'snmp_oid'});
|
||||
$wmi_query =~ s/\"/\'/g;
|
||||
|
||||
my $wmi_command = "$wmi_client -U \"". $agent_module->{'plugin_user'} ."\"%\"". $agent_module->{'plugin_pass'} . "\"";
|
||||
|
||||
# Custom namespace
|
||||
if ($agent_module->{'tcp_send'} ne '') {
|
||||
$agent_module->{'tcp_send'} =~ s/\"/\'/g;
|
||||
$wmi_command .= " --namespace=\"" . $agent_module->{'tcp_send'} . "\"";
|
||||
}
|
||||
|
||||
$wmi_command .= " //". $agent_module->{'ip_target'};
|
||||
$wmi_command .= " \"". $wmi_query . "\"";
|
||||
logger ($pa_config, "Executing AM # $id_am WMI command '$wmi_command'", 9);
|
||||
|
||||
my $module_data = `$wmi_command`;
|
||||
if (! defined($module_data)) {
|
||||
update_on_error ($pa_config, $id_am, $dbh);
|
||||
undef $agent_module;
|
||||
return;
|
||||
}
|
||||
|
||||
my @data = split("\n", $module_data);
|
||||
if ($#data < 2) {
|
||||
update_on_error ($pa_config, $id_am, $dbh);
|
||||
undef $agent_module;
|
||||
return;
|
||||
}
|
||||
|
||||
my @data2 = split(/\|/, $data[2]); # get third line (containing data)
|
||||
|
||||
# Take a specific field number from returned data. It uses tcp_port
|
||||
# field from tagente_module table.
|
||||
|
||||
$module_data = $data2[$agent_module -> {'tcp_port'}];
|
||||
|
||||
# Look for errors
|
||||
if ($module_data =~ /ERROR/) {
|
||||
update_on_error ($pa_config, $id_am, $dbh);
|
||||
undef $agent_module;
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Special word to know is something is OK or not,
|
||||
# for example "Running". Defined by user in console. It uses snmp_community
|
||||
# field from tagente_modulo.
|
||||
|
||||
if ($agent_module -> {'snmp_community'} ne ""){
|
||||
my $temp_filter1 = $agent_module -> {'snmp_community'};
|
||||
if ($module_data =~ /$temp_filter1/){
|
||||
$module_data = 1;
|
||||
} else {
|
||||
$module_data = 0;
|
||||
}
|
||||
}
|
||||
|
||||
# Get current timestamp
|
||||
my $timestamp = &UnixDate("today","%Y-%m-%d %H:%M:%S");
|
||||
my $utimestamp = &UnixDate("today","%s");
|
||||
|
||||
# If module execution get a valid value
|
||||
my %part;
|
||||
$part{'name'}[0] = $agent_module->{'nombre'};
|
||||
$part{'description'}[0] = "";
|
||||
$part{'data'}[0] = $module_data;
|
||||
my $tipo_modulo = dame_nombretipomodulo_idagentemodulo ($pa_config, $agent_module->{'id_tipo_modulo'}, $dbh);
|
||||
|
||||
# 1 - generic_data
|
||||
# 2 - generic_proc
|
||||
# 3 - generic_data_string
|
||||
# 4 - generic_data_inc
|
||||
|
||||
if (1 == $agent_module->{'id_tipo_modulo'}) {
|
||||
module_generic_data ($pa_config, \%part, $timestamp, $agent_name, $tipo_modulo, $dbh);
|
||||
}
|
||||
elsif (4 == $agent_module->{'id_tipo_modulo'}) {
|
||||
module_generic_data_inc ($pa_config, \%part, $timestamp, $agent_name, $tipo_modulo, $dbh);
|
||||
}
|
||||
elsif (3 == $agent_module->{'id_tipo_modulo'}) {
|
||||
module_generic_data_string ($pa_config, \%part, $timestamp, $agent_name, $tipo_modulo, $dbh);
|
||||
}
|
||||
# Generic_proc
|
||||
elsif (2 == $agent_module->{'id_tipo_modulo'}) {
|
||||
module_generic_proc ($pa_config, \%part, $timestamp, $agent_name, $tipo_modulo, $dbh);
|
||||
}
|
||||
else { # Unknown module!, this IS a problem
|
||||
logger ($pa_config, "WMI Server Problem with unknown module type '$tipo_modulo'", 0);
|
||||
update_on_error ($pa_config, $id_am, $dbh);
|
||||
undef $agent_module;
|
||||
undef %part;
|
||||
return 0;
|
||||
}
|
||||
# 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);
|
||||
|
||||
$exec_sql->finish(); #close tagent_plugin hash reference
|
||||
undef %part;
|
||||
undef $agent_module;
|
||||
}
|
|
@ -19,10 +19,11 @@ package PandoraFMS::Config;
|
|||
##########################################################################
|
||||
|
||||
use warnings;
|
||||
use POSIX qw(strftime);
|
||||
use Time::Local;
|
||||
use Date::Manip;
|
||||
use PandoraFMS::Tools;
|
||||
use PandoraFMS::DB;
|
||||
use PandoraFMS::Core;
|
||||
require Exporter;
|
||||
|
||||
our @ISA = ("Exporter");
|
||||
|
@ -31,15 +32,13 @@ our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
|
|||
our @EXPORT = qw(
|
||||
pandora_help_screen
|
||||
pandora_init
|
||||
pandora_loadconfig
|
||||
pandora_startlog
|
||||
pandora_load_config
|
||||
pandora_start_log
|
||||
);
|
||||
|
||||
# There is no global vars, all variables (setup) passed as hash reference
|
||||
|
||||
# version: Defines actual version of Pandora Server for this module only
|
||||
my $pandora_version = "3.0-dev";
|
||||
my $pandora_build="PS090305";
|
||||
my $pandora_build = "PS090310";
|
||||
our $VERSION = $pandora_version." ".$pandora_build;
|
||||
|
||||
# Setup hash
|
||||
|
@ -125,11 +124,8 @@ sub pandora_init {
|
|||
# Read external configuration file
|
||||
##########################################################################
|
||||
|
||||
sub pandora_loadconfig {
|
||||
sub pandora_load_config {
|
||||
my $pa_config = $_[0];
|
||||
my $opmode = $_[1]; # 0 dataserver, 1 network server, 2 snmp console
|
||||
# 3 recon srv, 4 plugin srv, 5 prediction srv
|
||||
# 6 WMI server, 7 export server
|
||||
my $archivo_cfg = $pa_config->{'pandora_path'};
|
||||
my $buffer_line;
|
||||
my @command_line;
|
||||
|
@ -162,6 +158,7 @@ sub pandora_loadconfig {
|
|||
$pa_config->{"predictionserver"} = 1; # default
|
||||
$pa_config->{"exportserver"} = 1; # default
|
||||
$pa_config->{"inventoryserver"} = 1; # default
|
||||
$pa_config->{"webserver"} = 1; # 3.0
|
||||
$pa_config->{"servermode"} = "";
|
||||
$pa_config->{'snmp_logfile'} = "/var/log/pandora_snmptrap.log";
|
||||
$pa_config->{"network_threads"} = 3; # Fixed default
|
||||
|
@ -171,18 +168,23 @@ sub pandora_loadconfig {
|
|||
$pa_config->{"alert_recovery"} = 0; # Introduced on 1.3.1
|
||||
$pa_config->{"snmp_checks"} = 1; # Introduced on 1.3.1
|
||||
$pa_config->{"snmp_timeout"} = 8; # Introduced on 1.3.1
|
||||
$pa_config->{"snmp_trapd"} = '/usr/sbin/snmptrapd'; # 3.0
|
||||
$pa_config->{"tcp_checks"} = 1; # Introduced on 1.3.1
|
||||
$pa_config->{"tcp_timeout"} = 20; # Introduced on 1.3.1
|
||||
$pa_config->{"snmp_proc_deadresponse"} = 1; # Introduced on 1.3.1 10 Feb08
|
||||
$pa_config->{"plugin_threads"} = 2; # Introduced on 2.0
|
||||
$pa_config->{"plugin_exec"} = 'pandora_exec'; # 3.0
|
||||
$pa_config->{"recon_threads"} = 2; # Introduced on 2.0
|
||||
$pa_config->{"prediction_threads"} = 1; # Introduced on 2.0
|
||||
$pa_config->{"plugin_timeout"} = 5; # Introduced on 2.0
|
||||
$pa_config->{"wmi_threads"} = 2; # Introduced on 2.0
|
||||
$pa_config->{"wmi_timeout"} = 5; # Introduced on 2.0
|
||||
$pa_config->{"wmi_client"} = 'wmic'; # 3.0
|
||||
$pa_config->{"compound_max_depth"} = 5; # Maximum nested compound alert depth. Not in config file.
|
||||
$pa_config->{"dataserver_threads"} = 2; # Introduced on 2.0
|
||||
$pa_config->{"inventory_threads"} = 2; # 2.1
|
||||
$pa_config->{"export_threads"} = 1; # 3.0
|
||||
$pa_config->{"web_threads"} = 1; # 3.0
|
||||
|
||||
# Internal MTA for alerts, each server need its own config.
|
||||
$pa_config->{"mta_address"} = '127.0.0.1'; # Introduced on 2.0
|
||||
|
@ -345,6 +347,12 @@ sub pandora_loadconfig {
|
|||
elsif ($parametro =~ m/^exportserver\s([0-9]*)/i) {
|
||||
$pa_config->{'exportserver'}= clean_blank($1);
|
||||
}
|
||||
elsif ($parametro =~ m/^inventoryserver\s([0-9]*)/i) {
|
||||
$pa_config->{'inventoryserver'}= clean_blank($1);
|
||||
}
|
||||
elsif ($parametro =~ m/^webserver\s([0-9]*)/i) {
|
||||
$pa_config->{'webserver'}= clean_blank($1);
|
||||
}
|
||||
elsif ($parametro =~ m/^servername\s(.*)/i) {
|
||||
$pa_config->{'servername'}= clean_blank($1);
|
||||
}
|
||||
|
@ -439,6 +447,27 @@ sub pandora_loadconfig {
|
|||
elsif ($parametro =~ m/^mcast_change_port\s([0-9]*)/i) {
|
||||
$pa_config->{'mcast_change_port'}= clean_blank($1);
|
||||
}
|
||||
elsif ($parametro =~ m/^wmi_threads\s([0-9]*)/i) {
|
||||
$pa_config->{'wmi_threads'}= clean_blank($1);
|
||||
}
|
||||
elsif ($parametro =~ m/^wmi_client\s(.*)/i) {
|
||||
$pa_config->{'wmi_client'}= clean_blank($1);
|
||||
}
|
||||
elsif ($parametro =~ m/^web_threads\s([0-9]*)/i) {
|
||||
$pa_config->{'web_threads'}= clean_blank($1);
|
||||
}
|
||||
elsif ($parametro =~ m/^snmp_trapd\s(.*)/i) {
|
||||
$pa_config->{'snmp_trapd'}= clean_blank($1);
|
||||
}
|
||||
elsif ($parametro =~ m/^plugin_exec\s(.*)/i) {
|
||||
$pa_config->{'plugin_exec'}= clean_blank($1);
|
||||
}
|
||||
elsif ($parametro =~ m/^inventory_threads\s([0-9]*)/i) {
|
||||
$pa_config->{'inventory_threads'}= clean_blank($1);
|
||||
}
|
||||
elsif ($parametro =~ m/^export_threads\s([0-9]*)/i) {
|
||||
$pa_config->{'export_threads'}= clean_blank($1);
|
||||
}
|
||||
} # end of loop for parameter #
|
||||
|
||||
|
||||
|
@ -458,103 +487,7 @@ sub pandora_loadconfig {
|
|||
print " [ERROR] Bad Config values. Be sure that $archivo_cfg is a valid setup file. \n\n";
|
||||
exit;
|
||||
}
|
||||
if (($opmode ==0) && ($pa_config->{"dataserver"} ne 1)) {
|
||||
print " [ERROR] You must enable 'dataserver' in setup file to run Pandora FMS Data Server. \n\n";
|
||||
exit;
|
||||
}
|
||||
if (($opmode ==1) && ($pa_config->{"networkserver"} ne 1)) {
|
||||
print " [ERROR] You must enable 'networkserver' in setup file to run Pandora FMS Network Server. \n\n";
|
||||
exit;
|
||||
}
|
||||
if (($opmode ==2) && ($pa_config->{"snmpconsole"} ne 1)) {
|
||||
print " [ERROR] You must enable 'snmpconsole' in setup file to run Pandora FMS SNMP Console. \n\n";
|
||||
exit;
|
||||
}
|
||||
if (($opmode ==3) && ($pa_config->{"reconserver"} ne 1)) {
|
||||
print " [ERROR] You must enable 'reconserver' in setup file to run Pandora FMS Recon server. \n\n";
|
||||
exit;
|
||||
}
|
||||
if (($opmode ==4) && ($pa_config->{"pluginserver"} ne 1)) {
|
||||
print " [ERROR] You must enable 'pluginserver' in setup file to run Pandora FMS Plugin server. \n\n";
|
||||
exit;
|
||||
}
|
||||
if (($opmode ==5) && ($pa_config->{"predictionserver"} ne 1)) {
|
||||
print " [ERROR] You must enable 'predictionserver' in setup file to run Pandora FMS Prediction server. \n\n";
|
||||
exit;
|
||||
}
|
||||
if (($opmode ==6) && ($pa_config->{"wmiserver"} ne 1)) {
|
||||
print " [ERROR] You must enable 'wmiserver' in setup file to run Pandora FMS WMI server. \n\n";
|
||||
exit;
|
||||
}
|
||||
if (($opmode ==7) && ($pa_config->{"exportserver"} ne 1)) {
|
||||
print " [ERROR] You must enable 'exportserver' in setup file to run Pandora FMS Export server. \n\n";
|
||||
exit;
|
||||
}
|
||||
# Show some config options in startup
|
||||
|
||||
if ($opmode == 0){
|
||||
if (($pa_config->{"quiet"} == 0) && ($pa_config->{"verbosity"} > 4)) {
|
||||
print " [*] You are running Pandora FMS Data Server. \n";
|
||||
}
|
||||
$parametro ="Pandora FMS Data Server";
|
||||
$pa_config->{"servermode"}="_Data";
|
||||
}
|
||||
if ($opmode == 1){
|
||||
if (($pa_config->{"quiet"} == 0) && ($pa_config->{"verbosity"} > 4)) {
|
||||
print " [*] You are running Pandora FMS Network Server. \n";
|
||||
}
|
||||
$parametro ="Pandora FMS Network Server";
|
||||
$pa_config->{"servermode"}="_Net";
|
||||
}
|
||||
if ($opmode == 2){
|
||||
if (($pa_config->{"quiet"} == 0) && ($pa_config->{"verbosity"} > 4)) {
|
||||
print " [*] You are running Pandora FMS SNMP Console. \n";
|
||||
}
|
||||
$parametro ="Pandora FMS SNMP Console";
|
||||
$pa_config->{"servermode"}="_SNMP";
|
||||
}
|
||||
if ($opmode == 3){
|
||||
if (($pa_config->{"quiet"} == 0) && ($pa_config->{"verbosity"} > 4)) {
|
||||
print " [*] You are running Pandora FMS Recon Server. \n";
|
||||
}
|
||||
$parametro ="Pandora FMS Recon Server";
|
||||
$pa_config->{"servermode"}="_Recon";
|
||||
}
|
||||
if ($opmode == 4){
|
||||
if (($pa_config->{"quiet"} == 0) && ($pa_config->{"verbosity"} > 4)) {
|
||||
print " [*] You are running Pandora FMS Plugin Server. \n";
|
||||
}
|
||||
$parametro ="Pandora FMS Plugin Server";
|
||||
$pa_config->{"servermode"}="_Plugin";
|
||||
}
|
||||
if ($opmode == 5){
|
||||
if (($pa_config->{"quiet"} == 0) && ($pa_config->{"verbosity"} > 4)) {
|
||||
print " [*] You are running Pandora FMS Prediction Server. \n";
|
||||
}
|
||||
$parametro ="Pandora FMS Prediction Server";
|
||||
$pa_config->{"servermode"}="_Prediction";
|
||||
}
|
||||
if ($opmode == 6){
|
||||
if (($pa_config->{"quiet"} == 0) && ($pa_config->{"verbosity"} > 4)) {
|
||||
print " [*] You are running Pandora FMS WMI Server. \n";
|
||||
}
|
||||
$parametro ="Pandora FMS WMI Server";
|
||||
$pa_config->{"servermode"}="_WMI";
|
||||
}
|
||||
if ($opmode == 7){
|
||||
if (($pa_config->{"quiet"} == 0) && ($pa_config->{"verbosity"} > 4)) {
|
||||
print " [*] You are running Pandora FMS Export Server. \n";
|
||||
}
|
||||
$parametro ="Pandora FMS Export Server";
|
||||
$pa_config->{"servermode"}="_Export";
|
||||
}
|
||||
if ($opmode == 8){
|
||||
if (($pa_config->{"quiet"} == 0) && ($pa_config->{"verbosity"} > 4)) {
|
||||
print " [*] You are running Pandora FMS Inventory Server. \n";
|
||||
}
|
||||
$parametro ="Pandora FMS Inventory Server";
|
||||
$pa_config->{"servermode"}="_Inventory";
|
||||
}
|
||||
if (($pa_config->{"quiet"} == 0) && ($pa_config->{"verbosity"} > 4)) {
|
||||
if ($pa_config->{"pandora_check"} == 1) {
|
||||
print " [*] MD5 Security enabled.\n";
|
||||
|
@ -567,34 +500,17 @@ sub pandora_loadconfig {
|
|||
logger ($pa_config, "Launching $pa_config->{'version'} $pa_config->{'build'}", 0);
|
||||
my $config_options = "Logfile at ".$pa_config->{"logfile"}.", Basepath is ".$pa_config->{"basepath"}.", Checksum is ".$pa_config->{"pandora_check"}.", Master is ".$pa_config->{"pandora_master"}.", SNMP Console is ".$pa_config->{"snmpconsole"}.", Server Threshold at ".$pa_config->{"server_threshold"}." sec, verbosity at ".$pa_config->{"verbosity"}.", Alert Threshold at $pa_config->{'alert_threshold'}, ServerName is '".$pa_config->{'servername'}.$pa_config->{"servermode"}."'";
|
||||
logger ($pa_config, "Config options: $config_options", 1);
|
||||
my $dbh;
|
||||
# Check valid Database variables and update server status
|
||||
eval {
|
||||
$dbh = DBI->connect("DBI:mysql:$pa_config->{'dbname'}:$pa_config->{'dbhost'}:3306", $pa_config->{'dbuser'}, $pa_config->{'dbpass'}, { RaiseError => 1, AutoCommit => 1 });
|
||||
pandora_updateserver ($pa_config, $pa_config->{'servername'}, 1, $opmode, $dbh); # Alive status
|
||||
};
|
||||
if ($@) {
|
||||
logger ($pa_config, "Error connecting database in init Phase. Aborting startup.",0);
|
||||
print (" [ERROR] Error connecting database in init Phase. Aborting startup. \n\n");
|
||||
print $@;
|
||||
exit;
|
||||
}
|
||||
if (($pa_config->{"quiet"} == 0) && ($pa_config->{"verbosity"} > 4)) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
sub pandora_startlog ($){
|
||||
my $pa_config = $_[0];
|
||||
sub pandora_start_log ($){
|
||||
my $pa_config = shift;
|
||||
|
||||
# Dump all errors to errorlog
|
||||
open STDERR, ">>$pa_config->{'errorlogfile'}" or die " [ERROR] Pandora FMS can't write to Errorlog. Aborting : \n $! \n";
|
||||
my $time_now = &UnixDate("today","%Y/%m/%d %H:%M:%S");
|
||||
print STDERR "$time_now - ".$pa_config->{'servername'}.$pa_config->{"servermode"}." Starting Pandora FMS Server. Error logging activated \n";
|
||||
open (STDERR, ">> " . $pa_config->{'errorlogfile'}) or die " [ERROR] Pandora FMS can't write to Errorlog. Aborting : \n $! \n";
|
||||
print STDERR strftime ("%Y-%m-%d %H:%M:%S", localtime()) . ' - ' . $pa_config->{'servername'} . $pa_config->{'servermode'} . " Starting Pandora FMS Server. Error logging activated \n";
|
||||
}
|
||||
|
||||
# End of function declaration
|
||||
# End of defined Code
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,246 @@
|
|||
package PandoraFMS::DataServer;
|
||||
##########################################################################
|
||||
# Pandora FMS Data Server.
|
||||
# Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org
|
||||
##########################################################################
|
||||
# Copyright (c) 2009 Ramon Novoa, rnovoa@artica.es
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public License
|
||||
# as published by the Free Software Foundation; version 2
|
||||
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
##########################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use threads;
|
||||
use threads::shared;
|
||||
use Thread::Semaphore;
|
||||
|
||||
use Time::Local;
|
||||
use XML::Simple;
|
||||
|
||||
use PandoraFMS::Tools;
|
||||
use PandoraFMS::DB;
|
||||
use PandoraFMS::Core;
|
||||
use PandoraFMS::ProducerConsumerServer;
|
||||
|
||||
# Inherits from PandoraFMS::ProducerConsumerServer
|
||||
our @ISA = qw(PandoraFMS::ProducerConsumerServer);
|
||||
|
||||
# Global variables
|
||||
my @TaskQueue :shared;
|
||||
my %PendingTasks :shared;
|
||||
my $Sem :shared = Thread::Semaphore->new;
|
||||
my $TaskSem :shared = Thread::Semaphore->new (0);
|
||||
|
||||
########################################################################################
|
||||
# Data Server class constructor.
|
||||
########################################################################################
|
||||
sub new ($$;$) {
|
||||
my ($class, $config, $dbh) = @_;
|
||||
|
||||
return undef unless $config->{'dataserver'} == 1;
|
||||
|
||||
# Call the constructor of the parent class
|
||||
my $self = $class->SUPER::new($config, 0, \&PandoraFMS::DataServer::data_producer, \&PandoraFMS::DataServer::data_consumer, $dbh);
|
||||
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Run.
|
||||
###############################################################################
|
||||
sub run ($) {
|
||||
my $self = shift;
|
||||
my $pa_config = $self->getConfig ();
|
||||
|
||||
print " [*] Starting Pandora FMS Data Server. \n";
|
||||
$self->setNumThreads ($pa_config->{'dataserver_threads'});
|
||||
$self->SUPER::run (\@TaskQueue, \%PendingTasks, $Sem, $TaskSem);
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Data producer.
|
||||
###############################################################################
|
||||
sub data_producer ($) {
|
||||
my $self = shift;
|
||||
my $pa_config = $self->getConfig ();
|
||||
|
||||
my @tasks;
|
||||
|
||||
# Read all files in the incoming directory
|
||||
opendir (DIR, $pa_config->{'incomingdir'})
|
||||
|| die "[FATAL] Cannot open Incoming data directory at " . $pa_config->{'incomingdir'} . ": $!";
|
||||
|
||||
while (defined (my $file_name = readdir(DIR))) {
|
||||
|
||||
# For backward compatibility
|
||||
if ($file_name =~ /^.*\.checksum$/) {
|
||||
unlink("$pa_config->{'incomingdir'}/$file_name");
|
||||
next;
|
||||
}
|
||||
|
||||
# Data files have the extension .data
|
||||
next if ($file_name !~ /^.*\.data$/);
|
||||
|
||||
push (@tasks, $file_name);
|
||||
}
|
||||
|
||||
closedir(DIR);
|
||||
return @tasks;
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Data consumer.
|
||||
###############################################################################
|
||||
sub data_consumer ($$) {
|
||||
my ($self, $task) = @_;
|
||||
my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ());
|
||||
|
||||
my $file_name = $pa_config->{'incomingdir'};
|
||||
|
||||
# Fix path
|
||||
$file_name .= "/" unless (substr ($file_name, -1, 1) eq '/');
|
||||
$file_name .= $task;
|
||||
|
||||
# Try to parse the XML 3 times
|
||||
my $xml_data;
|
||||
|
||||
for (1..3) {
|
||||
eval {
|
||||
threads->yield;
|
||||
$xml_data = XMLin ($file_name, forcearray => 'module');
|
||||
};
|
||||
|
||||
# Invalid XML
|
||||
if ($@) {
|
||||
print "$@\n";
|
||||
sleep (60);
|
||||
next;
|
||||
}
|
||||
|
||||
unlink ($file_name);
|
||||
process_xml_data ($self->getConfig (), $xml_data, $self->getDBH ());
|
||||
return;
|
||||
}
|
||||
|
||||
rename($file_name, $file_name . '_BADXML');
|
||||
pandora_event ($pa_config, "Unable to process XML data file ($file_name)", 0, 0, 0, 0, 0, 'error', $dbh);
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Process XML data coming from an agent.
|
||||
###############################################################################
|
||||
sub process_xml_data {
|
||||
my ($pa_config, $data, $dbh) = @_;
|
||||
|
||||
my ($agent_name, $agent_version, $timestamp, $interval, $os_version) =
|
||||
($data->{'agent_name'}, $data->{'version'}, $data->{'timestamp'},
|
||||
$data->{'interval'}, $data->{'os_version'});
|
||||
|
||||
# Unknown agent!
|
||||
if (! defined ($agent_name) || $agent_name eq '') {
|
||||
logger($pa_config, 'ERROR: Received data from an unknown agent', 2);
|
||||
return;
|
||||
}
|
||||
|
||||
# Check some variables
|
||||
$interval = 300 unless defined ($interval);
|
||||
$os_version = 'N/A' if (! defined ($os_version) || $os_version eq '');
|
||||
|
||||
# Get agent id
|
||||
my $agent_id = get_agent_id ($dbh, $agent_name);
|
||||
if ($agent_id < 1) {
|
||||
if ($pa_config->{'autocreate'} == 0) {
|
||||
logger($pa_config, "ERROR: There is no agent defined with name $agent_name", 3);
|
||||
return;
|
||||
}
|
||||
|
||||
# Create the agent
|
||||
my $os = pandora_get_os ($data->{'os'});
|
||||
$agent_id = pandora_create_agent ($pa_config, $pa_config->{'servername'}, $agent_name, '', 0, $pa_config->{'autocreate_group'}, 0, 0, $os, $dbh);
|
||||
return unless defined ($agent_id);
|
||||
}
|
||||
|
||||
pandora_update_agent ($pa_config, $timestamp, $agent_id, $os_version, $agent_version, $interval, $dbh);
|
||||
pandora_module_keep_alive ($pa_config, $agent_id, $agent_name, $dbh);
|
||||
|
||||
# Process modules
|
||||
foreach my $module_data (@{$data->{'module'}}) {
|
||||
|
||||
# Unnamed module
|
||||
next unless (defined ($module_data->{'name'}->[0]));
|
||||
|
||||
my $module_type = $module_data->{'type'}->[0];
|
||||
my $module_name = $module_data->{'name'}->[0];
|
||||
|
||||
# Single data
|
||||
if (! defined ($module_data->{'datalist'})) {
|
||||
my $data_timestamp = (defined ($module_data->{'timestamp'})) ? $module_data->{'timestamp'}->[0] : $timestamp;
|
||||
process_module_data ($pa_config, $module_data, $agent_name, $module_name, $module_type, $data_timestamp, $dbh);
|
||||
next;
|
||||
}
|
||||
|
||||
# Data list
|
||||
foreach my $list (@{$module_data->{'datalist'}}) {
|
||||
|
||||
# Empty list
|
||||
next unless defined ($list->{'data'});
|
||||
|
||||
foreach my $data (@{$list->{'data'}}) {
|
||||
|
||||
# No value
|
||||
next unless defined ($data->{'value'});
|
||||
|
||||
$module_data->{'data'} = $data->{'value'};
|
||||
my $data_timestamp = (defined ($data->{'timestamp'})) ? $data->{'timestamp'} : $timestamp;
|
||||
process_module_data ($pa_config, $module_data, $agent_name, $module_name,
|
||||
$module_type, $data_timestamp, $dbh);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# Process module data, creating module if necessary.
|
||||
##########################################################################
|
||||
sub process_module_data ($$$$$$$) {
|
||||
my ($pa_config, $data, $agent_name, $module_name, $module_type, $timestamp, $dbh) = @_;
|
||||
|
||||
my $agent = get_db_single_row ($dbh, 'SELECT * FROM tagente WHERE nombre = ?', $agent_name);
|
||||
return unless defined ($agent);
|
||||
|
||||
my $module = get_db_single_row ($dbh, 'SELECT * FROM tagente_modulo WHERE id_agente = ? AND nombre = ?', $agent->{'id_agente'}, $module_name);
|
||||
if (! defined ($module)) {
|
||||
my $module_id = get_module_id ($dbh, $module_type);
|
||||
return if ($module_id == -1 && $pa_config->{'autocreate'} == 0);
|
||||
|
||||
my ($min, $max, $description) = (0, 0, '');
|
||||
$max = $data->{'max'}->[0] if (defined ($data->{'max'}));
|
||||
$min = $data->{'min'}->[0] if (defined ($data->{'min'}));
|
||||
$description = $data->{'description'}->[0] if (defined ($data->{'description'}));
|
||||
pandora_create_module ($agent->{'id_agente'}, $module_id, $module_name,
|
||||
$max, $min, $description, $dbh);
|
||||
$module = get_db_single_row ($dbh, 'SELECT * FROM tagente_modulo WHERE id_agente = ? AND nombre = ?', $agent->{'id_agente'}, $module_name);
|
||||
return unless defined $module;
|
||||
}
|
||||
|
||||
if ($timestamp =~ /(\d+)\/(\d+)\/(\d+) +(\d+):(\d+):(\d+)/ ||
|
||||
$timestamp =~ /(\d+)\-(\d+)\-(\d+) +(\d+):(\d+):(\d+)/) {
|
||||
my $utimestamp = timelocal($6, $5, $4, $3, $2 - 1, $1 - 1900);
|
||||
pandora_process_module ($pa_config, $data->{'data'}->[0], $agent, $module, $module_type, $timestamp, $utimestamp, $dbh);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
__END__
|
|
@ -0,0 +1,476 @@
|
|||
package PandoraFMS::NetworkServer;
|
||||
##########################################################################
|
||||
# Pandora FMS Network Server.
|
||||
# Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org
|
||||
##########################################################################
|
||||
# Copyright (c) 2009 Ramon Novoa, rnovoa@artica.es
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public License
|
||||
# as published by the Free Software Foundation; version 2
|
||||
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
##########################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use threads;
|
||||
use threads::shared;
|
||||
use Thread::Semaphore;
|
||||
|
||||
use IO::Socket::INET;
|
||||
use Net::Ping;
|
||||
use POSIX qw(strftime);
|
||||
|
||||
use PandoraFMS::Tools;
|
||||
use PandoraFMS::DB;
|
||||
use PandoraFMS::Core;
|
||||
use PandoraFMS::ProducerConsumerServer;
|
||||
|
||||
# Inherits from PandoraFMS::ProducerConsumerServer
|
||||
our @ISA = qw(PandoraFMS::ProducerConsumerServer);
|
||||
|
||||
# Global variables
|
||||
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.
|
||||
########################################################################################
|
||||
sub new ($$$) {
|
||||
my ($class, $config, $dbh) = @_;
|
||||
|
||||
return undef unless $config->{'networkserver'} == 1;
|
||||
|
||||
if (! -e $config->{'snmpget'}) {
|
||||
print ' [E] ' . $config->{'snmpget'} . " needed by Pandora FMS Network Server not found.\n\n";
|
||||
return undef;
|
||||
}
|
||||
|
||||
# Call the constructor of the parent class
|
||||
my $self = $class->SUPER::new($config, 1, \&PandoraFMS::NetworkServer::data_producer, \&PandoraFMS::NetworkServer::data_consumer, $dbh);
|
||||
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Run.
|
||||
###############################################################################
|
||||
sub run ($) {
|
||||
my $self = shift;
|
||||
my $pa_config = $self->getConfig ();
|
||||
|
||||
print " [*] Starting Pandora FMS Network Server. \n";
|
||||
$self->setNumThreads ($pa_config->{'network_threads'});
|
||||
$self->SUPER::run (\@TaskQueue, \%PendingTasks, $Sem, $TaskSem);
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Data producer.
|
||||
###############################################################################
|
||||
sub data_producer ($) {
|
||||
my $self = shift;
|
||||
my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ());
|
||||
|
||||
my @tasks;
|
||||
my @rows;
|
||||
|
||||
if ($pa_config->{'pandora_master'} == 0) {
|
||||
@rows = get_db_rows ($dbh, 'SELECT tagente_modulo.id_agente_modulo, tagente_modulo.flag, UNIX_TIMESTAMP() - tagente_estado.current_interval - tagente_estado.last_execution_try AS time_left
|
||||
FROM tagente, tagente_modulo, tagente_estado
|
||||
WHERE server_name = ?
|
||||
AND tagente_modulo.id_agente = tagente.id_agente
|
||||
AND tagente.disabled = 0
|
||||
AND tagente_modulo.id_tipo_modulo > 4
|
||||
AND tagente_modulo.id_tipo_modulo < 19
|
||||
AND tagente_modulo.disabled = 0
|
||||
AND tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo
|
||||
AND (tagente_modulo.flag = 1 OR ((tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP()))
|
||||
ORDER BY tagente_modulo.flag DESC, time_left DESC, last_execution_try ASC ', $pa_config->{'servername'});
|
||||
} else {
|
||||
@rows = get_db_rows ($dbh, 'SELECT DISTINCT(tagente_modulo.id_agente_modulo), tagente_modulo.flag, tagente_estado.last_execution_try, UNIX_TIMESTAMP() - tagente_estado.current_interval - tagente_estado.last_execution_try AS time_left
|
||||
FROM tagente, tagente_modulo, tagente_estado
|
||||
WHERE ((server_name = ?) OR (server_name = ANY(SELECT server_name FROM tserver WHERE status = 0)))
|
||||
AND tagente_modulo.id_agente = tagente.id_agente
|
||||
AND tagente.disabled = 0
|
||||
AND tagente_modulo.disabled = 0
|
||||
AND tagente_modulo.id_tipo_modulo > 4
|
||||
AND tagente_modulo.id_tipo_modulo < 19
|
||||
AND tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo
|
||||
AND (tagente_modulo.flag = 1 OR ((tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP()))
|
||||
ORDER BY tagente_modulo.flag DESC, time_left DESC, last_execution_try ASC', $pa_config->{'servername'});
|
||||
}
|
||||
|
||||
foreach my $row (@rows) {
|
||||
|
||||
# Reset forced execution flag
|
||||
if ($row->{'flag'} == 1) {
|
||||
db_do ($dbh, 'UPDATE tagente_modulo SET flag = 0 WHERE id_agente_modulo = ?', $row->{'id_agente_modulo'});
|
||||
}
|
||||
|
||||
push (@tasks, $row->{'id_agente_modulo'});
|
||||
}
|
||||
|
||||
return @tasks;
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Data consumer.
|
||||
###############################################################################
|
||||
sub data_consumer ($$) {
|
||||
my ($self, $task) = @_;
|
||||
|
||||
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)
|
||||
# Makes a call to TCP modules to get a value.
|
||||
##########################################################################
|
||||
sub pandora_query_tcp (%$$$$$$$) {
|
||||
my $pa_config = $_[0];
|
||||
my $tcp_port = $_[1];
|
||||
my $ip_target = $_[2];
|
||||
my $module_result = $_[3];
|
||||
my $module_data = $_[4];
|
||||
my $tcp_send = $_[5];
|
||||
my $tcp_rcv = $_[6];
|
||||
my $id_tipo_modulo = $_[7];
|
||||
|
||||
my $counter;
|
||||
for ($counter =0; $counter < $pa_config->{'tcp_checks'}; $counter++){
|
||||
my $temp; my $temp2;
|
||||
my $tam;
|
||||
my $handle=IO::Socket::INET->new(
|
||||
Proto=>"tcp",
|
||||
PeerAddr=>$ip_target,
|
||||
Timeout=>$pa_config->{'tcp_timeout'},
|
||||
PeerPort=>$tcp_port,
|
||||
Blocking=>0 ); # Non blocking !!, very important !
|
||||
|
||||
if (defined ($handle)){
|
||||
# Multi request patch, submitted by Glen Eustace (new zealand)
|
||||
my @tcp_send = split( /\|/, $tcp_send );
|
||||
my @tcp_rcv = split( /\|/, $tcp_rcv );
|
||||
|
||||
next_pair:
|
||||
$tcp_send = shift( @tcp_send );
|
||||
$tcp_rcv = shift( @tcp_rcv );
|
||||
|
||||
if ((defined ($tcp_send)) && ($tcp_send ne "")){ # its Expected to sending data ?
|
||||
# Send data
|
||||
$handle->autoflush(1);
|
||||
$tcp_send =~ s/\^M/\r\n/g;
|
||||
# Replace Carriage rerturn and line feed
|
||||
$handle->send($tcp_send);
|
||||
}
|
||||
# we expect to receive data ? (non proc types)
|
||||
if ((defined ($tcp_rcv)) && (($tcp_rcv ne "") || ($id_tipo_modulo == 10) || ($id_tipo_modulo ==8) || ($id_tipo_modulo == 11))) {
|
||||
# Receive data, non-blocking !!!! (VERY IMPORTANT!)
|
||||
$temp2 = "";
|
||||
for ($tam=0; $tam<($pa_config->{'tcp_timeout'}); $tam++){
|
||||
$handle->recv($temp,16000,0x40);
|
||||
$temp2 = $temp2.$temp;
|
||||
if ($temp ne ""){
|
||||
$tam++; # If doesnt receive data, increase counter
|
||||
}
|
||||
sleep(1);
|
||||
}
|
||||
if ($id_tipo_modulo == 9){ # only for TCP Proc
|
||||
if ($temp2 =~ /$tcp_rcv/i){ # String match !
|
||||
if ( @tcp_send ) { # still more pairs
|
||||
goto next_pair;
|
||||
}
|
||||
$$module_data = 1;
|
||||
$$module_result = 0;
|
||||
$counter = $pa_config->{'tcp_checks'};
|
||||
} else {
|
||||
$$module_data = 0;
|
||||
$$module_result = 0;
|
||||
$counter = $pa_config->{'tcp_checks'};
|
||||
}
|
||||
} elsif ($id_tipo_modulo == 10 ){ # TCP String (no int conversion)!
|
||||
$$module_data = $temp2;
|
||||
$$module_result =0;
|
||||
} else { # TCP Data numeric (inc or data)
|
||||
if ($temp2 ne ""){
|
||||
if ($temp2 =~ /[A-Za-z\.\,\-\/\\\(\)\[\]]/){
|
||||
$$module_result = 1;
|
||||
$$module_data = 0; # invalid data
|
||||
$counter = $pa_config->{'tcp_checks'};
|
||||
} else {
|
||||
$$module_data = int($temp2);
|
||||
$$module_result = 0; # Successful
|
||||
$counter = $pa_config->{'tcp_checks'};
|
||||
}
|
||||
} else {
|
||||
$$module_result = 1;
|
||||
$$module_data = 0; # invalid data
|
||||
$counter = $pa_config->{'tcp_checks'};
|
||||
}
|
||||
}
|
||||
} else { # No expected data to receive, if connected and tcp_proc type successful
|
||||
if ($id_tipo_modulo == 9){ # TCP Proc
|
||||
$$module_result = 0;
|
||||
$$module_data = 1;
|
||||
$counter = $pa_config->{'tcp_checks'};
|
||||
}
|
||||
}
|
||||
$handle->close();
|
||||
undef ($handle);
|
||||
} else { # Cannot connect (open sock failed)
|
||||
$$module_result = 1; # Fail
|
||||
if ($id_tipo_modulo == 9){ # TCP Proc
|
||||
$$module_result = 0;
|
||||
$$module_data = 0; # Failed, but data exists
|
||||
$counter = $pa_config->{'tcp_checks'};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# SUB pandora_query_snmp (pa_config, oid, community, target, version, error, dbh)
|
||||
# Makes a call to SNMP modules to get a value,
|
||||
##########################################################################
|
||||
sub pandora_query_snmp (%$$$$$) {
|
||||
my $pa_config = $_[0];
|
||||
my $snmp_oid = $_[1];
|
||||
my $snmp_community =$_[2];
|
||||
my $snmp_target = $_[3];
|
||||
my $snmp_version = $_[4];
|
||||
# $_[5] contains error var.
|
||||
|
||||
if ($snmp_version ne '1' && $snmp_version ne '2'
|
||||
&& $snmp_version ne '2c' && $snmp_version ne '3') {
|
||||
$snmp_version = '1';
|
||||
}
|
||||
|
||||
my $snmp_timeout = $pa_config->{"snmp_timeout"};
|
||||
my $snmp_retries = $pa_config->{'snmp_checks'};
|
||||
|
||||
# TODO: Alternative version if command is not available or user select a new switch
|
||||
# with "use internal SNMP" option. At this moment, due to locks() external snmp is much faster
|
||||
|
||||
$_[5] = 0;
|
||||
my $snmpget_cmd = $pa_config->{"snmpget"};
|
||||
my $output = `$snmpget_cmd -v $snmp_version -r $snmp_retries -t $snmp_timeout -OUevqt -c $snmp_community $snmp_target $snmp_oid`;
|
||||
if ($output eq ""){
|
||||
$_[5] = 1;
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# SUB exec_network_module (paconfig, id_agente_modulo, dbh )
|
||||
# Execute network module task
|
||||
##########################################################################
|
||||
sub exec_network_module {
|
||||
my $pa_config = $_[0];
|
||||
my $id_agente_modulo = $_[1];
|
||||
my $dbh = $_[2];
|
||||
# Init variables
|
||||
|
||||
my @sql_data;
|
||||
if ((!defined($id_agente_modulo)) || ($id_agente_modulo eq "")){
|
||||
return 0;
|
||||
}
|
||||
my $module = get_db_single_row ($dbh, 'SELECT * FROM tagente_modulo WHERE id_agente_modulo = ?', $id_agente_modulo);
|
||||
if ($module == -1) {
|
||||
logger ($pa_config,"[ERROR] Processing data for invalid module", 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
my $error = "1";
|
||||
my $query_sql2;
|
||||
my $temp=0; my $tam; my $temp2;
|
||||
my $module_result = 1; # Fail by default
|
||||
my $module_data = 0;
|
||||
my $id_agente = $module->{'id_agente'};
|
||||
my $agent_name = get_agent_name ($dbh, $id_agente);
|
||||
my $id_tipo_modulo = $module->{'id_tipo_modulo'};
|
||||
my $ip_target = $module->{'ip_target'};
|
||||
my $snmp_oid = $module->{'snmp_oid'};
|
||||
my $snmp_community = $module->{'snmp_community'};
|
||||
my $tcp_port = $module->{'tcp_port'};
|
||||
my $tcp_send = $module->{'tcp_send'};
|
||||
my $tcp_rcv = $module->{'tcp_rcv'};
|
||||
|
||||
if ((defined($ip_target)) && ($ip_target)) {
|
||||
|
||||
# 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;
|
||||
}
|
||||
} 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
|
||||
}
|
||||
# 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
|
||||
if ((defined($snmp_oid)) && ($snmp_oid ne "") && (defined($snmp_community)) && ($snmp_community ne "")) { # Port check
|
||||
$temp2 = pandora_query_snmp ($pa_config, $snmp_oid, $snmp_community, $ip_target, $tcp_send, $error);
|
||||
} else {
|
||||
$error = 1
|
||||
}
|
||||
if ($error == 0) { # A correct SNMP Query
|
||||
$module_result = 0;
|
||||
# SNMP_DATA_PROC
|
||||
if ($id_tipo_modulo == 18){ #snmp_data_proc
|
||||
# RFC1213-MIB where it says that: SYNTAX INTEGER { up(1), down(2), testing(3),
|
||||
# unknown(4), dormant(5), notPresent(6), lowerLayerDown(7) }
|
||||
if ($temp2 != 1){ # up state is 1, down state in SNMP is 2 ....
|
||||
$temp2 = 0;
|
||||
}
|
||||
$module_data = $temp2;
|
||||
}
|
||||
# SNMP_DATA and SNMP_DATA_INC
|
||||
elsif (($id_tipo_modulo == 15) || ($id_tipo_modulo == 16) ){
|
||||
if (!is_numeric($temp2)){
|
||||
$module_result = 1;
|
||||
} else {
|
||||
$module_data = $temp2;
|
||||
}
|
||||
} else { # String SNMP
|
||||
$module_data = $temp2;
|
||||
}
|
||||
} else { # Failed SNMP-GET
|
||||
$module_data = 0;
|
||||
if ($id_tipo_modulo == 18){ # snmp_proc
|
||||
# Feature from 10Feb08. If snmp_proc_deadresponse = 1 and cannot contact by an error
|
||||
# this is a fail monitor
|
||||
if ($pa_config->{"snmp_proc_deadresponse"} eq "1"){
|
||||
$module_result = 0;
|
||||
} else {
|
||||
$module_result = 1;
|
||||
}
|
||||
} else {
|
||||
$module_result = 1; # No data, cannot connect
|
||||
}
|
||||
}
|
||||
# TCP Module
|
||||
# ----------
|
||||
} elsif (($id_tipo_modulo == 8) || ($id_tipo_modulo == 9) || ($id_tipo_modulo == 10) || ($id_tipo_modulo == 11)) { # TCP Module
|
||||
if ((defined($tcp_port)) && ($tcp_port < 65536) && ($tcp_port > 0)) { # Port check
|
||||
pandora_query_tcp ($pa_config, $tcp_port, $ip_target, \$module_result, \$module_data, $tcp_send, $tcp_rcv, $id_tipo_modulo);
|
||||
} else {
|
||||
# Invalid port, get no check
|
||||
$module_result = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Write data section
|
||||
my $utimestamp = time ();
|
||||
my $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime($utimestamp));
|
||||
|
||||
# Is everything goes ok
|
||||
if ($module_result == 0) {
|
||||
|
||||
pandora_process_module ($pa_config, $module_data, '', $module, '', $timestamp, $utimestamp, $dbh);
|
||||
|
||||
# Update agent last contact using Pandora version as agent version
|
||||
pandora_update_agent ($pa_config, $timestamp, $id_agente, $pa_config->{'servername'}.'_Net', $pa_config->{'version'}, -1, $dbh);
|
||||
|
||||
} else {
|
||||
# Modules who cannot connect or something go bad, update last_execution_try field
|
||||
pandora_update_module_on_error ($pa_config, $id_agente_modulo, $dbh);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
__END__
|
|
@ -0,0 +1,182 @@
|
|||
package PandoraFMS::PluginServer;
|
||||
##########################################################################
|
||||
# Pandora FMS Plugin Server.
|
||||
# Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org
|
||||
##########################################################################
|
||||
# Copyright (c) 2009 Ramon Novoa, rnovoa@artica.es
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public License
|
||||
# as published by the Free Software Foundation; version 2
|
||||
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
##########################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use threads;
|
||||
use threads::shared;
|
||||
use Thread::Semaphore;
|
||||
|
||||
use POSIX qw(strftime);
|
||||
use HTML::Entities;
|
||||
|
||||
use PandoraFMS::Tools;
|
||||
use PandoraFMS::DB;
|
||||
use PandoraFMS::Core;
|
||||
use PandoraFMS::ProducerConsumerServer;
|
||||
|
||||
# Inherits from PandoraFMS::ProducerConsumerServer
|
||||
our @ISA = qw(PandoraFMS::ProducerConsumerServer);
|
||||
|
||||
# Global variables
|
||||
my @TaskQueue :shared;
|
||||
my %PendingTasks :shared;
|
||||
my $Sem :shared = Thread::Semaphore->new;
|
||||
my $TaskSem :shared = Thread::Semaphore->new (0);
|
||||
|
||||
########################################################################################
|
||||
# Plugin Server class constructor.
|
||||
########################################################################################
|
||||
sub new ($$;$) {
|
||||
my ($class, $config, $dbh) = @_;
|
||||
|
||||
return undef unless $config->{'pluginserver'} == 1;
|
||||
|
||||
# Check for pandora_exec
|
||||
if (system($config->{'plugin_exec'} . ' > /dev/null 2>&1') != 256) {
|
||||
print " [E] pandora_exec not found.\n\n";
|
||||
return undef;
|
||||
}
|
||||
|
||||
# Call the constructor of the parent class
|
||||
my $self = $class->SUPER::new($config, 4, \&PandoraFMS::PluginServer::data_producer, \&PandoraFMS::PluginServer::data_consumer, $dbh);
|
||||
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Run.
|
||||
###############################################################################
|
||||
sub run ($) {
|
||||
my $self = shift;
|
||||
my $pa_config = $self->getConfig ();
|
||||
|
||||
print " [*] Starting Pandora FMS Plugin Server. \n";
|
||||
$self->setNumThreads ($pa_config->{'plugin_threads'});
|
||||
$self->SUPER::run (\@TaskQueue, \%PendingTasks, $Sem, $TaskSem);
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Data producer.
|
||||
###############################################################################
|
||||
sub data_producer ($) {
|
||||
my $self = shift;
|
||||
my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ());
|
||||
|
||||
my @tasks;
|
||||
my @rows;
|
||||
|
||||
if ($pa_config->{'pandora_master'} != 1) {
|
||||
@rows = get_db_rows ($dbh, 'SELECT tagente_modulo.id_agente_modulo, tagente_modulo.flag, UNIX_TIMESTAMP() - tagente_estado.current_interval - tagente_estado.last_execution_try AS time_left
|
||||
FROM tagente, tagente_modulo, tagente_estado
|
||||
WHERE server_name = ?
|
||||
AND tagente_modulo.id_agente = tagente.id_agente
|
||||
AND tagente.disabled = 0
|
||||
AND tagente_modulo.id_plugin != 0
|
||||
AND tagente_modulo.disabled = 0
|
||||
AND tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo
|
||||
AND (tagente_modulo.flag = 1 OR (tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP())
|
||||
ORDER BY tagente_modulo.flag DESC, time_left DESC, last_execution_try ASC', $pa_config->{'servername'});
|
||||
} else {
|
||||
@rows = get_db_rows ($dbh, 'SELECT DISTINCT(tagente_modulo.id_agente_modulo), tagente_modulo.flag, UNIX_TIMESTAMP() - tagente_estado.current_interval - tagente_estado.last_execution_try AS time_left
|
||||
FROM tagente, tagente_modulo, tagente_estado
|
||||
WHERE ((server_name = ?) OR (server_name = ANY(SELECT server_name FROM tserver WHERE status = 0)))
|
||||
AND tagente_modulo.id_agente = tagente.id_agente
|
||||
AND tagente.disabled = 0
|
||||
AND tagente_modulo.disabled = 0
|
||||
AND tagente_modulo.id_plugin != 0
|
||||
AND tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo
|
||||
AND (tagente_modulo.flag = 1 OR (tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP())
|
||||
ORDER BY tagente_modulo.flag DESC, time_left DESC, last_execution_try ASC', $pa_config->{'servername'});
|
||||
}
|
||||
|
||||
foreach my $row (@rows) {
|
||||
|
||||
# Reset forced execution flag
|
||||
if ($row->{'flag'} == 1) {
|
||||
db_do ($dbh, 'UPDATE tagente_modulo SET flag = 0 WHERE id_agente_modulo = ?', $row->{'id_agente_modulo'});
|
||||
}
|
||||
|
||||
push (@tasks, $row->{'id_agente_modulo'});
|
||||
}
|
||||
|
||||
return @tasks;
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Data consumer.
|
||||
###############################################################################
|
||||
sub data_consumer ($$) {
|
||||
my ($self, $module_id) = @_;
|
||||
my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ());
|
||||
|
||||
# Retrieve module data
|
||||
my $module = get_db_single_row ($dbh, 'SELECT * FROM tagente_modulo WHERE id_agente_modulo = ?', $module_id);
|
||||
return unless defined $module;
|
||||
|
||||
# Retrieve plugin data
|
||||
my $plugin = get_db_single_row ($dbh, 'SELECT * FROM tplugin WHERE id = ?', $module->{'id_plugin'});
|
||||
return unless defined $plugin;
|
||||
|
||||
# Use the smallest timeout
|
||||
my $timeout = ($plugin->{'max_timeout'} < $pa_config->{'plugin_timeout'}) ?
|
||||
$plugin->{'max_timeout'} : $pa_config->{'plugin_timeout'};
|
||||
|
||||
# Build command to execute
|
||||
my $command = $plugin->{'execute'};
|
||||
if ($plugin->{'net_dst_opt'} ne ''){
|
||||
$command .= ' ' . $plugin->{'net_dst_opt'} . ' ' . $module->{'ip_target'};
|
||||
}
|
||||
if ($plugin->{'net_port_opt'} ne '') {
|
||||
$command .= ' ' . $plugin->{'net_port_opt'} . ' ' . $module->{'tcp_port'};
|
||||
}
|
||||
if ($plugin->{'user_opt'} ne '') {
|
||||
$command .= ' ' . $plugin->{'user_opt'} . ' ' . $module->{'plugin_user'};
|
||||
}
|
||||
if ($plugin->{'pass_opt'} ne '') {
|
||||
$command .= ' ' . $plugin->{'pass_opt'} . ' ' . $module->{'plugin_pass'};
|
||||
}
|
||||
|
||||
# Extra parameter
|
||||
if ($module->{'plugin_parameter'} ne '') {
|
||||
$command .= ' ' . $module->{'plugin_parameter'};
|
||||
}
|
||||
|
||||
$command = decode_entities($command);
|
||||
logger ($pa_config, "Executing AM # $module_id plugin command '$command'", 9);
|
||||
|
||||
# Execute command
|
||||
$command = $pa_config->{'plugin_exec'} . ' ' . $timeout . ' ' . $command;
|
||||
my $module_data = `$command`;
|
||||
if (! defined $module_data || $module_data eq '') {
|
||||
pandora_update_module_on_error ($pa_config, $module_id, $dbh);
|
||||
return;
|
||||
}
|
||||
|
||||
my $utimestamp = time ();
|
||||
my $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime($utimestamp));
|
||||
|
||||
pandora_process_module ($pa_config, $module_data, '', $module, '', $timestamp, $utimestamp, $dbh);
|
||||
pandora_update_agent ($pa_config, $timestamp, $module->{'id_agente'}, $pa_config->{'servername'}.'_Plugin', $pa_config->{'version'}, -1, $dbh);
|
||||
}
|
||||
|
||||
1;
|
||||
__END__
|
|
@ -0,0 +1,242 @@
|
|||
package PandoraFMS::PredictionServer;
|
||||
##########################################################################
|
||||
# Pandora FMS Prediction Server.
|
||||
# Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org
|
||||
##########################################################################
|
||||
# Copyright (c) 2009 Ramon Novoa, rnovoa@artica.es
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public License
|
||||
# as published by the Free Software Foundation; version 2
|
||||
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
##########################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use threads;
|
||||
use threads::shared;
|
||||
use Thread::Semaphore;
|
||||
|
||||
use IO::Socket::INET;
|
||||
use Net::Ping;
|
||||
use POSIX qw(strftime);
|
||||
|
||||
use PandoraFMS::Tools;
|
||||
use PandoraFMS::DB;
|
||||
use PandoraFMS::Core;
|
||||
use PandoraFMS::ProducerConsumerServer;
|
||||
|
||||
# Inherits from PandoraFMS::ProducerConsumerServer
|
||||
our @ISA = qw(PandoraFMS::ProducerConsumerServer);
|
||||
|
||||
# Global variables
|
||||
my @TaskQueue :shared;
|
||||
my %PendingTasks :shared;
|
||||
my $Sem :shared = Thread::Semaphore->new;
|
||||
my $TaskSem :shared = Thread::Semaphore->new (0);
|
||||
|
||||
########################################################################################
|
||||
# Prediction Server class constructor.
|
||||
########################################################################################
|
||||
sub new ($$;$) {
|
||||
my ($class, $config, $dbh) = @_;
|
||||
|
||||
return undef unless $config->{'predictionserver'} == 1;
|
||||
|
||||
# Call the constructor of the parent class
|
||||
my $self = $class->SUPER::new($config, 5, \&PandoraFMS::PredictionServer::data_producer, \&PandoraFMS::PredictionServer::data_consumer, $dbh);
|
||||
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Run.
|
||||
###############################################################################
|
||||
sub run ($) {
|
||||
my $self = shift;
|
||||
my $pa_config = $self->getConfig ();
|
||||
|
||||
print " [*] Starting Pandora FMS Prediction Server. \n";
|
||||
$self->setNumThreads ($pa_config->{'prediction_threads'});
|
||||
$self->SUPER::run (\@TaskQueue, \%PendingTasks, $Sem, $TaskSem);
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Data producer.
|
||||
###############################################################################
|
||||
sub data_producer ($) {
|
||||
my $self = shift;
|
||||
my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ());
|
||||
|
||||
my @tasks;
|
||||
my @rows;
|
||||
|
||||
if ($pa_config->{'pandora_master'} != 1) {
|
||||
@rows = get_db_rows ($dbh, 'SELECT tagente_modulo.id_agente_modulo, tagente_modulo.flag
|
||||
FROM tagente, tagente_modulo, tagente_estado
|
||||
WHERE server_name = ?
|
||||
AND tagente_modulo.id_agente = tagente.id_agente
|
||||
AND tagente.disabled = 0
|
||||
AND tagente_modulo.prediction_module != 0
|
||||
AND tagente_modulo.disabled = 0
|
||||
AND tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo
|
||||
AND (tagente_modulo.flag = 1
|
||||
OR (tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP())
|
||||
ORDER BY last_execution_try ASC ', $pa_config->{'servername'});
|
||||
} else {
|
||||
@rows = get_db_rows ($dbh, 'SELECT DISTINCT(tagente_modulo.id_agente_modulo), tagente_modulo.flag
|
||||
FROM tagente, tagente_modulo, tagente_estado
|
||||
WHERE ((server_name = ?) OR (server_name = ANY(SELECT server_name FROM tserver WHERE status = 0)))
|
||||
AND tagente_modulo.id_agente = tagente.id_agente
|
||||
AND tagente.disabled = 0
|
||||
AND tagente_modulo.disabled = 0
|
||||
AND tagente_modulo.prediction_module != 0
|
||||
AND tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo
|
||||
AND (tagente_modulo.flag = 1 OR (tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP())
|
||||
ORDER BY last_execution_try ASC', $pa_config->{'servername'});
|
||||
}
|
||||
|
||||
foreach my $row (@rows) {
|
||||
|
||||
# Reset forced execution flag
|
||||
if ($row->{'flag'} == 1) {
|
||||
db_do ($dbh, 'UPDATE tagente_modulo SET flag = 0 WHERE id_agente_modulo = ?', $row->{'id_agente_modulo'});
|
||||
}
|
||||
|
||||
push (@tasks, $row->{'id_agente_modulo'});
|
||||
}
|
||||
|
||||
return @tasks;
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Data consumer.
|
||||
###############################################################################
|
||||
sub data_consumer ($$) {
|
||||
my ($self, $task) = @_;
|
||||
|
||||
exec_prediction_module ($self->getConfig (), $task, $self->getDBH ());
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# Execute prediction module.
|
||||
##########################################################################
|
||||
sub exec_prediction_module {
|
||||
my ($pa_config, $id_am, $dbh) = @_;
|
||||
|
||||
# Get a full hash for agent_module record reference ($agent_module)
|
||||
my $agent_module = get_db_single_row ($dbh, 'SELECT * FROM tagente_modulo WHERE id_agente_modulo = ?', $id_am);
|
||||
return unless defined $agent_module;
|
||||
|
||||
# Get a full hash for target agent_module record reference ($target_module)
|
||||
my $target_module = get_db_single_row ($dbh, 'SELECT * FROM tagente_modulo WHERE id_agente_modulo = ?', $agent_module->{'prediction_module'});
|
||||
return unless defined $target_module;
|
||||
|
||||
# Prediction mode explanation
|
||||
#
|
||||
# 0 is for target type of generic_proc. It compares latest data with current data. Needs to get
|
||||
# data on a "middle" interval, so if interval is 300, get data to compare with 150 before
|
||||
# and 150 in the future. If current data is ABOVE or BELOW average +- typical_deviation
|
||||
# this is a BAD value (0), if not is ok (1) and written in target module as is.
|
||||
# more interval configured for this module, more "margin" has to compare data.
|
||||
#
|
||||
# 1 is for target type of generic_data. It get's data in the future, using the interval given in
|
||||
# module. It gets average from current timestamp to INTERVAL in the future and gets average
|
||||
# value. Typical deviation is not used here.
|
||||
|
||||
# 0 proc, 1 data
|
||||
my $prediction_mode = ($agent_module->{'id_tipo_modulo'} == 2) ? 0 : 1;
|
||||
|
||||
# Initialize another global sub variables.
|
||||
my $module_data = 0; # 0 data for default
|
||||
|
||||
# Get current timestamp
|
||||
my $utimestamp = time ();
|
||||
my $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime($utimestamp));
|
||||
|
||||
# Get different data from each week one month ago (4 values)
|
||||
# $agent_module->{'module_interval'} uses a margin of interval to get average data from the past
|
||||
my @week_data;
|
||||
my @week_utimestamp;
|
||||
|
||||
for (my $i=0; $i<4; $i++){
|
||||
$week_utimestamp[$i] = $utimestamp - (84600*7*($i+1));
|
||||
# Adjust for proc prediction
|
||||
if ($prediction_mode == 0) {
|
||||
$week_utimestamp[$i] = $week_utimestamp[$i] - ($agent_module->{'module_interval'} / 2);
|
||||
}
|
||||
}
|
||||
|
||||
# Let's calculate statistical average using past data
|
||||
# n = total of real data values
|
||||
my ($n, $average, $temp1) = (0, 0, 0);
|
||||
for (my $i=0; $i < 4; $i++){
|
||||
my ($first_data, $last_data, $average_interval);
|
||||
my $sum_data = 0;
|
||||
|
||||
$temp1 = $week_utimestamp[$i] + $agent_module->{'module_interval'};
|
||||
# Get data for week $i in the past
|
||||
$average_interval = get_db_value ($dbh, 'SELECT AVG(datos) FROM tagente_datos WHERE id_agente_modulo = ? AND utimestamp > ? AND utimestamp < ?', $target_module->{'id_agente_modulo'}, $week_utimestamp[$i], $temp1);
|
||||
|
||||
# Need to get data outside interval because no data.
|
||||
if ($average_interval == 0){
|
||||
$last_data = get_db_value ($dbh, 'SELECT datos FROM tagente_datos WHERE id_agente_modulo = ? AND utimestamp > ? LIMIT 1', $target_module->{'id_agente_modulo'}, $week_utimestamp[$i]);
|
||||
$sum_data++ if ($last_data != 0);
|
||||
|
||||
$first_data = get_db_value ($dbh, 'SELECT datos FROM tagente_datos WHERE id_agente_modulo = ? AND utimestamp < ? LIMIT 1', $target_module->{'id_agente_modulo'}, $temp1);
|
||||
$sum_data++ if ($first_data != 0);
|
||||
|
||||
$week_data[$i] = (($last_data + $first_data) / $sum_data);
|
||||
} else {
|
||||
$week_data[$i] = $average_interval;
|
||||
}
|
||||
|
||||
# It's possible that one of the week_data[i] values was not valid (NULL)
|
||||
# so recheck it and relay on n=0 for "no data" values set to 0 in result
|
||||
# Calculate total ammount of valida data for each data sample
|
||||
if ((is_numeric($week_data[$i])) && ($week_data[$i] > 0)){
|
||||
$n++;
|
||||
# Average SUM
|
||||
$average = $average + $week_data[$i];
|
||||
}
|
||||
}
|
||||
|
||||
# Real average value
|
||||
$average = ($n > 0) ? ($average / $n) : 0;
|
||||
|
||||
# (PROC) Compare with current data
|
||||
if ($prediction_mode == 0){
|
||||
# Calculate typical deviation
|
||||
my $typical_deviation = 0;
|
||||
for (my $i=0; $i< $n; $i++){
|
||||
if ((is_numeric($week_data[$i])) && ($week_data[$i] > 0)) {
|
||||
$typical_deviation = $typical_deviation + (($week_data[$i] - $average)**2);
|
||||
}
|
||||
}
|
||||
$typical_deviation = sqrt ($typical_deviation / ($n-1));
|
||||
|
||||
my $current_value = get_db_value ($dbh, 'SELECT datos FROM tagente_estado WHERE id_agente_modulo = ?', $target_module->{'id_agente_modulo'});
|
||||
if ( ($current_value > ($average - $typical_deviation)) && ($current_value < ($average + $typical_deviation)) ){
|
||||
$module_data = 1; # OK !!
|
||||
} else {
|
||||
$module_data = 0; # Out of predictions
|
||||
}
|
||||
} else {
|
||||
# Prediction based on data
|
||||
$module_data = $average;
|
||||
}
|
||||
|
||||
pandora_process_module ($pa_config, $module_data, '', $agent_module, '', $timestamp, $utimestamp, $dbh);
|
||||
pandora_update_agent ($pa_config, $timestamp, $agent_module->{'id_agente'}, $pa_config->{'servername'}.'_Prediction', $pa_config->{'version'}, -1, $dbh);
|
||||
}
|
||||
|
||||
1;
|
||||
__END__
|
|
@ -0,0 +1,166 @@
|
|||
package PandoraFMS::ProducerConsumerServer;
|
||||
##########################################################################
|
||||
# Pandora FMS generic server.
|
||||
# Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org
|
||||
##########################################################################
|
||||
# Copyright (c) 2009 Ramon Novoa, rnovoa@artica.es
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public License
|
||||
# as published by the Free Software Foundation; version 2
|
||||
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
##########################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use threads;
|
||||
use threads::shared;
|
||||
use Thread::Semaphore;
|
||||
|
||||
use PandoraFMS::DB;
|
||||
use PandoraFMS::Core;
|
||||
use PandoraFMS::Server;
|
||||
|
||||
# inherits from PandoraFMS::Server
|
||||
our @ISA = qw(PandoraFMS::Server);
|
||||
|
||||
########################################################################################
|
||||
# ProducerConsumerServer class constructor.
|
||||
########################################################################################
|
||||
sub new ($$$$$;$) {
|
||||
my ($class, $config, $server_type, $producer,
|
||||
$consumer, $dbh) = @_;
|
||||
|
||||
# Call the constructor of the parent class
|
||||
my $self = $class->SUPER::new($config, $server_type, $dbh);
|
||||
|
||||
# Set producer/consumer functions
|
||||
$self->{'_producer'} = $producer;
|
||||
$self->{'_consumer'} = $consumer;
|
||||
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# Get producer function.
|
||||
########################################################################################
|
||||
sub getProducer ($) {
|
||||
my $self = shift;
|
||||
|
||||
return $self->{'_producer'};
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# Get consumer function.
|
||||
########################################################################################
|
||||
sub getConsumer ($) {
|
||||
my $self = shift;
|
||||
|
||||
return $self->{'_consumer'};
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Run.
|
||||
###############################################################################
|
||||
sub run ($$$$$) {
|
||||
my ($self, $task_queue, $pending_tasks, $sem, $task_sem) = @_;
|
||||
|
||||
# Launch consumer threads
|
||||
for (1..$self->getNumThreads ()) {
|
||||
my $thr = threads->create (\&PandoraFMS::ProducerConsumerServer::data_consumer, $self,
|
||||
$task_queue, $pending_tasks, $sem, $task_sem);
|
||||
return unless defined ($thr);
|
||||
$self->addThread ($thr->tid ());
|
||||
}
|
||||
|
||||
# Launch producer thread
|
||||
my $thr = threads->create (\&PandoraFMS::ProducerConsumerServer::data_producer, $self,
|
||||
$task_queue, $pending_tasks, $sem, $task_sem);
|
||||
return unless defined ($thr);
|
||||
$self->addThread ($thr->tid ());
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Queue pending tasks.
|
||||
###############################################################################
|
||||
sub data_producer ($$$$$) {
|
||||
my ($self, $task_queue, $pending_tasks, $sem, $task_sem) = @_;
|
||||
my $pa_config = $self->getConfig ();
|
||||
|
||||
# Connect to the DB
|
||||
my $dbh = db_connect ('mysql', $pa_config->{'dbname'}, $pa_config->{'dbhost'}, 3306,
|
||||
$pa_config->{'dbuser'}, $pa_config->{'dbpass'});
|
||||
$self->setDBH ($dbh);
|
||||
|
||||
while (1) {
|
||||
|
||||
# Get pending tasks
|
||||
my @tasks = &{$self->{'_producer'}}($self);
|
||||
|
||||
# Update queue size for statistics
|
||||
$self->setQueueSize ($#tasks);
|
||||
|
||||
foreach my $task (@tasks) {
|
||||
$sem->down;
|
||||
|
||||
if (defined $pending_tasks->{$task}) {
|
||||
$sem->up;
|
||||
next;
|
||||
}
|
||||
|
||||
# Queue task and signal consumers
|
||||
$pending_tasks->{$task} = 0;
|
||||
push (@{$task_queue}, $task);
|
||||
$task_sem->up;
|
||||
|
||||
$sem->up;
|
||||
}
|
||||
|
||||
threads->yield;
|
||||
sleep ($pa_config->{'server_threshold'});
|
||||
}
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Execute pending tasks.
|
||||
###############################################################################
|
||||
sub data_consumer ($$$$$) {
|
||||
my ($self, $task_queue, $pending_tasks, $sem, $task_sem) = @_;
|
||||
my $pa_config = $self->getConfig ();
|
||||
|
||||
# Connect to the DB
|
||||
my $dbh = db_connect ('mysql', $pa_config->{'dbname'}, $pa_config->{'dbhost'}, 3306,
|
||||
$pa_config->{'dbuser'}, $pa_config->{'dbpass'});
|
||||
$self->setDBH ($dbh);
|
||||
|
||||
while (1) {
|
||||
|
||||
# Wait for data
|
||||
$task_sem->down;
|
||||
|
||||
$sem->down;
|
||||
my $task = pop (@{$task_queue});
|
||||
$sem->up;
|
||||
|
||||
# Execute task
|
||||
&{$self->{'_consumer'}}($self, $task);
|
||||
|
||||
# Update task status
|
||||
$sem->down;
|
||||
delete ($pending_tasks->{$task});
|
||||
$sem->up;
|
||||
|
||||
threads->yield;
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
__END__
|
|
@ -0,0 +1,382 @@
|
|||
package PandoraFMS::ReconServer;
|
||||
##########################################################################
|
||||
# Pandora FMS Recon Server.
|
||||
# Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org
|
||||
##########################################################################
|
||||
# Copyright (c) 2009 Ramon Novoa, rnovoa@artica.es
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public License
|
||||
# as published by the Free Software Foundation; version 2
|
||||
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
##########################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use threads;
|
||||
use threads::shared;
|
||||
use Thread::Semaphore;
|
||||
|
||||
use IO::Socket::INET;
|
||||
use Net::Ping;
|
||||
use NetAddr::IP;
|
||||
use POSIX qw(strftime);
|
||||
|
||||
use PandoraFMS::Tools;
|
||||
use PandoraFMS::DB;
|
||||
use PandoraFMS::Core;
|
||||
use PandoraFMS::ProducerConsumerServer;
|
||||
|
||||
# Inherits from PandoraFMS::ProducerConsumerServer
|
||||
our @ISA = qw(PandoraFMS::ProducerConsumerServer);
|
||||
|
||||
# Global variables
|
||||
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;
|
||||
|
||||
########################################################################################
|
||||
# Recon Server class constructor.
|
||||
########################################################################################
|
||||
sub new ($$$$$$) {
|
||||
my ($class, $config, $dbh) = @_;
|
||||
|
||||
return undef unless $config->{'reconserver'} == 1;
|
||||
|
||||
# Call the constructor of the parent class
|
||||
my $self = $class->SUPER::new($config, 3, \&PandoraFMS::ReconServer::data_producer, \&PandoraFMS::ReconServer::data_consumer, $dbh);
|
||||
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Run.
|
||||
###############################################################################
|
||||
sub run ($) {
|
||||
my $self = shift;
|
||||
my $pa_config = $self->getConfig ();
|
||||
|
||||
print " [*] Starting Pandora FMS Recon Server. \n";
|
||||
$self->setNumThreads ($pa_config->{'recon_threads'});
|
||||
$self->SUPER::run (\@TaskQueue, \%PendingTasks, $Sem, $TaskSem);
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Data producer.
|
||||
###############################################################################
|
||||
sub data_producer ($) {
|
||||
my $self = shift;
|
||||
my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ());
|
||||
|
||||
my @tasks;
|
||||
|
||||
my $server_id = get_server_id ($dbh, $pa_config->{'servername'}, $self->getServerType ());
|
||||
return @tasks unless defined ($server_id);
|
||||
|
||||
my @rows = get_db_rows ($dbh, 'SELECT * FROM trecon_task
|
||||
WHERE id_recon_server = ?
|
||||
AND (status = 1 OR (utimestamp + interval_sweep) < UNIX_TIMESTAMP())', $server_id);
|
||||
foreach my $row (@rows) {
|
||||
|
||||
# Update task status
|
||||
update_recon_task ($pa_config, $dbh, $row->{'id_rt'}, 0);
|
||||
|
||||
push (@tasks, $row->{'id_rt'});
|
||||
}
|
||||
|
||||
return @tasks;
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Data consumer.
|
||||
###############################################################################
|
||||
sub data_consumer ($$) {
|
||||
my ($self, $task_id) = @_;
|
||||
my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ());
|
||||
|
||||
# Get recon task data
|
||||
my $task = get_db_single_row ($dbh, 'SELECT * FROM trecon_task WHERE id_rt = ?', $task_id);
|
||||
return -1 unless defined ($task);
|
||||
|
||||
# Get a NetAddr::IP object for the target network
|
||||
my $net_addr = new NetAddr::IP ($task->{'subnet'});
|
||||
if (! defined ($net_addr)) {
|
||||
logger ($pa_config, 'Invalid network ' . $task->{'subnet'} . ' for task ' . $task->{'name'}, 2);
|
||||
update_recon_task ($pa_config, $dbh, $task_id, -1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
# Scan the network for hosts
|
||||
my ($total_hosts, $hosts_found, $addr_found) = ($net_addr->num, 0, '');
|
||||
for (my $i = 1, $net_addr++; $net_addr < $net_addr->broadcast; $i++, $net_addr++) {
|
||||
|
||||
my $addr = (split(/\//, $net_addr))[0];
|
||||
update_recon_task ($pa_config, $dbh, $task_id, $i / ($total_hosts / 100));
|
||||
|
||||
# Does the host already exist?
|
||||
next if (addr_exists ($dbh, $addr) == 1);
|
||||
|
||||
# Is the host alive? (thanks to Evi for the TCP scans)
|
||||
my $alive = 0;
|
||||
if (icmp_scan ($addr, $pa_config->{'networktimeout'}) == 1) {
|
||||
$alive = 1;
|
||||
#Check for Remote Desktop & VNC (Desktop & Server machines)
|
||||
} elsif (tcp_scan ($addr, $pa_config->{'networktimeout'}, 3389) == 1 ||
|
||||
tcp_scan ($addr, $pa_config->{'networktimeout'}, 5900) == 1) {
|
||||
$alive = 1;
|
||||
#Check for management ports 10000 = Webmin, 161 = SNMP (Most embedded devices)
|
||||
} elsif (tcp_scan ($addr, $pa_config->{'networktimeout'}, 10000) == 1 ||
|
||||
tcp_scan ($addr, $pa_config->{'networktimeout'}, 161) == 1) {
|
||||
$alive = 1;
|
||||
#Check for SSH & Mail (Servers and Unix machines)
|
||||
} elsif (tcp_scan ($addr, $pa_config->{'networktimeout'}, 22) == 1 ||
|
||||
tcp_scan ($addr, $pa_config->{'networktimeout'}, 25) == 1) {
|
||||
$alive = 1;
|
||||
#Check for WWW & MySQL (Webservers and systems in a DMZ)
|
||||
} elsif (tcp_scan ($addr, $pa_config->{'networktimeout'}, 80) == 1 ||
|
||||
tcp_scan ($addr, $pa_config->{'networktimeout'}, 3306) == 1) {
|
||||
$alive = 1;
|
||||
}
|
||||
|
||||
next unless ($alive == 1);
|
||||
|
||||
$hosts_found++;
|
||||
$addr_found .= $addr . " ";
|
||||
|
||||
# Guess the OS
|
||||
my $id_os = guess_os ($pa_config, $addr);
|
||||
|
||||
# Resolve the address
|
||||
my $host_name = gethostbyaddr(inet_aton($addr), AF_INET);
|
||||
$host_name = $addr unless defined ($host_name);
|
||||
|
||||
# Get the parent host
|
||||
my $parent_id = get_host_parent ($pa_config, $addr, $dbh);
|
||||
|
||||
# Add the new address
|
||||
my $addr_id = add_address ($dbh, $addr);
|
||||
|
||||
# Crate a new agent
|
||||
my $agent_id = pandora_create_agent ($pa_config, $pa_config->{'servername'} . '_Recon',
|
||||
$host_name, $addr, $addr_id,
|
||||
$task->{'id_group'}, '', $parent_id, $task->{'id_os'}, $dbh);
|
||||
|
||||
# Crate network profile modules for the agent
|
||||
create_network_profile_modules ($pa_config, $dbh, $agent_id, $task->{'id_network_profile'}, $addr);
|
||||
|
||||
# Generate an event
|
||||
pandora_event ($pa_config, "[RECON] New host [$host_name] detected on network [" . $task->{'subnet'} . ']',
|
||||
$task->{'id_group'}, $agent_id, 2, 0, 0, 'recon_host_detected', $dbh);
|
||||
}
|
||||
|
||||
# Create an incident
|
||||
if ($hosts_found > 0 && $task->{'create_incident'} == 1){
|
||||
my $text = "At " . strftime ("%Y-%m-%d %H:%M:%S", localtime()) . " ($hosts_found) new hosts were detected by Pandora FMS Recon Server running on [" . $pa_config->{'servername'} . "_Recon]. This incident has been automatically created following instructions for this recon task [" . $task->{'id_group'} . "].\n\n";
|
||||
if ($task->{'id_network_profile'} > 0) {
|
||||
$text .= "Aditionally, and following instruction for this task, agent(s) has been created, with modules assigned to network component profile [" . get_nc_profile_name ($dbh, $task->{'id_network_profile'}) . "]. Please check this agent as soon as possible to verify it.";
|
||||
}
|
||||
$text .= "\n\nThis is the list of IP addresses found: \n\n$addr_found";
|
||||
pandora_create_incident ($pa_config, $dbh, "[RECON] New hosts detected", $text, 0, 0, 'Pandora FMS Recon Server', $task->{'id_group'});
|
||||
}
|
||||
|
||||
# Mark recon task as done
|
||||
update_recon_task ($pa_config, $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.
|
||||
##############################################################################
|
||||
sub tcp_scan ($$$) {
|
||||
my ($host, $timeout, $port) = $@;
|
||||
my $rc = 0;
|
||||
|
||||
eval {
|
||||
local $SIG{'ALRM'} = sub { return 0; };
|
||||
alarm ($timeout);
|
||||
my $handle=IO::Socket::INET->new(
|
||||
Proto => 'tcp',
|
||||
PeerAddr => $host,
|
||||
PeerPort => $port);
|
||||
$rc = 1 if ($handle);
|
||||
alarm (0);
|
||||
};
|
||||
|
||||
return 0 if ($@);
|
||||
return $rc;
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# Guess OS using xprobe2.
|
||||
##########################################################################
|
||||
sub guess_os {
|
||||
my ($pa_config, $host) = @_;
|
||||
|
||||
my $xprobe2 = $pa_config->{'xprobe2'};
|
||||
|
||||
# Other OS
|
||||
return 10 if (! -e $xprobe2);
|
||||
|
||||
# Execute xprobe2
|
||||
my $output = '';
|
||||
eval {
|
||||
$output = `$xprobe2 $host 2> /dev/null | grep "Running OS" 2> /dev/null | head -1 2> /dev/null`;
|
||||
};
|
||||
|
||||
# Check for errors
|
||||
return 10 if ($@);
|
||||
|
||||
return pandora_get_os ($output);
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# Return 1 if the given IP address already exists in the DB, 0 if not.
|
||||
##########################################################################
|
||||
sub addr_exists ($$) {
|
||||
my ($dbh, $ip_address) = @_;
|
||||
|
||||
my @addresses = get_db_rows ($dbh, 'SELECT * FROM taddress WHERE ip = ?', $ip_address);
|
||||
|
||||
# Address not found
|
||||
return 0 if ($#addresses < 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
##########################################################################
|
||||
# Return the ID of the agent with the given IP.
|
||||
##########################################################################
|
||||
sub get_agent_from_addr ($$$) {
|
||||
my ($pa_config, $dbh, $ip_address) = @_;
|
||||
|
||||
return 0 if (! defined ($ip_address) || $ip_address eq '');
|
||||
|
||||
my $agent_id = get_db_value ($dbh, 'SELECT id_agent FROM taddress, taddress_agent WHERE taddress_agent.id_a = taddress.id_a AND ip = ?', $ip_address);
|
||||
return (defined ($agent_id)) ? $agent_id : -1;
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# Update recon task status.
|
||||
##########################################################################
|
||||
sub update_recon_task {
|
||||
my ($pa_config, $dbh, $id_task, $status) = @_;
|
||||
|
||||
db_do ($dbh, 'UPDATE trecon_task SET utimestamp = ?, status = ? WHERE id_rt = ?', time (), $status, $id_task);
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# Add the given address to taddress.
|
||||
##########################################################################
|
||||
sub add_address ($$) {
|
||||
my ($dbh, $ip_address) = @_;
|
||||
|
||||
return db_insert ($dbh, 'INSERT INTO taddress (ip) VALUES (?)', $ip_address);
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# Create network profile modules for the given agent.
|
||||
##########################################################################
|
||||
sub create_network_profile_modules {
|
||||
my ($pa_config, $dbh, $agent_id, $np_id, $addr) = @_;
|
||||
|
||||
return unless ($np_id > 0);
|
||||
|
||||
# Get network components associated to the network profile
|
||||
my @np_components = get_db_rows ($dbh, 'SELECT * FROM tnetwork_profile_component WHERE id_np = ?', $np_id);
|
||||
|
||||
foreach my $np_component (@np_components) {
|
||||
|
||||
# Get network component data
|
||||
my $component = get_db_single_row ($dbh, 'SELECT * FROM tnetwork_component wHERE id_nc = ?', $np_component->{'id_nc'});
|
||||
next unless defined ($component);
|
||||
|
||||
# Create the module
|
||||
my $module_id = db_insert ($dbh, 'INSERT INTO tagente_modulo (id_agente, id_tipo_modulo, descripcion, nombre, max, min, module_interval, tcp_port, tcp_send, tcp_rcv, snmp_community, snmp_oid, ip_target, id_module_group, flag, disabled, plugin_user, plugin_pass, plugin_parameter, max_timeout, id_modulo )
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, 0, ?, ?, ?, ?, ?)',
|
||||
$agent_id, $component->{'type'}, $component->{'description'}, $component->{'name'}, $component->{'max'}, $component->{'min'}, $component->{'interval'}, $component->{'tcp_port'}, $component->{'tcp_send'}, $component->{'tcp_rcv'}, $component->{'snmp_community'},
|
||||
$component->{'snmp_oid'}, $addr, $component->{'id_module_group'}, $component->{'plugin_user'}, $component->{'plugin_pass'}, $component->{'plugin_parameter'}, $component->{'max_timeout'}, $component->{'id_modulo'});
|
||||
|
||||
logger($pa_config, 'Recon Server: Creating module ' . $component->{'name'} . " for agent $addr", 3);
|
||||
|
||||
# An entry in tagente_estado is necessary for the module to work
|
||||
db_insert ($dbh, 'INSERT INTO tagente_estado (id_agente_modulo, datos, timestamp, estado, id_agente, last_try, utimestamp, current_interval, running_by)
|
||||
VALUES (?, \'\', \'0000-00-00 00:00:00\', 1, ?, \'0000-00-00 00:00:00\', 0, ?, 0)',
|
||||
$module_id, $agent_id, $component->{'module_interval'});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# Returns the ID of the parent of the given host if available.
|
||||
##########################################################################
|
||||
sub get_host_parent ($$){
|
||||
my ($pa_config, $host, $dbh) = @_;
|
||||
|
||||
# Traceroute not available
|
||||
return 0 unless ($TracerouteAvailable != 0);
|
||||
|
||||
my $tr = Net::Traceroute::PurePerl->new (
|
||||
backend => 'PurePerl',
|
||||
host => $host,
|
||||
debug => 0,
|
||||
max_ttl => 15,
|
||||
query_timeout => $pa_config->{'networktimeout'},
|
||||
packetlen => 40,
|
||||
protocol => 'udp', # udp or icmp
|
||||
);
|
||||
|
||||
my $success = 0;
|
||||
|
||||
# Call traceroute
|
||||
eval {
|
||||
local $SIG{'ALRM'} = sub { return 0; };
|
||||
alarm($pa_config->{'networktimeout'});
|
||||
$success = $tr->traceroute();
|
||||
alarm(0);
|
||||
};
|
||||
|
||||
# Error or timeout
|
||||
return 0 if ($@);
|
||||
|
||||
# Traceroute was not successful
|
||||
return 0 if ($tr->hops < 2 || $success == 0);
|
||||
|
||||
my $parent_addr = $tr->hop_query_host($tr->hops - 1, 0);
|
||||
return get_agent_from_addr ($pa_config, $dbh, $parent_addr);
|
||||
}
|
||||
|
||||
1;
|
||||
__END__
|
|
@ -0,0 +1,178 @@
|
|||
package PandoraFMS::SNMPServer;
|
||||
##########################################################################
|
||||
# Pandora FMS SNMP Console.
|
||||
# Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org
|
||||
##########################################################################
|
||||
# Copyright (c) 2009 Ramon Novoa, rnovoa@artica.es
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public License
|
||||
# as published by the Free Software Foundation; version 2
|
||||
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
##########################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use threads;
|
||||
use threads::shared;
|
||||
use Thread::Semaphore;
|
||||
|
||||
use Time::Local;
|
||||
use XML::Simple;
|
||||
|
||||
use PandoraFMS::Tools;
|
||||
use PandoraFMS::DB;
|
||||
use PandoraFMS::Core;
|
||||
use PandoraFMS::Server;
|
||||
|
||||
# Load enterprise module
|
||||
enterprise_load ();
|
||||
|
||||
# Inherits from PandoraFMS::Server
|
||||
our @ISA = qw(PandoraFMS::Server);
|
||||
|
||||
########################################################################################
|
||||
# SNMP Server class constructor.
|
||||
########################################################################################
|
||||
sub new ($$;$) {
|
||||
my ($class, $config, $dbh) = @_;
|
||||
|
||||
return undef unless $config->{'snmpconsole'} == 1;
|
||||
|
||||
# Start snmptrapd
|
||||
if (system ($config->{'snmp_trapd'} .' -t -On -n -a -Lf ' . $config->{'snmp_logfile'} . ' -p /var/run/pandora_snmptrapd.pid -F %4y-%02.2m-%l[**]%02.2h:%02.2j:%02.2k[**]%a[**]%N[**]%w[**]%W[**]%q[**]%v\n 2>/dev/null') != 0) {
|
||||
print " [E] Could not start snmptrapd.\n\n";
|
||||
return undef;
|
||||
}
|
||||
|
||||
# Call the constructor of the parent class
|
||||
my $self = $class->SUPER::new($config, 2, $dbh);
|
||||
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Run.
|
||||
###############################################################################
|
||||
sub run ($) {
|
||||
my $self = shift;
|
||||
|
||||
print " [*] Starting Pandora FMS SNMP Console. \n";
|
||||
$self->SUPER::run (\&PandoraFMS::SNMPServer::pandora_snmptrapd);
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# Process SNMP log file.
|
||||
##########################################################################
|
||||
sub pandora_snmptrapd {
|
||||
my $self = shift;
|
||||
my $pa_config = $self->getConfig ();
|
||||
|
||||
# Connect to the DB
|
||||
my $dbh = db_connect ('mysql', $pa_config->{'dbname'}, $pa_config->{'dbhost'},
|
||||
3306, $pa_config->{'dbuser'}, $pa_config->{'dbpass'});
|
||||
$self->setDBH ($dbh);
|
||||
|
||||
# Wait for the SNMP log file to be available
|
||||
my $log_file = $pa_config->{'snmp_logfile'};
|
||||
sleep ($pa_config->{'server_threshold'}) while (! -e $log_file);
|
||||
open (SNMPLOGFILE, $log_file) or return;
|
||||
|
||||
# Process index file, if available
|
||||
my ($idx_file, $last_line, $last_size) = ($log_file . '.index', 0, 0);
|
||||
if (-e $idx_file) {
|
||||
open (INDEXFILE, $idx_file) or return;
|
||||
my $idx_data = <INDEXFILE>;
|
||||
close INDEXFILE;
|
||||
($last_line, $last_size) = split(/\s+/, $idx_data);
|
||||
}
|
||||
|
||||
my $log_size = (stat ($log_file))[7];
|
||||
|
||||
# New SNMP log file found
|
||||
if ($log_size < $last_size) {
|
||||
unlink ($idx_file);
|
||||
($last_line, $last_size) = (0, 0);
|
||||
}
|
||||
|
||||
# Skip already processed lines
|
||||
readline SNMPLOGFILE for (1..$last_line);
|
||||
|
||||
my $trap2agent = enterprise_hook('snmp_get_trap2agent', [$dbh]);
|
||||
|
||||
# Main loop
|
||||
while (1) {
|
||||
while (my $line = <SNMPLOGFILE>) {
|
||||
$last_line++;
|
||||
$last_size = (stat ($log_file))[7];
|
||||
|
||||
# Update index file
|
||||
open INDEXFILE, '>' . $idx_file;
|
||||
print INDEXFILE $last_line . ' ' . $last_size;
|
||||
close INDEXFILE;
|
||||
|
||||
# Skip Headers
|
||||
next if ($line =~ m/NET-SNMP/);
|
||||
|
||||
# Unknown data
|
||||
next if ($line !~ m/\[\*\*\]/);
|
||||
|
||||
my ($date, $time, $source, $oid,
|
||||
$type, $type_desc, $value, $data) = split(/\[\*\*\]/, $line);
|
||||
|
||||
my $timestamp = $date . ' ' . $time;
|
||||
$value = limpia_cadena ($value);
|
||||
|
||||
my ($custom_oid, $custom_type, $custom_value) = ('', '', $type_desc);
|
||||
|
||||
# Custom OID
|
||||
if ($type == 6) {
|
||||
|
||||
#String data
|
||||
next if ($data =~ m/STRING/) && ($data !~ m/([0-9\.]*)\s\=\s([A-Za-z0-9]*)\:\s\"(.+)\"/);
|
||||
|
||||
next if ($data !~ m/([0-9\.]*)\s\=\s([A-Za-z0-9]*)\:\s(.+)/);
|
||||
|
||||
($custom_oid, $custom_type, $custom_value) = ($1, $2, $3);
|
||||
$custom_value = limpia_cadena ($custom_value);
|
||||
}
|
||||
|
||||
# Insert the trap into the DB
|
||||
if (! defined(enterprise_hook ('snmp_insert_trap', [$pa_config, $source, $oid, $type, $value, $custom_oid, $custom_value, $custom_type, $timestamp, $dbh]))) {
|
||||
db_insert ($dbh, 'INSERT INTO ttrap (timestamp, source, oid, type, value, oid_custom, value_custom, type_custom) VALUES (?, ?, ?, ?, ?, ?, ?, ?)',
|
||||
$timestamp, $source, $oid, $type, $value, $custom_oid, $custom_value, $custom_type);
|
||||
logger ($pa_config, "Received SNMP Trap from $source", 4);
|
||||
|
||||
# Evaluate alerts for this trap
|
||||
pandora_evaluate_snmp_alerts ($pa_config, $source, $oid, $oid, $custom_oid . ' ' . $custom_value, $timestamp, $dbh);
|
||||
}
|
||||
|
||||
enterprise_hook ('snmp_trap2agent', [$trap2agent, $pa_config, $source, $oid, $value, $custom_oid, $custom_value, $timestamp, $dbh]);
|
||||
}
|
||||
|
||||
sleep ($pa_config->{'server_threshold'});
|
||||
}
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# Stop the server, killing snmptrapd before.
|
||||
########################################################################################
|
||||
sub stop () {
|
||||
my $self = shift;
|
||||
|
||||
system ('kill -9 `cat /var/run/pandora_snmptrapd.pid 2> /dev/null`');
|
||||
unlink ('/var/run/pandora_snmptrapd.pid');
|
||||
|
||||
$self->SUPER::stop ();
|
||||
}
|
||||
|
||||
1;
|
||||
__END__
|
|
@ -0,0 +1,230 @@
|
|||
package PandoraFMS::Server;
|
||||
##########################################################################
|
||||
# Pandora FMS generic server.
|
||||
# Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org
|
||||
##########################################################################
|
||||
# Copyright (c) 2009 Ramon Novoa, rnovoa@artica.es
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public License
|
||||
# as published by the Free Software Foundation; version 2
|
||||
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
##########################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use threads;
|
||||
use threads::shared;
|
||||
|
||||
use PandoraFMS::Core;
|
||||
|
||||
# defined in PandoraFMS::Core.pm
|
||||
our @ServerSuffixes;
|
||||
|
||||
########################################################################################
|
||||
# Server class constructor.
|
||||
########################################################################################
|
||||
sub new ($$$;$) {
|
||||
my $class = shift;
|
||||
my $self = {
|
||||
_pa_config => shift,
|
||||
_server_type => shift,
|
||||
_dbh => shift,
|
||||
_num_threads => 1,
|
||||
_threads => [],
|
||||
_queue_size => 0,
|
||||
};
|
||||
|
||||
# Thread kill signal handler
|
||||
#$SIG{'KILL'} = sub {
|
||||
# threads->exit() if threads->can('exit');
|
||||
# exit();
|
||||
#};
|
||||
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# Run.
|
||||
########################################################################################
|
||||
sub run ($$) {
|
||||
my ($self, $func) = @_;
|
||||
|
||||
for (1..$self->{'_num_threads'}) {
|
||||
my $thr = threads->create (\&{$func}, $self);
|
||||
return unless defined ($thr);
|
||||
push (@{$self->{'_threads'}}, $thr->tid ());
|
||||
}
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# Set the number of server threads.
|
||||
########################################################################################
|
||||
sub setNumThreads ($$) {
|
||||
my ($self, $num_threads) = @_;
|
||||
|
||||
$self->{'_num_threads'} = $num_threads;
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# Set the actual server queue size (used for statistics).
|
||||
########################################################################################
|
||||
sub setQueueSize ($$) {
|
||||
my ($self, $size) = @_;
|
||||
|
||||
$self->{'_queue_size'} = $size;
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# Get the number of server threads.
|
||||
########################################################################################
|
||||
sub getNumThreads ($$) {
|
||||
my $self = shift;
|
||||
|
||||
return $self->{'_num_threads'};
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# Get consumer function.
|
||||
########################################################################################
|
||||
sub getConsumer ($) {
|
||||
my $self = shift;
|
||||
|
||||
return $self->{'_consumer'};
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# Set DB handler.
|
||||
########################################################################################
|
||||
sub setDBH ($$) {
|
||||
my ($self, $dbh) = @_;
|
||||
|
||||
$self->{'_dbh'} = $dbh;
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# Get DB handler.
|
||||
########################################################################################
|
||||
sub getDBH ($) {
|
||||
my $self = shift;
|
||||
|
||||
return $self->{'_dbh'};
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# Get config.
|
||||
########################################################################################
|
||||
sub getConfig ($) {
|
||||
my $self = shift;
|
||||
|
||||
return $self->{'_pa_config'};
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# Get server type.
|
||||
########################################################################################
|
||||
sub getServerType ($) {
|
||||
my $self = shift;
|
||||
|
||||
return $self->{'_server_type'};
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# Add a thread to the server thread list.
|
||||
########################################################################################
|
||||
sub addThread ($$) {
|
||||
my ($self, $tid) = @_;
|
||||
push (@{$self->{'_threads'}}, $tid);
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# Returns 1 if all server threads are running, 0 otherwise.
|
||||
########################################################################################
|
||||
sub checkThreads ($) {
|
||||
my $self = shift;
|
||||
|
||||
foreach my $tid (@{$self->{'_threads'}}) {
|
||||
my $thr = threads->object ($tid);
|
||||
return 0 unless defined ($thr);
|
||||
#return 0 unless $thr->is_running ();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# Generate a 'going up' event.
|
||||
########################################################################################
|
||||
sub upEvent ($) {
|
||||
my $self = shift;
|
||||
|
||||
return unless defined ($self->{'_dbh'});
|
||||
pandora_event ($self->{'_pa_config'}, $self->{'_pa_config'}->{'servername'} .
|
||||
$ServerTypes[$self->{'_server_type'}] . ' going UP',
|
||||
0, 0, 3, 0, 0, 'system', $self->{'_dbh'});
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# Generate a 'going down' event.
|
||||
########################################################################################
|
||||
sub downEvent ($) {
|
||||
my $self = shift;
|
||||
|
||||
return unless defined ($self->{'_dbh'});
|
||||
pandora_event ($self->{'_pa_config'}, $self->{'_pa_config'}->{'servername'} .
|
||||
$ServerTypes[$self->{'_server_type'}] . ' going DOWN',
|
||||
0, 0, 4, 0, 0, 'system', $self->{'_dbh'});
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# Update server status.
|
||||
########################################################################################
|
||||
sub update ($) {
|
||||
my $self = shift;
|
||||
|
||||
eval {
|
||||
pandora_update_server ($self->{'_pa_config'}, $self->{'_dbh'}, $self->{'_pa_config'}->{'servername'},
|
||||
1, $self->{'_server_type'}, $self->{'_num_threads'}, $self->{'_queue_size'});
|
||||
};
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# Stop the server, killing all server threads.
|
||||
########################################################################################
|
||||
sub stop ($) {
|
||||
my $self = shift;
|
||||
|
||||
# Update server status
|
||||
pandora_update_server ($self->{'_pa_config'}, $self->{'_dbh'}, $self->{'_pa_config'}->{'servername'},
|
||||
0, $self->{'_server_type'});
|
||||
|
||||
# Generate an event
|
||||
$self->downEvent ();
|
||||
|
||||
# Kill server threads
|
||||
foreach my $tid (@{$self->{'_threads'}}) {
|
||||
my $thr = threads->object($tid);
|
||||
next unless defined ($thr);
|
||||
|
||||
# A kill method might not be available
|
||||
#if ($thr->can('kill')) {
|
||||
# $thr->kill('KILL')->detach();
|
||||
#} else {
|
||||
$thr->detach();
|
||||
#}
|
||||
}
|
||||
}
|
||||
|
||||
# End of function declaration
|
||||
# End of defined Code
|
||||
|
||||
1;
|
||||
__END__
|
|
@ -20,8 +20,7 @@ package PandoraFMS::Tools;
|
|||
|
||||
use warnings;
|
||||
use Time::Local;
|
||||
use Date::Manip; # Needed to manipulate DateTime formats of input, output and compare
|
||||
use POSIX qw(setsid);
|
||||
use POSIX qw(setsid strftime);
|
||||
use Mail::Sendmail; # New in 2.0. Used to sendmail internally, without external scripts
|
||||
|
||||
require Exporter;
|
||||
|
@ -43,6 +42,7 @@ our @EXPORT = qw(
|
|||
pandora_trash_ascii
|
||||
enterprise_hook
|
||||
enterprise_load
|
||||
print_message
|
||||
);
|
||||
|
||||
##########################################################################
|
||||
|
@ -257,7 +257,7 @@ sub logger {
|
|||
$datos = "[V".$verbose_level."] ".$datos;
|
||||
}
|
||||
|
||||
my $time_now = &UnixDate("today","%Y/%m/%d %H:%M:%S");
|
||||
my $time_now = strftime ("%Y-%m-%d %H:%M:%S", localtime());
|
||||
if (-e $fichero){
|
||||
my $filesize = (stat($fichero))[7];
|
||||
if ( $filesize > $pa_config->{'max_log_size'}) {
|
||||
|
@ -321,25 +321,21 @@ sub float_equal {
|
|||
}
|
||||
|
||||
##########################################################################
|
||||
# sub enterprise_load ()
|
||||
# Tries to load the PandoraEnterprise module. Must be called once before
|
||||
# enterprise_hook ().
|
||||
##########################################################################
|
||||
sub enterprise_load () {
|
||||
eval {
|
||||
require PandoraFMS::Enterprise;
|
||||
};
|
||||
eval 'use PandoraFMS::Enterprise;';
|
||||
return 0 if ($@);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
##########################################################################
|
||||
# sub enterprise_hook ($function_name, \@arguments)
|
||||
# Tries to call a PandoraEnterprise function. Returns undef if unsuccessful.
|
||||
##########################################################################
|
||||
sub enterprise_hook ($$) {
|
||||
my $func = $_[0];
|
||||
my @args = @{$_[1]};
|
||||
my $output;
|
||||
my $func = shift;
|
||||
my @args = @{shift ()};
|
||||
|
||||
# Temporarily disable strict refs
|
||||
no strict 'refs';
|
||||
|
@ -348,14 +344,22 @@ sub enterprise_hook ($$) {
|
|||
$func = 'PandoraFMS::Enterprise::' . $func;
|
||||
|
||||
# Try to call the function
|
||||
$output = eval { &$func (@args); };
|
||||
my $output = eval { &$func (@args); };
|
||||
|
||||
# Check for errors
|
||||
if ($@) {
|
||||
return undef;
|
||||
}
|
||||
else {
|
||||
return $output;
|
||||
return undef if ($@);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# Prints a message to STDOUT at the given log level.
|
||||
##########################################################################
|
||||
sub print_message ($$$) {
|
||||
my ($pa_config, $message, $log_level) = @_;
|
||||
|
||||
if ($pa_config->{'verbosity'} > $log_level){
|
||||
print STDOUT $message . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,195 @@
|
|||
package PandoraFMS::WMIServer;
|
||||
##########################################################################
|
||||
# Pandora FMS WMI Server.
|
||||
# Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org
|
||||
##########################################################################
|
||||
# Copyright (c) 2009 Ramon Novoa, rnovoa@artica.es
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public License
|
||||
# as published by the Free Software Foundation; version 2
|
||||
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
##########################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use threads;
|
||||
use threads::shared;
|
||||
use Thread::Semaphore;
|
||||
|
||||
use POSIX qw(strftime);
|
||||
use HTML::Entities;
|
||||
|
||||
use PandoraFMS::Tools;
|
||||
use PandoraFMS::DB;
|
||||
use PandoraFMS::Core;
|
||||
use PandoraFMS::ProducerConsumerServer;
|
||||
|
||||
# Inherits from PandoraFMS::ProducerConsumerServer
|
||||
our @ISA = qw(PandoraFMS::ProducerConsumerServer);
|
||||
|
||||
# Global variables
|
||||
my @TaskQueue :shared;
|
||||
my %PendingTasks :shared;
|
||||
my $Sem :shared = Thread::Semaphore->new;
|
||||
my $TaskSem :shared = Thread::Semaphore->new (0);
|
||||
|
||||
########################################################################################
|
||||
# NetworkServer class constructor.
|
||||
########################################################################################
|
||||
sub new ($$;$) {
|
||||
my ($class, $config, $dbh) = @_;
|
||||
|
||||
return undef unless $config->{'wmiserver'} == 1;
|
||||
|
||||
# Check for a WMI client
|
||||
if (system ($config->{'wmi_client'} . ' > /dev/null 2>&1') != 256) {
|
||||
print ' [E] ' . $config->{'wmi_client'} . " not found. Pandora FMS WMI Server needs a DCOM/WMI client.\n\n";
|
||||
return undef;
|
||||
}
|
||||
|
||||
# Call the constructor of the parent class
|
||||
my $self = $class->SUPER::new($config, 6, \&PandoraFMS::WMIServer::data_producer, \&PandoraFMS::WMIServer::data_consumer, $dbh);
|
||||
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Run.
|
||||
###############################################################################
|
||||
sub run ($) {
|
||||
my $self = shift;
|
||||
my $pa_config = $self->getConfig ();
|
||||
|
||||
print " [*] Starting Pandora FMS WMI Server. \n";
|
||||
$self->setNumThreads ($pa_config->{'wmi_threads'});
|
||||
$self->SUPER::run (\@TaskQueue, \%PendingTasks, $Sem, $TaskSem);
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Data producer.
|
||||
###############################################################################
|
||||
sub data_producer ($) {
|
||||
my $self = shift;
|
||||
my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ());
|
||||
|
||||
my @tasks;
|
||||
my @rows;
|
||||
|
||||
if ($pa_config->{'pandora_master'} != 1) {
|
||||
@rows = get_db_rows ($dbh, 'SELECT tagente_modulo.id_agente_modulo, tagente_modulo.flag UNIX_TIMESTAMP() - tagente_estado.current_interval - tagente_estado.last_execution_try AS time_left
|
||||
FROM tagente, tagente_modulo, tagente_estado
|
||||
WHERE server_name = ?
|
||||
AND tagente_modulo.id_agente = tagente.id_agente
|
||||
AND tagente.disabled = 0
|
||||
AND tagente_modulo.id_modulo = 6
|
||||
AND tagente_modulo.disabled = 0
|
||||
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 tagente_modulo.flag DESC, time_left DESC, last_execution_try ASC', $pa_config->{'servername'});
|
||||
} else {
|
||||
@rows = get_db_rows ($dbh, 'SELECT DISTINCT(tagente_modulo.id_agente_modulo), tagente_modulo.flag, UNIX_TIMESTAMP() - tagente_estado.current_interval - tagente_estado.last_execution_try AS time_left
|
||||
FROM tagente, tagente_modulo, tagente_estado, tserver
|
||||
WHERE ((server_name = ?) OR (server_name = ANY(SELECT server_name FROM tserver WHERE status = 0)))
|
||||
AND tagente_modulo.id_agente = tagente.id_agente
|
||||
AND tagente.disabled = 0
|
||||
AND tagente_modulo.disabled = 0
|
||||
AND tagente_modulo.id_modulo = 6
|
||||
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 tagente_modulo.flag DESC, time_left DESC, last_execution_try ASC', $pa_config->{'servername'});
|
||||
}
|
||||
|
||||
foreach my $row (@rows) {
|
||||
|
||||
# Reset forced execution flag
|
||||
if ($row->{'flag'} == 1) {
|
||||
db_do ($dbh, 'UPDATE tagente_modulo SET flag = 0 WHERE id_agente_modulo = ?', $row->{'id_agente_modulo'});
|
||||
}
|
||||
|
||||
push (@tasks, $row->{'id_agente_modulo'});
|
||||
}
|
||||
|
||||
return @tasks;
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Data consumer.
|
||||
###############################################################################
|
||||
sub data_consumer ($$) {
|
||||
my ($self, $module_id) = @_;
|
||||
my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ());
|
||||
|
||||
my $module = get_db_single_row ($dbh, 'SELECT * FROM tagente_modulo WHERE id_agente_modulo = ?', $module_id);
|
||||
return unless defined $module;
|
||||
|
||||
# Build command to execute
|
||||
my $wmi_command = $pa_config->{'wmi_client'} . ' -U "' . $module->{'plugin_user'} . '"%"' . $module->{'plugin_pass'} . '"';
|
||||
|
||||
# Use a custom namespace
|
||||
my $namespace = $module->{'tcp_send'};
|
||||
if ($namespace ne '') {
|
||||
$namespace =~ s/\"/\'/g;
|
||||
$wmi_command .= ' --namespace="' . $namespace . '"';
|
||||
}
|
||||
|
||||
# WMI query
|
||||
my $wmi_query = decode_entities($module->{'snmp_oid'});
|
||||
$wmi_query =~ s/\"/\'/g;
|
||||
|
||||
$wmi_command .= ' //' . $module->{'ip_target'} . ' "' . $wmi_query . '"';
|
||||
logger ($pa_config, "Executing AM # $module_id WMI command '$wmi_command'", 9);
|
||||
|
||||
# Execute command
|
||||
my $module_data = `$wmi_command`;
|
||||
if (! defined ($module_data)) {
|
||||
pandora_update_module_on_error ($pa_config, $module_id, $dbh);
|
||||
return;
|
||||
}
|
||||
|
||||
# Parse command output. Example:
|
||||
# CLASS: Win32_Processor
|
||||
# DeviceID|LoadPercentage
|
||||
# CPU0|2
|
||||
my @output = split("\n", $module_data);
|
||||
if ($#output < 2) {
|
||||
pandora_update_module_on_error ($pa_config, $module_id, $dbh);
|
||||
return;
|
||||
}
|
||||
|
||||
# Check for errors
|
||||
if ($output[0] =~ /ERROR/) {
|
||||
pandora_update_module_on_error ($pa_config, $module_id, $dbh);
|
||||
return;
|
||||
}
|
||||
|
||||
# Get the first row (line 3)
|
||||
my @row = split(/\|/, $output[2]);
|
||||
|
||||
# Get the specified column
|
||||
$module_data = $row[$module->{'tcp_port'}];
|
||||
|
||||
# Regexp
|
||||
if ($module->{'snmp_community'} ne ''){
|
||||
my $filter = $module->{'snmp_community'};
|
||||
$module_data = ($module_data =~ /$filter/) ? 1 : 0;
|
||||
}
|
||||
|
||||
my $utimestamp = time ();
|
||||
my $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime($utimestamp));
|
||||
|
||||
pandora_process_module ($pa_config, $module_data, '', $module, '', $timestamp, $utimestamp, $dbh);
|
||||
pandora_update_agent ($pa_config, $timestamp, $module->{'id_agente'}, $pa_config->{'servername'} . '_WMI', $pa_config->{'version'}, -1, $dbh);
|
||||
}
|
||||
|
||||
1;
|
||||
__END__
|
|
@ -1,44 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Global Startup / Control script for Pandora FMS
|
||||
# Written by A. Delgado, contributed to Pandora FMS project
|
||||
# (c) A.Delgado 2008
|
||||
|
||||
if [ $# -eq 0 ]
|
||||
then
|
||||
|
||||
echo -e "\nPandora FMS 2.0 Control script - http://pandorafms.org
|
||||
Usage: pandora start/stop [server] [server] ...
|
||||
|
||||
Servers : pandora_server pandora_network pandora_recon pandora_snmpconsole \n pandora_prediction pandora_plugin pandora_wmi \n"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
ACCION=$1
|
||||
SERVIDOR2=$2
|
||||
SERVIDOR3=$3
|
||||
SERVIDOR4=$4
|
||||
SERVIDOR5=$5
|
||||
SERVIDOR6=$6
|
||||
SERVIDOR7=$7
|
||||
SERVIDOR8=$8
|
||||
|
||||
if [ $# -eq 1 ]
|
||||
then
|
||||
/etc/init.d/pandora_server $ACCION
|
||||
/etc/init.d/pandora_network $ACCION
|
||||
/etc/init.d/pandora_recon $ACCION
|
||||
/etc/init.d/pandora_snmpconsole $ACCION
|
||||
/etc/init.d/pandora_prediction $ACCION
|
||||
/etc/init.d/pandora_plugin $ACCION
|
||||
/etc/init.d/pandora_wmi $ACCION
|
||||
else
|
||||
[ ! -z $SERVIDOR2 ] && /etc/init.d/$SERVIDOR2 $ACCION && echo -e "\n$ACCION server $SERVIDOR2\n"
|
||||
[ ! -z $SERVIDOR3 ] && /etc/init.d/$SERVIDOR3 $ACCION && echo -e "\n$ACCION server $SERVIDOR3\n"
|
||||
[ ! -z $SERVIDOR4 ] && /etc/init.d/$SERVIDOR4 $ACCION && echo -e "\n$ACCION server $SERVIDOR4\n"
|
||||
[ ! -z $SERVIDOR5 ] && /etc/init.d/$SERVIDOR5 $ACCION && echo -e "\n$ACCION server $SERVIDOR5\n"
|
||||
[ ! -z $SERVIDOR6 ] && /etc/init.d/$SERVIDOR6 $ACCION && echo -e "\n$ACCION server $SERVIDOR6\n"
|
||||
[ ! -z $SERVIDOR7 ] && /etc/init.d/$SERVIDOR7 $ACCION && echo -e "\n$ACCION server $SERVIDOR7\n"
|
||||
[ ! -z $SERVIDOR8 ] && /etc/init.d/$SERVIDOR8 $ACCION && echo -e "\n$ACCION server $SERVIDOR8\n"
|
||||
fi
|
|
@ -1,74 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Pandora FMS Network Server, startup script
|
||||
# Copyright (c) 2006-2008 Sancho Lerena, <slerena@gmail.com>
|
||||
# Linux Version (generic)
|
||||
# v2.1 Build 081030
|
||||
# http://www.pandorafms.com
|
||||
|
||||
# Configurable path and filenames
|
||||
PANDORA_HOME="/etc/pandora/pandora_server.conf"
|
||||
PANDORA_PID_PATH="/var/run"
|
||||
PANDORA_PID=$PANDORA_PID_PATH/pandora_network.pid
|
||||
PANDORA_DAEMON=/usr/local/bin/pandora_network
|
||||
|
||||
# Main script
|
||||
|
||||
if [ ! -d "$PANDORA_PID_PATH" ]
|
||||
then
|
||||
echo "Pandora FMS cannot write it's PID file in $PANDORA_PID_PATH. Please create that directory"
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ ! -f $PANDORA_DAEMON ]
|
||||
then
|
||||
echo "Pandora FMS Network Server not found, please check setup and read manual"
|
||||
exit
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
OLD_PATH="`pwd`"
|
||||
PANDORA_PID=$(pidof -x $PANDORA_DAEMON)
|
||||
if [ ! -z $PANDORA_PID ]
|
||||
then
|
||||
echo "Pandora FMS Network Server is currently running on this machine with PID ($PANDORA_PID). Aborting now..."
|
||||
exit 1
|
||||
else
|
||||
rm -f $PANDORA_PID
|
||||
fi
|
||||
|
||||
$PANDORA_DAEMON $PANDORA_HOME -D
|
||||
sleep 1
|
||||
|
||||
PANDORA_PID=$(pidof -x $PANDORA_DAEMON)
|
||||
if [ ! -z "$PANDORA_PID" ]
|
||||
then
|
||||
echo "Pandora Network Server is now running with PID $PANDORA_PID"
|
||||
else
|
||||
echo "Cannot start Pandora FMS Network Server. Aborted."
|
||||
fi
|
||||
cd "$OLD_PATH"
|
||||
;;
|
||||
stop)
|
||||
PANDORA_PID=$(pidof -x $PANDORA_DAEMON)
|
||||
if [ -z $PANDORA_PID ]
|
||||
then
|
||||
echo "Pandora FMS Network Server is not running, cannot stop it."
|
||||
exit 1
|
||||
else
|
||||
echo "Stopping Pandora FMS Network Server"
|
||||
kill $PANDORA_PID > /dev/null 2>&1
|
||||
rm -f $PANDORA_PID
|
||||
fi
|
||||
;;
|
||||
force-reload|restart)
|
||||
$0 stop
|
||||
sleep 2
|
||||
$0 start
|
||||
;;
|
||||
*)
|
||||
echo "Usage: pandora_network {start|stop|restart}"
|
||||
exit 1
|
||||
esac
|
||||
|
|
@ -45,12 +45,6 @@ install () {
|
|||
cp pandora_* /etc/init.d
|
||||
rm /etc/init.d/pandora_*_installer
|
||||
ln -s /etc/init.d/pandora_server /etc/rc2.d/S90pandora_server 2> /dev/null
|
||||
ln -s /etc/init.d/pandora_recon /etc/rc2.d/S90pandora_recon 2> /dev/null
|
||||
ln -s /etc/init.d/pandora_network /etc/rc2.d/S90pandora_network 2> /dev/null
|
||||
ln -s /etc/init.d/pandora_snmpconsole /etc/rc2.d/S90pandora_snmpconsole 2> /dev/null
|
||||
ln -s /etc/init.d/pandora_plugin /etc/rc2.d/S90pandora_plugin 2> /dev/null
|
||||
ln -s /etc/init.d/pandora_prediction /etc/rc2.d/S90pandora_prediction 2> /dev/null
|
||||
ln -s /etc/init.d/pandora_wmi /etc/rc2.d/S90pandora_wmi 2> /dev/null
|
||||
fi
|
||||
|
||||
mkdir /usr/share/pandora 2> /dev/null
|
||||
|
@ -84,29 +78,10 @@ uninstall () {
|
|||
rm -Rf /etc/pandora/pandora_server.conf 2> /dev/null
|
||||
|
||||
rm -Rf /etc/init.d/pandora_server 2> /dev/null
|
||||
rm -Rf /etc/init.d/pandora_network 2> /dev/null
|
||||
rm -Rf /etc/init.d/pandora_recon 2> /dev/null
|
||||
rm -Rf /etc/init.d/pandora_snmpconsole 2> /dev/null
|
||||
rm -Rf /etc/init.d/pandora_prediction 2> /dev/null
|
||||
rm -Rf /etc/init.d/pandora_wmi 2> /dev/null
|
||||
rm -Rf /etc/init.d/pandora_plugin 2> /dev/null
|
||||
|
||||
rm -Rf /etc/rc2.d/S90pandora_server 2> /dev/null
|
||||
rm -Rf /etc/rc2.d/S90pandora_recon 2> /dev/null
|
||||
rm -Rf /etc/rc2.d/S90pandora_network 2> /dev/null
|
||||
rm -Rf /etc/rc2.d/S90pandora_snmpconsole 2> /dev/null
|
||||
rm -Rf /etc/rc2.d/S90pandora_wmi 2> /dev/null
|
||||
rm -Rf /etc/rc2.d/S90pandora_prediction 2> /dev/null
|
||||
rm -Rf /etc/rc2.d/S90pandora_plugin 2> /dev/null
|
||||
|
||||
rm -Rf /usr/bin/pandora_exec 2> /dev/null
|
||||
rm -Rf /usr/bin/pandora_wmi 2> /dev/null
|
||||
rm -Rf /usr/bin/pandora_server 2> /dev/null
|
||||
rm -Rf /usr/bin/pandora_snmpconsole 2> /dev/null
|
||||
rm -Rf /usr/bin/pandora_recon 2> /dev/null
|
||||
rm -Rf /usr/bin/pandora_network 2> /dev/null
|
||||
rm -Rf /usr/bin/pandora_prediction 2> /dev/null
|
||||
rm -Rf /usr/bin/pandora_plugin 2> /dev/null
|
||||
|
||||
rm -Rf /usr/share/pandora
|
||||
rm -Rf /etc/cron.daily/pandora_purge_db
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Pandora FMS Plugin Server, startup script
|
||||
# Copyright (c) 2006-2008 Sancho Lerena, <slerena@gmail.com>
|
||||
# Linux Version (generic)
|
||||
# v2.1 Build 081030
|
||||
# http://www.pandorafms.com
|
||||
|
||||
# Configurable path and filenames
|
||||
PANDORA_HOME="/etc/pandora/pandora_server.conf"
|
||||
PANDORA_PID_PATH="/var/run"
|
||||
PANDORA_PID=$PANDORA_PID_PATH/pandora_plugin.pid
|
||||
PANDORA_DAEMON=/usr/local/bin/pandora_plugin
|
||||
|
||||
# Main script
|
||||
|
||||
if [ ! -d "$PANDORA_PID_PATH" ]
|
||||
then
|
||||
echo "Pandora FMS Plugin Server cannot write it's PID file in $PANDORA_PID_PATH. Please create that directory"
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ ! -f $PANDORA_DAEMON ]
|
||||
then
|
||||
echo "Pandora FMS Plugin Server not found, please check setup and read manual"
|
||||
exit
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
OLD_PATH="`pwd`"
|
||||
PANDORA_PID=$(pidof -x $PANDORA_DAEMON)
|
||||
if [ ! -z $PANDORA_PID ]
|
||||
then
|
||||
echo "Pandora FMS Plugin Server is currently running on this machine with PID ($PANDORA_PID). Aborting now..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
$PANDORA_DAEMON $PANDORA_HOME -D
|
||||
sleep 1
|
||||
|
||||
PANDORA_PID=$(pidof -x $PANDORA_DAEMON)
|
||||
if [ ! -z "$PANDORA_PID" ]
|
||||
then
|
||||
echo "Pandora FMS Plugin Server is now running with PID $PANDORA_PID"
|
||||
else
|
||||
echo "Cannot start Pandora FMS Plugin Server. Aborted."
|
||||
fi
|
||||
cd "$OLD_PATH"
|
||||
;;
|
||||
stop)
|
||||
PANDORA_PID=$(pidof -x $PANDORA_DAEMON)
|
||||
if [ -z $PANDORA_PID ]
|
||||
then
|
||||
echo "Pandora FMS Plugin Server is not running, cannot stop it."
|
||||
exit 1
|
||||
else
|
||||
echo "Stopping Pandora FMS Plugin Server"
|
||||
kill $PANDORA_PID > /dev/null 2>&1
|
||||
rm -f $PANDORA_PID
|
||||
fi
|
||||
;;
|
||||
force-reload|restart)
|
||||
$0 stop
|
||||
sleep 2
|
||||
$0 start
|
||||
;;
|
||||
*)
|
||||
echo "Usage: pandora_plugin {start|stop|restart}"
|
||||
exit 1
|
||||
esac
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Pandora FMS Prediction Server, startup script
|
||||
# Copyright (c) 2006-2008 Sancho Lerena, <slerena@gmail.com>
|
||||
# Linux Version (generic)
|
||||
# v2.1 Build 081030
|
||||
# http://www.pandorafms.com
|
||||
|
||||
# Configurable path and filenames
|
||||
PANDORA_HOME="/etc/pandora/pandora_server.conf"
|
||||
PANDORA_PID_PATH="/var/run"
|
||||
PANDORA_PID=$PANDORA_PID_PATH/pandora_prediction.pid
|
||||
PANDORA_DAEMON=/usr/local/bin/pandora_prediction
|
||||
|
||||
# Main script
|
||||
|
||||
if [ ! -d "$PANDORA_PID_PATH" ]
|
||||
then
|
||||
echo "Pandora FMS cannot write it's PID file in $PANDORA_PID_PATH. Please create that directory"
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ ! -f $PANDORA_DAEMON ]
|
||||
then
|
||||
echo "Pandora FMS Prediction Server not found, please check setup and read manual"
|
||||
exit
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
OLD_PATH="`pwd`"
|
||||
PANDORA_PID=$(pidof -x $PANDORA_DAEMON)
|
||||
if [ ! -z $PANDORA_PID ]
|
||||
then
|
||||
echo "Pandora FMS Prediction Server is currently running on this machine with PID ($PANDORA_PID). Aborting now..."
|
||||
exit 1
|
||||
else
|
||||
rm -f $PANDORA_PID
|
||||
fi
|
||||
|
||||
$PANDORA_DAEMON $PANDORA_HOME -D
|
||||
sleep 1
|
||||
|
||||
PANDORA_PID=$(pidof -x $PANDORA_DAEMON)
|
||||
if [ ! -z "$PANDORA_PID" ]
|
||||
then
|
||||
echo "Pandora FMS Prediction Server is now running with PID $PANDORA_PID"
|
||||
else
|
||||
echo "Cannot start Pandora FMS Prediction Server. Aborted."
|
||||
fi
|
||||
cd "$OLD_PATH"
|
||||
;;
|
||||
stop)
|
||||
PANDORA_PID=$(pidof -x $PANDORA_DAEMON)
|
||||
if [ -z $PANDORA_PID ]
|
||||
then
|
||||
echo "Pandora FMS Prediction Server is not running, cannot stop it."
|
||||
exit 1
|
||||
else
|
||||
echo "Stopping Pandora FMS Prediction Server"
|
||||
kill $PANDORA_PID > /dev/null 2>&1
|
||||
rm -f $PANDORA_PID
|
||||
fi
|
||||
;;
|
||||
force-reload|restart)
|
||||
$0 stop
|
||||
sleep 2
|
||||
$0 start
|
||||
;;
|
||||
*)
|
||||
echo "Usage: pandora_prediction {start|stop|restart}"
|
||||
exit 1
|
||||
esac
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Pandora FMS Recon Server, startup script
|
||||
# Copyright (c) 2006-2008 Sancho Lerena, <slerena@gmail.com>
|
||||
# Linux Version (generic)
|
||||
# v2.1 Build 081030
|
||||
# http://www.pandorafms.com
|
||||
|
||||
# Configurable path and filenames
|
||||
PANDORA_HOME="/etc/pandora/pandora_server.conf"
|
||||
PANDORA_PID_PATH="/var/run"
|
||||
PANDORA_PID=$PANDORA_PID_PATH/pandora_recon.pid
|
||||
PANDORA_DAEMON=/usr/local/bin/pandora_recon
|
||||
|
||||
# Main script
|
||||
|
||||
if [ ! -d "$PANDORA_PID_PATH" ]
|
||||
then
|
||||
echo "Pandora FMS cannot write it's PID file in $PANDORA_PID_PATH. Please create that directory"
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ ! -f $PANDORA_DAEMON ]
|
||||
then
|
||||
echo "Pandora FMS Recon Server not found, please check setup and read manual"
|
||||
exit
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
OLD_PATH="`pwd`"
|
||||
PANDORA_PID=$(pidof -x $PANDORA_DAEMON)
|
||||
if [ ! -z $PANDORA_PID ]
|
||||
then
|
||||
echo "Pandora FMS Recon Server is currently running on this machine with PID ($PANDORA_PID). Aborting now..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
$PANDORA_DAEMON $PANDORA_HOME -D
|
||||
sleep 1
|
||||
|
||||
PANDORA_PID=$(pidof -x $PANDORA_DAEMON)
|
||||
if [ ! -z "$PANDORA_PID" ]
|
||||
then
|
||||
echo "Pandora Recon Server is now running with PID $PANDORA_PID"
|
||||
else
|
||||
echo "Cannot start Pandora FMS Recon Server. Aborted."
|
||||
fi
|
||||
cd "$OLD_PATH"
|
||||
;;
|
||||
stop)
|
||||
PANDORA_PID=$(pidof -x $PANDORA_DAEMON)
|
||||
if [ -z $PANDORA_PID ]
|
||||
then
|
||||
echo "Pandora FMS Recon Server is not running, cannot stop it."
|
||||
exit 1
|
||||
else
|
||||
echo "Stopping Pandora FMS Recon Server"
|
||||
kill $PANDORA_PID > /dev/null 2>&1
|
||||
rm -f $PANDORA_PID
|
||||
fi
|
||||
;;
|
||||
force-reload|restart)
|
||||
$0 stop
|
||||
sleep 2
|
||||
$0 start
|
||||
;;
|
||||
*)
|
||||
echo "Usage: pandora_recon {start|stop|restart}"
|
||||
exit 1
|
||||
esac
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Pandora FMS Data Server, startup script
|
||||
# Pandora FMS Server, startup script
|
||||
# Copyright (c) 2006-2008 Sancho Lerena, <slerena@gmail.com>
|
||||
# Linux Version (generic)
|
||||
# v2.1 Build 081030
|
||||
|
@ -9,7 +9,7 @@
|
|||
# Configurable path and filenames
|
||||
PANDORA_HOME="/etc/pandora/pandora_server.conf"
|
||||
PANDORA_PID_PATH="/var/run"
|
||||
PANDORA_PID=$PANDORA_PID_PATH/pandora_dataserver.pid
|
||||
PANDORA_PID=$PANDORA_PID_PATH/pandora_server.pid
|
||||
PANDORA_DAEMON=/usr/local/bin/pandora_server
|
||||
|
||||
# Main script
|
||||
|
@ -22,7 +22,7 @@ fi
|
|||
|
||||
if [ ! -f $PANDORA_DAEMON ]
|
||||
then
|
||||
echo "Pandora FMS Data Server not found, please check setup and read manual"
|
||||
echo "Pandora FMS Server not found, please check setup and read manual"
|
||||
exit
|
||||
fi
|
||||
|
||||
|
@ -32,7 +32,7 @@ case "$1" in
|
|||
PANDORA_PID=$(pidof -x $PANDORA_DAEMON)
|
||||
if [ ! -z $PANDORA_PID ]
|
||||
then
|
||||
echo "Pandora FMS Data Server is currently running on this machine with PID ($PANDORA_PID). Aborting now..."
|
||||
echo "Pandora FMS Server is currently running on this machine with PID ($PANDORA_PID). Aborting now..."
|
||||
exit 1
|
||||
else
|
||||
rm -f $PANDORA_PID
|
||||
|
@ -44,9 +44,9 @@ case "$1" in
|
|||
PANDORA_PID=$(pidof -x $PANDORA_DAEMON)
|
||||
if [ ! -z "$PANDORA_PID" ]
|
||||
then
|
||||
echo "Pandora Data Server is now running with PID $PANDORA_PID"
|
||||
echo "Pandora Server is now running with PID $PANDORA_PID"
|
||||
else
|
||||
echo "Cannot start Pandora FMS Data Server. Aborted."
|
||||
echo "Cannot start Pandora FMS Server. Aborted."
|
||||
fi
|
||||
cd "$OLD_PATH"
|
||||
;;
|
||||
|
@ -54,10 +54,10 @@ case "$1" in
|
|||
PANDORA_PID=$(pidof -x $PANDORA_DAEMON)
|
||||
if [ -z $PANDORA_PID ]
|
||||
then
|
||||
echo "Pandora FMS Data Server is not running, cannot stop it."
|
||||
echo "Pandora FMS Server is not running, cannot stop it."
|
||||
exit 1
|
||||
else
|
||||
echo "Stopping Pandora FMS Data Server"
|
||||
echo "Stopping Pandora FMS Server"
|
||||
kill $PANDORA_PID > /dev/null 2>&1
|
||||
rm -f $PANDORA_PID
|
||||
fi
|
||||
|
|
|
@ -67,31 +67,12 @@ else
|
|||
cp pandora_* /etc/init.d/
|
||||
rm /etc/init.d/pandora_server_installer
|
||||
ln -s /etc/init.d/pandora_server /etc/rc2.d/S90pandora_server
|
||||
ln -s /etc/init.d/pandora_recon /etc/rc2.d/S90pandora_recon
|
||||
ln -s /etc/init.d/pandora_network /etc/rc2.d/S90pandora_network
|
||||
ln -s /etc/init.d/pandora_snmpconsole /etc/rc2.d/S90pandora_snmpconsole
|
||||
ln -s /etc/init.d/pandora_plugin /etc/rc2.d/S90pandora_plugin
|
||||
ln -s /etc/init.d/pandora_prediction /etc/rc2.d/S90pandora_prediction
|
||||
ln -s /etc/init.d/pandora_wmi /etc/rc2.d/S90pandora_wmi
|
||||
fi
|
||||
|
||||
if [ -e /usr/local/bin/pandora_server ]
|
||||
then
|
||||
ln -s /usr/local/bin/pandora_server /usr/bin/pandora_server
|
||||
ln -s /usr/local/bin/pandora_snmpconsole /usr/bin/pandora_snmpconsole
|
||||
ln -s /usr/local/bin/pandora_recon /usr/bin/pandora_recon
|
||||
ln -s /usr/local/bin/pandora_network /usr/bin/pandora_network
|
||||
ln -s /usr/local/bin/pandora_prediction /usr/bin/pandora_prediction
|
||||
ln -s /usr/local/bin/pandora_plugin /usr/bin/pandora_plugin
|
||||
ln -s /usr/local/bin/pandora_wmi /usr/bin/pandora_wmi
|
||||
else
|
||||
ln -s /usr/bin/pandora_server /usr/local/bin/pandora_server
|
||||
ln -s /usr/bin/pandora_network /usr/local/bin/pandora_network
|
||||
ln -s /usr/bin/pandora_recon /usr/local/bin/pandora_recon
|
||||
ln -s /usr/bin/pandora_plugin /usr/local/bin/pandora_plugin
|
||||
ln -s /usr/bin/pandora_prediction /usr/local/bin/pandora_prediction
|
||||
ln -s /usr/bin/pandora_snmpconsole /usr/local/bin/pandora_snmpconsole
|
||||
ln -s /usr/bin/pandora_wmi /usr/local/bin/pandora_wmi
|
||||
fi
|
||||
|
||||
mkdir /usr/share/pandora
|
||||
|
@ -126,36 +107,12 @@ uninstall () {
|
|||
rm -Rf /var/log/pandora/ 2> /dev/null
|
||||
rm -Rf /etc/pandora/pandora_server.conf 2> /dev/null
|
||||
rm -Rf /etc/init.d/pandora_server 2> /dev/null
|
||||
rm -Rf /etc/init.d/pandora_network 2> /dev/null
|
||||
rm -Rf /etc/init.d/pandora_recon 2> /dev/null
|
||||
rm -Rf /etc/init.d/pandora_snmpconsole 2> /dev/null
|
||||
rm -Rf /etc/init.d/pandora_prediction 2> /dev/null
|
||||
rm -Rf /etc/init.d/pandora_wmi 2> /dev/null
|
||||
rm -Rf /etc/init.d/pandora_plugin 2> /dev/null
|
||||
|
||||
rm -Rf /etc/rc2.d/S90pandora_server 2> /dev/null
|
||||
rm -Rf /etc/rc2.d/S90pandora_recon 2> /dev/null
|
||||
rm -Rf /etc/rc2.d/S90pandora_network 2> /dev/null
|
||||
rm -Rf /etc/rc2.d/S90pandora_snmpconsole 2> /dev/null
|
||||
rm -Rf /etc/rc2.d/S90pandora_wmi 2> /dev/null
|
||||
rm -Rf /etc/rc2.d/S90pandora_prediction 2> /dev/null
|
||||
rm -Rf /etc/rc2.d/S90pandora_plugin 2> /dev/null
|
||||
|
||||
rm -Rf /usr/local/bin/pandora_server 2> /dev/null
|
||||
rm -Rf /usr/local/bin/pandora_snmpconsole 2> /dev/null
|
||||
rm -Rf /usr/local/bin/pandora_recon 2> /dev/null
|
||||
rm -Rf /usr/local/bin/pandora_network 2> /dev/null
|
||||
rm -Rf /usr/local/bin/pandora_wmi 2> /dev/null
|
||||
rm -Rf /usr/local/bin/pandora_prediction 2> /dev/null
|
||||
rm -Rf /usr/local/bin/pandora_plugin 2> /dev/null
|
||||
|
||||
rm -Rf /usr/bin/pandora_wmi 2> /dev/null
|
||||
rm -Rf /usr/bin/pandora_server 2> /dev/null
|
||||
rm -Rf /usr/bin/pandora_snmpconsole 2> /dev/null
|
||||
rm -Rf /usr/bin/pandora_recon 2> /dev/null
|
||||
rm -Rf /usr/bin/pandora_network 2> /dev/null
|
||||
rm -Rf /usr/bin/pandora_prediction 2> /dev/null
|
||||
rm -Rf /usr/bin/pandora_plugin 2> /dev/null
|
||||
|
||||
rm -Rf /usr/share/pandora
|
||||
rm -Rf /etc/cron.daily/pandora_purge_db
|
||||
|
|
|
@ -1,152 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Pandora FMS SNMP Console, startup script
|
||||
# Copyright (c) 2006-2008 Sancho Lerena, <slerena@gmail.com>
|
||||
# Linux Version (generic)
|
||||
# v2.0 Build 080903
|
||||
# http://www.pandorafms.com
|
||||
|
||||
# Compatible with NetSNMP 5.1 or higher
|
||||
|
||||
# Configurable path and filenames
|
||||
PANDORA_HOME="/etc/pandora/pandora_server.conf"
|
||||
PANDORA_PID_PATH="/var/run/"
|
||||
PANDORA_PID=$PANDORA_PID_PATH/pandora_snmp.pid
|
||||
PANDORA_DAEMON=/usr/local/bin/pandora_snmpconsole
|
||||
|
||||
DAEMON_LOG="/var/log/pandora/pandora_snmptrap.log"
|
||||
DAEMON_PID="$PANDORA_PID_PATH/pandora_snmptrapd.pid"
|
||||
DAEMON_PATH=/usr/sbin/snmptrapd
|
||||
|
||||
# Dont touch this call unless you know are doing.
|
||||
# For different versions of NetSNMP Trap daemon, it's possible you need to change some options
|
||||
# Please refer NetSNMP documentation in that case.
|
||||
DAEMON_OPTIONS="-t -On -n -a -Lf $DAEMON_LOG -p $DAEMON_PID -F %4y-%02.2m-%l[**]%02.2h:%02.2j:%02.2k[**]%a[**]%N[**]%w[**]%W[**]%q[**]%v\n"
|
||||
DAEMON="$DAEMON_PATH $DAEMON_OPTIONS"
|
||||
|
||||
if [ ! -d "$PANDORA_PID_PATH" ]
|
||||
then
|
||||
echo "Pandora FMS cannot write it's PID file in $PANDORA_PID_PATH. Please create that directory"
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ ! -f "$DAEMON_PATH" ]
|
||||
then
|
||||
echo "NetSNMP snmptrapd not found at $DAEMON_PATH, please check setup and read manual"
|
||||
exit
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
if [ -f $DAEMON_PID ]
|
||||
then
|
||||
CHECK_PID=`cat $DAEMON_PID`
|
||||
CHECK_PID_RESULT=`ps aux | grep -v grep | grep "$CHECK_PID" | grep "snmp" | wc -l`
|
||||
if [ $CHECK_PID_RESULT == 1 ]
|
||||
then
|
||||
echo "NetSNMP Trap daemon is currently running on this machine with PID ($CHECK_PID). Aborting now..."
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
|
||||
SNMP_WARNING=`ps aux | grep "$DAEMON_PATH" | grep -v grep | wc -l`
|
||||
if [ $SNMP_WARNING == 1 ]
|
||||
then
|
||||
echo "WARNING: Seems to be already running a SNMP trap daemon on this system not associated with Pandora FMS"
|
||||
echo "Check manually if their output logfile is been used for Pandora FMS and it's format is correct"
|
||||
fi
|
||||
|
||||
# Launch SNMP TRAP Daemon
|
||||
$DAEMON
|
||||
|
||||
sleep 1
|
||||
if [ ! -f $DAEMON_LOG ]
|
||||
then
|
||||
echo "Problem with NetSNMP Trap daemon (Logfile $DAEMON_LOG not found!). Aborting"
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ -f $DAEMON_PID ]
|
||||
then
|
||||
CHECK_PID=`cat $DAEMON_PID`
|
||||
CHECK_PID_RESULT=`ps aux | grep -v grep | grep "$CHECK_PID" | grep "snmp" | wc -l`
|
||||
if [ $CHECK_PID_RESULT != 1 ]
|
||||
then
|
||||
echo "Problem starting NetSNMP Trap daemon on this machine (PID File not correct). Aborting now..."
|
||||
exit
|
||||
fi
|
||||
else
|
||||
echo "Problem starting NetSNMP Trap daemon on this machine (Cannot get PID File). Aborting now..."
|
||||
exit
|
||||
fi
|
||||
|
||||
RESULT="`cat $DAEMON_LOG | grep 'errno 13' 2> /dev/null`"
|
||||
if [ -z "$RESULT" ]
|
||||
then
|
||||
echo "NetSNMP Trap daemon is now running with PID `cat $DAEMON_PID 2> /dev/null`"
|
||||
else
|
||||
echo "NetSNMP cannot open port (udp/162). Please execute as root user"
|
||||
rm -f $DAEMON_PID 2> /dev/null
|
||||
fi
|
||||
|
||||
if [ -f $PANDORA_PID ]
|
||||
then
|
||||
CHECK_PID=`cat $PANDORA_PID`
|
||||
CHECK_PID_RESULT=`ps aux | grep -v grep | grep "$CHECK_PID" | grep "pandora_snmpconsole" | wc -l`
|
||||
if [ $CHECK_PID_RESULT == 1 ]
|
||||
then
|
||||
echo "Pandora FMS SNMP Server is currently running on this machine with PID ($CHECK_PID). Aborting now..."
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
|
||||
$PANDORA_DAEMON $PANDORA_HOME -D
|
||||
sleep 1
|
||||
|
||||
MYPID=`ps aux | grep "$PANDORA_DAEMON" | grep -v grep | tail -1 | awk '{print $2}'`
|
||||
if [ ! -z "$MYPID" ]
|
||||
then
|
||||
echo $MYPID > $PANDORA_PID
|
||||
echo "Pandora FMS SNMP Server is now running with PID $MYPID"
|
||||
else
|
||||
echo "Cannot start Pandora FMS SNMP Server. Aborted"
|
||||
fi
|
||||
cd "$OLD_PATH"
|
||||
;;
|
||||
stop)
|
||||
if [ -f $DAEMON_PID ]
|
||||
then
|
||||
echo "Stopping NetSNMP Trap daemon"
|
||||
PID_1=`cat $DAEMON_PID`
|
||||
if [ ! -z "`ps -F -p $PID_1 | grep -v grep | grep 'snmptrapd'`" ]
|
||||
then
|
||||
kill -9 `cat $DAEMON_PID 2> /dev/null`
|
||||
fi
|
||||
rm -f $DAEMON_PID 2> /dev/null > /dev/null
|
||||
rm -f $DAEMON_LOG 2> /dev/null > /dev/null
|
||||
else
|
||||
echo "NetSNMP Trap daemon is not running, cannot stop it."
|
||||
fi
|
||||
|
||||
if [ -f $PANDORA_PID ]
|
||||
then
|
||||
echo "Stopping Pandora SNMP Console"
|
||||
PID_2=`cat $PANDORA_PID`
|
||||
if [ ! -z "`ps -F -p $PID_2 | grep -v grep | grep 'pandora_snmpconsole'`" ]
|
||||
then
|
||||
kill `cat $PANDORA_PID` 2> /dev/null > /dev/null
|
||||
fi
|
||||
rm -f $PANDORA_PID
|
||||
else
|
||||
echo "Pandora FMS SNMP Console is not running, cannot stop it."
|
||||
fi
|
||||
;;
|
||||
force-reload|restart)
|
||||
$0 stop
|
||||
$0 start
|
||||
;;
|
||||
*)
|
||||
echo "Usage: pandora_snmpconsole {start|stop|restart}"
|
||||
exit 1
|
||||
esac
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Pandora FMS WMI Server, startup script
|
||||
# Copyright (c) 2006-2008 Sancho Lerena, <slerena@gmail.com>
|
||||
# Linux Version (generic)
|
||||
# v2.1 Build 081030
|
||||
# http://www.pandorafms.com
|
||||
|
||||
# Configurable path and filenames
|
||||
PANDORA_HOME="/etc/pandora/pandora_server.conf"
|
||||
PANDORA_PID_PATH="/var/run"
|
||||
PANDORA_PID=$PANDORA_PID_PATH/pandora_wmi.pid
|
||||
PANDORA_DAEMON=/usr/local/bin/pandora_wmi
|
||||
|
||||
# Main script
|
||||
|
||||
if [ ! -d "$PANDORA_PID_PATH" ]
|
||||
then
|
||||
echo "Pandora FMS WMI Server cannot write it's PID file in $PANDORA_PID_PATH. Please create that directory"
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ ! -f $PANDORA_DAEMON ]
|
||||
then
|
||||
echo "Pandora FMS WMI Server not found, please check setup and read manual"
|
||||
exit
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
OLD_PATH="`pwd`"
|
||||
PANDORA_PID=$(pidof -x $PANDORA_DAEMON)
|
||||
if [ ! -z $PANDORA_PID ]
|
||||
then
|
||||
echo "Pandora FMS WMI Server is currently running on this machine with PID ($PANDORA_PID). Aborting now..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
$PANDORA_DAEMON $PANDORA_HOME -D
|
||||
sleep 1
|
||||
|
||||
PANDORA_PID=$(pidof -x $PANDORA_DAEMON)
|
||||
if [ ! -z "$PANDORA_PID" ]
|
||||
then
|
||||
echo "Pandora FMS WMI Server is now running with PID $PANDORA_PID"
|
||||
else
|
||||
echo "Cannot start Pandora FMS WMI Server. Aborted."
|
||||
fi
|
||||
cd "$OLD_PATH"
|
||||
;;
|
||||
stop)
|
||||
PANDORA_PID=$(pidof -x $PANDORA_DAEMON)
|
||||
if [ -z $PANDORA_PID ]
|
||||
then
|
||||
echo "Pandora FMS WMI Server is not running, cannot stop it."
|
||||
exit 1
|
||||
else
|
||||
echo "Stopping Pandora FMS WMI Server"
|
||||
kill $PANDORA_PID > /dev/null 2>&1
|
||||
rm -f $PANDORA_PID
|
||||
fi
|
||||
;;
|
||||
force-reload|restart)
|
||||
$0 stop
|
||||
sleep 2
|
||||
$0 start
|
||||
;;
|
||||
*)
|
||||
echo "Usage: pandora_plugin {start|stop|restart}"
|
||||
exit 1
|
||||
esac
|
||||
|
|
@ -17,6 +17,8 @@
|
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
################################################################################
|
||||
|
||||
use POSIX qw(strftime);
|
||||
|
||||
# Configure here target (AGENT_ID for Stress)
|
||||
|
||||
my $target_module = -1; # -1 for all modules of that agent
|
||||
|
@ -29,15 +31,14 @@ my $target_days = 30;
|
|||
|
||||
# Includes list
|
||||
use strict;
|
||||
use Time::Local; # DateTime basic manipulation
|
||||
use DBI; # DB interface with MySQL
|
||||
use Date::Manip; # Date/Time manipulation
|
||||
use Math::Trig; # Math functions
|
||||
|
||||
# Pandora Modules
|
||||
use PandoraFMS::Config;
|
||||
use PandoraFMS::Tools;
|
||||
use PandoraFMS::DB;
|
||||
use PandoraFMS::Core;
|
||||
|
||||
################################################################################
|
||||
################################################################################
|
||||
|
@ -55,7 +56,7 @@ my %pa_config;
|
|||
pandora_init(\%pa_config,"Pandora DB Stress tool");
|
||||
|
||||
# Read config file for Global variables
|
||||
pandora_loadconfig (\%pa_config,0); #Start like a data server
|
||||
pandora_load_config (\%pa_config,0); #Start like a data server
|
||||
|
||||
# open database, only ONCE. We pass reference to DBI handler ($dbh) to all subprocess
|
||||
my $dbh = DBI->connect("DBI:mysql:$pa_config{'dbname'}:$pa_config{'dbhost'}:3306",$pa_config{'dbuser'}, $pa_config{'dbpass'}, { RaiseError => 1, AutoCommit => 1 });
|
||||
|
@ -79,11 +80,10 @@ if ($target_agent ne -1){
|
|||
|
||||
my $s_idag = $dbh->prepare($query_idag);
|
||||
$s_idag ->execute;
|
||||
my @data;
|
||||
if ($s_idag->rows != 0) {
|
||||
while (@data = $s_idag->fetchrow_array()) {
|
||||
while (my $module = $s_idag->fetchrow_hashref()) {
|
||||
# Fill this module with data !
|
||||
process_module (\%pa_config, $data[0], $target_interval, $data[4], $target_days, $data[2], $data[1], $dbh);
|
||||
process_module (\%pa_config, $module, $target_interval, $target_days, $dbh);
|
||||
}
|
||||
}
|
||||
$s_idag->finish();
|
||||
|
@ -99,35 +99,31 @@ print " [*] All work done\n\n";
|
|||
# (random) or periodic curve (cuve) values.
|
||||
##############################################################################
|
||||
|
||||
sub process_module(){
|
||||
my $pa_config = $_[0];
|
||||
my $id_agentemodulo = $_[1];
|
||||
my $target_interval = $_[2];
|
||||
my $target_name = $_[3];
|
||||
my $target_days = $_[4];
|
||||
my $target_type = $_[5];
|
||||
my $target_agent = $_[6];
|
||||
my $dbh = $_[7];
|
||||
sub process_module($$$$$){
|
||||
my ($pa_config, $module, $target_interval, $target_days, $dbh) = @_;
|
||||
|
||||
my $id_agentemodulo = $module->{'id_agente_modulo'};
|
||||
my $target_name = $module->{'nombre'};
|
||||
my $target_agent = $module->{'id_agente'};
|
||||
|
||||
my $factor;
|
||||
$target_type = dame_nombretipomodulo_idagentemodulo ($pa_config, $target_type, $dbh);
|
||||
|
||||
my $valor = 0; # value storage for data generation
|
||||
my $a; # loopcounter
|
||||
my $b; # counter
|
||||
print " [*] Processing module $target_name \n";
|
||||
my $agent_name = dame_agente_nombre ($pa_config, $target_agent, $dbh);
|
||||
my $agent_name = get_agent_name ($dbh, $target_agent);
|
||||
my $err; # not used
|
||||
# Init start time to now - target_days
|
||||
my $fecha_actual = &UnixDate("today","%Y-%m-%d %H:%M:%S");
|
||||
my $m_timestamp = DateCalc($fecha_actual,"- $target_days days",\$err);
|
||||
my $mysql_date;
|
||||
my $bUpdateDatos;
|
||||
my $utimestamp = time () - (86400 * $target_days);
|
||||
my $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime($utimestamp));
|
||||
|
||||
# Calculate how many iterations need to fill data range
|
||||
# $target_days*min*sec / $target_interval
|
||||
|
||||
my $iterations = ($target_days * 24 * 60 * 60) / $target_interval;
|
||||
|
||||
print " [D] ID_AgenteMoludo $id_agentemodulo Interval $target_interval ModuleName $target_name Days $target_days Type $target_type Agent $target_agent \n";
|
||||
print " [D] ID_AgenteMoludo $id_agentemodulo Interval $target_interval ModuleName $target_name Days $target_days Agent $target_agent \n";
|
||||
|
||||
open (LOG,">> pandora_dbstress.log");
|
||||
# Generate MATH/Curve data for beautiful Drawings
|
||||
|
@ -141,18 +137,19 @@ sub process_module(){
|
|||
if ($b > 180){
|
||||
$b =0;
|
||||
}
|
||||
$m_timestamp = DateCalc($m_timestamp,"+ $target_interval seconds",\$err);
|
||||
$mysql_date = &UnixDate($m_timestamp,"%Y-%m-%d %H:%M:%S");
|
||||
$utimestamp += $target_interval;
|
||||
my $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime($utimestamp));
|
||||
$valor = $valor * $b * 10;
|
||||
$valor = sprintf("%.2f", $valor);
|
||||
$valor =~ s/\,/\./g;
|
||||
$valor =~ s/\,/\./g;
|
||||
if (($a % 20) == 0) {
|
||||
print "\r -> ".int($a / ($iterations / 100))."% generated for ($target_name) ";
|
||||
}
|
||||
pandora_lastagentcontact($pa_config, $mysql_date, $agent_name, "none","1.2", $target_interval, $dbh);
|
||||
pandora_update_agent($pa_config, $timestamp, $target_agent, "none","1.2", $target_interval, $dbh);
|
||||
# print LOG $mysql_date, $target_name, $valor, "\n";
|
||||
pandora_writedata($pa_config,$mysql_date,$agent_name,$target_type,$target_name,$valor,0,0,"",$dbh,\$bUpdateDatos);
|
||||
pandora_writestate ($pa_config,$agent_name,$target_type,$target_name,$valor,100,$dbh,$bUpdateDatos);
|
||||
pandora_process_module ($pa_config, $valor, '', $module, '', '', $utimestamp, $dbh);
|
||||
#pandora_writedata($pa_config,$mysql_date,$agent_name,$target_type,$target_name,$valor,0,0,"",$dbh,\$bUpdateDatos);
|
||||
#pandora_writestate ($pa_config,$agent_name,$target_type,$target_name,$valor,100,$dbh,$bUpdateDatos);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,15 +160,16 @@ sub process_module(){
|
|||
$valor = rand(15) + rand(15) + rand(15) + rand(15) + rand(15) + rand(15);
|
||||
$valor = sprintf("%.2f", $valor);
|
||||
$valor =~ s/\,/\./g;
|
||||
$m_timestamp = DateCalc($m_timestamp,"+ $target_interval seconds",\$err);
|
||||
$mysql_date = &UnixDate($m_timestamp,"%Y-%m-%d %H:%M:%S");
|
||||
$utimestamp += $target_interval;
|
||||
my $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime($utimestamp));
|
||||
if ($a % 20 == 0) {
|
||||
print "\r -> ".int($a / ($iterations / 100))."% generated for ($target_name) ";
|
||||
}
|
||||
pandora_lastagentcontact($pa_config, $mysql_date, $agent_name, "none","1.2", $target_interval, $dbh);
|
||||
pandora_update_agent($pa_config, $timestamp, $target_agent, "none","1.2", $target_interval, $dbh);
|
||||
#print LOG $mysql_date, $target_name, $valor, "\n";
|
||||
pandora_writedata($pa_config,$mysql_date,$agent_name,$target_type,$target_name,$valor,0,0,"",$dbh,\$bUpdateDatos);
|
||||
pandora_writestate ($pa_config,$agent_name,$target_type,$target_name,$valor,100,$dbh,$bUpdateDatos);
|
||||
pandora_process_module ($pa_config, $valor, '', $module, '', '', $utimestamp, $dbh);
|
||||
#pandora_writedata($pa_config,$mysql_date,$agent_name,$target_type,$target_name,$valor,0,0,"",$dbh,\$bUpdateDatos);
|
||||
#pandora_writestate ($pa_config,$agent_name,$target_type,$target_name,$valor,100,$dbh,$bUpdateDatos);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -185,15 +183,16 @@ sub process_module(){
|
|||
} else {
|
||||
$valor = 0;
|
||||
}
|
||||
$m_timestamp = DateCalc($m_timestamp,"+ $target_interval seconds",\$err);
|
||||
$mysql_date = &UnixDate($m_timestamp,"%Y-%m-%d %H:%M:%S");
|
||||
$utimestamp += $target_interval;
|
||||
my $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime($utimestamp));
|
||||
if ($a % 20 eq 0) {
|
||||
print "\r -> ".int($a / ($iterations / 100))."% generated for ($target_name) ";
|
||||
}
|
||||
pandora_lastagentcontact($pa_config, $mysql_date, $agent_name, "none","1.2", $target_interval, $dbh);
|
||||
pandora_update_agent($pa_config, $timestamp, $target_agent, "none","1.2", $target_interval, $dbh);
|
||||
#print LOG $mysql_date, $target_name, $valor, "\n";
|
||||
pandora_writedata($pa_config,$mysql_date,$agent_name,$target_type,$target_name,$valor,0,0,"",$dbh,\$bUpdateDatos);
|
||||
pandora_writestate ($pa_config,$agent_name,$target_type,$target_name,$valor,$valor,$dbh,$bUpdateDatos);
|
||||
pandora_process_module ($pa_config, $valor, '', $module, '', '', $utimestamp, $dbh);
|
||||
#pandora_writedata($pa_config,$mysql_date,$agent_name,$target_type,$target_name,$valor,0,0,"",$dbh,\$bUpdateDatos);
|
||||
#pandora_writestate ($pa_config,$agent_name,$target_type,$target_name,$valor,$valor,$dbh,$bUpdateDatos);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -202,15 +201,16 @@ sub process_module(){
|
|||
if ( $target_name =~ /text/i ){
|
||||
for ($a=1;$a<$iterations;$a++){
|
||||
$valor = pandora_trash_ascii (rand(100)+50);
|
||||
$m_timestamp = DateCalc($m_timestamp,"+ $target_interval seconds",\$err);
|
||||
$mysql_date = &UnixDate($m_timestamp,"%Y-%m-%d %H:%M:%S");
|
||||
$utimestamp += $target_interval;
|
||||
my $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime($utimestamp));
|
||||
if ($a % 20 eq 0) {
|
||||
print "\r -> ".int($a / ($iterations / 100))."% generated for ($target_name) ";
|
||||
}
|
||||
pandora_lastagentcontact($pa_config, $mysql_date, $agent_name, "none","1.2", $target_interval, $dbh);
|
||||
pandora_update_agent($pa_config, $timestamp, $target_agent, "none","1.2", $target_interval, $dbh);
|
||||
#print LOG $mysql_date, $target_name, $valor, "\n";
|
||||
pandora_writedata($pa_config,$mysql_date,$agent_name,$target_type,$target_name,$valor,0,0,"",$dbh,\$bUpdateDatos);
|
||||
pandora_writestate ($pa_config,$agent_name,$target_type,$target_name,$valor,100,$dbh,$bUpdateDatos);
|
||||
pandora_process_module ($pa_config, $valor, '', $module, '', '', $utimestamp, $dbh);
|
||||
#pandora_writedata($pa_config,$mysql_date,$agent_name,$target_type,$target_name,$valor,0,0,"",$dbh,\$bUpdateDatos);
|
||||
#pandora_writestate ($pa_config,$agent_name,$target_type,$target_name,$valor,100,$dbh,$bUpdateDatos);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue