2008-03-13 Sancho Lerena <slerena@gmail.com>

* lib/PandoraFMS/Config.pm: New pandora_startlog function. Added support to manage PID
    in daemon mode. Added support for quiet mode. Added prediction_threads option. 

    * lib/PandoraFMS/Tools.pm: daemonize function now manages PID and store in a file when
    it forks. 

    * lib/PandoraFMS/DB.pm: Removed some gotos.  Modified generic-access DB functions and 
    added one to manage entire row in a hash: get_db_free_row ().

    * bin/pandora_plugin: A lot of fixes. This code actually works fine :-)

    * bin/pandora_prediction: First version of usable code. Works but not seriously tested.

    * bin/pandora_network: Adjusted to work with new features (quiet mode) and new db 
    schema. Some code cleanup.

    * util/pandora_dbstress.pl: Updated default values.

    * util/pandora_dbstress.README: Improved README documentation for dbstress tool.



git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@747 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f
This commit is contained in:
slerena 2008-03-13 18:33:44 +00:00
parent 5cfd5b4353
commit b2ece3be75
9 changed files with 858 additions and 253 deletions

View File

@ -1,3 +1,25 @@
2008-03-13 Sancho Lerena <slerena@gmail.com>
* lib/PandoraFMS/Config.pm: New pandora_startlog function. Added support to manage PID
in daemon mode. Added support for quiet mode. Added prediction_threads option.
* lib/PandoraFMS/Tools.pm: daemonize function now manages PID and store in a file when
it forks.
* lib/PandoraFMS/DB.pm: Removed some gotos. Modified generic-access DB functions and
added one to manage entire row in a hash: get_db_free_row ().
* bin/pandora_plugin: A lot of fixes. This code actually works fine :-)
* bin/pandora_prediction: First version of usable code. Works but not seriously tested.
* bin/pandora_network: Adjusted to work with new features (quiet mode) and new db
schema. Some code cleanup.
* util/pandora_dbstress.pl: Updated default values.
* util/pandora_dbstress.README: Improved README documentation for dbstress tool.
2008-03-11 Manuel Arostegui <marostegui@artica.es>
* pandora_server, pandora_network, pandora_recon:

View File

