From df0127985c82a4ef412c54d4390442325754e5d7 Mon Sep 17 00:00:00 2001
From: slerena <slerena@gmail.com>
Date: Fri, 25 Jul 2008 18:52:37 +0000
Subject: [PATCH] 2008-07-25  Sancho Lerena <slerena@gmail.com>

	* pandora_network: Added a defined() check for tcp_send string.

	* pandora_server: Added call to function pandora_planned_downtime().
	This implements planned downtimes on data server only.

	* DB.pm: Small optimization on bad data: pandora_writedata and
	pandora_writestate return -1 on bad values and skip processing data.
	More checks on undefined data (pandora_writestate).
	Added code for planned downtimes, in function pandora_planned_downtime().
	Patch for adding [RECOVER] on f2/f3 if blank. Submitted by Kato Atsushi
	Now Monitor down has priority Warning and Monitor UP priority normal.

	* pandora_*servers*: Added inmediatly status change in tserver table on
	controlled shutdown, this could be a ordered shutdown, a kill or a CTRL-C



git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@974 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f
---
 pandora_server/ChangeLog               |  17 +++
 pandora_server/bin/pandora_network     |   8 +-
 pandora_server/bin/pandora_plugin      |   7 +-
 pandora_server/bin/pandora_prediction  |   5 +-
 pandora_server/bin/pandora_recon       |   7 +-
 pandora_server/bin/pandora_server      |   5 +-
 pandora_server/bin/pandora_snmpconsole |   8 +-
 pandora_server/bin/pandora_wmi         |   7 +-
 pandora_server/lib/PandoraFMS/DB.pm    | 199 ++++++++++++++++++-------
 9 files changed, 194 insertions(+), 69 deletions(-)

diff --git a/pandora_server/ChangeLog b/pandora_server/ChangeLog
index d5f470796d..1ce30b9c90 100644
--- a/pandora_server/ChangeLog
+++ b/pandora_server/ChangeLog
@@ -1,3 +1,20 @@
+2008-07-25  Sancho Lerena <slerena@gmail.com>
+
+	* pandora_network: Added a defined() check for tcp_send string.
+
+	* pandora_server: Added call to function pandora_planned_downtime().
+	This implements planned downtimes on data server only.
+
+	* DB.pm: Small optimization on bad data: pandora_writedata and 
+	pandora_writestate return -1 on bad values and skip processing data. 
+	More checks on undefined data (pandora_writestate). 
+	Added code for planned downtimes, in function pandora_planned_downtime().
+	Patch for adding [RECOVER] on f2/f3 if blank. Submitted by Kato Atsushi
+	Now Monitor down has priority Warning and Monitor UP priority normal.
+
+	* pandora_*servers*: Added inmediatly status change in tserver table on 
+	controlled shutdown, this could be a ordered shutdown, a kill or a CTRL-C
+
 2008-07-23  Sancho Lerena <slerena@gmail.com>
 
 	* Makefile.PL: Removed reference to export_server.
diff --git a/pandora_server/bin/pandora_network b/pandora_server/bin/pandora_network
index 4353bcb847..cb62fe60c9 100755
--- a/pandora_server/bin/pandora_network
+++ b/pandora_server/bin/pandora_network
@@ -1,12 +1,16 @@
 #!/usr/bin/perl
+
 ##########################################################################
 # Pandora FMS Network Server
+# http://www.pandorafms.com
 ##########################################################################
 # Copyright (c) 2006-2008 Sancho Lerena, slerena@gmail.com
 #           (c) 2006-2008 Artica Soluciones Tecnologicas S.L
+#
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
 # as published by the Free Software Foundation; version 2
+#
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
@@ -382,7 +386,7 @@ next_pair:
 			$tcp_send = shift( @tcp_send );
 			$tcp_rcv  = shift( @tcp_rcv );
 
