From d836ad78174f636cb07cf3869a49ab474c3dfd09 Mon Sep 17 00:00:00 2001
From: Ramon Novoa
Date: Mon, 17 Dec 2007 17:04:37 +0000
Subject: [PATCH] 2007-12-17 Ramon Novoa
* util/n2p.pl: Added to repository. Nagios to Pandora FMS migration
script.
* util/n2p.README: Added to repository. Nagios to Pandora FMS migration
guide.
git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@684 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f
---
pandora_server/ChangeLog | 8 +
pandora_server/util/n2p.README | 90 +++
pandora_server/util/n2p.pl | 1188 ++++++++++++++++++++++++++++++++
3 files changed, 1286 insertions(+)
create mode 100644 pandora_server/util/n2p.README
create mode 100755 pandora_server/util/n2p.pl
diff --git a/pandora_server/ChangeLog b/pandora_server/ChangeLog
index 7ed613691c..13ab51eb37 100644
--- a/pandora_server/ChangeLog
+++ b/pandora_server/ChangeLog
@@ -1,3 +1,11 @@
+2007-12-17 Ramon Novoa
+
+ * util/n2p.pl: Added to repository. Nagios to Pandora FMS migration
+ script.
+
+ * util/n2p.README: Added to repository. Nagios to Pandora FMS migration
+ guide.
+
2007-12-04 Sancho Lerena
* lib/PandoraFMS/Config.pm, bin/pandora_network: This little portion of
diff --git a/pandora_server/util/n2p.README b/pandora_server/util/n2p.README
new file mode 100644
index 0000000000..554e76e0af
--- /dev/null
+++ b/pandora_server/util/n2p.README
@@ -0,0 +1,90 @@
+= NAGIOS 2.x TO PANDORA FMS 1.3 MIGRATION GUIDE =
+
+== Introduction ==
+
+Nagios and Pandora FMS have a similar goal, but they approach it in
+different ways. While Nagios is monolithic and event oriented, Pandora
+FMS is modular and data oriented.
+
+This guide will try to help you replicate your Nagios 2.x setup using
+an installed Pandora FMS 1.3, and assumes a basic knowledge of both
+tools. You should have read Pandora FMS's documentation by now :-)
+
+One of Nagios main disadvantages is it's text based configuration,
+and the fact that any change requires a complete service restart.
+
+For a large Nagios setup, going through all the configuration files can
+be a lengthy process. I have written a perl script that I hope will help
+you automate the process, you can get it from:
+
+It is in early development and far from perfect, any questions, comments
+or corrections are more than welcome. Please send them to
+rnovoa AT artica DOT es.
+
+== Hosts, Groups and Services ==
+
+There are at least three options to replicate the Nagios host and
+service setup:
+
+* If the number of hosts to monitor is small enough, you can manually
+create an agent for each host and a module for each service. You can
+even define a network template and assign it to each agent. This should
+be trivial.
+
+* If you want to monitor a network range, you can create a new recon
+task, define a network template, and let Pandora FMS's Recon Server do
+all the work.
+
+* If you have a large, custom setup, you can use the helper script to
+help you automate the process. More on that in the next chapter.
+
+If you are not using the helper script, you will have to manually create
+any new groups you want, but chances are Pandora FMS's default groups
+will suit your needs.
+
+== Using the helper script ==
+
+First of all, edit the script and change the variables $db_name, $db_host,
+$db_port, $db_user and $db_pass to point to Pandora FMS's database.
+
+You can run the script to see all the options:
+
+ $ ./n2p.pl
+
+The script takes as input any Nagios configuration files that have
+template, host, group, service or command definitions.
+
+Run the script with the following options and see the output. Pandora
+FMS's database will be left untouched:
+
+ $ ./n2p.pl -s -v [nagios_cfg_file] ...
+
+File order is important for inheritance to work. If a host uses a host
+template, the file containing the template should be passed to the
+script first.
+
+If your Nagios setup was detected correctly, run the script again. This
+time Pandora FMS's database will be changed to replicate your setup:
+
+ $ ./n2p.pl -v -a [nagios_cfg_file] ...
+
+Now you can log-in in Pandora FMS's web console and check the new
+setup. If you want to undo any changes done by the script to the database,
+just run it with the following options:
+
+ $ ./n2p.pl -v -u [nagios_cfg_file] ...
+
+== Notifications ==
+
+Nagios notifications are equivalent to Pandora FMS's alerts.
+
+Right now the helper script only creates alerts of type 'Internal
+audit'. Any other alerts, like 'eMail' or 'SMS Text', have to be
+manually added.
+
+== Other Configuration Options ==
+
+There are some Nagios configuration options that do not have an equivalent
+in Pandora FMS or are not treated by the helper script. Again, feel free
+to send any request or suggestions to rnovoa AT artica DOT es.
+
diff --git a/pandora_server/util/n2p.pl b/pandora_server/util/n2p.pl
new file mode 100755
index 0000000000..77ca041719
--- /dev/null
+++ b/pandora_server/util/n2p.pl
@@ -0,0 +1,1188 @@
+#!/usr/bin/perl -s
+################################################################################
+#
+# Copyright (c) 2007 Ramon Novoa, rnovoa@artica.es
+# Copyright (c) 2007 Artica Soluciones Tecnologicas S.L.
+#
+# n2p.pl Reads Nagios 2.x configuration files and replicates the setup
+# using an installed Pandora FMS 1.3.
+#
+# 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 of the License.
+#
+# 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.
+#
+################################################################################
+
+package n2p;
+
+# All variables have to be declared
+use strict 'vars';
+
+use DBI;
+
+# DB connection info
+my $dbh;
+my $db_name = "pandora";
+my $db_host = "localhost";
+my $db_port = "3306";
+my $db_user = "pandora";
+my $db_pass = "pandora";
+
+# Program version
+my $n2p_version = "0.1";
+my $n2p_build = "071214";
+
+# Pandora FMS version
+my $pandora_version = "1.3";
+
+# Report file
+my $report_file = "n2p.html";
+
+# Found hosts
+my %hosts;
+
+# Found host templates
+my %host_templates;
+
+# Found groups
+my %groups;
+
+# Found services
+my %services;
+
+# Found service templates
+my %service_templates;
+
+# Found commands
+my %commands;
+
+################################################################################
+## SUB write_log
+## Write log messages.
+################################################################################
+sub write_log {
+
+ if (defined ($::v)) {
+ print ("$_[0]\n");
+ }
+}
+
+################################################################################
+## SUB print_help
+## Print help screen.
+################################################################################
+sub print_help {
+
+ print ("Usage: $0 [options] [nagios_cfg_file] ...\n\n");
+ print ("Reads Nagios 2.x configuration files and replicates the setup using an installed Pandora FMS 1.3.\n\n");
+ print ("Options:\n\t-a Enable alerts.\n");
+ print ("\t-h Generate an HTML report.\n");
+ print ("\t-s Simulate, do not change Pandora FMS's database.\n");
+ print ("\t-u Undo any changes done to Pandora FMS's database.\n");
+ print ("\t-v Be verbose.\n\n");
+}
+
+################################################################################
+## SUB write_report
+## Write a report containing all the information collected from Nagios
+## configuration files.
+## TODO: Write Pandora FMS agent and module information.
+################################################################################
+sub write_report {
+ my $i;
+ my $name;
+ my $object;
+ my $class = 1;
+
+ open (FILE_HANDLER, ">$report_file") || die ("Error opening file $report_file for writing.");
+
+ print FILE_HANDLER
+'
+
+
+
+ n2p Report
+
+
+
+ n2p Report
+ Index
+
+
+
+ Host Templates
+
+
+
+ Template Name |
+ Inherits from |
+ Check Command |
+ Check Interval (s) |
+ Notification |
+ Notification Interval (s) |
+
';
+ # Host templates
+ while (($name, $object) = each (%host_templates)){
+ $class = $class == 1 ? 2 : 1;
+ print FILE_HANDLER "
+
+ $name |
+ $object->{'use'} |
+ $object->{'check_command'} |
+ $object->{'check_interval'} |
+ $object->{'notification'} |
+ $object->{'notification_interval'} |
+
";
+ }
+
+ print FILE_HANDLER
+ '
+ Index
+
+ Hosts
+
+
+
+ Host Name |
+ Alias |
+ Address |
+ Inherits from |
+ Check Command |
+ Check Interval (s) |
+ Group |
+ Network Server |
+ Notification |
+ Notification Interval (s) |
+
';
+ # Hosts
+ while (($name, $object) = each (%hosts)){
+ $class = $class == 1 ? 2 : 1;
+ print FILE_HANDLER "
+
+ $name |
+ $object->{'alias'} |
+ $object->{'address'} |
+ {'use'}\">$object->{'use'} |
+ {'check_command'}\">$object->{'check_command'} |
+ $object->{'check_interval'} |
+ {'group_name'}\">$object->{'group_name'} |
+ $object->{'network_server_id'} |
+ $object->{'notification'} |
+ $object->{'notification_interval'} |
+
";
+ }
+
+ print FILE_HANDLER
+ '
+ Index
+
+ Groups
+
+
+
+ Group Name |
+ Alias |
+ Members |
+
';
+ # Groups
+ while (($name, $object) = each (%groups)){
+ $class = $class == 1 ? 2 : 1;
+ print FILE_HANDLER "
+
+ $name |
+ $object->{'alias'} |
+ $object->{'members'} |
+
";
+ }
+
+ print FILE_HANDLER
+ '
+ Index
+
+ Service Templates
+
+
+
+ Template Name |
+ Inherits from |
+ Notification |
+ Notification Interval (s) |
+
';
+ # Service templates
+ while (($name, $object) = each (%service_templates)){
+ $class = $class == 1 ? 2 : 1;
+ print FILE_HANDLER "
+
+ $name |
+ $object->{'use'} |
+ $object->{'notification'} |
+ $object->{'notification_interval'} |
+
";
+ }
+
+ print FILE_HANDLER
+ '
+ Index
+
+ Services
+
+
+
+ Command Name |
+ Inherits from |
+ Arguments |
+ Hosts |
+ Notification |
+ Notification Interval (s) |
+
';
+ # Services
+ while (($name, $object) = each (%services)){
+ $class = $class == 1 ? 2 : 1;
+ print FILE_HANDLER "
+
+ $name |
+ {'use'}\">$object->{'use'} |
+ $object->{'arguments'} |
+ $object->{'host_name'} |
+ $object->{'notification'} |
+ $object->{'notification_interval'} |
+
";
+ }
+
+ print FILE_HANDLER
+ '
+ Index
+
+ Commands
+
+
+
+ Command Name |
+ Command Line |
+
';
+ # Commands
+ while (($name, $object) = each (%commands)){
+ $class = $class == 1 ? 2 : 1;
+ print FILE_HANDLER "
+
+ $name |
+ $object->{'command_line'} |
+
";
+ }
+
+ print FILE_HANDLER
+ '
+ Index
+
+
+';
+
+}
+
+################################################################################
+## SUB read_config
+## Parse a Nagios configuration file.
+################################################################################
+sub read_config {
+ my $line;
+ my $var;
+
+ open (FILE_HANDLER, $_[0]) || die ("Error opening file " . $_[0] . "for reading.");
+
+ # Search for object definitions
+ while ($line = ) {
+
+ # Comment
+ if ($line =~ /^[ \t]*#.*/) {
+ next;
+ }
+
+ # Definition
+ if ($line =~ /[ \t]*define[ \t]+(\w+)[ \t]*{.*/i) {
+
+ $var = uc ($1);
+
+ # Host definition
+ if ($var eq 'HOST') {
+ write_log ("\tReading host definition...");
+ read_host ();
+ }
+
+ # Host group definition
+ if ($var eq 'HOSTGROUP') {
+ write_log ("\tReading group definition...");
+ read_group ();
+ }
+
+ # Service definition
+ if ($var eq 'SERVICE') {
+ write_log ("\tReading service definition...");
+ read_service ();
+ }
+
+ # Command definition
+ if ($var eq 'COMMAND') {
+ write_log ("\tReading command definition...");
+ read_command ();
+ }
+ }
+ }
+
+ close (FILE_HANDLER);
+}
+
+################################################################################
+## SUB read_host
+## Read and store a host definition.
+################################################################################
+sub read_host {
+ my $line;
+ my $var;
+ my $address = '';
+ my $alias = '';
+ my $check_command = '';
+ # Default interval for Host Alive modules will be 5 minutes
+ my $check_interval = 300;
+ my $host_name = '';
+ my $name = '';
+ my $notification = '';
+ # Default interval for alerts will be 5 minutes
+ my $notification_interval = 300;
+ my $use = '';
+
+ while ($line = ) {
+
+ # End of host definition
+ if ($line =~ /[ \t]*}.*/) {
+
+ # A host template
+ if ($name ne '') {
+
+ write_log ("\t\tFound host template $name" . ($use eq '' ? '' : " (inherits from $use)"));
+
+ $host_templates{$name} = {
+ "address" => $address,
+ "alias" => $alias,
+ "check_command" => $check_command,
+ "check_interval" => $check_interval,
+ "notification" => $notification,
+ "notification_interval" => $notification_interval,
+ "use" => $use,
+ };
+ }
+ # A host
+ else{
+ write_log ("\t\tFound host $host_name" . ($use eq '' ? '' : " (inherits from $use)"));
+
+ $hosts{$host_name} = {
+ "address" => $address,
+ "alias" => $alias,
+ "check_command" => $check_command,
+ "check_interval" => $check_interval,
+ # Group All will be used by default
+ "group_name" => 'All',
+ "id" => -1,
+ # Network servers will be assigned later
+ "network_server_id" => -1,
+ "notification" => $notification,
+ "notification_interval" => $notification_interval,
+ "use" => $use,
+ };
+ }
+
+ return;
+ }
+
+ # Host variables
+ if ($line =~ /[ \t]*(\S+)[ \t]+(\S+).*/) {
+
+ $var = uc ($1);
+
+ if ($var eq "ADDRESS") {
+ $address = $2;
+ }
+ elsif ($var eq "ALIAS") {
+ $alias = $2;
+ }
+ elsif ($var eq "CHECK_COMMAND") {
+ $check_command = $2;
+ }
+ elsif ($var eq "CHECK_INTERVAL") {
+ # Pandora FMS needs seconds
+ $check_interval = 60 * $2;
+ }
+ elsif ($var eq "HOST_NAME") {
+ $host_name = $2;
+ }
+ elsif ($var eq "NAME") {
+ $name = $2;
+ }
+ elsif ($var eq "NOTIFICATIONS_ENABLED") {
+ $notification = $2;
+ }
+ elsif ($var eq "NOTIFICATION_INTERVAL") {
+ # Pandora FMS needs seconds
+ $notification_interval = 60 * $2;
+ }
+ # Inheritance has to be resolved now to allow
+ # value overriding
+ elsif ($var eq "USE") {
+ $use = $2;
+
+ $check_command = $host_templates{$use}->{'check_command'};
+ $check_interval = $host_templates{$use}->{'check_interval'};
+ $notification = $host_templates{$use}->{'notification'};
+ $notification_interval = $host_templates{$use}->{'notification_interval'};
+ }
+ }
+ }
+}
+
+################################################################################
+## SUB read_group
+## Read and store a group definition.
+################################################################################
+sub read_group {
+ my $line;
+ my $var;
+ my $alias = '';
+ my $hostgroup_name = '';
+ my $members = '';
+
+ while ($line = ) {
+
+ # End of group definition
+ if ($line =~ /[ \t]*}.*/) {
+
+ write_log ("\t\tFound group $hostgroup_name");
+
+ $groups{$hostgroup_name} = {
+ "alias" => $alias,
+ "id" => -1,
+ "members" => $members,
+ };
+
+ return;
+ }
+
+ # Host group variables
+ if ($line =~ /[ \t]*(\S+)[ \t]+(\S+).*/) {
+
+ $var = uc ($1);
+
+ if ($var eq "ALIAS") {
+ $alias = $2;
+ }
+ elsif ($var eq "HOSTGROUP_NAME") {
+ $hostgroup_name = $2;
+ }
+ elsif ($var eq "MEMBERS") {
+ $members = $2;
+ }
+ }
+ }
+}
+
+################################################################################
+## SUB read_service
+## Read and store a service definition.
+################################################################################
+sub read_service {
+ my $line;
+ my $var;
+ my $arguments = '';
+ my @argument_array;
+ my $check_command = '';
+ my $description = '';
+ my $host_name = '';
+ my $name = '';
+ my $notification = '';
+ # Default interval for alerts will be 5 minutes
+ my $notification_interval = 300;
+ my $use = '';
+
+ while ($line = ) {
+
+ # End of service definition
+ if ($line =~ /[ \t]*}.*/) {
+
+ # A service template
+ if ($name ne '') {
+
+ write_log ("\t\tFound service template $name" . ($use eq '' ? '' : " (inherits from $use)"));
+
+ $service_templates{$name} = {
+ "notification" => $notification,
+ "notification_interval" => $notification_interval,
+ "use" => $use,
+ };
+ }
+ # A service
+ else{
+ write_log ("\t\tFound service $check_command for hosts $host_name " . ($use eq '' ? '' : " (inherits from $use)"));
+
+ $services{$check_command} = {
+ "arguments" => $arguments,
+ "description" => $description,
+ "host_name" => $host_name,
+ "notification" => $notification,
+ "notification_interval" => $notification_interval,
+ "use" => $use,
+ };
+ }
+
+ return;
+ }
+
+ # Service variables
+ if ($line =~ /[ \t]*(\S+)[ \t]+(\S+).*/) {
+
+ $var = uc ($1);
+
+ if ($var eq "CHECK_COMMAND") {
+ @argument_array = split (/!/, $2);
+ $check_command = shift (@argument_array);
+ $arguments = join (/!/, @argument_array);
+ }
+ elsif ($var eq "HOST_NAME") {
+ $host_name = $2;
+ }
+ elsif ($var eq "NAME") {
+ $name = $2;
+ }
+ elsif ($var eq "NOTIFICATIONS_ENABLED") {
+ $notification = $2;
+ }
+ elsif ($var eq "NOTIFICATION_INTERVAL") {
+ # Pandora FMS needs seconds
+ $notification_interval = 60 * $2;
+ }
+ elsif ($var eq "SERVICE_DESCRIPTION") {
+ $description = $2;
+ }
+ # Inheritance has to be resolved now to allow
+ # value overriding
+ elsif ($var eq "USE") {
+ $use = $2;
+
+ $notification = $service_templates{$use}->{'notification'};
+ $notification_interval = $service_templates{$use}->{'notification_interval'};
+ }
+ }
+ }
+}
+
+################################################################################
+## SUB read_command
+## Read and store a command definition.
+################################################################################
+sub read_command {
+ my $line;
+ my $var;
+ my $command_line = '';
+ my $command_name = '';
+
+ while ($line = ) {
+
+ # End of command definition
+ if ($line =~ /[ \t]*}.*/) {
+
+ write_log ("\t\tFound command $command_name");
+
+ $commands{$command_name} = {
+ "command_line" => $command_line,
+ };
+
+ return;
+ }
+
+ # Command variables
+ if ($line =~ /[ \t]*(\S+)[ \t]+(.*)/) {
+
+ $var = uc ($1);
+
+ if ($var eq "COMMAND_LINE") {
+ $command_line = $2;
+ }
+ elsif ($var eq "COMMAND_NAME") {
+ $command_name = $2;
+ }
+ }
+ }
+}
+
+################################################################################
+## SUB configure_db
+## Configure Pandora FMS's database.
+################################################################################
+sub configure_db {
+
+ # Configure groups first
+ write_log ("Configuring groups...");
+ configure_db_groups ();
+
+ # Update host with the corresponding group information
+ update_host_group_name ();
+
+ # Update host information with a Pandora FMS network server
+ write_log ("Assigning network servers...");
+ update_host_network_server_id ();
+
+ # Configure hosts
+ write_log ("Configuring hosts...");
+ configure_db_hosts ();
+
+ # Configure modules and alerts
+ write_log ("Configuring modules...");
+ configure_db_modules ();
+}
+
+################################################################################
+## SUB configure_db_hosts
+## Configure Pandora FMS network agents.
+################################################################################
+sub configure_db_hosts {
+ my $host;
+ my $host_name;
+ my $host_id;
+ my $group_id;
+ my $sth_insert;
+ my @data;
+
+ # SQL Insert agent
+ $sth_insert = $dbh->prepare ("INSERT INTO tagente (nombre, direccion, comentarios, id_grupo, modo, intervalo, id_os, os_version, agent_version, disabled, agent_type, id_server) VALUES (?, ?, ?, ?, 0, ?, 11, 'Net', '$pandora_version', 0, 1, 2)") || die ("Error preparing statement: " . $sth_insert->errstr);
+
+ # Parse hosts
+ while (($host_name, $host) = each (%hosts)) {
+
+ # Check that the host does not exist
+ if (get_host_id ($host_name) != -1) {
+ die ("Error: host $host_name already exists");
+ }
+
+ # Create the host
+ write_log ("\tCreating host $host_name...");
+
+ # Group does not exist, should not happen
+ $group_id = get_group_id ($host->{'group_name'});
+ if ($group_id == -1) {
+ die ("Error: Group " . $host->{'group_name'} . " does not exists");
+ }
+
+ $sth_insert->execute ($host_name, $host->{'address'}, $host->{'alias'}, $group_id, $host->{'check_interval'}) || die ("Error executing statement: " . $sth_insert->errstr);
+
+ # Read and store the host id for later use
+ $host_id = get_host_id ($host_name);
+ $hosts{$host_name}->{'id'} = $host_id;
+ }
+}
+
+################################################################################
+## SUB configure_db_groups
+## Configure groups.
+################################################################################
+sub configure_db_groups {
+ my $group;
+ my $group_id;
+ my $group_name;
+ my $sth_insert;
+ my $sth_select;
+ my @data;
+
+ # SQL Insert group
+ $sth_insert = $dbh->prepare ("INSERT INTO tgrupo (nombre, icon, parent, disabled) VALUES (?, 'computer', '0', '0')") || die ("Error preparing statement: " . $sth_insert->errstr);
+
+ # Parse groups
+ while (($group_name, $group) = each (%groups)) {
+
+ # Check that the group does not exist
+ if (get_group_id ($group_name) != -1) {
+ die ("\tError: group $group_name already exists");
+ }
+
+ # Create the group
+ write_log ("\tCreating group $group_name...");
+ $sth_insert->execute ($group_name) || die ("Error executing statement: " . $sth_insert->errstr);
+
+ # Read and store the group id for later use
+ $group_id = get_group_id ($group_name);
+ $groups{$group_name}->{'id'} = $group_id;
+ }
+}
+
+################################################################################
+## SUB configure_db_modules
+## Configure modules for each host.
+################################################################################
+sub configure_db_modules {
+ my $host;
+ my $host_name;
+ my @host_array;
+ my $service;
+ my $service_name;
+
+ # Configure check_command service module for each host
+ while (($host_name, $host) = each (%hosts)) {
+
+ configure_db_guess_module ($host->{'check_command'}, $host_name, $host->{'notification'}, $host->{'notification_interval'});
+ }
+
+ # Configure other services
+ while (($service_name, $service) = each (%services)) {
+
+ # Configure modules for all hosts defined in service
+ @host_array = split (/,/, $service->{'host_name'});
+
+ foreach $host_name (@host_array) {
+ configure_db_guess_module ($service_name, $host_name, $service->{'notification'}, $service->{'notification_interval'});
+ }
+ }
+}
+
+################################################################################
+## SUB configure_db_guess_module
+## Guess and configure the appropiate Pandora FMS module given a Nagios service.
+################################################################################
+sub configure_db_guess_module {
+ my $service = $_[0];
+ my $agent_address;
+ my $host_id;
+ my $host_name = $_[1];
+ my $notification = $_[2];
+ my $alert_interval = $_[3];
+ my $module_id;
+ my $sth_mod;
+ my $sth_state;
+
+ # Host does not exist, should not happen
+ if (! defined ($hosts{$host_name})) {
+ die ("Agent $host_name does not exist");
+ }
+
+ # Command does not exist
+ if (! defined ($commands{$service})) {
+ write_log ("\tCommand $service does not exist, skipping...");
+ return;
+ }
+
+ $agent_address = $hosts{$host_name}->{'address'};
+ $host_id = $hosts{$host_name}->{'id'};
+
+ # SQL Insert module
+ $sth_mod = $dbh->prepare ("INSERT INTO tagente_modulo (id_agente, id_tipo_modulo, descripcion, nombre, max, min, module_interval, tcp_port, tcp_send, tcp_rcv, ip_target, id_module_group, flag, id_modulo) VALUES (?, ?, ?, ?, 0, 0, ?, ?, ?, ?, ?, ?, 0, 0)") || die ("Error preparing statement: " . $sth_mod->errstr);
+
+ # SQL Without an entry in tagente_estado a module will not work
+ $sth_state = $dbh->prepare ("INSERT INTO tagente_estado (id_agente_modulo) VALUES (?)") || die ("Error preparing statement: " . $sth_state->errstr);
+
+ $service = uc ($service);
+ if ($service eq "CHECK-HOST-ALIVE") {
+
+ # Host Alive
+ write_log ("\tAdding Host Alive module to host $host_name...");
+
+ $sth_mod->execute ($host_id, 6, 'Check if host is alive using ICMP ping check.', 'Host Alive', 120, 0, '', '', $agent_address, 2) || die ("Error executing statement: " . $sth_mod->errstr);
+
+ # Get the module id
+ $module_id = get_module_id ('Host Alive', $host_id);
+
+ # Module not found, should not happen
+ if ($module_id == -1) {
+ die ("Module Host Alive for agent $host_id not found");
+ }
+
+ # Create an entry for the module in tagente_estado
+ $sth_state->execute ($module_id) || die ("Error executing statement: " . $sth_mod->errstr);
+
+ # Create an alert if necessary
+ if ($notification == 1 && defined ($::a)) {
+ write_log ("\t\tAdding alert (type 3) to module...");
+ configure_db_alert ($module_id, "Host seems to be down", "Host seems to be down", $alert_interval);
+ }
+ }
+ elsif ($service eq "CHECK_HTTP") {
+
+ # Check HTTP Server
+ write_log ("\tAdding Check HTTP Server module to host $host_name...");
+
+ $sth_mod->execute ($host_id, 9, 'Test APACHE2 HTTP service remotely (Protocol response, not only openport)', 'Check HTTP Server', 120, 80, 'GET / HTTP/1.0^M^M', 'HTTP/1.1 200 OK', $agent_address, 3) || die ("Error executing statement: " . $sth_mod->errstr);
+
+ # Get the module id
+ $module_id = get_module_id ('Check HTTP Server', $host_id);
+
+ # Module not found, should not happen
+ if ($module_id == -1) {
+ die ("Module Check HTTP Server for agent $host_id not found");
+ }
+
+ # Create an entry for the module in tagente_estado
+ $sth_state->execute ($module_id) || die ("Error executing statement: " . $sth_mod->errstr);
+
+ # Create an alert if necessary
+ if ($notification == 1 && defined ($::a)) {
+ write_log ("\t\tAdding alert (type 3) to module...");
+ configure_db_alert ($module_id, "HTTP Server seems to be down", "HTTP Server seems to be down", $alert_interval);
+ }
+ }
+ elsif ($service eq "CHECK_FTP") {
+
+ # Check FTP Server
+ write_log ("\tAdding Check FTP Server module to host $host_name...");
+
+ $sth_mod->execute ($host_id, 9, 'Check FTP protocol, not only check port.', 'Check FTP Server', 120, 21, 'QUIT', '221', $agent_address, 3) || die ("Error executing statement: " . $sth_mod->errstr);
+
+ # Get the module id
+ $module_id = get_module_id ('Check FTP Server', $host_id);
+
+ # Module not found, should not happen
+ if ($module_id == -1) {
+ die ("Module Check FTP Server for agent $host_id not found");
+ }
+
+ # Create an entry for the module in tagente_estado
+ $sth_state->execute ($module_id) || die ("Error executing statement: " . $sth_mod->errstr);
+
+ # Create an alert if necessary
+ if ($notification == 1 && defined ($::a)) {
+ write_log ("\t\tAdding alert (type 3) to module...");
+ configure_db_alert ($module_id, "FTP Server seems to be down", "FTP Server seems to be down", $alert_interval);
+ }
+ }
+ else {
+ write_log ("\tUnknown service $service for host $host_name...");
+
+ # Do not generate an alert for an unknown service
+ $notification = 0;
+ }
+
+}
+
+################################################################################
+## SUB configure_db_alert
+## Configure an alert for a given module.
+## TODO: Add more alert types.
+################################################################################
+sub configure_db_alert {
+ my $module_id = $_[0];
+ my $alert_desc = $_[1];
+ my $alert_text = $_[2];
+ my $alert_interval = $_[3];
+ my $sth_alert;
+
+ # SQL Insert alert
+ $sth_alert = $dbh->prepare ("INSERT INTO talerta_agente_modulo (id_agente_modulo, id_alerta, descripcion, dis_max, dis_min, time_threshold, max_alerts, alert_text) VALUES (?, ?, ?, ?, ?, ?, ?, ?)") || die ("Error preparing statement: " . $sth_alert->errstr);
+
+ # Insert alert
+ $sth_alert->execute ($module_id, 3, $alert_desc, 1, 1, $alert_interval, 1, $alert_text) || die ("Error executing statement: " . $sth_alert->errstr);
+}
+
+################################################################################
+## SUB update_host_group_name
+## Assigns to each host the corresponding group information.
+################################################################################
+sub update_host_group_name {
+ my $group;
+ my $group_name;
+ my $member;
+ my @members;
+
+ while (($group_name, $group) = each (%groups)) {
+
+ # Read members
+ @members = split (/,/, $group->{'members'});
+
+ # Assume we are parsing a valid Nagios config file,
+ # no need to check whether a group member really exists or not
+ foreach $member (@members) {
+ $hosts{$member}->{'group_name'} = $group_name;
+ }
+ }
+}
+
+################################################################################
+## SUB update_host_network_server_id
+## Assigns a Pandora FMS network server to each group.
+################################################################################
+sub update_host_network_server_id {
+ my $i;
+ my $host;
+ my $host_name;
+ my $group;
+ my $group_name;
+ my $member;
+ my @members;
+ my @servers;
+ my @data;
+ my $sth;
+
+ # SQL Get a list of Pandora FMS network servers
+ $sth = $dbh->prepare ("SELECT id_server FROM tserver WHERE network_server = 1") || die ("Error preparing statement: " . $sth->errstr);
+
+
+ $sth->execute () || die ("Error executing statement: " . $sth->errstr);
+ while (@data = $sth->fetchrow_array ()) {
+ push (@servers, $data[0]);
+ }
+
+ # No network server found, this should not happen
+ if ($#servers == -1) {
+ die ("Error: no network servers found");
+ }
+
+ # Assign a network server to each group
+ $i = 0;
+ while (($group_name, $group) = each (%groups)) {
+
+ # Read members
+ @members = split (/,/, $group->{'members'});
+
+ write_log ("\tGroup $group_name assigned to network server $servers[$i]");
+
+ # Assume we are parsing a valid Nagios config file,
+ # no need to check whether a group member really exists or not
+ foreach $member (@members) {
+ $hosts{$member}->{'network_server_id'} = $servers[$i];
+ }
+
+ # Balance network server load
+ $i++;
+ if ($i > $#servers) {
+ $i = $#servers > 0 ? $i % $#servers : 0;
+ }
+ }
+
+ # Assign a network server to hosts with no assigned group
+ while (($host_name, $host) = each (%hosts)) {
+
+ if ($host->{'network_server_id'} == -1) {
+ write_log ("\tHost $host_name assigned to network server $servers[$i]");
+ $host->{'network_server_id'} = $servers[$i];
+ }
+ }
+}
+
+################################################################################
+## SUB roll_back
+## Undo any changes done to the DB.
+################################################################################
+sub roll_back {
+ my $host;
+ my $host_id;
+ my $host_name;
+ my $group;
+ my $group_name;
+ my $sth_del_host;
+ my $sth_del_group;
+ my $sth_del_module;
+ my $sth_del_state;
+ my $sth_del_alert;
+ my $sth_sel;
+ my @data;
+
+ write_log("Rolling back...");
+
+ # SQL Delete hosts
+ $sth_del_host = $dbh->prepare ("DELETE FROM tagente WHERE nombre = ?") || die ("Error preparing statement: " . $sth_del_host->errstr);
+
+ # SQL Delete groups
+ $sth_del_group = $dbh->prepare ("DELETE FROM tgrupo WHERE nombre = ?") || die ("Error preparing statement: " . $sth_del_group->errstr);
+
+ # SQL Delete modules
+ $sth_del_module = $dbh->prepare ("DELETE FROM tagente_modulo WHERE id_agente_modulo = ?") || die ("Error preparing statement: " . $sth_del_module->errstr);
+ $sth_del_state = $dbh->prepare ("DELETE FROM tagente_estado WHERE id_agente_modulo = ?") || die ("Error preparing statement: " . $sth_del_state->errstr);
+
+ # SQL Delete alerts associated with a module
+ $sth_del_alert = $dbh->prepare ("DELETE FROM talerta_agente_modulo WHERE id_agente_modulo = ?") || die ("Error preparing statement: " . $sth_del_alert->errstr);
+
+ # SQL Get all modules associated with an agent
+ $sth_sel = $dbh->prepare ("SELECT id_agente_modulo FROM tagente_modulo WHERE id_agente = ?") || die ("Error preparing statement: " . $sth_sel->errstr);
+
+ # Delete hosts
+ while (($host_name, $host) = each (%hosts)) {
+
+ write_log("\tDeleting host $host_name...");
+
+ # Get all modules associated with the host
+ $host_id = get_host_id ($host_name);
+ if ($host_id == -1) {
+ next;
+ }
+
+ $sth_sel->execute ($host_id) || die ("Error executing statement: " . $sth_sel->errstr);
+
+ # Delete alerts and modules
+ write_log("\t\tDeleting alerts and modules associated with host...");
+
+ while (@data = $sth_sel->fetchrow_array ()) {
+ $sth_del_alert->execute ($data[0]) || die ("Error executing statement: " . $sth_del_alert->errstr);
+ $sth_del_module->execute ($data[0]) || die ("Error executing statement: " . $sth_del_module->errstr);
+ $sth_del_state->execute ($data[0]) || die ("Error executing statement: " . $sth_del_state->errstr);
+ }
+
+ # Delete host
+ $sth_del_host->execute ($host_name) || die ("Error executing statement: " . $sth_del_host->errstr);
+ }
+
+ # Delete groups
+ while (($group_name, $group) = each (%groups)) {
+
+ write_log("\tDeleting group $group_name...");
+
+ $sth_del_group->execute ($group_name) || die ("Error executing statement: " . $sth_del_group->errstr);
+
+ }
+
+}
+
+################################################################################
+## SUB get_host_id
+## Get the id of a host given its name.
+################################################################################
+sub get_host_id {
+ my $name = $_[0];
+ my $sth;
+ my @data;
+
+ # SQL Get host id
+ $sth = $dbh->prepare ("SELECT id_agente FROM tagente WHERE nombre = ?") || die ("Error preparing statement: " . $sth->errstr);
+
+ $sth->execute ($name) || die ("Error executing statement: " . $sth->errstr);
+
+ # Agent not found
+ if ($sth->rows == 0) {
+ return -1;
+ }
+
+ @data = $sth->fetchrow_array ();
+
+ # Return id
+ return $data[0];
+}
+
+################################################################################
+## SUB get_group_id
+## Get the id of a group given its name.
+################################################################################
+sub get_group_id {
+ my $name = $_[0];
+ my $sth;
+ my @data;
+
+ # SQL Get group id
+ $sth = $dbh->prepare ("SELECT id_grupo FROM tgrupo WHERE nombre = ?") || die ("Error preparing statement: " . $sth->errstr);
+
+ $sth->execute ($name) || die ("Error executing statement: " . $sth->errstr);
+
+ # Group not found
+ if ($sth->rows == 0) {
+ return -1;
+ }
+
+ @data = $sth->fetchrow_array ();
+
+ # Return id
+ return $data[0];
+}
+
+################################################################################
+## SUB get_module_id
+## Get the id of a module given its name and the id of the host.
+################################################################################
+sub get_module_id {
+ my $name = $_[0];
+ my $host_id = $_[1];
+ my $sth;
+ my @data;
+
+ # SQL Get module id
+ $sth = $dbh->prepare ("SELECT id_agente_modulo FROM tagente_modulo WHERE id_agente = ? AND nombre = ?") || die ("Error preparing statement: " . $sth->errstr);
+
+ $sth->execute ($host_id, $name) || die ("Error executing statement: " . $sth->errstr);
+
+ # Module not found
+ if ($sth->rows == 0) {
+ return -1;
+ }
+
+ @data = $sth->fetchrow_array ();
+
+ # Return id
+ return $data[0];
+}
+
+################################################################################
+# Main
+################################################################################
+
+my $file;
+
+# Check command line arguments
+if ($#ARGV < 0) {
+ print_help ();
+ exit;
+}
+
+# Check that all files exist
+foreach $file (@ARGV) {
+ if (! -f $file) {
+ die "File \'$file\' does not exist.";
+ }
+}
+
+# Check connection to the DB
+$dbh = DBI->connect ("DBI:mysql:$db_name:$db_host:$db_port", $db_user, $db_pass) || die "Error connecting to the database.";
+
+# Parse Nagios configuration files
+foreach $file (@ARGV) {
+ write_log ("Reading file $file...");
+ read_config ($file);
+}
+
+# Simulation, do now write any changes to the DB
+if (defined ($::s)) {
+ $dbh->disconnect ();
+ write_log ("Done.");
+ exit;
+}
+
+# Roll back and undo any changes
+if (defined ($::u)) {
+ roll_back ();
+}
+# Configure Pandora's DB
+else {
+ configure_db ();
+ if (defined ($::h)) {
+ write_log ("Generating report...");
+ write_report ();
+ }
+}
+
+$dbh->disconnect ();
+write_log ("Done.");