@ -62,13 +62,20 @@ pandora_loadconfig (\%pa_config,1);
# Audit server starting
pandora_audit (\%pa_config, "Pandora FMS Network Daemon starting", "SYSTEM", "System");
print " [*] Starting up network threads\n";
if ( $pa_config{"daemon"} eq "1" ) {
print " [*] Backgrounding Pandora FMS Network Server process.\n\n";
&daemonize;
# Thread startup
if ($pa_config{"quiet"} == 0){
print " [*] Starting up network threads\n";
}
# Daemonize and put in background
if ( $pa_config{"daemon"} eq "1" ){
if ($pa_config{"quiet"} eq "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++){
@ -78,9 +85,15 @@ for (my $ax=0; $ax < $pa_config{'network_threads'}; $ax++){
# Launch now the network producer thread
threads->new( \&pandora_network_producer, \%pa_config);
print " [*] All threads loaded and running \n\n";
# 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);
# 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",
@ -122,7 +135,9 @@ sub pandora_network_consumer ($$) {
my $pa_config = $_[0];
my $thread_id = $_[1];
if ($pa_config->{"quiet"} == 0){
print " [*] Starting up Network Consumer Thread # $thread_id \n";
}
my $data_id_agent_module;
# Create Database handler
@ -170,7 +185,10 @@ sub pandora_network_consumer ($$) {
sub pandora_network_producer ($) {
my $pa_config = $_[0];
if ($pa_config->{"quiet"} == 0){
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 });
@ -192,13 +210,17 @@ sub pandora_network_producer ($) {
FROM
tagente, tagente_modulo, tagente_estado
WHERE
id_server = $server_id
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 (
@ -215,12 +237,16 @@ sub pandora_network_producer ($) {
FROM
tagente, tagente_modulo, tagente_estado, tserver
WHERE
( (tagente.id_server = $server_id AND tagente_modulo.id_agente = tagente.id_agente) OR
(tagente.id_server != $server_id AND tagente_modulo.id_agente = tagente.id_agente AND tagente.id_server = tserver.id_server AND tserver.status = 0)
( (tagente.id_network_server = $server_id AND tagente_modulo.id_agente = tagente.id_agente) OR
(tagente.id_network_server != $server_id AND tagente_modulo.id_agente = tagente.id_agente AND tagente.id_network_server = tserver.id_server AND tserver.status = 0)
) 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
@ -600,10 +626,12 @@ sub exec_network_module {
}
}
# --------------------------------------------------------
# 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;
@ -626,17 +654,19 @@ sub exec_network_module {
}
else {
logger ($pa_config, "Problem with unknown module type '$tipo_modulo'", 0);
goto skipdb_execmod;
$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 {
# $module_result != 0)
}
if ($module_result != 0) {
if ($module_interval == 0){
$module_interval = dame_intervalo ($pa_config, $id_agente, $dbh);
}
# Modules who cannot connect or something go bad, update last_execution_try field
logger ($pa_config, "Cannot obtain exec Network Module $nombre from agent $agent_name", 4);
my $query_act = "UPDATE tagente_estado SET current_interval = $module_interval, last_execution_try = $utimestamp WHERE id_agente_modulo = $id_agente_modulo ";
@ -644,7 +674,4 @@ sub exec_network_module {
$a_idages->execute;
$a_idages->finish();
}
skipdb_execmod:
#$dbh->disconnect();
}

View File

@ -57,27 +57,30 @@ pandora_loadconfig (\%pa_config, 4);
# Audit server starting
pandora_audit (\%pa_config, "Pandora FMS Plugin server starting", "SYSTEM", "System");
print " [*] Starting up plugin threads\n";
die "Aqui me quedo";
if ( $pa_config{"daemon"} eq "1" ) {
# 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";
&daemonize;
}
&pandora_daemonize ( \%pa_config);
}
=for COMMENT BLOCK
# 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);
}
=cut
# Launch now the producer thread
threads->new( \&pandora_plugin_producer, \%pa_config);
print " [*] All threads loaded and running \n\n";
# 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'};
@ -88,7 +91,7 @@ my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost:3306",
# Server keepalive thread running in main thread on a infinite loop
while (1) {
pandora_serverkeepaliver (\%pa_config, 1, $dbh);
pandora_serverkeepaliver (\%pa_config, 4, $dbh);
threads->yield;
sleep ($pa_config{"server_threshold"});
}
@ -120,7 +123,9 @@ 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
@ -139,6 +144,7 @@ sub pandora_plugin_consumer ($$) {
{
lock $queue_lock;
$data_id_agent_module = shift(@pending_task);
#print "[CLIENT] Pop out of queue module (pending queue) $data_id_agent_module \n";
delete($pending_task_hash{$data_id_agent_module});
$current_task_hash{$data_id_agent_module}=1;
}
@ -147,6 +153,7 @@ sub pandora_plugin_consumer ($$) {
eval {
# Call network execution process
# exec_network_module ( $pa_config, $data_id_agent_module, $dbh);
print "[CLIENT] Executing module $data_id_agent_module \n";
exec_plugin_module ($pa_config, $data_id_agent_module, $dbh);
};
if ($@){
@ -158,6 +165,7 @@ sub pandora_plugin_consumer ($$) {
# not been processed, but has been freed from task queue
{
lock $queue_lock;
#print "[CLIENT] Removing from queue (current task) module $data_id_agent_module \n";
delete($current_task_hash{$data_id_agent_module});
}
$counter = 0;
@ -191,13 +199,15 @@ sub pandora_plugin_producer ($) {
FROM
tagente, tagente_modulo, tagente_estado
WHERE
id_server = $server_id
id_plugin_server = $server_id
AND
tagente_modulo.id_agente = tagente.id_agente
AND
tagente.disabled = 0
AND
tagente_modulo.id_tipo_modulo > 4
tagente_modulo.id_plugin != 0
AND
tagente_modulo.disabled = 0
AND
tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo
AND (
@ -214,23 +224,28 @@ sub pandora_plugin_producer ($) {
FROM
tagente, tagente_modulo, tagente_estado, tserver
WHERE
( (tagente.id_server = $server_id AND tagente_modulo.id_agente = tagente.id_agente) OR
(tagente.id_server != $server_id AND tagente_modulo.id_agente = tagente.id_agente AND tagente.id_server = tserver.id_server AND tserver.status = 0)
( (tagente.id_plugin_server = $server_id AND tagente_modulo.id_agente = tagente.id_agente) OR
(tagente.id_plugin_server != $server_id AND tagente_modulo.id_agente = tagente.id_agente AND tagente.id_plugin_server = tserver.id_server AND tserver.status = 0)
) AND
tagente.disabled = 0
AND
tagente_modulo.id_tipo_modulo > 4
tagente_modulo.disabled = 0
AND
tagente_modulo.id_plugin != 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 last_execution_try ASC";
}
#print "[DEBUG] SQL is $query1 \n";
$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];
print "[DEBUG] Procesando candidato $data_id_agente_modulo\n";
# Skip modules already queued
if ((!defined($pending_task_hash{$data_id_agente_modulo})) &&
(!defined($current_task_hash{$data_id_agente_modulo}))) {
@ -239,6 +254,7 @@ sub pandora_plugin_producer ($) {
}
# Locking scope, do not remove redundant { }
{
#print "[DEBUG] Metiendo $data_id_agente_modulo en cola \n";
lock $queue_lock;
push (@pending_task, $data_id_agente_modulo);
$pending_task_hash {$data_id_agente_modulo}=1;
@ -246,6 +262,7 @@ sub pandora_plugin_producer ($) {
}
}
#logger ($pa_config, "Items in Network Pending Queue: ".scalar(@pending_task), 5);
#print "[DEBUG] Items in Network Pending Queue: ".scalar(@pending_task);
$exec_sql1->finish();
sleep($pa_config->{"server_threshold"});
} # Main loop
@ -263,17 +280,17 @@ sub exec_plugin_module {
# Set global variables for this sub
my $timeout = $pa_config->{'plugin_timeout'};
my $agent_plugin; # hash container for tagent_plugin record
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_plugin)
# 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_plugin = $exec_sql->fetchrow_hashref;
$agent_module = $exec_sql->fetchrow_hashref;
# Get a full hash for plugin record reference ($plugin)
$query_sql = "SELECT * FROM tplugin WHERE id = ".$agent_plugin->{'id_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;
@ -284,7 +301,7 @@ sub exec_plugin_module {
}
# Initialize another global sub variables.
my $agent_name = dame_agente_nombre ($pa_config, $agent_plugin->{'id_agente'}, $dbh);
my $agent_name = dame_agente_nombre ($pa_config, $agent_module->{'id_agente'}, $dbh);
my $module_result = 1; # Fail by default
my $module_data = 0; # 0 data for default
my $module_interval = 0;
@ -293,23 +310,23 @@ sub exec_plugin_module {
my $exec_output = "";
my $plugin_command = $plugin->{"execute"};
if ($plugin->{'net_dst_opt'} ne ""){
$plugin_command = $plugin_command . " ". $plugin->{'net_dst_opt'} ." ". $agent_plugin->{'ip_target'};
$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_plugin->{'tcp_port'};
$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_plugin->{'plugin_user'};
$plugin_command = $plugin_command . " ". $plugin->{'user_opt'} ." ". $agent_module->{'plugin_user'};
}
if ($plugin->{'pass_opt'} ne "") {
$plugin_command = $plugin_command . " ". $plugin->{'pass_opt'} ." ". $agent_plugin->{'plugin_pass'};
$plugin_command = $plugin_command . " ". $plugin->{'pass_opt'} ." ". $agent_module->{'plugin_pass'};
}
# Proccess field / optional / dynamic field
if ($agent_plugin->{'plugin_parameter'} ne "") {
$plugin_command = $plugin_command . $agent_plugin->{'plugin_parameter'};
if ($agent_module->{'plugin_parameter'} ne "") {
$plugin_command = $plugin_command . " ". $agent_module->{'plugin_parameter'};
}
logger ($pa_config, "Executing AM # $id_am plugin command '$plugin_command'", 9);
# Final command line execution is stored at "plugin_command"
eval {
alarm ($timeout);
@ -317,12 +334,18 @@ sub exec_plugin_module {
alarm(0); # Cancel the pending alarm if plugin call returns alive
$module_result = 0; # If comes here, this is a successfull exec
};
# print "[DEBUG] Output for $plugin_command is --$module_data-- \n";
# Timeout
if ($@ =~ /PANDORA PLUGIN SERVER TIMED OUT/) {
logger ($pa_config, "[ERROR] Plugin Task for module ".$agent_plugin->{'id_agente_modulo'}." causes a system timeout in exec", 1);
# resuming eval block...
} else {
logger ($pa_config, "[ERROR] Plugin Task for module ".$agent_plugin->{'id_agente_modulo'}." causes an unknown system error", 1);
logger ($pa_config, "[ERROR] Plugin Task for module ".$agent_module->{'id_agente_modulo'}." causes a system timeout in exec", 1);
logger ($pa_config, "Executing plugin command '$plugin_command'", 9);
print "[DEBUG] Executing plugin TIMEOUT\n";
# General error, not timed-out
} elsif ($module_result == 1) {
logger ($pa_config, "[ERROR] Plugin Task for module ".$agent_module->{'id_agente_modulo'}." causes an unknown system error", 1);
logger ($pa_config, "[ERROR] $@", 1);
print "[DEBUG] Executing plugin ERROR $@\n";
}
sub timed_out {
@ -335,46 +358,60 @@ sub exec_plugin_module {
# If module execution get a valid value
if ($module_result == 0) {
print "[DEBUG] MODULERESULT = 0\n";
my %part;
$part{'name'}[0] = $agent_plugin->{'id_agent'};
$part{'name'}[0] = $agent_module->{'nombre'};
$part{'description'}[0] = "";
$part{'data'}[0] = $module_data;
my $tipo_modulo = $agent_plugin->{'id_module_type'};
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 == $tipo_modulo) {
if (1 == $agent_module->{'id_tipo_modulo'}) {
module_generic_data ($pa_config, \%part, $timestamp, $agent_name, $tipo_modulo, $dbh);
}
elsif (4 == $tipo_modulo) {
elsif (4 == $agent_module->{'id_tipo_modulo'}) {
module_generic_data_inc ($pa_config, \%part, $timestamp, $agent_name, $tipo_modulo, $dbh);
}
elsif (3 == $tipo_modulo) {
elsif (3 == $agent_module->{'id_tipo_modulo'}) {
module_generic_data_string ($pa_config, \%part, $timestamp, $agent_name, $tipo_modulo, $dbh);
}
elsif (2 == $tipo_modulo) {
# Generic_proc
elsif (2 == $agent_module->{'id_tipo_modulo'}) {
print "[DEBUG FINAL]: ".$agent_module->{'nombre'}." ".$module_data." ".$tipo_modulo." ".$agent_name. " ".$timestamp;
module_generic_proc ($pa_config, \%part, $timestamp, $agent_name, $tipo_modulo, $dbh);
}
else {
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);
goto skipdb_execmod;
print "[DEBUG] Executing plugin UNKONWN MODULE TYPE$@\n";
$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 {
# If module execution get a INVALID value
if ($agent_plugin->{'intervalo'} == 0){
$module_interval = dame_intervalo ($pa_config, $agent_plugin->{'id_agente'}, $dbh);
}
# If something went wrong in module processing...
if ($module_result != 0){
print "[DEBUG] MODULERESULT != 0\n";
# If module execution get a INVALID value
if ($agent_module->{'intervalo'} == 0){
$module_interval = dame_intervalo ($pa_config, $agent_module->{'id_agente'}, $dbh);
}
# Modules who cannot connect or something go bad, update last_execution_try field
logger ($pa_config, "Cannot obtain exec plugin Module ".$agent_plugin->{'nombre'}." from agent $agent_name", 3);
my $query_act = "UPDATE tagente_estado SET current_interval = $module_interval, last_execution_try = $utimestamp WHERE id_agente_modulo = ".$agent_plugin->{'id_agente_modulo'};
logger ($pa_config, "Cannot obtain exec plugin Module ".$agent_module->{'nombre'}." from agent $agent_name", 2);
my $query_act = "UPDATE tagente_estado SET current_interval = $module_interval, last_execution_try = $utimestamp WHERE id_agente_modulo = ".$agent_module->{'id_agente_modulo'};
$dbh->do($query_act);
}
skipdb_execmod:
$exec_sql->finish(); #close tagent_plugin hash reference
}

View File

@ -0,0 +1,413 @@
#!/usr/bin/perl
##########################################################################
# Pandora FMS Prediction Server
##########################################################################
# 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 on a received signal
########################################################################################
sub pandora_shutdown {
logger (\%pa_config,"Pandora FMS Prediction Server Shutdown by signal ",0);
print " [*] Shutting down Pandora FMS Prediction Server (received signal)...\n";
exit;
}
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;
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
if (scalar(@pending_task) > 0){
{
lock $queue_lock;
$data_id_agent_module = shift(@pending_task);
print "[CLIENT] Pop out of queue module (pending queue) $data_id_agent_module \n";
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);
print "[PREDICT-CLIENT] Executing module # $data_id_agent_module \n";
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;
print "[CLIENT] Removing from queue (current task) module $data_id_agent_module \n";
delete($current_task_hash{$data_id_agent_module});
}
$counter = 0;
} else {
$counter ++;
}
}
}
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_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP()
OR
tagente_modulo.flag = 1
)
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, tserver
WHERE
( (tagente.id_prediction_server = $server_id AND tagente_modulo.id_agente = tagente.id_agente) OR
(tagente.id_prediction_server != $server_id AND tagente_modulo.id_agente = tagente.id_agente AND tagente.id_prediction_server = tserver.id_server AND tserver.status = 0)
) 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_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP() OR tagente_modulo.flag = 1 )
ORDER BY last_execution_try ASC";
}
# print "[DEBUG] SQL is $query1 \n";
$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];
print "[DEBUG] Procesando candidato $data_id_agente_modulo\n";
# 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 { }
{
print "[DEBUG] Metiendo $data_id_agente_modulo en cola \n";
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);
print "[DEBUG] Items in Network Pending Queue: ".scalar(@pending_task);
$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++){
print "DEBUG HASH REF ".$target_module->{'id_agente_modulo'};
print "\n";
$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;
print "DEBUG SQL - $query_sql \n";
$week_data[$i] = get_db_free_field ($query_sql, $dbh);
# 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
print "Value of n is $n \n";
if ($n > 0){
$average = $average / $n;
} else {
$average = 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));
# (PROC) Compare with current data
if ($prediction_mode == 0){
$query_sql = 'SELECT data 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_data_inc ($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);
}

View File

@ -27,15 +27,18 @@ require Exporter;
our @ISA = ("Exporter");
our %EXPORT_TAGS = ( 'all' => [ qw( ) ] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw( pandora_help_screen
our @EXPORT = qw(
pandora_help_screen
pandora_init
pandora_loadconfig );
pandora_loadconfig
pandora_startlog
);
# 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 = "2.0-dev";
my $pandora_build="PS080226";
my $pandora_build="PS080311";
our $VERSION = $pandora_version." ".$pandora_build;
# Setup hash
@ -48,11 +51,13 @@ my %pa_config;
##########################################################################
sub help_screen {
printf "\n\nSyntax: \n pandora_server < fullpathname to pandora server configuration file > [ options ] \n\n";
printf "\nSyntax: \n\n pandora_server < fullpathname to pandora server configuration file > [ options ] \n\n";
printf "Following options are optional : \n";
printf " -v : Verbose mode activated, give more information in logfile \n";
printf " -d : Debug mode activated, give extensive information in logfile \n";
printf " -D : Daemon mode (runs in backgroup)\n";
printf " -P <file> : Store PID to file.\n";
printf " -q : Quiet startup\n";
printf " -h : This screen, show a little help screen \n";
printf " \n";
exit;
@ -67,8 +72,8 @@ sub pandora_init {
my $pa_config = $_[0];
my $init_string = $_[1];
printf "\n$init_string $pandora_version Build $pandora_build Copyright (c) 2004-2008 ArticaST\n";
printf "This program is Free Software, licensed under the terms of GPL License v2.\n";
printf "You can download latest versions and documentation at http://pandora.sourceforge.net. \n\n";
printf "This program is OpenSource, licensed under the terms of GPL License version 2.\n";
printf "You can download latest versions and documentation at http://pandora.sourceforge.net \n\n";
# Load config file from command line
if ($#ARGV == -1 ){
@ -78,6 +83,8 @@ sub pandora_init {
}
$pa_config->{"verbosity"}=1; # Verbose 1 by default
$pa_config->{"daemon"}=0; # Daemon 0 by default
$pa_config->{'PID'}=""; # PID file not exist by default
$pa_config->{"quiet"}=0; # Daemon 0 by default
# If there are not valid parameters
my $parametro;
@ -90,9 +97,15 @@ sub pandora_init {
elsif ($parametro =~ m/-v\z/i) {
$pa_config->{"verbosity"}=5;
}
elsif ($parametro =~ m/^-P\z/i) {
$pa_config->{'PID'}= clean_blank($ARGV[$ax+1]);
}
elsif ($parametro =~ m/-d\z/) {
$pa_config->{"verbosity"}=10;
}
elsif ($parametro =~ m/-q\z/) {
$pa_config->{"quiet"}=1;
}
elsif ($parametro =~ m/-D\z/) {
$pa_config->{"daemon"}=1;
}
@ -161,15 +174,19 @@ sub pandora_loadconfig {
$pa_config->{"tcp_timeout"} = 20; # Introduced on 1.3.1
$pa_config->{"snmp_proc_deadresponse"} = 0; # Introduced on 1.3.1 10 Feb08
$pa_config->{"plugin_threads"} = 3; # Introduced on 2.0
$pa_config->{"prediction_threads"} = 3; # Introduced on 2.0
$pa_config->{"plugin_timeout"} = 5; # Introduced on 2.0
$pa_config->{"wmi_threads"} = 3; # Introduced on 2.0
$pa_config->{"wmi_timeout"} = 5; # Introduced on 2.0
# Check for UID0
if ($pa_config->{"quiet"} != 0){
if ($> == 0){
printf " [W] Not all Pandora FMS components need to be executed as root\n";
printf " please consider starting it with a non-privileged user.\n";
}
}
# Check for file
if ( ! -e $archivo_cfg ) {
printf "\n [ERROR] Cannot open configuration file at $archivo_cfg. \n";
@ -250,6 +267,9 @@ sub pandora_loadconfig {
elsif ($parametro =~ m/^dataserver\s([0-9]*)/i){
$pa_config->{'dataserver'}= clean_blank($1);
}
elsif ($parametro =~ m/^networkserver\s([0-9]*)/i){
$pa_config->{'networkserver'}= clean_blank($1);
}
elsif ($parametro =~ m/^pluginserver\s([0-9]*)/i){
$pa_config->{'pluginserver'}= clean_blank($1);
}
@ -316,6 +336,9 @@ sub pandora_loadconfig {
elsif ($parametro =~ m/^plugin_threads\s([0-9]*)/i) {
$pa_config->{'plugin_threads'}= clean_blank($1);
}
elsif ($parametro =~ m/^prediction_threads\s([0-9]*)/i) {
$pa_config->{'prediction_threads'}= clean_blank($1);
}
elsif ($parametro =~ m/^plugin_timeout\s([0-9]*)/i) {
$pa_config->{'plugin_timeout'}= clean_blank($1);
}
@ -326,7 +349,10 @@ sub pandora_loadconfig {
} # end of loop for parameter #
if ( $pa_config->{"verbosity"} > 0){
if (($pa_config->{"verbosity"} > 0) && ($pa_config->{"quiet"} == 0)){
if ($pa_config->{"PID"} ne ""){
print " [*] PID File is written at ".$pa_config->{'PID'}."\n";
}
print " [*] Server basepath is ".$pa_config->{'basepath'}."\n";
print " [*] Server logfile at ".$pa_config->{"logfile"}."\n";
print " [*] Server errorlogfile at ".$pa_config->{"errorlogfile"}."\n";
@ -367,6 +393,9 @@ sub pandora_loadconfig {
print " [ERROR] You must enable 'wmiserver' in setup file to run Pandora FMS WMI server. \n\n";
exit;
}
# Show some config options in startup
if ($pa_config->{"quiet"} == 0){
if ($opmode == 0){
print " [*] You are running Pandora FMS Data Server. \n";
$parametro ="Pandora FMS Data Server";
@ -408,9 +437,10 @@ sub pandora_loadconfig {
if ($pa_config->{"pandora_master"} == 1) {
print " [*] This server is running in MASTER mode.\n";
}
}
logger ($pa_config, "Launching $parametro $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");
logger ($pa_config, "Config options: $config_options", 1);
my $dbh;
# Check valid Database variables and update server status
eval {
@ -423,15 +453,24 @@ sub pandora_loadconfig {
print $@;
exit;
}
if ($pa_config->{"quiet"} == 0){
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);
# Dump all errors to errorlog
open STDERR, ">>$pa_config->{'errorlogfile'}" or die " [ERROR] Pandora FMS can't write to Errorlog. Aborting : \n $!";
my $time_now = &UnixDate("today","%Y/%m/%d %H:%M:%S");
print STDERR "$time_now - ".$pa_config->{'servername'}." Starting Pandora FMS server. Error logging activated \n";
}
sub pandora_startlog ($){
my $pa_config = $_[0];
# 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";
# This redirect ANY output to errorlog. Not a good idea for real usage !
# open STDOUT, ">>$pa_config->{'errorlogfile'}"
}
# End of function declaration
# End of defined Code

View File

@ -33,7 +33,8 @@ require Exporter;
our @ISA = ("Exporter");
our %EXPORT_TAGS = ( 'all' => [ qw( ) ] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw( crea_agente_modulo
our @EXPORT = qw(
crea_agente_modulo
dame_server_id
dame_agente_id
dame_agente_modulo_id
@ -64,7 +65,9 @@ our @EXPORT = qw( crea_agente_modulo
execute_alert
give_network_component_profile_name
pandora_create_incident
give_db_value
get_db_value
get_db_free_row
get_db_free_field
);
# Spanish translation note:
@ -374,18 +377,22 @@ sub pandora_writestate (%$$$$$$$) {
# now we use only local timestamp to stamp state of modules
my $pa_config = $_[0];
my $nombre_agente = $_[1];
my $tipo_modulo = $_[2];
my $tipo_modulo = $_[2]; # passed as string
my $nombre_modulo = $_[3];
my $datos = $_[4]; # Careful: Dont pass a hash, only a single value
my $estado = $_[5];
my $dbh = $_[6];
my $needs_update = $_[7];
my $timestamp = &UnixDate ("today", "%Y-%m-%d %H:%M:%S");
my $utimestamp; # integer version of timestamp
$utimestamp = &UnixDate($timestamp,"%s"); # convert from human to integer
my @data;
my $cambio = 0;
my $id_grupo;
# Get current timestamp / unix numeric time
my $timestamp = &UnixDate ("today", "%Y-%m-%d %H:%M:%S"); # string timestamp
my $utimestamp = &UnixDate($timestamp,"%s"); # convert from human to integer
# Get server id
my $server_name = $pa_config->{'servername'}.$pa_config->{"servermode"};
my $id_server = dame_server_id($pa_config, $server_name, $dbh);
@ -395,8 +402,9 @@ sub pandora_writestate (%$$$$$$$) {
my $id_agente = dame_agente_id ($pa_config, $nombre_agente, $dbh);
my $id_modulo = dame_modulo_id ($pa_config, $tipo_modulo, $dbh);
my $id_agente_modulo = dame_agente_modulo_id($pa_config, $id_agente, $id_modulo, $nombre_modulo, $dbh);
if (($id_agente == -1) || ($id_agente_modulo == -1)) {
goto fin_pandora_writestate;
return 0;
}
# Seek for agent_interval or module_interval
@ -453,17 +461,16 @@ sub pandora_writestate (%$$$$$$$) {
pandora_event ($pa_config, $descripcion, $id_grupo, $id_agente, $dbh);
}
if ($needs_update == 1) {
$query_act = "UPDATE tagente_estado SET utimestamp = $utimestamp, datos = $datos, cambio = '$cambio', timestamp = '$timestamp', estado = '$estado', id_agente = $id_agente, last_try = '$timestamp', current_interval = '$module_interval', running_by = $id_server, last_execution_try = $utimestamp WHERE id_agente_modulo = '$id_agente_modulo'";
$query_act = "UPDATE tagente_estado SET utimestamp = $utimestamp, datos = $datos, cambio = '$cambio', timestamp = '$timestamp', estado = '$estado', id_agente = $id_agente, last_try = '$timestamp', current_interval = '$module_interval', running_by = $id_server, last_execution_try = $utimestamp WHERE id_agente_modulo = $id_agente_modulo";
} else { # dont update last_try field, that it's the field
# we use to check last update time in database
$query_act = "UPDATE tagente_estado SET utimestamp = $utimestamp, datos = $datos, cambio = '$cambio', timestamp = '$timestamp', estado = '$estado', id_agente = $id_agente, current_interval = '$module_interval', running_by = $id_server, last_execution_try = $utimestamp WHERE id_agente_modulo = '$id_agente_modulo'";
$query_act = "UPDATE tagente_estado SET utimestamp = $utimestamp, datos = $datos, cambio = '$cambio', timestamp = '$timestamp', estado = '$estado', id_agente = $id_agente, current_interval = '$module_interval', running_by = $id_server, last_execution_try = $utimestamp WHERE id_agente_modulo = $id_agente_modulo";
}
}
my $a_idages = $dbh->prepare($query_act);
$a_idages->execute;
$a_idages->finish();
$s_idages->finish();
fin_pandora_writestate:
}
##########################################################################
@ -529,11 +536,11 @@ sub pandora_accessupdate (%$$) {
}
# Update keepalive module (if present, if there is more than one, only updates first one!).
my $id_agent_module = give_db_free ("SELECT id_agente_modulo FROM tagente_modulo WHERE id_agente = $id_agent AND id_tipo_modulo = 100", $dbh);
my $id_agent_module = get_db_free_field ("SELECT id_agente_modulo FROM tagente_modulo WHERE id_agente = $id_agent AND id_tipo_modulo = 100", $dbh);
if ($id_agent_module ne -1){
my $agent_name = give_db_free ("SELECT nombre FROM tagente WHERE id_agente = $id_agent", $dbh);
my $agent_name = get_db_free_field ("SELECT nombre FROM tagente WHERE id_agente = $id_agent", $dbh);
my $module_typename = "keep_alive";
my $module_name = give_db_free ("SELECT nombre FROM tagente_modulo WHERE id_agente_modulo = $id_agent_module", $dbh);
my $module_name = get_db_free_field ("SELECT nombre FROM tagente_modulo WHERE id_agente_modulo = $id_agent_module", $dbh);
pandora_writestate ($pa_config, $agent_name, $module_typename, $module_name, 1, 0, $dbh, 1);
}
}
@ -961,7 +968,9 @@ fin_DB_insert_datos:
##########################################################################
sub pandora_serverkeepaliver (%$$) {
my $pa_config= $_[0];
my $opmode = $_[1]; # 0 dataserver, 1 network server, 2 snmp console, 3 recon server
my $opmode = $_[1]; # 0 dataserver, 1 network server, 2 snmp console
# 3 recon srv, 4 plugin srv, 5 prediction srv
# 6 WMI server
my $dbh = $_[2];
my $version_data;
my $pandorasuffix;
@ -1024,7 +1033,7 @@ sub pandora_updateserver (%$$$) {
} elsif ($opmode == 4){
$pandorasuffix = "_Plugin";
} elsif ($opmode == 5){
$pandorasuffix = "_IA";
$pandorasuffix = "_Prediction";
} elsif ($opmode == 6){
$pandorasuffix = "_WMI";
} else {
@ -1382,7 +1391,7 @@ sub dame_modulo_id (%$$) {
if ($s_idag->rows == 0) {
logger($pa_config, "ERROR dame_modulo_id(): Cannot find module called $nombre_modulo ",1);
logger($pa_config, "ERROR: SQL Query is $query_idag ",2);
$id_modulo = -1;
$id_modulo = 0;
} else {
@data = $s_idag->fetchrow_array();
$id_modulo = $data[0];
@ -1686,7 +1695,7 @@ sub crea_agente_modulo (%$$$$$$$) {
# Generic access to a field ($field) given a table
# give_db_value (field_name_to_be_returned, table, field_search, condition_value, dbh)
# ---------------------------------------------------------------
sub give_db_value ($$$$$) {
sub get_db_value ($$$$$) {
my $field = $_[0];
my $table = $_[1];
my $field_search = $_[2];
@ -1706,9 +1715,10 @@ sub give_db_value ($$$$$) {
}
# ---------------------------------------------------------------
# Generic access to a field ($field) given a table
# Free SQL sentence. Return first field on exit
# ---------------------------------------------------------------
sub give_db_free ($$) {
sub get_db_free_field ($$) {
my $condition = $_[0];
my $dbh = $_[1];
@ -1724,6 +1734,28 @@ sub give_db_free ($$) {
return -1;
}
# ---------------------------------------------------------------
# Free SQL sentence. Return entire hash in row
# ---------------------------------------------------------------
sub get_db_free_row ($$) {
my $condition = $_[0];
my $dbh = $_[1];
my $rowref;
my $query = $condition;
my $s_idag = $dbh->prepare($query);
$s_idag ->execute;
if ($s_idag->rows != 0) {
$rowref = $s_idag->fetchrow_hashref;
$s_idag->finish();
return $rowref;
}
return -1;
}
# End of function declaration
# End of defined Code

View File

@ -27,7 +27,8 @@ require Exporter;
our @ISA = ("Exporter");
our %EXPORT_TAGS = ( 'all' => [ qw( ) ] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw( daemonize
our @EXPORT = qw(
pandora_daemonize
logger
limpia_cadena
md5check
@ -43,15 +44,23 @@ our @EXPORT = qw( daemonize
# Put program in background (for daemon mode)
##########################################################################
sub daemonize {
chdir '/tmp' or die "Can't chdir to /tmp: $!";
sub pandora_daemonize {
my $pa_config = $_[0];
open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
open STDOUT, '>>/dev/null' or die "Can't write to /dev/null: $!";
open STDERR, '>>/dev/null' or die "Can't write to /dev/null: $!";
chdir '/tmp' or die "Can't chdir to /tmp: $!";
defined(my $pid = fork) or die "Can't fork: $!";
exit if $pid;
setsid or die "Can't start a new session: $!";
umask 0;
# Store PID of this process in file presented by config token
if ($pa_config->{'PID'} ne ""){
open (FILE, "> ".$pa_config->{'PID'}) or die "[FATAL] Cannot open PIDfile at ".$pa_config->{'PID'};
print FILE "$$";
close (FILE);
}
}

View File

@ -1,8 +1,34 @@
This small utility is make to test your database speed in Pandora Scheme.
Pandora FMS DB Stress
=====================
You need to create an agent and assing modules for automated data injection with this tool. Name this modules acording this:
This is a small tool to test your database performance. It also could be used to "pregenerate" random or periodic data (using trigonometry functions) and populate ficticious modules.
You need to create an agent and assign modules for automated data injection with this tool. You need to name that modules according to this notation:
random - To generate "random" data.
curve - To generate a math curve using trigonometrical functions, useful to see interpolation working with different intervals, etc
boolean - Generate "random" boolean data.
So you could use any name that contains words "random, curve or boolean", for example:
random_1 or curve_other
You only could choose "data server" kind of module.
Finetuning DB stress tool
=========================
Tool is preconfigured to search in all agents for modules called random, curve or boolean, and to use a interval of 300 and during 30 days.
If want to modify this behaviour you should edit pandora_dbstress script and modify some variables at the top of file:
# Configure here target (AGENT_ID for Stress)
my $target_module = -1; # -1 for all modules of that agent
my $target_agent = -1;
my $target_interval = 300;
my $target_days = 30;
Set there target_module (for a fixed module) or set -1 to process all matching targets
Set there target_agent (for a specific agent).
Set target_interval in seconds for default module interval data periodicity.
Set target_days, number of days in the past from current timestamp.

View File

@ -21,8 +21,8 @@
my $target_module = -1; # -1 for all modules of that agent
my $target_agent = -1;
my $target_interval = 1200;
my $target_days = 12;
my $target_interval = 300;
my $target_days = 30;
################################################################################
################################################################################