-		        if ($tcp_send ne ""){ # its Expected to sending data ?
+		        if  ((defined($tcp_send)) && ($tcp_send ne "")){ # its Expected to sending data ?
 			        # Send data
 			        $handle->autoflush(1);
 			        $tcp_send =~ s/\^M/\r\n/g;
@@ -390,7 +394,7 @@ next_pair:
 			        $handle->send($tcp_send);
 		        }
 		        # we expect to receive data ? (non proc types)
-		        if (($tcp_rcv ne "") || ($id_tipo_modulo == 10) || ($id_tipo_modulo ==8) || ($id_tipo_modulo == 11)) {
+		        if ((defined($tcp_rcv)) && (($tcp_rcv ne "") || ($id_tipo_modulo == 10) || ($id_tipo_modulo ==8) || ($id_tipo_modulo == 11))) {
 			        # Receive data, non-blocking !!!! (VERY IMPORTANT!)
 			        $temp2 = "";
 			        for ($tam=0; $tam<($pa_config->{'tcp_timeout'}); $tam++){
diff --git a/pandora_server/bin/pandora_plugin b/pandora_server/bin/pandora_plugin
index eb9dfc656f..a8df4584b3 100755
--- a/pandora_server/bin/pandora_plugin
+++ b/pandora_server/bin/pandora_plugin
@@ -1,15 +1,15 @@
 #!/usr/bin/perl
 
-eval 'exec /usr/bin/perl  -S $0 ${1+"$@"}'
-    if 0; # not running under some shell
 ##########################################################################
 # Pandora FMS Plugin Server
+# http://www.pandorafms.com
 ##########################################################################
 # Copyright (c) 2008 Sancho Lerena, slerena@gmail.com
 #           (c) 2008 Artica Soluciones Tecnologicas S.L
+#
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; version 2 (only).
+# 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
@@ -116,6 +116,7 @@ sub pandora_shutdown {
     print " [*] Shutting down ".$pa_config{'servername'}.$pa_config{"servermode"} ."(received signal)...\n";
     pandora_event (\%pa_config, $pa_config{'servername'}.$pa_config{"servermode"}." going Down", 0,
                                    0, 4, 0, 0, "system", $dbh);
+	pandora_updateserver (\%pa_config, $pa_config{'servername'}, 0, 4, $dbh);
     exit;
 }
 
diff --git a/pandora_server/bin/pandora_prediction b/pandora_server/bin/pandora_prediction
index 63c9e0e6e6..21d4bac517 100755
--- a/pandora_server/bin/pandora_prediction
+++ b/pandora_server/bin/pandora_prediction
@@ -1,12 +1,12 @@
 #!/usr/bin/perl
 
-eval 'exec /usr/bin/perl  -S $0 ${1+"$@"}'
-    if 0; # not running under some shell
 ##########################################################################
 # Pandora FMS Prediction Server
+# http://www.pandorafms.com
 ##########################################################################
 # Copyright (c) 2008 Sancho Lerena, slerena@gmail.com
 #           (c) 2008 Artica Soluciones Tecnologicas S.L
+#
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
 # as published by the Free Software Foundation; version 2.
@@ -116,6 +116,7 @@ sub pandora_shutdown {
     print " [*] Shutting down ".$pa_config{'servername'}.$pa_config{"servermode"} ."(received signal)...\n";
     pandora_event (\%pa_config, $pa_config{'servername'}.$pa_config{"servermode"}." going Down", 0,
                                    0, 4, 0, 0, "system", $dbh);
+	pandora_updateserver (\%pa_config, $pa_config{'servername'}, 0, 5, $dbh);
     exit;
 }
 
diff --git a/pandora_server/bin/pandora_recon b/pandora_server/bin/pandora_recon
index dd228f52a1..21b86adadf 100755
--- a/pandora_server/bin/pandora_recon
+++ b/pandora_server/bin/pandora_recon
@@ -1,16 +1,16 @@
 #!/usr/bin/perl
 
-eval 'exec /usr/bin/perl  -S $0 ${1+"$@"}'
-    if 0; # not running under some shell
 ##########################################################################
 # Pandora FMS Recon Server
+# http://www.pandorafms.com
 ##########################################################################
 # Copyright (c) 2007-2008 Sancho Lerena, slerena@gmail.com
-# Copyright (c) 2007-2008 Artica Soluciones Tecnologicas S.L
+#           (c) 2007-2008 Artica Soluciones Tecnologicas S.L
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
 # as published by the Free Software Foundation; version 2
+#
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
@@ -643,5 +643,6 @@ sub pandora_shutdown {
     logger (\%pa_config,"Pandora FMS Server '".$pa_config{'servername'}.$pa_config{"servermode"}."' Shutdown by signal ",0);
     print " [*] Shutting down ".$pa_config{'servername'}.$pa_config{"servermode"} ."(received signal)...\n";
     pandora_event (\%pa_config, $pa_config{'servername'}.$pa_config{"servermode"}." going Down", 0, 0, 4, 0, 0, "system", $dbh);
+	pandora_updateserver (\%pa_config, $pa_config{'servername'}, 0, 3, $dbh);
     exit;
 }
diff --git a/pandora_server/bin/pandora_server b/pandora_server/bin/pandora_server
index 6bc89c8615..9bdd139177 100755
--- a/pandora_server/bin/pandora_server
+++ b/pandora_server/bin/pandora_server
@@ -90,10 +90,11 @@ my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost:3306",
 			$pa_config{'dbpass'},
 			{ RaiseError => 1, AutoCommit => 1 });
 
-# KeepAlive checks for Agents, only for master servers, in separate thread
+
 while (1) {
-	keep_alive_check (\%pa_config, $dbh);
 	pandora_serverkeepaliver (\%pa_config, 0, $dbh);
+	pandora_planned_downtime (\%pa_config, $dbh);
+	keep_alive_check (\%pa_config, $dbh);
 	threads->yield;
 	sleep ($pa_config{"server_threshold"});
 }
diff --git a/pandora_server/bin/pandora_snmpconsole b/pandora_server/bin/pandora_snmpconsole
index 0c8233dcc1..4f8d90fa4f 100755
--- a/pandora_server/bin/pandora_snmpconsole
+++ b/pandora_server/bin/pandora_snmpconsole
@@ -43,8 +43,9 @@ $SIG{'INT'} = 'pandora_shutdown';
 
 # Inicio del bucle principal de programa
 pandora_init(\%pa_config,"Pandora SNMP Console");
+
 # Read config file for Global variables
-pandora_loadconfig (\%pa_config,2);
+pandora_loadconfig (\%pa_config, 2);
 
 # Audit server starting
 pandora_audit (\%pa_config, "Pandora Server SNMP Console Daemon starting", "SYSTEM", "System");
@@ -82,7 +83,7 @@ sub pandora_snmptrapd {
 	my $sql_insert;
 	my @index_data;
 
-	if ( ! -e $snmp_logfile) { # Wait until a snmplogfile exists
+	while ( ! -e $snmp_logfile) { # Wait until a snmplogfile exists
 		sleep 5; 
 	}
 	open (SNMPLOGFILE, $snmp_logfile);
@@ -308,10 +309,11 @@ sub calcula_alerta_snmp {
 # Close system
 ########################################################################################
 sub pandora_shutdown {
-    logger (\%pa_config,"Pandora FMS Server '".$pa_config{'servername'}.$pa_config{"servermode"}."' Shutdown by signal ",0);
+    logger (\%pa_config, "Pandora FMS Server '".$pa_config{'servername'}.$pa_config{"servermode"}."' Shutdown by signal ",0);
     print " [*] Shutting down ".$pa_config{'servername'}.$pa_config{"servermode"} ."(received signal)...\n";
 	my $dbh = DBI->connect("DBI:mysql:$pa_config{'dbname'}:$pa_config{'dbhost'}:3306",$pa_config{'dbuser'}, $pa_config{'dbpass'}, { RaiseError => 1, AutoCommit => 1 });
     pandora_event (\%pa_config, $pa_config{'servername'}.$pa_config{"servermode"}." going Down", 0,
                                    0, 4, 0, 0, "system", $dbh);
+	pandora_updateserver (\%pa_config, $pa_config{'servername'}, 0, 2, $dbh);
     exit;
 }
diff --git a/pandora_server/bin/pandora_wmi b/pandora_server/bin/pandora_wmi
index 053ceb7e9b..f7abcee643 100755
--- a/pandora_server/bin/pandora_wmi
+++ b/pandora_server/bin/pandora_wmi
@@ -1,12 +1,14 @@
 #!/usr/bin/perl
 ##########################################################################
-# Pandora FMS Plugin Server
+# Pandora FMS WMI Server
+# http://www.pandorafms.com
 ##########################################################################
 # Copyright (c) 2008 Sancho Lerena, slerena@gmail.com
 #           (c) 2008 Artica Soluciones Tecnologicas S.L
+#
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; version 2 (only).
+# 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
@@ -144,6 +146,7 @@ sub pandora_shutdown {
     print " [*] Shutting down ".$pa_config{'servername'}.$pa_config{"servermode"} ."(received signal)...\n";
     pandora_event (\%pa_config, $pa_config{'servername'}.$pa_config{"servermode"}." going Down", 0,
                                    0, 4, 0, 0, "system", $dbh);
+	pandora_updateserver (\%pa_config, $pa_config{'servername'}, 0, 6, $dbh);
     exit;
 }
 
diff --git a/pandora_server/lib/PandoraFMS/DB.pm b/pandora_server/lib/PandoraFMS/DB.pm
index 6f558eefee..4a5df8a385 100644
--- a/pandora_server/lib/PandoraFMS/DB.pm
+++ b/pandora_server/lib/PandoraFMS/DB.pm
@@ -62,6 +62,7 @@ our @EXPORT = qw(
 		pandora_generate_alerts
 		pandora_generate_compound_alerts
 		pandora_process_alert
+		pandora_planned_downtime
 		module_generic_proc
 		module_generic_data
 		module_generic_data_inc
@@ -491,8 +492,10 @@ sub execute_alert (%$$$$$$$$$$$$$$$) {
         $field3 = $data_alert->{'al_campo3'};
     } else {
         $field1 = $data_alert->{'al_campo1'};
-        $field2 = $data_alert->{'al_f2_recovery'};
-        $field3 = $data_alert->{'al_f3_recovery'};
+		# Patch for adding [RECOVER] on f2/f3 if blank. Submitted by Kato Atsushi
+        $field2 = $data_alert->{'al_f2_recovery'} || "[RECOVER]" . $data_alert->{'al_campo2'};
+        $field3 = $data_alert->{'al_f3_recovery'} || "[RECOVER]" . $data_alert->{'al_campo3'};
+		# End of patch
     }
 
 	# Get values for commandline, reading from talerta.
@@ -567,7 +570,6 @@ sub execute_alert (%$$$$$$$$$$$$$$$) {
 ##########################################################################
 
 sub pandora_writestate (%$$$$$$$) {
-	# my $timestamp = $_[0];
 	# slerena, 05/10/04 : Fixed bug because differences between agent / server time source.
 	# now we use only local timestamp to stamp state of modules
 	my $pa_config = $_[0];
@@ -599,32 +601,38 @@ sub pandora_writestate (%$$$$$$$) {
 
 	# Valid agent ?
 	if (($id_agente ==  -1) || ($id_agente_modulo == -1)) {
-		return 0;
+		return -1;
 	}
 
 	# Valid string data ? (not null)
 	if (($id_modulo == 3) || ($id_modulo == 17) || ($id_modulo == 10) || ($id_modulo == 23)){
 			if ($datos eq "") {
-				return 0;
+				return -1;
 			}
 	}
 
-
+	# Take group for this module
 
     my $id_grupo = dame_grupo_agente($pa_config, $id_agente,$dbh);
 
-	# Seek for agent_interval or module_interval
+	# Get data for this module from tagent_module table
+
 	my $query_idag = "SELECT * FROM tagente_modulo WHERE id_agente = $id_agente AND id_agente_modulo = " . $id_agente_modulo;
 	my $s_idag = $dbh->prepare($query_idag);
 	$s_idag ->execute;
 	if ($s_idag->rows == 0) {
 		logger( $pa_config, "ERROR Cannot find agenteModulo $id_agente_modulo",4);
 		logger( $pa_config, "ERROR: SQL Query is $query_idag ",10);
-		return 0;
+		return -1;
 	} else  {
 		@data = $s_idag->fetchrow_array();
 	}
 
+	if (!defined($data[23])){
+		return -1;
+	}
+
+	# Get module interval or agent interval if module don't defined
 	my $id_module_type	= $data[2];
 	my $module_interval = $data[7];
 	if ($module_interval == 0){
@@ -632,7 +640,8 @@ sub pandora_writestate (%$$$$$$$) {
  	}
 	$s_idag->finish();
 
-	# Check alert subroutine
+	# Check alert subroutine - Protect execution on an eval block
+
 	eval {
 		pandora_generate_alerts ($pa_config, $timestamp, $nombre_agente, $id_agente, $id_agente_modulo, $id_module_type, $id_grupo, $datos, $dbh);
 	};
@@ -643,22 +652,27 @@ sub pandora_writestate (%$$$$$$$) {
 
 	# $id_agente is agent ID to update ".dame_nombreagente_agentemodulo ($id_agente_modulo)."
 	# Let's see if there is any entry at tagente_estado table
+
 	my $idages = "SELECT * from tagente_estado WHERE id_agente_modulo = $id_agente_modulo";
 	my $s_idages = $dbh->prepare($idages);
 	$s_idages ->execute;
 
-	# Postprocess
-	if (($data[23] != 0) && (is_numeric($data[23]))){
+	# Postprocess management
+
+	if ((defined($data[23])) && ($data[23] != 0) && (is_numeric($data[23]))){
 		if (($id_modulo == 1) || ($id_modulo == 7) || ($id_modulo == 15) || ($id_modulo == 22) || ($id_modulo == 4) || ($id_modulo == 8) || ($id_modulo == 16) ){
 			$datos = $datos * $data[23];
 		}
 	}
 
+	# Apply Mysql quotes to data to prepare for database insertion / update
+
 	$datos = $dbh->quote($datos); # Parse data entry for adecuate SQL representation.
 
 	my $query_act; # OJO que dentro de una llave solo tiene existencia en esa llave !!
 	if ($s_idages->rows == 0) { # Doesnt exist entry in table, lets make the first entry
 		logger($pa_config, "Create entry in tagente_estado for module $nombre_modulo",4);
+
         $query_act = "INSERT INTO tagente_estado (id_agente_modulo, datos, timestamp, estado, cambio, id_agente, last_try, utimestamp, current_interval, running_by, last_execution_try) VALUES ($id_agente_modulo,$datos,'$timestamp','$estado','1',$id_agente,'$timestamp',$utimestamp, $module_interval, $id_server, $utimestamp)"; # Cuando se hace un insert, siempre hay un cambio de estado
 
 	} else { # There are an entry in table already
@@ -667,35 +681,50 @@ sub pandora_writestate (%$$$$$$$) {
             $needs_update = 1;
         }
 
-	    # Se supone que $data[5](estado) ( nos daria el estado ANTERIOR
+	    # $data[5](status, should give us prev. status)
     	# For xxxx_PROC type (boolean / monitor), create an event if state has changed
 	    if (( $data[5] != $estado) && (($tipo_modulo =~/keep_alive/) || ($tipo_modulo =~ /proc/))) {
 	        # Cambio de estado detectado !
 	        $cambio = 1;
             $needs_update = 1;
-	        # Este seria el momento oportuno de probar a saltar la alerta si estuviera definida
+
 		    # Makes an event entry, only if previous state changes, if new state, doesnt give any alert
-		    my $descripcion;
-            my $event_type;
+		    my $description;
+
             if ( $estado == 0) {
-                $descripcion = "Monitor ($nombre_modulo) goes up ";
-                $event_type = "monitor_up";
+                $description = "Monitor ($nombre_modulo) goes up ";
+				pandora_event ($pa_config, $description, $id_grupo,
+							$id_agente, 2, 0, $id_agente_modulo, 
+							"monitor_up", $dbh);
             }
 		    if ( $estado == 1) {
-    			$descripcion = "Monitor ($nombre_modulo) goes down";
-                $event_type = "monitor_down";
+    			$description = "Monitor ($nombre_modulo) goes down";
+				pandora_event ($pa_config, $description, $id_grupo,
+							$id_agente, 3, 0, $id_agente_modulo, 
+							"monitor_down", $dbh);
 		    }
 
-            pandora_event ($pa_config, $descripcion, $id_grupo,
-                        $id_agente, 2, 0, $id_agente_modulo, 
-                        $event_type, $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";
-        } 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, 
+							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";
         }
     }
 	my $a_idages = $dbh->prepare($query_act);
@@ -816,17 +845,17 @@ sub module_generic_proc (%$$$$$) {
 	if (ref($a_min) eq "HASH") {
 		$a_min = "";
 	}
-	pandora_writedata ($pa_config, $a_timestamp, $agent_name, $module_type, $a_name, 
-                        $a_datos, $a_max, $a_min, $a_desc, $dbh, \$bUpdateDatos);
-
-	# Check for status: <1 state 1 (Bad), >= 1 state 0 (Good)
-	# Calculamos su estado
-	if ( $a_datos >= 1 ) { 
-		$estado = 0;
-	} else { 
-		$estado = 1;
+	if (pandora_writedata ($pa_config, $a_timestamp, $agent_name, $module_type, $a_name, 
+                        $a_datos, $a_max, $a_min, $a_desc, $dbh, \$bUpdateDatos) != -1){
+		# Check for status: <1 state 1 (Bad), >= 1 state 0 (Good)
+		# Calculamos su estado
+		if ( $a_datos >= 1 ) { 
+			$estado = 0;
+		} else { 
+			$estado = 1;
+		}
+		pandora_writestate ($pa_config, $agent_name, $module_type, $a_name, $a_datos, $estado, $dbh, $bUpdateDatos);
 	}
-	pandora_writestate ($pa_config, $agent_name, $module_type, $a_name, $a_datos, $estado, $dbh, $bUpdateDatos);
 }
 
 ##########################################################################
@@ -882,9 +911,10 @@ sub module_generic_data (%$$$$$) {
 		if (ref($a_min) eq "HASH") {
 			$a_min = "";
 		}
-		pandora_writedata($pa_config, $m_timestamp,$agent_name,$module_type,$m_name,$m_data,$a_max,$a_min,$a_desc,$dbh,\$bUpdateDatos);
-		# Numeric data has status N/A (100) always
-		pandora_writestate ($pa_config, $agent_name, $module_type, $m_name, $m_data, 100, $dbh, $bUpdateDatos);
+		if (pandora_writedata($pa_config, $m_timestamp,$agent_name,$module_type,$m_name,$m_data,$a_max,$a_min,$a_desc,$dbh,\$bUpdateDatos) != -1){
+			# Numeric data has status N/A (100) always
+			pandora_writestate ($pa_config, $agent_name, $module_type, $m_name, $m_data, 100, $dbh, $bUpdateDatos);
+		}
 	} else {
 		logger($pa_config, "(data) Invalid data value received from $agent_name, module $m_name", 3);
 	}
@@ -1003,9 +1033,10 @@ sub module_generic_data_inc (%$$$$$) {
 
 		# Update of tagente_datos and tagente_estado ? (only where there is a difference (or reset))
 		if ($no_existe == 0){
-			pandora_writedata ($pa_config, $m_timestamp, $agent_name, $module_type, $m_name, $new_data, $a_max, $a_min, $a_desc, $dbh, \$bUpdateDatos);
-			# Inc status is always 100 (N/A)
-			pandora_writestate ($pa_config, $agent_name, $module_type, $m_name, $new_data, 100, $dbh, $bUpdateDatos);
+			if (pandora_writedata ($pa_config, $m_timestamp, $agent_name, $module_type, $m_name, $new_data, $a_max, $a_min, $a_desc, $dbh, \$bUpdateDatos) != -1){
+				# Inc status is always 100 (N/A)
+				pandora_writestate ($pa_config, $agent_name, $module_type, $m_name, $new_data, 100, $dbh, $bUpdateDatos);
+			}
 		}
 	} else {
 		logger ($pa_config, "(data_inc) Invalid data received from $agent_name, module $m_name", 2);
@@ -1045,9 +1076,10 @@ sub module_generic_data_string (%$$$$$) {
         if (ref($a_min) eq "HASH") {
                 $a_min = "";
         }
-	pandora_writedata($pa_config, $m_timestamp, $agent_name, $module_type, $m_name, $m_data, $a_max, $a_min, $a_desc, $dbh, \$bUpdateDatos);
+	if (pandora_writedata($pa_config, $m_timestamp, $agent_name, $module_type, $m_name, $m_data, $a_max, $a_min, $a_desc, $dbh, \$bUpdateDatos) != -1){
     	# String type has no state (100 = N/A)
-	pandora_writestate ($pa_config, $agent_name, $module_type, $m_name, $m_data, 100, $dbh, $bUpdateDatos);
+		pandora_writestate ($pa_config, $agent_name, $module_type, $m_name, $m_data, 100, $dbh, $bUpdateDatos);
+	}
 }
 
 
@@ -1086,13 +1118,13 @@ sub pandora_writedata (%$$$$$$$$$$){
 	# Check if exists module and agent_module reference in DB, 
 	# if not, and learn mode activated, insert module in DB
 	if ($id_agente eq "-1"){
-		goto fin_DB_insert_datos;
+		return -1;
 	}
 
 	my $id_modulo = dame_modulo_id($pa_config, $tipo_modulo,$dbh);
 	if (($id_modulo == 3) || ($id_modulo == 17) || ($id_modulo == 10) || ($id_modulo == 23)){
 		if ($datos eq "") {
-			return 0;
+			return -1;
 		}
 	}
 
@@ -1141,7 +1173,7 @@ sub pandora_writedata (%$$$$$$$$$$){
 			$needscreate = 1; # Really needs to be created
 		} else {
 			logger( $pa_config, "VERBOSE: pandora_insertdata cannot find module definition ($nombre_modulo / $tipo_modulo )for agent $nombre_agente - Use LEARN MODE for autocreate.", 3);
-			goto fin_DB_insert_datos;
+			return -1;
 		}
 	} # Module exists or has been created
 	
@@ -1234,7 +1266,7 @@ sub pandora_writedata (%$$$$$$$$$$){
 			$dbh->do($query); # Makes insertion in database
 		}
 	}
-fin_DB_insert_datos:
+	return 0;
 }
 
 ##########################################################################
@@ -1287,6 +1319,73 @@ sub pandora_serverkeepaliver (%$$) {
 	$pa_config->{"keepalive"} = $pa_config->{"keepalive"} - $pa_config->{"server_threshold"};
 }
 
+##########################################################################
+## SUB pandora_planned_downtime  (pa_config, dbh)
+## Update planned downtimes.
+##########################################################################
+sub pandora_planned_downtime (%$) {
+    my $pa_config= $_[0];
+	my $dbh = $_[1];
+	
+	my $data_ref;
+	my $data_ref2;
+	my $query_handle;
+	my $query_handle2;
+	my $query_sql;
+	my $datestamp = &UnixDate("today","%Y-%m-%d");
+	my $timestamp = &UnixDate("today","%H:%M:%S");
+
+
+	# Activate a planned downtime: Set agents as disabled for Planned Downtime
+
+	$query_sql = "SELECT * FROM tplanned_downtime WHERE executed = 0 AND start <= '$datestamp' AND start_time <= '$timestamp' AND stop >= '$datestamp' AND stop_time >'$timestamp' ";
+
+	$query_handle = $dbh->prepare($query_sql);
+	$query_handle ->execute;
+	if ($query_handle->rows != 0) {
+		while ($data_ref = $query_handle->fetchrow_hashref()){
+			# Raise event in system to notify planned downtime has started.
+			$dbh->do("UPDATE tplanned_downtime SET executed=1 WHERE id = ".$data_ref->{'id'});
+			pandora_event ($pa_config, "Server ".$pa_config->{'servername'}." started planned downtime: ".$data_ref->{'description'}, 0, 0, 1, 0, 0, "system", $dbh);
+			$query_sql = "SELECT * FROM tplanned_downtime_agents WHERE id_downtime = ".$data_ref->{'id'};
+			$query_handle2 = $dbh->prepare($query_sql);
+			$query_handle2 ->execute;
+			if ($query_handle2->rows != 0) {
+				while ($data_ref2 = $query_handle2->fetchrow_hashref()){
+				$dbh->do("UPDATE tagente SET disabled=1 WHERE id_agente = ".$data_ref2->{'id_agent'});
+				}
+			}
+			$query_handle2->finish();
+		}
+	}
+	$query_handle->finish();
+
+	# Deactivate a planned downtime: Set agents as disabled for Planned Downtime
+
+	$query_sql = "SELECT * FROM tplanned_downtime WHERE executed = 1 AND stop <= '$datestamp' AND stop_time <= '$timestamp'";
+	$query_handle = $dbh->prepare($query_sql);
+	$query_handle ->execute;
+	if ($query_handle->rows != 0) {
+		while ($data_ref = $query_handle->fetchrow_hashref()){
+			# Raise event in system to notify planned downtime has started.
+			$dbh->do("UPDATE tplanned_downtime SET executed=0 WHERE id = ".$data_ref->{'id'});
+			pandora_event ($pa_config, "Server ".$pa_config->{'servername'}." stopped planned downtime: ".$data_ref->{'description'}, 0, 0, 1, 0, 0, "system", $dbh);
+			$query_sql = "SELECT * FROM tplanned_downtime_agents WHERE id_downtime = ".$data_ref->{'id'};
+			$query_handle2 = $dbh->prepare($query_sql);
+			$query_handle2 ->execute;
+			if ($query_handle2->rows != 0) {
+				while ($data_ref2 = $query_handle2->fetchrow_hashref()){
+				$dbh->do("UPDATE tagente SET disabled=0 WHERE id_agente = ".$data_ref2->{'id_agent'});
+				}
+			}
+			$query_handle2->finish();
+		}
+	}
+	$query_handle->finish();
+	
+}
+
+
 ##########################################################################
 ## SUB pandora_updateserver (pa_config, status, dbh)
 ## Update server status
@@ -1347,13 +1446,10 @@ sub pandora_updateserver (%$$$) {
 			
 			# Some fields of tserver should be updated ONLY when server is going up
 			if ($data[3] == 0){ # If down, update to get up the server
-				
 				logger( $pa_config, "Server ".$data[1]." going UP ",1);
 				$sql_update_post = ", laststart = '$timestamp', version = '$version_data'";
-
 			}
 			
-
 			if ($opmode == 0){
 				$sql_update = "data_server = 1";
 			} elsif ($opmode == 1){
@@ -1368,7 +1464,6 @@ sub pandora_updateserver (%$$$) {
 				$sql_update = "prediction_server = 1";
             } elsif ($opmode == 6) {
 				$sql_update = "wmi_server = 1";
-                # $sql_update = "update tserver set version = '$version_data', status = $status, laststart = '$timestamp', keepalive = '$timestamp', wmi_server = 1, master =  $pa_config->{'pandora_master'}, checksum = 0 where id_server = $id_server";
             }
 
 			$sql_update = "UPDATE tserver SET $sql_update $sql_update_post , status = $status, keepalive = '$timestamp', master =  $pa_config->{'pandora_master'} WHERE id_server = $id_server";