Merge branch 'ent-10849-cambiar-modo-del-servidor-un-solo-proceso-muchos-hilos-varios-procesos-algunos-hilos' into 'develop'

Ent 10849 cambiar modo del servidor un solo proceso muchos hilos varios procesos algunos hilos

See merge request artica/pandorafms!6883
This commit is contained in:
Daniel Rodriguez 2024-03-01 08:49:37 +00:00
commit f786e28bca
7 changed files with 159 additions and 62 deletions

View File

@ -132,18 +132,6 @@ sub pandora_startup () {
# Grab config tokens shared with the console and not in the .conf
pandora_get_sharedconfig (\%Config, $DBH);
# Kill any running server threads.
stop_server_threads();
# Start the task execution thread.
start_server_thread(\&pandora_server_tasks, [\%Config]);
# Start the policy queue thread.
start_server_thread(\&pandora_process_policy_queue, [\%Config]) if ($Config{'__enterprise_enabled'} == 1 && $Config{'policy_manager'} == 1);
# Start agent autoconfiguration thread.
start_server_thread(\&pandora_agent_autoconfiguration_scheduled, [\%Config]) if ($Config{'__enterprise_enabled'} == 1 && $Config{'autoconfigure_agents'} == 1);
pandora_audit (\%Config, $Config{'rb_product_name'} . ' Server Daemon starting', 'SYSTEM', 'System', $DBH);
# Load servers
@ -168,6 +156,18 @@ sub pandora_startup () {
# There are enterprise metaconsole servers!
enterprise_hook('load_enterprise_servers', [\@Servers, \%Config, $DBH]);
# Kill any running server threads.
stop_server_threads();
# Start the task execution thread.
start_server_thread(\&pandora_server_tasks, [\%Config]);
# Start the policy queue thread.
start_server_thread(\&pandora_process_policy_queue, [\%Config]) if ($Config{'__enterprise_enabled'} == 1 && $Config{'policy_manager'} == 1);
# Start agent autoconfiguration thread.
start_server_thread(\&pandora_agent_autoconfiguration_scheduled, [\%Config]) if ($Config{'__enterprise_enabled'} == 1 && $Config{'autoconfigure_agents'} == 1);
# Start the netflow daemon if necessary
pandora_start_netflow_daemon ();
@ -806,7 +806,13 @@ sub main() {
# Update server status
foreach my $server (@Servers) {
die ($server->getErrStr ()) unless ($server->checkThreads () == 1);
# Check server threads.
die ($server->getErrStr()) unless ($server->checkThreads() == 1);
# Check (and restart if needed) child processes.
$server->run() if ($server->checkProc() == 0);
$server->update();
}

View File

@ -816,6 +816,9 @@ madeserver_autofit 7d
# Model sensitivity. A lower value triggers less anomalies (PANDORA FMS ENTERPRISE ONLY).
madeserver_sensitivity 0.1
# If set to 1, Pandora FMS servers will run in separate processes.
multiprocess 0
# If greater than 0, generate an event when more than the specified number of XML data files are queued for an agent.
too_many_xml 10

View File

@ -589,6 +589,8 @@ sub pandora_load_config {
$pa_config->{"madeserver"} = 0; # 774.
$pa_config->{"multiprocess"} = 0; # 775.
$pa_config->{"too_many_xml"} = 10; # 776.
$pa_config->{"mail_subject_encoding"} = 'MIME-Header'; # 776.
@ -1416,10 +1418,13 @@ sub pandora_load_config {
elsif ($parametro =~ m/^ssl_verify\s+([0-1])/i) {
$pa_config->{'ssl_verify'} = clean_blank($1);
}
elsif ($parametro =~ m/^madeserver\s+([0-1])/i){
elsif ($parametro =~ m/^madeserver\s+([0-1])/i) {
$pa_config->{'madeserver'}= clean_blank($1);
}
elsif ($parametro =~ m/^too_many_xml\s+([0-9]*)/i){
elsif ($parametro =~ m/^multiprocess\s+([0-1])/i) {
$pa_config->{'multiprocess'}= clean_blank($1);
}
elsif ($parametro =~ m/^too_many_xml\s+([0-9]*)/i) {
$pa_config->{'too_many_xml'}= clean_blank($1);
}
} # end of loop for parameter #

View File

@ -156,7 +156,7 @@ sub db_connect ($$$$$$) {
$RDBMS_QUOTE_STRING = '"';
# Connect to MySQL
my $dbh = DBI->connect("DBI:mysql:$db_name:$db_host:$db_port;$SSL_OPTS", $db_user, $db_pass, { RaiseError => 1, AutoCommit => 1 });
my $dbh = DBI->connect("DBI:mysql:$db_name:$db_host:$db_port;$SSL_OPTS", $db_user, $db_pass, { RaiseError => 1, AutoCommit => 1, AutoInactiveDestroy => 1 });
return undef unless defined ($dbh);
# Enable auto reconnect

View File

@ -31,6 +31,7 @@ BEGIN { push @INC, '/usr/lib/perl5'; }
use PandoraFMS::DB;
use PandoraFMS::Core;
use PandoraFMS::Server;
use PandoraFMS::Tools;
# Inherits from PandoraFMS::Server
our @ISA = qw(PandoraFMS::Server);
@ -48,10 +49,16 @@ sub new ($$$$$;$) {
# Call the constructor of the parent class
my $self = $class->SUPER::new($config, $server_type, $dbh);
# Set producer/consumer functions
# Set producer/consumer functions and wrappers
$self->{'_producer_wrapper'} = \&PandoraFMS::ProducerConsumerServer::data_producer;
$self->{'_consumer_wrapper'} = \&PandoraFMS::ProducerConsumerServer::data_consumer;
$self->{'_producer'} = $producer;
$self->{'_consumer'} = $consumer;
# Configure forking
$self->{'_fork'} = $config->{'multiprocess'} == 1 ? 1 : 0;
$self->{'_child_pid'} = undef;
# Run!
$RUN = 1;
@ -77,6 +84,15 @@ sub getConsumer ($) {
return $self->{'_consumer'};
}
########################################################################################
# Enable forking.
########################################################################################
sub setFork ($) {
my $self = shift;
$self->{'_fork'} = 1;
}
###############################################################################
# Run.
###############################################################################
@ -87,6 +103,36 @@ sub run ($$$$$) {
$self->update ();
$self->setServerID ();
# Run the server in a new process.
if ($self->{'_fork'} == 1) {
# Ignore SIGCHLD.
$SIG{CHLD} = 'IGNORE';
# Fork!
$self->{'_child_pid'} = fork();
die($!) unless defined($self->{'_child_pid'});
}
# The parent should exit.
# The child will start the producer/consumer threads.
if (defined($self->{'_child_pid'})) {
if ($self->{'_child_pid'} != 0) {
return;
} else {
# Restore the SIGCHLD handler.
$SIG{CHLD} = 'DEFAULT';
# Rename the process to prevent conflicts.
my $suffix = lc(get_server_name($self->getServerType()));
$0 =~ s/pandora_server/pandora_$suffix/;
# Clone the DB handle to prevent errors.
$self->{'_dbh'} = $self->{'_dbh'}->clone();
}
}
# Launch consumer threads
for (1..$self->getNumThreads ()) {
@ -112,9 +158,10 @@ sub run ($$$$$) {
# Make consumer stats reachable from the thread
$self->{'_consumer_stats'}->{threads->tid()} = $consumer_stats;
PandoraFMS::ProducerConsumerServer::data_consumer->(@_);
$self->{'_consumer_wrapper'}->(@_);
}, $self, $task_queue, $pending_tasks, $sem, $task_sem
);
return unless defined ($thr);
$self->addThread ($thr->tid ());
@ -122,7 +169,6 @@ sub run ($$$$$) {
$self->{'_consumer_stats'}->{$thr->tid()} = $consumer_stats;
}
# Enable producer stats
my $producer_stats = shared_clone({
'tstamp' => time(),
@ -132,10 +178,8 @@ sub run ($$$$$) {
'task_queue' => $task_queue,
});
# Launch producer thread
my $thr = threads->create ({'exit' => 'thread_only'},
sub {
my ($self, $task_queue, $pending_tasks, $sem, $task_sem) = @_;
# When fork is enabled, the child runs the producer in a loop.
if (defined($self->{'_child_pid'}) && $self->{'_child_pid'} == 0) {
local $SIG{'KILL'} = sub {
$RUN = 0;
$task_sem->up();
@ -143,17 +187,33 @@ sub run ($$$$$) {
exit 0;
};
# Make producer stats reachable from the thread
$self->{'_producer_stats'}->{threads->tid()} = $producer_stats;
$self->{'_producer_wrapper'}->($self, $task_queue, $pending_tasks, $sem, $task_sem);
exit 0;
}
# Launch producer thread
else {
my $thr = threads->create ({'exit' => 'thread_only'},
sub {
my ($self, $task_queue, $pending_tasks, $sem, $task_sem) = @_;
local $SIG{'KILL'} = sub {
$RUN = 0;
$task_sem->up();
$sem->up();
exit 0;
};
PandoraFMS::ProducerConsumerServer::data_producer->(@_);
}, $self, $task_queue, $pending_tasks, $sem, $task_sem
);
return unless defined ($thr);
$self->addThread ($thr->tid ());
# Make producer stats reachable from the thread
$self->{'_producer_stats'}->{threads->tid()} = $producer_stats;
# Make producer stats reachable from the main program
$self->{'_producer_stats'}->{$thr->tid()} = $producer_stats;
$self->{'_producer_wrapper'}->(@_);
}, $self, $task_queue, $pending_tasks, $sem, $task_sem
);
return unless defined ($thr);
$self->addThread ($thr->tid ());
# Make producer stats reachable from the main program
$self->{'_producer_stats'}->{$thr->tid()} = $producer_stats;
}
}
###############################################################################
@ -185,7 +245,7 @@ sub data_producer ($$$$$) {
$sem->up;
next;
}
# Queue task and signal consumers
$pending_tasks->{$task} = 0;
push (@{$task_queue}, $task);
@ -280,6 +340,10 @@ sub data_consumer ($$$$$) {
sub DESTROY {
my $self = shift;
if (defined($self->{'_child_pid'}) && $self->{'_child_pid'} != 0) {
kill(9, $self->{'_child_pid'});
}
$RUN = 0;
}

View File

@ -270,6 +270,24 @@ sub checkThreads ($) {
return 1;
}
########################################################################################
# Returns 1 if the child process is running or there is no child process, 0 otherwise.
########################################################################################
sub checkProc ($) {
my $self = shift;
# Should there be a child process?
if (defined($self->{'_child_pid'}) && $self->{'_child_pid'} != 0) {
# Is the child process running?
if (kill(0, $self->{'_child_pid'}) == 0) {
return 0;
}
}
return 1;
}
########################################################################################
# Generate a 'going up' event.
########################################################################################

View File

@ -58,6 +58,36 @@ sub new ($$;$) {
return undef unless defined ($config->{'webserver'}) and ($config->{'webserver'} == 1);
# Use Goliat with CURL
if ($config->{'web_engine'} eq 'curl') {
require PandoraFMS::Goliat::GoliatCURL;
PandoraFMS::Goliat::GoliatCURL->import;
# Check for CURL binary
if (system ("curl -V >/dev/null 2>&1") >> 8 != 0) {
logger ($config, ' [E] CURL binary not found. Install CURL or uncomment the web_engine configuration token to use LWP.', 1);
print_message ($config, ' [E] CURL binary not found. Install CURL or uncomment the web_engine configuration token to use LWP.', 1);
return undef;
}
# Check for pandora_exec binary
if (system ("\"" . $config->{'plugin_exec'} . "\" 10 echo >/dev/null 2>&1") >> 8 != 0) {
logger ($config, ' [E] ' . $config->{'plugin_exec'} . ' not found. Please install it or add it to the PATH.', 1);
print_message ($config, ' [E] ' . $config->{'plugin_exec'} . ' not found. Please install it or add it to the PATH.', 1);
return undef;
}
}
# Use LWP by default
else {
require PandoraFMS::Goliat::GoliatLWP;
PandoraFMS::Goliat::GoliatLWP->import;
if (! LWP::UserAgent->can('ssl_opts')) {
logger($config, "LWP version $LWP::VERSION does not support SSL. Make sure version 6.0 or higher is installed.", 1);
print_message ($config, " [W] LWP version $LWP::VERSION does not support SSL. Make sure version 6.0 or higher is installed.", 1);
}
}
# Initialize semaphores and queues
@TaskQueue = ();
%PendingTasks = ();
@ -80,35 +110,6 @@ sub run ($) {
print_message ($pa_config, " [*] Starting " . $pa_config->{'rb_product_name'} . " Web Server.", 1);
# Use Goliat with CURL
if ($pa_config->{'web_engine'} eq 'curl') {
require PandoraFMS::Goliat::GoliatCURL;
PandoraFMS::Goliat::GoliatCURL->import;
# Check for CURL binary
if (system ("curl -V >$DEVNULL 2>&1") >> 8 != 0) {
logger ($pa_config, ' [E] CURL binary not found. Install CURL or uncomment the web_engine configuration token to use LWP.', 1);
print_message ($pa_config, ' [E] CURL binary not found. Install CURL or uncomment the web_engine configuration token to use LWP.', 1);
return undef;
}
# Check for pandora_exec binary
if (system ("\"" . $pa_config->{'plugin_exec'} . "\" 10 echo >$DEVNULL 2>&1") >> 8 != 0) {
logger ($pa_config, ' [E] ' . $pa_config->{'plugin_exec'} . ' not found. Please install it or add it to the PATH.', 1);
print_message ($pa_config, ' [E] ' . $pa_config->{'plugin_exec'} . ' not found. Please install it or add it to the PATH.', 1);
return undef;
}
}
# Use LWP by default
else {
require PandoraFMS::Goliat::GoliatLWP;
PandoraFMS::Goliat::GoliatLWP->import;
if (! LWP::UserAgent->can('ssl_opts')) {
logger($pa_config, "LWP version $LWP::VERSION does not support SSL. Make sure version 6.0 or higher is installed.", 1);
print_message ($pa_config, " [W] LWP version $LWP::VERSION does not support SSL. Make sure version 6.0 or higher is installed.", 1);
}
}
$self->setNumThreads ($pa_config->{'web_threads'});
$self->SUPER::run (\@TaskQueue, \%PendingTasks, $Sem, $TaskSem);
}