2009-01-12 Sancho Lerena <slerena@artica.es>

This is a MAJOR upgrade that _BREAK_ your current 2.1 trunk version.
	Needs an upgrade of DB Schema. At this time no conversion tool has been
	provided. Libs and console needs also to be re-deployed.
	
	* pandora_server: KeepAlive module is now processed OUTSIDE 
	pandora_lastagentcontact() function, in it's own function. This makes that
	keepalive only be refreshed on agent data, not network. This should 
	make keepalive works as "agent down detector" in a definitive way, also
	it's an important performance improvement operation.
	
	* pandora_db.pl: Performance improvements. If compact days = 0 skip. 
	Compactation and delete needs to be improved in speed.
	
	* DB.pm: Added more generic DB access functions (db_insert, db_update, 
	db_delete). Major rewrite of pandora_writestate(). Now uses three different
	values for status (NORMAL, WARNING, CRITICAL) and manage all modules like
	old monitor modules. Uses new fields for control event flip/flop with a 
	counter. Also uses new WARNING/CRITICAL thresholds to calculate in store-
	time the status.
	
	pandora_accessupdate() Function now uses only utimestamp. Tagente_datos and 
	tagente_datos_string has been updated and do not use timestamp (string) and
	id_agent index anymore. Big improvement has been noticed in performance 
	tests after this change !. tagente_datos_inc has been modified also.
	
	pandora_writedata() needs a lot of improvement :(. Added support for 
	modules without history. 



git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@1325 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f
This commit is contained in:
slerena 2009-01-12 02:44:39 +00:00
parent 1493bb66cd
commit bcf0d1e1c5
4 changed files with 278 additions and 182 deletions

View File

@ -1,3 +1,33 @@
2009-01-12 Sancho Lerena <slerena@artica.es>
This is a MAJOR upgrade that _BREAK_ your current 2.1 trunk version.
Needs an upgrade of DB Schema. At this time no conversion tool has been
provided. Libs and console needs also to be re-deployed.
* pandora_server: KeepAlive module is now processed OUTSIDE
pandora_lastagentcontact() function, in it's own function. This makes that
keepalive only be refreshed on agent data, not network. This should
make keepalive works as "agent down detector" in a definitive way, also
it's an important performance improvement operation.
* pandora_db.pl: Performance improvements. If compact days = 0 skip.
Compactation and delete needs to be improved in speed.
* DB.pm: Added more generic DB access functions (db_insert, db_update,
db_delete). Major rewrite of pandora_writestate(). Now uses three different
values for status (NORMAL, WARNING, CRITICAL) and manage all modules like
old monitor modules. Uses new fields for control event flip/flop with a
counter. Also uses new WARNING/CRITICAL thresholds to calculate in store-
time the status.
pandora_accessupdate() Function now uses only utimestamp. Tagente_datos and
tagente_datos_string has been updated and do not use timestamp (string) and
id_agent index anymore. Big improvement has been noticed in performance
tests after this change !. tagente_datos_inc has been modified also.
pandora_writedata() needs a lot of improvement :(. Added support for
modules without history.
2008-12-23 Ramon Novoa <rnovoa@artica.es> 2008-12-23 Ramon Novoa <rnovoa@artica.es>
* bin/pandora_recon: Added a timeout to pandora_getparent(). The call * bin/pandora_recon: Added a timeout to pandora_getparent(). The call

View File

@ -359,6 +359,7 @@ sub process_datafile {
if ($id_agente > 0) { if ($id_agente > 0) {
pandora_lastagentcontact ($pa_config, $timestamp, $agent_name, $os_version, $agent_version, $interval, $dbh); pandora_lastagentcontact ($pa_config, $timestamp, $agent_name, $os_version, $agent_version, $interval, $dbh);
update_keepalive_module ($pa_config, $id_agente, $agent_name, $dbh);
foreach my $part(@{$datos->{module}}) { foreach my $part(@{$datos->{module}}) {
$tipo_modulo = $part->{type}->[0]; $tipo_modulo = $part->{type}->[0];
$module_name = $part->{name}->[0]; $module_name = $part->{name}->[0];

View File

@ -3,11 +3,11 @@ package PandoraFMS::DB;
# Database Package # Database Package
# Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org # Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org
########################################################################## ##########################################################################
# Copyright (c) 2004-2008 Sancho Lerena, slerena@gmail.com # Copyright (c) 2004-2009 Sancho Lerena, slerena@gmail.com
# Copyright (c) 2005-2008 Artica Soluciones Tecnologicas S.L # Copyright (c) 2005-2009 Artica Soluciones Tecnologicas S.L
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU Lesser General Public License
# as published by the Free Software Foundation; version 2 # as published by the Free Software Foundation; version 2
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
@ -52,12 +52,14 @@ our @EXPORT = qw(
dame_nombretipomodulo_idagentemodulo dame_nombretipomodulo_idagentemodulo
dame_ultimo_contacto dame_ultimo_contacto
give_networkserver_status give_networkserver_status
pandora_writedata
pandora_writestate
pandora_updateserver pandora_updateserver
pandora_serverkeepaliver pandora_serverkeepaliver
pandora_audit pandora_audit
pandora_lastagentcontact pandora_lastagentcontact
pandora_writedata
pandora_writestate
pandora_evaluate_alert pandora_evaluate_alert
pandora_evaluate_compound_alert pandora_evaluate_compound_alert
pandora_generate_alerts pandora_generate_alerts
@ -73,9 +75,14 @@ our @EXPORT = qw(
execute_alert execute_alert
give_network_component_profile_name give_network_component_profile_name
pandora_create_incident pandora_create_incident
update_keepalive_module
get_db_value get_db_value
get_db_free_row get_db_free_row
get_db_free_field get_db_free_field
db_insert
db_update
db_delete
); );
# Spanish translation note: # Spanish translation note:
@ -586,9 +593,8 @@ sub pandora_writestate (%$$$$$$$) {
my $tipo_modulo = $_[2]; # passed as string my $tipo_modulo = $_[2]; # passed as string
my $nombre_modulo = $_[3]; my $nombre_modulo = $_[3];
my $datos = $_[4]; # Careful: This don't reference a hash, only a single value my $datos = $_[4]; # Careful: This don't reference a hash, only a single value
my $estado = $_[5]; my $dbh = $_[5];
my $dbh = $_[6]; my $needs_update = $_[6];
my $needs_update = $_[7];
my @data; my @data;
my $cambio = 0; my $cambio = 0;
@ -604,15 +610,21 @@ sub pandora_writestate (%$$$$$$$) {
# Get id # Get id
# BE CAREFUL: We don't verify the strings chains # BE CAREFUL: We don't verify the strings chains
# TO DO: Verify errors # TO DO: Verify errors
my $id_agente = dame_agente_id ($pa_config, $nombre_agente, $dbh); my $agent_data = get_db_free_row ("SELECT * FROM tagente WHERE nombre = '$nombre_agente'", $dbh);
my $id_modulo = dame_modulo_id ($pa_config, $tipo_modulo, $dbh); if ($agent_data == -1){
my $id_agente_modulo = dame_agente_modulo_id($pa_config, $id_agente, $id_modulo, $nombre_modulo, $dbh);
# Valid agent ?
if (($id_agente == -1) || ($id_agente_modulo == -1)) {
return -1; return -1;
} }
my $id_modulo = dame_modulo_id ($pa_config, $tipo_modulo, $dbh);
my $id_agente_modulo = dame_agente_modulo_id($pa_config, $agent_data->{'id_agente'}, $id_modulo, $nombre_modulo, $dbh);
# Valid agent ?
if ($id_agente_modulo == -1) {
return -1;
}
my $module_data = get_db_free_row ("SELECT * FROM tagente_modulo WHERE id_agente_modulo = $id_agente_modulo", $dbh);
# Valid string data ? (not null) # Valid string data ? (not null)
if (($id_modulo == 3) || ($id_modulo == 17) || ($id_modulo == 10) || ($id_modulo == 23)){ if (($id_modulo == 3) || ($id_modulo == 17) || ($id_modulo == 10) || ($id_modulo == 23)){
if ($datos eq "") { if ($datos eq "") {
@ -621,121 +633,137 @@ sub pandora_writestate (%$$$$$$$) {
} }
# Take group for this module # Take group for this module
my $id_grupo = dame_grupo_agente($pa_config, $agent_data->{'id_agente'}, $dbh);
my $id_grupo = dame_grupo_agente($pa_config, $id_agente,$dbh);
# 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 -1;
} else {
@data = $s_idag->fetchrow_array();
}
# Postprocess management # Postprocess management
if ( defined($data->{'post_process'}) && ($data->{'post_process'}> 0)) {
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) ){ 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]; $datos = $datos * $data->{'post_process'};
} }
} }
$s_idag->finish(); # Status management
my $estado = 0; # Normal (OK) by default
# Only PROC modules have min_critical/max_critical default
if ( $tipo_modulo =~ m/proc/ ){
if ($module_data->{'min_critical'} eq $module_data->{'max_critical'}){
$module_data->{'min_critical'} = 0;
$module_data->{'max_critical'} = 1;
}
}
if ($module_data->{'min_warning'} ne $module_data->{'max_warning'}){
if (($datos >= $module_data->{'min_warning'}) && ($datos < $module_data->{'max_warning'})){
$estado = 2;
}
if (($datos >= $module_data->{'min_warning'}) && ($module_data->{'max_warning'} < $module_data->{'min_warning'})){
$estado = 2;
}
}
if ($module_data->{'min_critical'} ne $module_data->{'max_critical'}){
if (($datos >= $module_data->{'min_critical'}) && ($datos < $module_data->{'max_critical'})){
$estado = 1;
}
if (($datos >= $module_data->{'min_critical'}) && ($module_data->{'max_critical'} < $module_data->{'min_critical'})){
$estado = 1;
}
}
# Get module interval or agent interval if module don't defined # Get module interval or agent interval if module don't defined
my $id_module_type = $data[2]; my $module_interval = $module_data->{'module_interval'};
my $module_interval = $data[7]; if ($module_data->{'module_interval'} == 0){
if ($module_interval == 0){ $module_interval = dame_intervalo ($pa_config, $module_data->{'id_agente'}, $dbh);
$module_interval = dame_intervalo ($pa_config, $id_agente, $dbh);
} }
$s_idag->finish();
# Check alert subroutine - Protect execution on an eval block # Check alert subroutine - Protect execution on an eval block
eval { eval {
pandora_generate_alerts ($pa_config, $timestamp, $nombre_agente, $id_agente, $id_agente_modulo, $id_module_type, $id_grupo, $datos, $dbh); pandora_generate_alerts ($pa_config, $timestamp, $nombre_agente, $module_data->{'id_agente'}, $id_agente_modulo, $id_module_type, $id_grupo, $datos, $dbh);
}; };
if ($@) { if ($@) {
logger($pa_config, "ERROR: Error in SUB calcula_alerta(). ModuleName: $nombre_modulo ModuleType: $tipo_modulo AgentName: $nombre_agente", 4); logger($pa_config, "ERROR: Error in SUB calcula_alerta(). ModuleName: $nombre_modulo ModuleType: $tipo_modulo AgentName: $nombre_agente", 4);
logger($pa_config, "ERROR Code: $@",10) logger($pa_config, "ERROR Code: $@",10)
} }
# $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 # Let's see if there is any entry at tagente_estado table
my $data_status = get_db_free_row ("SELECT * from tagente_estado WHERE id_agente_modulo = ". $module_data->{'id_agente_modulo'}, $dbh);
my $idages = "SELECT * from tagente_estado WHERE id_agente_modulo = $id_agente_modulo";
my $s_idages = $dbh->prepare($idages);
$s_idages ->execute;
# Apply Mysql quotes to data to prepare for database insertion / update # Apply Mysql quotes to data to prepare for database insertion / update
$datos = $dbh->quote($datos); # Parse data entry for adecuate SQL representation. $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 !! my $query_act;
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 if ($data_status == -1) { # 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, id_agente, last_try, utimestamp, current_interval, running_by, last_execution_try, last_status, status_changes) VALUES (". $module_data->{'id_agente_modulo'} ." , $datos,'$timestamp',". $estado ." , " . $agent_data->{'id_agente'}. ",'$timestamp',$utimestamp, $module_interval, $id_server, $utimestamp, 0, 0)";
} else { # There are an entry in table already } else { # An entry in table already exists
@data = $s_idages->fetchrow_array(); $data_status->{'estado'} = $estado;
if ( $data[11] == 0){ if ( $data_status->{'last_execution_try'} == 0){
$needs_update = 1; $needs_update = 1;
} }
# $data[5](status, should give us prev. status) # Track status change
# For xxxx_PROC type (boolean / monitor), create an event if state has changed if ( $data_status->{'last_status'} == $data_status->{'estado'}){
if (( $data[5] != $estado) && (($tipo_modulo =~/keep_alive/) || ($tipo_modulo =~ /proc/))) { $data_status->{'status_changes'} = 0;
# Cambio de estado detectado !
$cambio = 1;
$needs_update = 1;
# Makes an event entry, only if previous state changes, if new state, doesnt give any alert
my $description;
if ( $estado == 0) {
$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) {
$description = "Monitor ($nombre_modulo) goes down";
pandora_event ($pa_config, $description, $id_grupo,
$id_agente, 3, 0, $id_agente_modulo,
"monitor_down", $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 { } else {
$data_status->{'status_changes'} = $data_status->{'status_changes'} + 1 ;
# dont update last_try field, that it's the field # Raise event ?
# we use to check last update time in database if ($data_status->{'status_changes'} > $module_data->{'min_ff_event'}){
$query_act = "UPDATE tagente_estado SET $needs_update = 1;
utimestamp = $utimestamp, datos = $datos, cambio = '$cambio', my $event_type = "";
timestamp = '$timestamp', estado = '$estado', id_agente = $id_agente, my $status_name = "";
current_interval = '$module_interval', running_by = $id_server, my $severity = 0;
last_execution_try = $utimestamp WHERE id_agente_modulo = $id_agente_modulo";
if (($data_status->{'last_status'} == 0) && ($data_status->{'estado'} == 2)){
$event_type = "going_up_warning";
$status_name = "going up to WARNING";
$severity = 3;
} elsif (($data_status->{'last_status'} == 1) && ($data_status->{'estado'} == 2)){
$event_type = "going_down_warning";
$status_name = "going down to WARNING";
$severity = 3;
} elsif ($data_status->{'estado'} == 1){
$event_type = "going_up_critical";
$status_name = "going up to CRITICAL";
$severity = 4;
} elsif ($data_status->{'estado'} == 0){
$event_type = "going_down_normal";
$status_name = "going down to NORMAL";
$severity = 2;
}
$data_status->{'status_changes'} = 0;
$data_status->{'last_status'} = $data_status->{'estado'};
my $description = "Module ".$module_data->{'nombre'}." ($datos) is $status_name";
pandora_event ($pa_config, $description, $id_grupo,
$module_data->{'id_agente'}, $severity, 0, $module_data->{'id_agente_modulo'},
$event_type, $dbh);
if ($event_type eq "going_down_warning"){
# Clean up and system mark all active CRITICAL events for this module
db_update ("UPDATE tevento SET estado=1 WHERE id_agentmodule = ".$module_data->{'id_agente_modulo'}." AND event_type = 'going_up_critical'", $dbh);
}
elsif ($event_type eq "going_down_normal"){
# Clean up and system mark all active WARNING and CRITICAL events for this module
db_update ("UPDATE tevento SET estado=1 WHERE id_agentmodule = ".$module_data->{'id_agente_modulo'}." AND (event_type = 'going_up_warning' OR event_type = 'going_down_warning' OR event_type = 'going_up_critical')", $dbh);
}
}
} }
}
my $a_idages = $dbh->prepare($query_act); my $needs_update_sql = "";
$a_idages->execute; if ($needs_update == 1) {
$a_idages->finish(); $needs_update_sql = " , last_try = '$timestamp' ";
$s_idages->finish(); }
$query_act = "UPDATE tagente_estado SET utimestamp = $utimestamp, datos = $datos, last_status = " . $data_status->{'last_status'} . ", status_changes = " . $data_status->{'status_changes'} . ", timestamp = '$timestamp', estado = ".$data_status->{'estado'}.", id_agente = $module_data->{'id_agente'}, current_interval = $module_interval, running_by = $id_server, last_execution_try = $utimestamp " . $needs_update_sql . " WHERE id_agente_modulo = ". $module_data->{'id_agente_modulo'};
}
db_update ($query_act, $dbh);
} }
########################################################################## ##########################################################################
@ -776,39 +804,9 @@ sub pandora_accessupdate (%$$) {
if ($id_agent != -1){ if ($id_agent != -1){
my $intervalo = dame_intervalo ($pa_config, $id_agent, $dbh); my $intervalo = dame_intervalo ($pa_config, $id_agent, $dbh);
my $timestamp = &UnixDate("today","%Y-%m-%d %H:%M:%S"); my $utimestamp = &UnixDate("today","%s");
my $temp = $intervalo / 2; my $query2 = "INSERT INTO tagent_access (id_agent, utimestamp) VALUES ($id_agent,'$utimestamp')";
my $fecha_limite = DateCalc($timestamp,"- $temp seconds",\$err); $dbh->do($query2);
$fecha_limite = &UnixDate($fecha_limite,"%Y-%m-%d %H:%M:%S");
# Fecha limite has limit date, if there are records below this date
# we cannot insert any data in Database. We use a limit based on agent_interval / 2
# So if an agent has interval 300, could have a max of 24 records per hour in access_table
# This is to do not saturate database with access records (because if you hace a network module with interval 30, you have
# a new record each 30 seconds !
# Compare with tagente.ultimo_contacto (tagent_lastcontact in english), so this will have
# the latest update for this agent
my $query = "select count(*) from tagent_access where id_agent = $id_agent and timestamp > '$fecha_limite'";
my $query_exec = $dbh->prepare($query);
my @data_row;
$query_exec ->execute;
@data_row = $query_exec->fetchrow_array();
$temp = $data_row[0];
$query_exec->finish();
if ( $temp == 0) { # We need update access time
my $query2 = "insert into tagent_access (id_agent, timestamp) VALUES ($id_agent,'$timestamp')";
$dbh->do($query2);
logger($pa_config,"Updating tagent_access for agent id $id_agent",9);
}
# Update keepalive module (if present, if there is more than one, only updates first one!).
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 = get_db_free_field ("SELECT nombre FROM tagente WHERE id_agente = $id_agent", $dbh);
my $module_typename = "keep_alive";
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);
}
} }
} }
@ -852,14 +850,7 @@ sub module_generic_proc (%$$$$$) {
} }
if (pandora_writedata ($pa_config, $a_timestamp, $agent_name, $module_type, $a_name, if (pandora_writedata ($pa_config, $a_timestamp, $agent_name, $module_type, $a_name,
$a_datos, $a_max, $a_min, $a_desc, $dbh, \$bUpdateDatos) != -1){ $a_datos, $a_max, $a_min, $a_desc, $dbh, \$bUpdateDatos) != -1){
# Check for status: <1 state 1 (Bad), >= 1 state 0 (Good) pandora_writestate ($pa_config, $agent_name, $module_type, $a_name, $a_datos, $dbh, $bUpdateDatos);
# 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);
} }
} }
@ -917,8 +908,7 @@ sub module_generic_data (%$$$$$) {
$a_min = ""; $a_min = "";
} }
if (pandora_writedata($pa_config, $m_timestamp,$agent_name,$module_type,$m_name,$m_data,$a_max,$a_min,$a_desc,$dbh,\$bUpdateDatos) != -1){ 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, $dbh, $bUpdateDatos);
pandora_writestate ($pa_config, $agent_name, $module_type, $m_name, $m_data, 100, $dbh, $bUpdateDatos);
} }
} else { } else {
logger($pa_config, "(data) Invalid data value received from $agent_name, module $m_name", 3); logger($pa_config, "(data) Invalid data value received from $agent_name, module $m_name", 3);
@ -1022,12 +1012,12 @@ sub module_generic_data_inc (%$$$$$) {
# Update of tagente_datos_inx (AUX TABLE) # Update of tagente_datos_inx (AUX TABLE)
if ($no_existe == 1){ if ($no_existe == 1){
my $query = "INSERT INTO tagente_datos_inc (id_agente_modulo,datos, timestamp, utimestamp) VALUES ($id_agente_modulo, '$m_data', '$m_timestamp', $m_utimestamp)"; my $query = "INSERT INTO tagente_datos_inc (id_agente_modulo,datos, utimestamp) VALUES ($id_agente_modulo, '$m_data', $m_utimestamp)";
$dbh->do($query); $dbh->do($query);
} else { } else {
# Data exists previously # Data exists previously
if ($diferencia != 0) { if ($diferencia != 0) {
my $query2 = "UPDATE tagente_datos_inc SET timestamp='$m_timestamp', utimestamp = $m_utimestamp, datos = '$m_data' WHERE id_agente_modulo = $id_agente_modulo"; my $query2 = "UPDATE tagente_datos_inc SET utimestamp = $m_utimestamp, datos = '$m_data' WHERE id_agente_modulo = $id_agente_modulo";
$dbh->do($query2); $dbh->do($query2);
} }
} }
@ -1040,7 +1030,7 @@ sub module_generic_data_inc (%$$$$$) {
if ($no_existe == 0){ if ($no_existe == 0){
if (pandora_writedata ($pa_config, $m_timestamp, $agent_name, $module_type, $m_name, $new_data, $a_max, $a_min, $a_desc, $dbh, \$bUpdateDatos) != -1){ 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) # Inc status is always 100 (N/A)
pandora_writestate ($pa_config, $agent_name, $module_type, $m_name, $new_data, 100, $dbh, $bUpdateDatos); pandora_writestate ($pa_config, $agent_name, $module_type, $m_name, $new_data, $dbh, $bUpdateDatos);
} }
} }
} else { } else {
@ -1083,7 +1073,7 @@ sub module_generic_data_string (%$$$$$) {
} }
if (pandora_writedata($pa_config, $m_timestamp, $agent_name, $module_type, $m_name, $m_data, $a_max, $a_min, $a_desc, $dbh, \$bUpdateDatos) != -1){ 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) # 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, $dbh, $bUpdateDatos);
} }
} }
@ -1095,6 +1085,11 @@ sub module_generic_data_string (%$$$$$) {
########################################################################## ##########################################################################
# Optimizations:
# Pass id_agent, and id_agent_module as parameters
# Separate detection of existance of tagente_modulo before calling this function
# Pass Entire hash reference with tagente_modulo record
sub pandora_writedata (%$$$$$$$$$$){ sub pandora_writedata (%$$$$$$$$$$){
my $pa_config = $_[0]; my $pa_config = $_[0];
my $timestamp = $_[1]; my $timestamp = $_[1];
@ -1148,31 +1143,32 @@ sub pandora_writedata (%$$$$$$$$$$){
# take max and min values for this id_agente_module # take max and min values for this id_agente_module
if ($id_agente_modulo != -1){ # ID AgenteModulo does exists if ($id_agente_modulo != -1){ # ID AgenteModulo does exists
my $agent_module_row = get_db_free_row ("SELECT * FROM tagente_modulo WHERE id_agente_modulo = $id_agente_modulo", $dbh);
# Postprocess and get MAX/MIN only for numeric moduletypes # Postprocess and get MAX/MIN only for numeric moduletypes
if (($id_modulo != 3) && ($id_modulo != 17) && ($id_modulo != 10) && ($id_modulo != 23)){ if (($id_modulo != 3) && ($id_modulo != 17) && ($id_modulo != 10) && ($id_modulo != 23)){
my $query_idag = "SELECT * FROM tagente_modulo WHERE id_agente = $id_agente AND id_agente_modulo = ".$id_agente_modulo; $max = $agent_module_row->{'max'};
my $s_idag = $dbh->prepare($query_idag); $min = $agent_module_row->{'min'};
$s_idag ->execute;
if ($s_idag->rows == 0) {
logger( $pa_config, "ERROR Cannot find agenteModulo $id_agente_modulo",6);
logger( $pa_config, "ERROR: SQL Query is $query_idag ",10);
} else {
@data = $s_idag->fetchrow_array();
}
$max = $data[5];
$min = $data[6];
# Postprocess # Postprocess
if ((defined($data[23])) && ($data[23] != 0) && (is_numeric($data[23]))){ if ((defined($agent_module_row->{'post_process'})) && ($agent_module_row->{'post_process'} != 0) && (is_numeric($agent_module_row->{'post_process'}))){
$datos = $datos * $data[23]; $datos = $datos * $agent_module_row->{'post_process'};
} }
$s_idag->finish();
} else { } else {
$max = ""; $max = "";
$min = ""; $min = "";
} }
# history_data detection. If this module don't have history, exit from here now with returncode 0
if ($agent_module_row->{'history_data'} == 0){
if ( defined $Ref_bUpdateDatos ) {
$$Ref_bUpdateDatos = 1; # TODO: Make check of status change here.
}
return 0;
}
} else { # Id AgenteModulo DOESNT exist, it could need to be created... } else { # Id AgenteModulo DOESNT exist, it could need to be created...
if (dame_learnagente($pa_config, $id_agente, $dbh) eq "1" ){ if (dame_learnagente($pa_config, $id_agente, $dbh) eq "1" ){
# Try to write a module and agent_module definition for that datablock # Try to write a module and agent_module definition for that datablock
@ -1248,7 +1244,7 @@ sub pandora_writedata (%$$$$$$$$$$){
$datos = $dbh->quote($datos); $datos = $dbh->quote($datos);
$timestamp = $dbh->quote($timestamp); $timestamp = $dbh->quote($timestamp);
# Parse data entry for adecuate SQL representation. # Parse data entry for adecuate SQL representation.
$query = "INSERT INTO tagente_datos_string (id_agente_modulo, datos, timestamp, utimestamp, id_agente) VALUES ($id_agente_modulo, $datos, $timestamp, $utimestamp, $id_agente)"; $query = "INSERT INTO tagente_datos_string (id_agente_modulo, datos, utimestamp) VALUES ($id_agente_modulo, $datos, $utimestamp)";
} elsif (is_numeric($datos)){ } elsif (is_numeric($datos)){
if ($max != $min) { if ($max != $min) {
if (int($datos) > $max) { if (int($datos) > $max) {
@ -1265,7 +1261,7 @@ sub pandora_writedata (%$$$$$$$$$$){
$datos = $dbh->quote($datos); $datos = $dbh->quote($datos);
$timestamp = $dbh->quote($timestamp); $timestamp = $dbh->quote($timestamp);
# Parse data entry for adecuate SQL representation. # Parse data entry for adecuate SQL representation.
$query = "INSERT INTO tagente_datos (id_agente_modulo, datos, timestamp, utimestamp, id_agente) VALUES ($id_agente_modulo, $datos, $timestamp, $utimestamp, $id_agente)"; $query = "INSERT INTO tagente_datos (id_agente_modulo, datos, utimestamp) VALUES ($id_agente_modulo, $datos, $utimestamp)";
} }
# If data is out of limits, do not insert into database # If data is out of limits, do not insert into database
if ($outlimit == 0){ if ($outlimit == 0){
@ -1509,18 +1505,39 @@ sub pandora_lastagentcontact (%$$$$$$) {
pandora_accessupdate ($pa_config, $id_agente, $dbh); pandora_accessupdate ($pa_config, $id_agente, $dbh);
my $query = ""; my $query = "";
if ($interval == -1){ # no update for interval field (some old agents doest support it) if ($interval == -1){ # no update for interval field (some old agents doest support it)
$query = "update tagente set agent_version = '$agent_version', ultimo_contacto_remoto = '$timestamp', ultimo_contacto = '$time_now', os_version = '$os_data' where id_agente = $id_agente"; $query = "UPDATE tagente SET agent_version = '$agent_version', ultimo_contacto_remoto = '$timestamp', ultimo_contacto = '$time_now', os_version = '$os_data' WHERE id_agente = $id_agente";
} else { } else {
$query = "update tagente set intervalo = $interval, agent_version = '$agent_version', ultimo_contacto_remoto = '$timestamp', ultimo_contacto = '$time_now', os_version = '$os_data' where id_agente = $id_agente"; $query = "UPDATE tagente SET intervalo = $interval, agent_version = '$agent_version', ultimo_contacto_remoto = '$timestamp', ultimo_contacto = '$time_now', os_version = '$os_data' WHERE id_agente = $id_agente";
} }
logger( $pa_config, "pandora_lastagentcontact: Updating Agent last contact data for $nombre_agente",6); logger( $pa_config, "pandora_lastagentcontact: Updating Agent last contact data for $nombre_agente",6);
logger( $pa_config, "pandora_lastagentcontact: SQL Query: ".$query,10); logger( $pa_config, "pandora_lastagentcontact: SQL Query: ".$query, 10);
my $sag = $dbh->prepare($query); db_update ($query, $dbh);
$sag ->execute;
$sag ->finish();
} }
##########################################################################
## SUB update_keepalive_module
##
## Updates keepalive module from one agent. This only should be called
## when processing an agent, only one time, and not to be used on network
## or other agentless modules
##########################################################################
sub update_keepalive_module (%$) {
my $pa_config= $_[0];
my $id_agent = $_[1];
my $agent_name = $_[2];
my $dbh = $_[3];
# Update keepalive module
# if present, if there is more than one (nosense), only updates first one!
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 $module_typename = "keep_alive";
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, $dbh, 1);
}
}
########################################################################## ##########################################################################
## SUB pandora_incident (pa_config, dbh, title, text, priority, status, origin, id_group ## SUB pandora_incident (pa_config, dbh, title, text, priority, status, origin, id_group
@ -2145,6 +2162,43 @@ sub get_db_free_row ($$) {
} }
# ---------------------------------------------------------------
# Insert SQL sentence. Returns ID of row inserted
# ---------------------------------------------------------------
sub db_insert ($$) {
my $query= $_[0];
my $dbh = $_[1];
$dbh->do($query);
return $dbh->{'mysql_insertid'};
}
# ---------------------------------------------------------------
# UPDATE SQL sentence.
# ---------------------------------------------------------------
sub db_update ($$) {
my $query= $_[0];
my $dbh = $_[1];
$dbh->do($query);
}
# ---------------------------------------------------------------
# DELETE SQL sentence.
# ---------------------------------------------------------------
sub db_delete ($$) {
my $query= $_[0];
my $dbh = $_[1];
$dbh->do($query);
}
########################################################################## ##########################################################################
# SUB pandora_create_agent (pa_config, dbh, target_ip, target_ip_id, # SUB pandora_create_agent (pa_config, dbh, target_ip, target_ip_id,
# id_group, network_server_assigned, name, id_os) # id_group, network_server_assigned, name, id_os)

View File

@ -25,7 +25,7 @@ use DBI; # DB interface with MySQL
use Date::Manip; # Date/Time manipulation use Date::Manip; # Date/Time manipulation
# version: define la version actual del programa # version: define la version actual del programa
my $version = "2.0 PS080903"; my $version = "2.1 PS090105";
# Setup variables # Setup variables
my $dirname=""; my $dirname="";
@ -42,7 +42,7 @@ my $config_days_purge;
my $config_step_compact;# Step compact variable defines "how-fine" is thecompact algorithm. 1 Hour its very fine, 24 hours is bad value my $config_step_compact;# Step compact variable defines "how-fine" is thecompact algorithm. 1 Hour its very fine, 24 hours is bad value
# FLUSH in each IO # FLUSH in each IO
$| = 1; $| = 0;
pandora_init(); pandora_init();
@ -77,6 +77,7 @@ sub pandora_purgedb {
my $buffer; my $buffer2; my $buffer3; my $buffer; my $buffer2; my $buffer3;
my $err; # error code in datecalc function my $err; # error code in datecalc function
my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost:3306",$dbuser, $dbpass,{RaiseError => 1, AutoCommit => 1 }); my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost:3306",$dbuser, $dbpass,{RaiseError => 1, AutoCommit => 1 });
# Calculate limit for deletion, today - $days # Calculate limit for deletion, today - $days
my $limit_timestamp = DateCalc("today","-$days days",\$err); my $limit_timestamp = DateCalc("today","-$days days",\$err);
my $limit_timestamp2 = DateCalc($limit_timestamp,"+1 minute",\$err); my $limit_timestamp2 = DateCalc($limit_timestamp,"+1 minute",\$err);
@ -84,18 +85,33 @@ sub pandora_purgedb {
my $timestamp = &UnixDate("today","%Y-%m-%d %H:%M:%S"); my $timestamp = &UnixDate("today","%Y-%m-%d %H:%M:%S");
my $limit_access = DateCalc("today","-24 hours",\$err); my $limit_access = DateCalc("today","-24 hours",\$err);
$limit_access = &UnixDate($limit_access,"%Y-%m-%d %H:%M:%S"); $limit_access = &UnixDate($limit_access,"%Y-%m-%d %H:%M:%S");
my $ulimit_timestamp = &UnixDate($limit_access,"%s");
print "[PURGE] Deleting old access data (More than 24hr) \n"; print "[PURGE] Deleting old access data (More than 24hr) \n";
$dbh->do("DELETE FROM tagent_access WHERE timestamp < '$limit_access'"); $dbh->do("DELETE FROM tagent_access WHERE utimestamp < '$ulimit_timestamp'");
my $limit_event = DateCalc("today","-$config_days_purge days",\$err);
my $limit_event = DateCalc("today","-$config_days_purge days",\$err); $limit_event = &UnixDate($limit_event,"%Y-%m-%d %H:%M:%S");
$limit_event = &UnixDate($limit_event,"%Y-%m-%d %H:%M:%S"); print "[PURGE] Deleting old event data (More than $config_days_purge days)... \n";
print "[PURGE] Deleting old event data (More than $config_days_purge days)... \n"; $dbh->do("DELETE FROM tevento WHERE utimestamp < '$ulimit_timestamp'");
$dbh->do("DELETE FROM tevento WHERE timestamp < '$limit_event'");
print "[PURGE] Deleting old data... \n"; print "[PURGE] Deleting old data... \n";
$dbh->do ("DELETE FROM tagente_datos WHERE utimestamp < '$ulimit_timestamp'");
print "[PURGE] Delete old data (string) ... \n";
$dbh->do ("DELETE FROM tagente_datos_string WHERE utimestamp < '$ulimit_timestamp'");
print "[PURGE] Delete old session data \n";
db_delete ("DELETE FROM tsesion WHERE utimestamp < $ulimit_timestamp", $dbh);
print "[PURGE] Delete old data from SNMP Traps \n";
db_delete("DELETE FROM ttrap WHERE timestamp < '$limit_timestamp'", $dbh);
return;
# Performance killer !
# Lets insert the last value on $limit_timestamp + 1 minute for each id_agente_modulo # Lets insert the last value on $limit_timestamp + 1 minute for each id_agente_modulo
my $query_idag = "select count(distinct(id_agente_modulo)) from tagente_datos where timestamp < '$limit_timestamp'"; my $query_idag = "select count(distinct(id_agente_modulo)) from tagente_datos where utimestamp < '$ulimit_timestamp'";
my $idag = $dbh->prepare($query_idag); my $idag = $dbh->prepare($query_idag);
$idag ->execute; $idag ->execute;
my @datarow; my @datarow;
@ -106,7 +122,7 @@ sub pandora_purgedb {
my $different_modules = $datarow[0]; my $different_modules = $datarow[0];
$idag->finish; $idag->finish;
my $query_idag = "select distinct(id_agente_modulo) from tagente_datos WHERE timestamp < '$limit_timestamp'"; my $query_idag = "select distinct(id_agente_modulo) from tagente_datos WHERE utimestamp < '$ulimit_timestamp'";
my $idag = $dbh->prepare($query_idag); my $idag = $dbh->prepare($query_idag);
$idag ->execute; $idag ->execute;
my @datarow; my @datarow;
@ -118,7 +134,7 @@ sub pandora_purgedb {
print "\r[PURGE] ".$counter / ($different_modules / 100)."% Deleted"; print "\r[PURGE] ".$counter / ($different_modules / 100)."% Deleted";
} }
$buffer = $datarow[0]; $buffer = $datarow[0];
my $query_idag2 = "select * from tagente_datos where timestamp < '$limit_timestamp' and id_agente_modulo = $buffer order by timestamp desc limit 1"; my $query_idag2 = "select * from tagente_datos where utimestamp < '$ulimit_timestamp' and id_agente_modulo = $buffer ORDER BY by utimestamp DESC limit 1";
my $idag2 = $dbh->prepare($query_idag2); my $idag2 = $dbh->prepare($query_idag2);
$idag2 ->execute; $idag2 ->execute;
@ -131,7 +147,7 @@ sub pandora_purgedb {
} }
} }
# Execute DELETE # Execute DELETE
my $query_idag3 = "delete from tagente_datos where timestamp < '$limit_timestamp' and id_agente_modulo = $buffer "; my $query_idag3 = "DELETE FROM tagente_datos WHERE utimestamp < '$ulimit_timestamp' and id_agente_modulo = $buffer ";
my $idag3 = $dbh->prepare($query_idag3); my $idag3 = $dbh->prepare($query_idag3);
$idag3->execute; $idag3->execute;
$idag3->finish(); $idag3->finish();
@ -148,16 +164,7 @@ sub pandora_purgedb {
if ($verbosity > 0){ if ($verbosity > 0){
print "\n[PURGE] Deleting string data until $limit_timestamp \n"; print "\n[PURGE] Deleting string data until $limit_timestamp \n";
} }
my $limit_utimestamp = &UnixDate($limit_timestamp, "%s");
# Deleting string data
$dbh->do ("DELETE FROM tagente_datos_string WHERE utimestamp < $limit_utimestamp");
# Deleting session data
$dbh->do ("DELETE FROM tsesion WHERE utimestamp < $limit_utimestamp");
# Deleting SNMP data
$dbh->do ("DELETE FROM ttrap WHERE timestamp < '$limit_timestamp'");
$dbh->disconnect(); $dbh->disconnect();
} }
@ -176,6 +183,10 @@ sub pandora_compactdb {
my %value_hash; my %value_hash;
my $err; my $err;
if ($days == 0){
return;
}
# Connect to the database # Connect to the database
my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost:3306",$dbuser, $dbpass, my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost:3306",$dbuser, $dbpass,
{ RaiseError => 1, AutoCommit => 1 }); { RaiseError => 1, AutoCommit => 1 });