2013-03-01 Ramon Novoa <rnovoa@artica.es>

* lib/PandoraFMS/Core.pm,
	  lib/PandoraFMS/DB.pm,
	  lib/PandoraFMS/DataServer.pm: Refactored some GIS code. Still needs
	  testing.



git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@7768 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f
This commit is contained in:
ramonn 2013-03-01 14:27:52 +00:00
parent c446ba8028
commit c28bd6b165
4 changed files with 270 additions and 252 deletions

View File

@ -1,3 +1,10 @@
2013-03-01 Ramon Novoa <rnovoa@artica.es>
* lib/PandoraFMS/Core.pm,
lib/PandoraFMS/DB.pm,
lib/PandoraFMS/DataServer.pm: Refactored some GIS code. Still needs
testing.
2013-02-28 Sancho Lerena <slerena@artica.es> 2013-02-28 Sancho Lerena <slerena@artica.es>
* Config.pm: updated version. * Config.pm: updated version.

View File

@ -1878,90 +1878,122 @@ defined also the parent is updated.
=cut =cut
########################################################################## ##########################################################################
sub pandora_update_agent ($$$$$$$;$$$$$$) { sub pandora_update_agent ($$$$$$$;$$) {
my ($pa_config, $agent_timestamp, $agent_id, $os_version, my ($pa_config, $agent_timestamp, $agent_id, $os_version,
$agent_version, $agent_interval, $dbh, $timezone_offset, $agent_version, $agent_interval, $dbh, $timezone_offset,
$longitude, $latitude, $altitude, $position_description, $parent_agent_id) = @_; $parent_agent_id) = @_;
my $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime());
# No access update for data without interval. # No access update for data without interval.
# Single modules from network server, for example. This could be very # Single modules from network server, for example. This could be very Heavy for Pandora FMS
# Heavy for Pandora FMS
if ($agent_interval != -1){ if ($agent_interval != -1){
pandora_access_update ($pa_config, $agent_id, $dbh); pandora_access_update ($pa_config, $agent_id, $dbh);
} else {
# Do not update the agent interval
$agent_interval = undef;
} }
# No update for interval, timezone and position fields (some old agents don't support it) # Update tagente
if ($agent_interval == -1){ my $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime());
db_do($dbh, 'UPDATE tagente SET agent_version = ?, ultimo_contacto_remoto = ?, ultimo_contacto = ?, os_version = ? WHERE id_agente = ?', my ($set, $values) = db_update_get_values ({'agent_version' => $agent_version,
$agent_version, $agent_timestamp, $timestamp, $os_version, $agent_id); 'intervalo' => $agent_interval,
'ultimo_contacto_remoto' => $agent_timestamp,
'ultimo_contacto' => $timestamp,
'os_version' => $os_version,
'timezone_offset' => $timezone_offset,
'id_parent' => $parent_agent_id,
});
db_do ($dbh, "UPDATE tagente SET $set WHERE id_agente = ?", @{$values}, $agent_id);
}
##########################################################################
=head2 C<< pandora_update_gis_data (I<$pa_config>, I<$dbh>, I<$agent_id>, I<$longitude>, I<$latitude>, I<$altitude>) >>
Update agent GIS information.
=cut
##########################################################################
sub pandora_update_gis_data ($$$$$$$$) {
my ($pa_config, $dbh, $agent_id, $agent_name, $longitude, $latitude, $altitude, $position_description, $timestamp) = @_;
logger($pa_config, "Updating GIS data for agent $agent_name (long: $longitude lat: $latitude alt: $altitude)", 10);
# Check for valid longitude and latitude
if (!defined($longitude) || $longitude !~ /[-+]?[0-9,11,12]/ ||
!defined($latitude) || $latitude !~ /[-+]?[0-9,11,12]/) {
return; return;
} }
if ( defined ($timezone_offset)) {
if (defined($parent_agent_id)) {
# Update the table tagente with all the new data and set the new parent
db_do ($dbh, 'UPDATE tagente SET intervalo = ?, agent_version = ?, ultimo_contacto_remoto = ?, ultimo_contacto = ?, os_version = ?,
timezone_offset = ?, id_parent = ? WHERE id_agente = ?', $agent_interval, $agent_version, $agent_timestamp,
$timestamp, $os_version, $timezone_offset, $parent_agent_id, $agent_id);
}
else {
# Update the table tagente with all the new data
db_do ($dbh, 'UPDATE tagente SET intervalo = ?, agent_version = ?, ultimo_contacto_remoto = ?, ultimo_contacto = ?, os_version = ?,
timezone_offset = ? WHERE id_agente = ?', $agent_interval, $agent_version, $agent_timestamp, $timestamp, $os_version, $timezone_offset, $agent_id);
}
}
else {
if (defined($parent_agent_id)) {
# Update the table tagente with all the new data and set the new parent
db_do ($dbh, 'UPDATE tagente SET intervalo = ?, agent_version = ?, ultimo_contacto_remoto = ?, ultimo_contacto = ?, os_version = ?, id_parent = ?
WHERE id_agente = ?', $agent_interval, $agent_version, $agent_timestamp, $timestamp, $os_version, $parent_agent_id, $agent_id);
}
else {
# Update the table tagente with all the new data
db_do ($dbh, 'UPDATE tagente SET intervalo = ?, agent_version = ?, ultimo_contacto_remoto = ?, ultimo_contacto = ?, os_version = ? WHERE id_agente = ?',
$agent_interval, $agent_version, $agent_timestamp, $timestamp, $os_version, $agent_id);
}
}
my $update_gis_data= get_db_value ($dbh, 'SELECT update_gis_data FROM tagente WHERE id_agente = ?', $agent_id);
#Test if we have received the optional position parameters
if (defined ($longitude) && defined ($latitude) && $pa_config->{'activate_gis'} == 1 && $update_gis_data == 1 ){
# Get the last position to see if it has moved.
my $last_agent_position= get_db_single_row ($dbh, 'SELECT * FROM tgis_data_status WHERE tagente_id_agente = ?', $agent_id);
if(defined($last_agent_position)) {
logger($pa_config, "Old Agent data: current_longitude=". $last_agent_position->{'current_longitude'}. " current_latitude="
.$last_agent_position->{'current_latitude'}. " current_altitude=". $last_agent_position->{'current_altitude'}. " ID: $agent_id ", 10);
# If the agent has moved outside the range stablised as location error
if (distance_moved($pa_config, $last_agent_position->{'stored_longitude'}, $last_agent_position->{'stored_latitude'},
$last_agent_position->{'stored_altitude'}, $longitude, $latitude, $altitude) > $pa_config->{'location_error'}) {
#Archive the old position and save new one as status
archive_agent_position($pa_config, $last_agent_position->{'start_timestamp'},$timestamp,$last_agent_position->{'stored_longitude'}, $last_agent_position->{'stored_latitude'},
$last_agent_position->{'stored_altitude'},$last_agent_position->{'description'}, $last_agent_position->{'number_of_packages'},$agent_id, $dbh);
if(!defined($altitude) ) {
$altitude = 0;
}
# Save the agent position in the tgis_data_status table
update_agent_position($pa_config, $longitude, $latitude, $altitude, $agent_id, $dbh, $longitude, $latitude, $altitude, $timestamp, $position_description);
}
else { #the agent has not moved enougth so just update the status table
update_agent_position ($pa_config, $longitude, $latitude, $altitude, $agent_id, $dbh);
}
}
else {
logger($pa_config, "There was not previous positional data, storing first positioal status",8);
save_agent_position($pa_config, $longitude, $latitude, $altitude, $agent_id, $dbh, $timestamp, $position_description);
}
}
else {
logger($pa_config, "Agent id $agent_id positional data ignored (update_gis_data = $update_gis_data)",10);
}
# Altitude is optional
if (!defined($altitude) || $altitude !~ /[-+]?[0-9,11,12]/) {
$altitude = '';
}
# Get position description
if ((!defined($position_description))) {
# This code gets description (Reverse Geocoding) from a current GPS coordinates using Google maps API
# This requires a connection to internet and could be very slow and have a huge impact in performance.
# Other methods for reverse geocoding are OpenStreetmaps, in nternet or in a local server
if ($pa_config->{'google_maps_description'}){
my $content = get ('http://maps.google.com/maps/geo?q='.$latitude.','.$longitude.'&output=csv&sensor=false');
my @address = split (/\"/,$content);
$position_description = $address[1];
}
elsif ($pa_config->{'openstreetmaps_description'}){
# Sample Query: http://nominatim.openstreetmap.org/reverse?format=csv&lat=40.43197&lon=-3.6993818&zoom=18&addressdetails=1&email=info@pandorafms.org
# Email address is sent by courtesy to OpenStreetmaps people.
# I read the API :-), thanks guys for your work.
# Change here URL to make request to a local openstreetmap server
my $content = get ('http://nominatim.openstreetmap.org/reverse?format=csv&lat='.$latitude.'&lon='.$longitude.'&zoom=18&addressdetails=1&email=info@pandorafms.org');
if ((defined($content)) && ($content ne "")){
# Yep, I need to parse the XML output.
my $xs1 = XML::Simple->new();
my $doc = $xs1->XMLin($content);
$position_description = safe_input ($doc->{result}{content});
} else {
$position_description = "";
}
}
if (!defined($position_description)){
$position_description = "";
}
logger($pa_config, "Getting GIS Data=longitude=$longitude latitude=$latitude altitude=$altitude position_description=$position_description", 10);
}
# Get the last position to see if it has moved.
my $last_agent_position= get_db_single_row ($dbh, 'SELECT * FROM tgis_data_status WHERE tagente_id_agente = ?', $agent_id);
if(defined($last_agent_position)) {
logger($pa_config, "Old Agent data: current_longitude=". $last_agent_position->{'current_longitude'}. " current_latitude=".$last_agent_position->{'current_latitude'}. " current_altitude=". $last_agent_position->{'current_altitude'}. " ID: $agent_id ", 10);
# If the agent has moved outside the range stablised as location error
if (distance_moved($pa_config, $last_agent_position->{'stored_longitude'}, $last_agent_position->{'stored_latitude'}, $last_agent_position->{'stored_altitude'}, $longitude, $latitude, $altitude) > $pa_config->{'location_error'}) {
#Archive the old position and save new one as status
archive_agent_position($pa_config, $last_agent_position->{'start_timestamp'}, $timestamp,$last_agent_position->{'stored_longitude'}, $last_agent_position->{'stored_latitude'}, $last_agent_position->{'stored_altitude'},$last_agent_position->{'description'}, $last_agent_position->{'number_of_packages'},$agent_id, $dbh);
$altitude = 0 if (!defined($altitude));
# Save the agent position in the tgis_data_status table
update_agent_position($pa_config, $longitude, $latitude, $altitude, $agent_id, $dbh, $longitude, $latitude, $altitude, $timestamp, $position_description);
}
# The agent has not moved enougth so just update the status table
else {
update_agent_position ($pa_config, $longitude, $latitude, $altitude, $agent_id, $dbh);
}
}
else {
logger($pa_config, "There was not previous positional data, storing first positioal status", 10);
save_agent_position($pa_config, $longitude, $latitude, $altitude, $agent_id, $dbh, $timestamp, $position_description);
}
} }
########################################################################## ##########################################################################
@ -2372,40 +2404,38 @@ sub pandora_create_agent ($$$$$$$$$$;$$$$$$$) {
$longitude, $latitude, $altitude, $position_description, $longitude, $latitude, $altitude, $position_description,
$custom_id, $url_address) = @_; $custom_id, $url_address) = @_;
if (!defined($custom_id)) { logger ($pa_config, "Server '$server_name' creating agent '$agent_name' address '$address'.", 10);
$custom_id = '';
}
if (!defined($url_address)) {
$url_address = '';
}
if (!defined($group_id)) { if (!defined($group_id)) {
$group_id = $pa_config->{'autocreate_group'}; $group_id = $pa_config->{'autocreate_group'};
} if (! defined (get_group_name ($dbh, $group_id))) {
logger ($pa_config, "Server '$server_name' creating agent '$agent_name' address '$address'.", 10); logger($pa_config, "Group id $group_id does not exist (check autocreate_group config token)", 3);
return;
$description = "Created by $server_name" unless ($description ne '');
my $agent_id;
# Test if the optional positional parameters are defined or GIS is disabled
if (!defined ($timezone_offset) ) {
$agent_id = db_insert ($dbh, 'id_agente', 'INSERT INTO tagente (nombre, direccion, comentarios, id_grupo, id_os, server_name, intervalo, id_parent, modo, custom_id, url_address)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?)', safe_input($agent_name), $address, $description, $group_id, $os_id, $server_name, $interval, $parent_id, $custom_id, $url_address);
}
else {
$agent_id = db_insert ($dbh, 'id_agente', 'INSERT INTO tagente (nombre, direccion, comentarios, id_grupo, id_os, server_name, intervalo, id_parent,
timezone_offset, modo, custom_id, url_address) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?)', safe_input($agent_name), $address,
$description, $group_id, $os_id, $server_name, $interval, $parent_id, $timezone_offset, $custom_id, $url_address);
}
if (defined ($longitude) && defined ($latitude ) && $pa_config->{'activate_gis'} == 1 ) {
if (!defined($altitude)) {
$altitude = 0;
} }
}
$description = "Created by $server_name" unless ($description ne '');
my ($columns, $values) = db_insert_get_values ({ 'nombre' => safe_input($agent_name),
'direccion' => $address,
'comentarios' => $description,
'id_grupo' => $group_id,
'id_os' => $os_id,
'server_name' => $server_name,
'intervalo' => $interval,
'id_parent' => $parent_id,
'modo' => 1,
'custom_id' => $custom_id,
'url_address' => $url_address,
'timezone_offset' => $timezone_offset
});
my $agent_id = db_insert ($dbh, 'id_agente', "INSERT INTO tagente $columns", @{$values});
# Save GIS data
if (defined ($longitude) && defined ($latitude ) && $pa_config->{'activate_gis'} == 1 ) {
# Save the first position # Save the first position
my $utimestamp = time (); my $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime (time ()));
my $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime ($utimestamp));
save_agent_position($pa_config, $longitude, $latitude, $altitude, $agent_id, $dbh, $timestamp, $position_description) ; save_agent_position($pa_config, $longitude, $latitude, $altitude, $agent_id, $dbh, $timestamp, $position_description) ;
} }
@ -3223,25 +3253,24 @@ Saves a new agent GIS information record in B<tgis_data_status> table.
sub save_agent_position($$$$$$;$$) { sub save_agent_position($$$$$$;$$) {
my ($pa_config, $current_longitude, $current_latitude, $current_altitude, $agent_id, $dbh, $start_timestamp, $description) = @_; my ($pa_config, $current_longitude, $current_latitude, $current_altitude, $agent_id, $dbh, $start_timestamp, $description) = @_;
if (!defined($description)) {
$description = '';
}
logger($pa_config, "Updating agent position: longitude=$current_longitude, latitude=$current_latitude, altitude=$current_altitude, start_timestamp=$start_timestamp agent_id=$agent_id", 10); logger($pa_config, "Updating agent position: longitude=$current_longitude, latitude=$current_latitude, altitude=$current_altitude, start_timestamp=$start_timestamp agent_id=$agent_id", 10);
if (defined($start_timestamp)) { # Set some default values
# Upadate the timestamp of the received agent $description = '' if (!defined($description));
db_do ($dbh, 'INSERT INTO tgis_data_status (tagente_id_agente, current_longitude , current_latitude, current_altitude, $current_altitude = 0 if (!defined($current_altitude));
stored_longitude , stored_latitude, stored_altitude, start_timestamp, description) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)',
$agent_id, $current_longitude, $current_latitude, $current_altitude, $current_longitude, my ($columns, $values) = db_insert_get_values ({ 'tagente_id_agente' => $agent_id,
$current_latitude, $current_altitude, $start_timestamp, $description); 'current_longitude' => $current_longitude,
} 'current_latitude' => $current_latitude,
else { 'current_altitude' => $current_altitude,
# Upadate the data of the received agent using the default timestamp 'stored_longitude' => $current_longitude,
db_do ($dbh, 'INSERT INTO tgis_data_status (tagente_id_agente, current_longitude , current_latitude, current_altitude, 'stored_latitude' => $current_latitude,
stored_longitude , stored_latitude, stored_altitude, description) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ', 'stored_altitude' => $current_altitude,
$agent_id, $current_longitude, $current_latitude, $current_altitude, $current_longitude, 'start_timestamp' => $start_timestamp,
$current_latitude, $current_altitude, , $description); 'description' => $description
} });
db_do ($dbh, "INSERT INTO tgis_data_status $columns", @{$values});
} }
########################################################################## ##########################################################################
@ -3255,6 +3284,7 @@ Updates agent GIS information in B<tgis_data_status> table.
sub update_agent_position($$$$$$;$$$$$) { sub update_agent_position($$$$$$;$$$$$) {
my ($pa_config, $current_longitude, $current_latitude, $current_altitude, my ($pa_config, $current_longitude, $current_latitude, $current_altitude,
$agent_id, $dbh, $stored_longitude, $stored_latitude, $stored_altitude, $start_timestamp, $description) = @_; $agent_id, $dbh, $stored_longitude, $stored_latitude, $stored_altitude, $start_timestamp, $description) = @_;
if (defined($stored_longitude) && defined($stored_latitude) && defined($start_timestamp) ) { if (defined($stored_longitude) && defined($stored_latitude) && defined($start_timestamp) ) {
# Upadate all the position data of the agent # Upadate all the position data of the agent
logger($pa_config, "Updating agent position: current_longitude=$current_longitude, current_latitude=$current_latitude, logger($pa_config, "Updating agent position: current_longitude=$current_longitude, current_latitude=$current_latitude,
@ -3607,7 +3637,7 @@ sub pandora_group_statistics ($$) {
# Update the record. # Update the record.
db_do ($dbh, "DELETE FROM tgroup_stat WHERE id_group = $group"); db_do ($dbh, "DELETE FROM tgroup_stat WHERE id_group = $group");
db_do ($dbh, "INSERT INTO tgroup_stat (id_group, modules, normal, critical, warning, unknown, " . db_reserved_word ('non-init') . ", alerts, alerts_fired, agents, agents_unknown, utimestamp) VALUES ($group, $modules, $normal, $critical, $warning, $unknown, $non_init, $alerts, $alerts_fired, $agents, $agents_unknown, UNIX_TIMESTAMP())"); db_do ($dbh, "INSERT INTO tgroup_stat (id_group, modules, normal, critical, warning, unknown, " . $PandoraFMS::DB::RDBMS_QUOTE . 'non-init' . $PandoraFMS::DB::RDBMS_QUOTE . ", alerts, alerts_fired, agents, agents_unknown, utimestamp) VALUES ($group, $modules, $normal, $critical, $warning, $unknown, $non_init, $alerts, $alerts_fired, $agents, $agents_unknown, UNIX_TIMESTAMP())");
} }

View File

@ -37,12 +37,13 @@ our @EXPORT = qw(
db_disconnect db_disconnect
db_do db_do
db_insert db_insert
db_insert_get_values
db_process_insert db_process_insert
db_process_update db_process_update
db_reserved_word
db_string db_string
db_text db_text
db_update db_update
db_update_get_values
get_action_id get_action_id
get_addr_id get_addr_id
get_agent_addr_id get_agent_addr_id
@ -80,18 +81,26 @@ our @EXPORT = qw(
get_agent_modules get_agent_modules
get_agentmodule_status get_agentmodule_status
get_agentmodule_data get_agentmodule_data
$RDBMS
$RDBMS_QUOTE
); );
# Relational database management system in use
our $RDBMS = '';
# Character used to quote reserved words in the current RDBMS
our $RDBMS_QUOTE = '';
########################################################################## ##########################################################################
## Connect to the DB. ## Connect to the DB.
########################################################################## ##########################################################################
my $RDBMS = '';
sub db_connect ($$$$$$) { sub db_connect ($$$$$$) {
my ($rdbms, $db_name, $db_host, $db_port, $db_user, $db_pass) = @_; my ($rdbms, $db_name, $db_host, $db_port, $db_user, $db_pass) = @_;
if ($rdbms eq 'mysql') { if ($rdbms eq 'mysql') {
$RDBMS = 'mysql'; $RDBMS = 'mysql';
$RDBMS_QUOTE = '`';
# Connect to MySQL # Connect to MySQL
my $dbh = DBI->connect("DBI:mysql:$db_name:$db_host:$db_port", $db_user, $db_pass, { RaiseError => 1, AutoCommit => 1 }); my $dbh = DBI->connect("DBI:mysql:$db_name:$db_host:$db_port", $db_user, $db_pass, { RaiseError => 1, AutoCommit => 1 });
return undef unless defined ($dbh); return undef unless defined ($dbh);
@ -106,6 +115,7 @@ sub db_connect ($$$$$$) {
} }
elsif ($rdbms eq 'postgresql') { elsif ($rdbms eq 'postgresql') {
$RDBMS = 'postgresql'; $RDBMS = 'postgresql';
$RDBMS_QUOTE = '"';
# Connect to PostgreSQL # Connect to PostgreSQL
my $dbh = DBI->connect("DBI:Pg:dbname=$db_name;host=$db_host;port=$db_port", $db_user, $db_pass, { RaiseError => 1, AutoCommit => 1 }); my $dbh = DBI->connect("DBI:Pg:dbname=$db_name;host=$db_host;port=$db_port", $db_user, $db_pass, { RaiseError => 1, AutoCommit => 1 });
@ -114,6 +124,7 @@ sub db_connect ($$$$$$) {
return $dbh; return $dbh;
} elsif ($rdbms eq 'oracle') { } elsif ($rdbms eq 'oracle') {
$RDBMS = 'oracle'; $RDBMS = 'oracle';
$RDBMS_QUOTE = '"';
# Connect to Oracle # Connect to Oracle
my $dbh = DBI->connect("DBI:Oracle:dbname=$db_name;host=$db_host;port=$db_port;sid=pandora", $db_user, $db_pass, { RaiseError => 1, AutoCommit => 1 }); my $dbh = DBI->connect("DBI:Oracle:dbname=$db_name;host=$db_host;port=$db_port;sid=pandora", $db_user, $db_pass, { RaiseError => 1, AutoCommit => 1 });
@ -616,11 +627,11 @@ sub db_insert ($$$;@) {
} }
# PostgreSQL # PostgreSQL
elsif ($RDBMS eq 'postgresql') { elsif ($RDBMS eq 'postgresql') {
$insert_id = get_db_value ($dbh, $query . ' RETURNING ' . db_reserved_word ($index), @values); $insert_id = get_db_value ($dbh, $query . ' RETURNING ' . $RDBMS_QUOTE . $index . $RDBMS_QUOTE, @values);
} }
# Oracle # Oracle
elsif ($RDBMS eq 'oracle') { elsif ($RDBMS eq 'oracle') {
my $sth = $dbh->prepare($query . ' RETURNING ' . db_reserved_word (uc ($index)) . ' INTO ?'); my $sth = $dbh->prepare($query . ' RETURNING ' . $RDBMS_QUOTE . (uc ($index)) . $RDBMS_QUOTE . ' INTO ?');
for (my $i = 0; $i <= $#values; $i++) { for (my $i = 0; $i <= $#values; $i++) {
$sth->bind_param ($i+1, $values[$i]); $sth->bind_param ($i+1, $values[$i]);
} }
@ -776,8 +787,13 @@ sub db_do ($$;@) {
my ($dbh, $query, @values) = @_; my ($dbh, $query, @values) = @_;
#DBI->trace( 3, '/tmp/dbitrace.log' ); #DBI->trace( 3, '/tmp/dbitrace.log' );
use Carp;
eval {
$dbh->do($query, undef, @values); $dbh->do($query, undef, @values);
};
if ($@) {
print "QUERY: $query\n";
}
} }
######################################################################## ########################################################################
@ -794,21 +810,6 @@ sub is_agent_address ($$$) {
return (defined ($id_ag)) ? $id_ag : 0; return (defined ($id_ag)) ? $id_ag : 0;
} }
########################################################################
## Escape the given reserved word.
########################################################################
sub db_reserved_word ($) {
my $reserved_word = shift;
# MySQL
return '`' . $reserved_word . '`' if ($RDBMS eq 'mysql');
# PostgreSQL
return '"' . $reserved_word . '"' if ($RDBMS eq 'postgresql' || $RDBMS eq 'oracle');
return $reserved_word;
}
########################################################################## ##########################################################################
## Quote the given string. ## Quote the given string.
########################################################################## ##########################################################################
@ -885,6 +886,65 @@ sub get_priority_name ($) {
return ''; return '';
} }
########################################################################
## Get the set string and array of values to perform un update from a hash.
########################################################################
sub db_update_get_values ($) {
my ($set_ref) = @_;
my $set = '';
my @values;
while (my ($key, $value) = each (%{$set_ref})) {
# Not value for the given column
next if (! defined ($value));
$set .= "$key = ?,";
push (@values, $value);
}
# Remove the last ,
chop ($set);
return ($set, \@values);
}
########################################################################
## Get the string and array of values to perform an insert from a hash.
########################################################################
sub db_insert_get_values ($) {
my ($insert_ref) = @_;
my $columns = '(';
my @values;
while (my ($key, $value) = each (%{$insert_ref})) {
# Not value for the given column
next if (! defined ($value));
$columns .= $PandoraFMS::DB::RDBMS_QUOTE . "$key" . $PandoraFMS::DB::RDBMS_QUOTE . ",";
push (@values, $value);
}
# Remove the last , and close the parentheses
chop ($columns);
$columns .= ')';
# No columns
if ($columns eq '()') {
return;
}
# Add placeholders for the values
$columns .= ' VALUES (' . ("?," x ($#values + 1));
# Remove the last , and close the parentheses
chop ($columns);
$columns .= ')';
return ($columns, \@values);
}
# End of function declaration # End of function declaration
# End of defined Code # End of defined Code

View File

@ -213,7 +213,7 @@ sub process_xml_data ($$$$$) {
# Timezone offset must be an integer beween -12 and +12 # Timezone offset must be an integer beween -12 and +12
if (!defined($timezone_offset) || $timezone_offset !~ /[-+]?[0-9,11,12]/) { if (!defined($timezone_offset) || $timezone_offset !~ /[-+]?[0-9,11,12]/) {
$timezone_offset = 0; # Default value $timezone_offset = 0;
} }
# Parent Agent Name # Parent Agent Name
@ -227,69 +227,6 @@ sub process_xml_data ($$$$$) {
logger($pa_config,"Parent_agent_name: $parent_agent_name parent_id: $parent_id",10); logger($pa_config,"Parent_agent_name: $parent_agent_name parent_id: $parent_id",10);
} }
my $valid_position_data = 1;
# Get GIS information
my ($longitude, $latitude, $altitude, $position_description) = (
$data->{'longitude'}, $data->{'latitude'}, $data->{'altitude'},
$data->{'position_description'});
if ($pa_config->{'activate_gis'}) {
# Validate the GIS informtation
if (!defined($altitude) || $altitude !~ /[-+]?[0-9,11,12]/) {
$altitude = ''; # Default value
# This could be a valid position data, not always will get altitude
}
if (!defined($longitude) || $longitude !~ /[-+]?[0-9,11,12]/) {
$longitude = ''; # Default value
$valid_position_data = 0;
}
if (!defined($latitude) || $latitude !~ /[-+]?[0-9,11,12]/) {
$latitude = ''; # Default value
$valid_position_data = 0;
}
if ((!defined($position_description)) && ($latitude ne '')) { #FIXME: Validate the data with a regexp
# This code gets description (Reverse Geocoding) from a current GPS coordinates using Google maps API
# This requires a connection to internet and could be very slow and have a huge impact in performance.
# Other methods for reverse geocoding are OpenStreetmaps, in nternet or in a local server
if ($pa_config->{'google_maps_description'}){
my $content = get ('http://maps.google.com/maps/geo?q='.$latitude.','.$longitude.'&output=csv&sensor=false');
my @address = split (/\"/,$content);
$position_description = $address[1];
}
elsif ($pa_config->{'openstreetmaps_description'}){
# Sample Query: http://nominatim.openstreetmap.org/reverse?format=csv&lat=40.43197&lon=-3.6993818&zoom=18&addressdetails=1&email=info@pandorafms.org
# Email address is sent by courtesy to OpenStreetmaps people.
# I read the API :-), thanks guys for your work.
# Change here URL to make request to a local openstreetmap server
my $content = get ('http://nominatim.openstreetmap.org/reverse?format=csv&lat='.$latitude.'&lon='.$longitude.'&zoom=18&addressdetails=1&email=info@pandorafms.org');
if ((defined($content)) && ($content ne "")){
# Yep, I need to parse the XML output.
my $xs1 = XML::Simple->new();
my $doc = $xs1->XMLin($content);
$position_description = safe_input ($doc->{result}{content});
} else {
$position_description = "";
}
}
}
if (!defined($position_description)){
$position_description = "";
}
logger($pa_config, "Getting GIS Data=timezone_offset=$timezone_offset longitude=$longitude latitude=$latitude altitude=$altitude position_description=$position_description", 8);
}
# Unknown agent! # Unknown agent!
if (! defined ($agent_name) || $agent_name eq '') { if (! defined ($agent_name) || $agent_name eq '') {
logger($pa_config, "$file_name has data from an unnamed agent", 3); logger($pa_config, "$file_name has data from an unnamed agent", 3);
@ -300,26 +237,25 @@ sub process_xml_data ($$$$$) {
if ( $data->{'timestamp'} =~ /AUTO/ ){ if ( $data->{'timestamp'} =~ /AUTO/ ){
$timestamp = strftime ("%Y/%m/%d %H:%M:%S", localtime()); $timestamp = strftime ("%Y/%m/%d %H:%M:%S", localtime());
} }
else { # Apply an offset to the timestamp
if ($timezone_offset != 0) { elsif ($timezone_offset != 0) {
# Modify the timestamp with the timezone_offset # Modify the timestamp with the timezone_offset
logger($pa_config, "Unmodified timestamp = $timestamp", 5); logger($pa_config, "Applied a timezone offset of $timestamp to agent " . $data->{'agent_name'}, 10);
$timestamp =~ /(\d+)[\/|\-](\d+)[\/|\-](\d+) +(\d+):(\d+):(\d+)/;
logger($pa_config, "Unmodified timestamp = $1/$2/$3 $4:$5:$6", 5); # Calculate the start date to add the offset
my $utimestamp = ($timezone_offset * 3600); my $utimestamp = 0;
eval { eval {
$utimestamp += timelocal($6, $5, $4, $3, $2 -1 , $1 - 1900); if ($timestamp =~ /(\d+)[\/|\-](\d+)[\/|\-](\d+) +(\d+):(\d+):(\d+)/) {
}; $utimestamp = timelocal($6, $5, $4, $3, $2 -1 , $1 - 1900);
if ($@) { }
logger($pa_config,"WARNING: Invalid timestamp ($@) using server timestamp.", 4); };
$timestamp = strftime ("%Y/%m/%d %H:%M:%S", localtime());
} # Apply the offset if there were no errors
logger($pa_config, "Seconds timestamp = $timestamp modified timestamp in seconds $utimestamp with timezone_offset = $timezone_offset", 5); if (! $@ && $utimestamp != 0) {
$timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime($utimestamp)); $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime($utimestamp + ($timezone_offset * 3600)));
} }
logger($pa_config, "Modified timestamp = $timestamp with timezone_offset = $timezone_offset", 5);
} }
# Check some variables # Check some variables
$interval = 300 if (! defined ($interval) || $interval eq ''); $interval = 300 if (! defined ($interval) || $interval eq '');
@ -351,21 +287,9 @@ sub process_xml_data ($$$$$) {
my $description = ''; my $description = '';
$description = $data->{'description'} if (defined ($data->{'description'})); $description = $data->{'description'} if (defined ($data->{'description'}));
# Create the agent
if ($valid_position_data == 1 && $pa_config->{'activate_gis'} != 0 ) {
logger($pa_config, "Creating agent $agent_name at long: $longitude lat: $latitude alt: $altitude", 5);
}
else { # Ignore agent positional data
logger($pa_config, "Creating agent $agent_name", 5);
$longitude = undef;
$latitude = undef;
$altitude = undef;
$position_description = undef;
}
$agent_id = pandora_create_agent($pa_config, $pa_config->{'servername'}, $agent_name, $address, $group_id, $parent_id, $os, $agent_id = pandora_create_agent($pa_config, $pa_config->{'servername'}, $agent_name, $address, $group_id, $parent_id, $os,
$description, $interval, $dbh, $timezone_offset, $longitude, $latitude, $altitude, $position_description, $custom_id, $url_address); $description, $interval, $dbh, $timezone_offset, undef, undef, undef, undef, $custom_id, $url_address);
if (! defined ($agent_id)) { if (! defined ($agent_id)) {
return; return;
@ -419,12 +343,16 @@ sub process_xml_data ($$$$$) {
$agent_version = $agent->{'agent_version'}; $agent_version = $agent->{'agent_version'};
$timezone_offset = $agent->{'timezone_offset'}; $timezone_offset = $agent->{'timezone_offset'};
$parent_id = $agent->{'id_parent'}; $parent_id = $agent->{'id_parent'};
} }
else { # Learning mode # Learning mode
else {
# Update agent address if necessary # Update agent address if necessary
if ($address ne '' && $address ne $agent->{'direccion'}) { if ($address ne '' && $address ne $agent->{'direccion'}) {
# Update the main address # Update the main address
pandora_update_agent_address ($pa_config, $agent_id, $agent_name, $address, $dbh); pandora_update_agent_address ($pa_config, $agent_id, $agent_name, $address, $dbh);
# Update the addres list if necessary # Update the addres list if necessary
pandora_add_agent_address($pa_config, $agent_id, $address, $dbh); pandora_add_agent_address($pa_config, $agent_id, $address, $dbh);
} }
@ -479,23 +407,16 @@ sub process_xml_data ($$$$$) {
} }
} }
# Update GIS data only if is allowed and is valid position
if ($valid_position_data == 1 && $pa_config->{'activate_gis'} != 0) {
logger($pa_config, "Updating agent $agent_name at long: $longitude lat: $latitude alt: $altitude parent_id: $parent_id", 5);
}
else {
$longitude = undef;
$latitude = undef;
$altitude = undef;
$position_description = undef;
}
# Update agent information # Update agent information
pandora_update_agent($pa_config, $timestamp, $agent_id, $os_version, $agent_version, $interval, $dbh, $timezone_offset, pandora_update_agent($pa_config, $timestamp, $agent_id, $os_version, $agent_version, $interval, $dbh, $timezone_offset, $parent_id);
$longitude, $latitude, $altitude, $position_description, $parent_id);
# Update GIS data
if ($pa_config->{'activate_gis'} != 0 && $agent->{'update_gis_data'} == 1) {
pandora_update_gis_data ($pa_config, $dbh, $agent_id, $agent_name, $data->{'longitude'}, $data->{'latitude'}, $data->{'altitude'}, $data->{'position_description'}, $timestamp);
}
# Update keep alive modules
pandora_module_keep_alive ($pa_config, $agent_id, $agent_name, $server_id, $dbh); pandora_module_keep_alive ($pa_config, $agent_id, $agent_name, $server_id, $dbh);
# Process modules # Process modules