pandorafms/pandora_server/bin/pandora_server

306 lines
9.3 KiB
Perl
Executable File

#!/usr/bin/perl
##########################################################################
# Pandora FMS Server
# Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org
##########################################################################
# Copyright (c) 2005-2010 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.
##########################################################################
use strict;
use warnings;
use POSIX qw(strftime);
# Default lib dir for RPM and DEB packages
use lib '/usr/lib/perl5';
# Pandora Modules
use PandoraFMS::DB;
use PandoraFMS::Config;
use PandoraFMS::Tools;
use PandoraFMS::Core;
use PandoraFMS::DataServer;
use PandoraFMS::NetworkServer;
use PandoraFMS::SNMPServer;
use PandoraFMS::ReconServer;
use PandoraFMS::WMIServer;
use PandoraFMS::PluginServer;
use PandoraFMS::PredictionServer;
# Global vars
my %Config;
my @Servers;
my $DBH;
########################################################################################
# Server shutdown. Handler to do a controlled shutdown.
########################################################################################
sub pandora_shutdown () {
logger (\%Config, 'Pandora FMS Server \'' . $Config{'servername'} . '\' Shutdown by signal ', 1);
# Stop servers
foreach my $server (@Servers) {
$server->downEvent ();
$server->stop ();
}
print_message (\%Config, ' [*] Shutting down ' . $Config{'servername'} . "(received signal)...\n", 1);
db_disconnect ($DBH);
exit (0);
}
########################################################################################
# Server startup.
########################################################################################
sub pandora_startup () {
# Start logging
pandora_start_log (\%Config);
# Connect to the DB
$DBH = db_connect ('mysql', $Config{'dbname'}, $Config{'dbhost'}, 3306,
$Config{'dbuser'}, $Config{'dbpass'});
# Grab config tokens shared with the console and not in the .conf
pandora_get_sharedconfig (\%Config, $DBH);
pandora_audit (\%Config, 'Pandora FMS Server Daemon starting', 'SYSTEM', 'System', $DBH);
# Load servers
pandora_reset_server (\%Config, $DBH);
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 restart.
########################################################################################
sub pandora_restart () {
# Stop the servers
foreach my $server (@Servers) {
$server->stop ();
}
# Remove the servers
while (pop (@Servers)) {};
# Close STDERR, redirected by pandora_start_log
close (STDERR);
# Wait before trying to start again
sleep ($Config{'restart_delay'});
# Start the servers
pandora_startup ();
}
########################################################################################
# Server crash. Handler to write in the log unhandled errors and write it to console
########################################################################################
sub pandora_crash () {
my $full_error = "";
# Avoid show messages about enterprise library loading failurem, VERY
# confussing, all of them are warnigs and not critical, and user should be
# worried about that. If perl has a more "clean" way to avoid this messages
# will be nice to replace this code, but at this time it's the only way I know
foreach my $error_line (@_) {
if ($error_line !~ m/Enterprise/i && $error_line !~ m/Format_XS/i && $error_line !~ m/ConfigLocal/i){
logger (\%Config, '[E] \'' . $Config{'servername'} . "': $error_line", 1);
} else {
if ($error_line !~ m/Can\'t\slocate/) {
logger (\%Config, '[E] \'' . $Config{'servername'} . "': $error_line", 1);
} else {
# Known errors of loading Enterprise, Format_XS and ConfigLocal
# modules, non fatal.
return;
}
}
$full_error .= $error_line;
}
logger (\%Config, 'Pandora FMS Server \'' . $Config{'servername'} . '\' unhandled error.', 1);
# It's interesting show by console problems, not only in logs. This helps
# to solve stupid problems like Database credential problems for example
print_message (\%Config, ' [E] Unhandled error in "' . $Config{'servername'} . "\". See more information in logfiles at '/var/log/pandora' \n", 0);
print_message (\%Config, " Error description:\n", 0);
print_message (\%Config, $full_error, 0);
}
$SIG{'TERM'} = 'pandora_shutdown';
$SIG{'INT'} = 'pandora_shutdown';
# Error handler needs to be reviewed, Enterprise not found errors are too nasty :(
$SIG{__DIE__} = 'pandora_crash';
# Prevent alarm from bombing the main thread when called within a thread
$SIG{'ALRM'} = 'IGNORE';
# Initialize
pandora_init(\%Config, 'Pandora FMS Server');
pandora_load_config (\%Config);
# Load enterprise module
if (enterprise_load (\%Config) == 0) {
print_message (\%Config, " [*] Pandora FMS Enterprise module not available.", 1);
} else {
print_message (\%Config, " [*] Pandora FMS Enterprise module loaded.", 1);
}
# Daemonize and put in background
if ($Config{'daemon'} == 1) {
print_message (\%Config, " [*] Backgrounding Pandora FMS Server process.\n", 1);
pandora_daemonize (\%Config);
}
# Start the servers
pandora_startup ();
# Generate 'going up' events
foreach my $server (@Servers) {
$server->upEvent ();
}
# Main loop
my $time_ref = time ();
my $counter = 0;
while (1) {
eval {
# TASKS DONE EACH 5 SECONDS (Low latency tasks)
# ---------------------------------------------
# Server status update each 5 seconds
# Neightbourhood problem detection each 5 seconds
# Forced alerts each 5 seconds as well
if (($counter % 5) == 0) {
# Update server status
foreach my $server (@Servers) {
die ($server->getErrStr ()) unless ($server->checkThreads () == 1);
$server->update ();
}
# Update fallen servers
db_do ($DBH, "UPDATE tserver SET status = 0 WHERE keepalive < ?", strftime ("%Y-%m-%d %H:%M:%S", localtime(time() - $Config{'keepalive'})));
# Update forced alerts
pandora_exec_forced_alerts (\%Config, $DBH);
}
# TASKS DONE EACH 30 SECONDS (Med latency tasks)
# ---------------------------------------------
# Tasks executed only each Server Threshold x 30 secs, for low-priority tasks
if (($counter % 30) == 0) {
# Keepalive module control.(very DB intensive, not run frecuently
pandora_module_keep_alive_nd (\%Config, $DBH);
# Multicast status report each 30 x Server Threshold secs
enterprise_hook('mcast_status_report', [\%Config, $DBH]);
}
# TASKS DONE EACH 60 SECONDS (Low latency tasks)
# ---------------------------------------------
if (($counter % 60) == 0) {
# Downtimes are executed only 30 x Server Threshold secs
pandora_planned_downtime (\%Config, $DBH);
# Realtime stats (Only master server!) - ( VERY HEAVY !)
# Realtimestats == 1, generated by WEB Console, not by server!
if ($Config{"pandora_master"} == 1
&& defined($Config{"realtimestats"})
&& $Config{"realtimestats"} == 0){
# Check if I need to refresh stats
my $last_execution_stats = get_db_value ($DBH, "SELECT MAX(utimestamp) FROM tgroup_stat");
if (!defined($last_execution_stats) || $last_execution_stats < (time() - $Config{"stats_interval"})){
pandora_group_statistics (\%Config, $DBH);
pandora_server_statistics (\%Config, $DBH);
}
# Pandora self monitoring
if (defined($Config{"self_monitoring"})
&& $Config{"self_monitoring"} == 1){
pandora_self_monitoring (\%Config, $DBH);
}
}
}
};
# Restart on error or auto restart
if ($@) {
if ($Config{'restart'} eq '0') {
print_message (\%Config, $@, 1);
pandora_shutdown ();
}
# Generate 'restarting' events
foreach my $server (@Servers) {
$server->restartEvent ($@);
}
logger (\%Config, 'Pandora FMS Server restarting (' . $@ . ') in ' . $Config{'restart_delay'} . ' seconds.', 1);
pandora_restart ();
} elsif (($Config{'auto_restart'} > 0) && (time () - $time_ref > $Config{'auto_restart'})) {
$time_ref = time ();
# Mute
open(OLDOUT, ">&STDOUT");
open (STDOUT, '>/dev/null');
# Restart
pandora_restart ();
# Unmute
open(STDOUT, ">&OLDOUT");
close (OLDOUT);
}
# Avoid counter overflow
if ($counter > 10000){
$counter = 0;
} else {
$counter++;
}
threads->yield;
sleep (1);
}