* Created Tools->nice_exit

* Changed all methods that returned 'undef' on error to return '!!error!!' instead.
* Created Convert->round(), ->comma(), ->bytes_to_human_readable() and ->human_readable_to_bytes().
* Created Database->archive_databases(), ->check_lock_age(), ->lock_file() and ->resync_databases() (last one is not started yet).

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 7 years ago
parent 6080ae0bb3
commit 9936554cdb
  1. 47
      AN/Tools.pm
  2. 22
      AN/Tools/Alert.pm
  3. 723
      AN/Tools/Convert.pm
  4. 220
      AN/Tools/Database.pm
  5. 8
      AN/Tools/Storage.pm
  6. 16
      AN/Tools/System.pm
  7. 10
      AN/an-tools.xml
  8. 2
      striker.conf

@ -19,6 +19,7 @@ my $THIS_FILE = "Tools.pm";
### Methods; ### Methods;
# data # data
# environment # environment
# nice_exit
# _add_hash_reference # _add_hash_reference
# _hostname # _hostname
# _make_hash_reference # _make_hash_reference
@ -127,7 +128,14 @@ sub new
UUID => "", UUID => "",
}, },
sys => { sys => {
database => {
local_lock_active => 0,
locking_reap_age => 300,
log_transactions => 0,
maximum_batch_size => 25000,
},
host_type => "", host_type => "",
use_base2 => 1,
}, },
}; };
@ -283,6 +291,32 @@ sub environment
return ($an->{ENV_VALUES}{ENVIRONMENT}); return ($an->{ENV_VALUES}{ENVIRONMENT});
} }
=head2 nice_exit
This is a simple method to exit cleanly, closing database connections and exiting with the set exit code.
Parameters;
=head3 exit_code (optional)
If set, this will be the exit code. The default is to exit with code C<< 0 >>.
=cut
sub nice_exit
{
my $self = shift;
my $parameter = shift;
my $an = $self;
my $exit_code = defined $parameter->{exit_code} ? $parameter->{exit_code} : 0;
# Close database connections (if any).
$an->Database->disconnect();
exit($exit_code);
}
############################################################################################################# #############################################################################################################
# Public methods used to access sub modules. # # Public methods used to access sub modules. #
############################################################################################################# #############################################################################################################
@ -608,16 +642,16 @@ sub _set_paths
# Executables # Executables
$an->data->{path} = { $an->data->{path} = {
configs => { configs => {
'pg_hba.conf' => "/var/lib/pgsql/data/pg_hba.conf", 'pg_hba.conf' => "/var/lib/pgsql/data/pg_hba.conf",
'postgresql.conf' => "/var/lib/pgsql/data/postgresql.conf", 'postgresql.conf' => "/var/lib/pgsql/data/postgresql.conf",
ssh_config => "/etc/ssh/ssh_config", ssh_config => "/etc/ssh/ssh_config",
'striker.conf' => "/etc/striker/striker.conf", 'striker.conf' => "/etc/striker/striker.conf",
}, },
data => { data => {
passwd => "/etc/passwd", passwd => "/etc/passwd",
}, },
directories => { directories => {
backups => "/usr/sbin/striker/backups", backups => "/usr/sbin/striker/backups",
'cgi-bin' => "/var/www/cgi-bin", 'cgi-bin' => "/var/www/cgi-bin",
html => "/var/www/html", html => "/var/www/html",
@ -625,7 +659,8 @@ sub _set_paths
tools => "/usr/sbin/striker", tools => "/usr/sbin/striker",
units => "/usr/lib/systemd/system", units => "/usr/lib/systemd/system",
}, },
exe => { exe => {
'an-report-memory' => "/usr/sbin/an-report-memory",
'chmod' => "/usr/bin/chmod", 'chmod' => "/usr/bin/chmod",
'chown' => "/usr/bin/chown", 'chown' => "/usr/bin/chown",
cp => "/usr/bin/cp", cp => "/usr/bin/cp",
@ -640,12 +675,16 @@ sub _set_paths
logger => "/usr/bin/logger", logger => "/usr/bin/logger",
'mkdir' => "/usr/bin/mkdir", 'mkdir' => "/usr/bin/mkdir",
ping => "/usr/bin/ping", ping => "/usr/bin/ping",
pgrep => "/usr/bin/pgrep",
psql => "/usr/bin/psql", psql => "/usr/bin/psql",
'postgresql-setup' => "/usr/bin/postgresql-setup", 'postgresql-setup' => "/usr/bin/postgresql-setup",
su => "/usr/bin/su", su => "/usr/bin/su",
systemctl => "/usr/bin/systemctl", systemctl => "/usr/bin/systemctl",
uuidgen => "/usr/bin/uuidgen", uuidgen => "/usr/bin/uuidgen",
}, },
'lock' => {
database => "/tmp/an-tools.database.lock",
},
secure => { secure => {
postgres_pgpass => "/var/lib/pgsql/.pgpass", postgres_pgpass => "/var/lib/pgsql/.pgpass",
}, },

@ -72,7 +72,7 @@ sub parent
This is used by scan agents that need to track whether an alert was sent when a sensor dropped below/rose above a set alert threshold. For example, if a sensor alerts at 20°C and clears at 25°C, this will be called when either value is passed. When passing the warning threshold, the alert is registered and sent to the user. Once set, no further warning alerts are sent. When the value passes over the clear threshold, this is checked and if an alert was previously registered, it is removed and an "all clear" message is sent. In this way, multiple alerts will not go out if a sensor floats around the warning threshold and a "cleared" message won't be sent unless a "warning" message was previously sent. This is used by scan agents that need to track whether an alert was sent when a sensor dropped below/rose above a set alert threshold. For example, if a sensor alerts at 20°C and clears at 25°C, this will be called when either value is passed. When passing the warning threshold, the alert is registered and sent to the user. Once set, no further warning alerts are sent. When the value passes over the clear threshold, this is checked and if an alert was previously registered, it is removed and an "all clear" message is sent. In this way, multiple alerts will not go out if a sensor floats around the warning threshold and a "cleared" message won't be sent unless a "warning" message was previously sent.
If there is a problem, C<< undef >> is returned. If there is a problem, C<< !!error!! >> is returned.
Parameters; Parameters;
@ -125,7 +125,7 @@ sub check_alert_sent
{ {
# Nope # Nope
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0093"}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0093"});
return(undef); return("!!error!!");
} }
# Do we have an alert name? # Do we have an alert name?
@ -133,7 +133,7 @@ sub check_alert_sent
{ {
# Nope # Nope
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Alert->check_alert_sent()", parameter => "name" }}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Alert->check_alert_sent()", parameter => "name" }});
return(undef); return("!!error!!");
} }
# Do we have an record locator? # Do we have an record locator?
@ -141,7 +141,7 @@ sub check_alert_sent
{ {
# Nope # Nope
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Alert->check_alert_sent()", parameter => "record_locator" }}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Alert->check_alert_sent()", parameter => "record_locator" }});
return(undef); return("!!error!!");
} }
# Do we know who is setting this?? # Do we know who is setting this??
@ -149,7 +149,7 @@ sub check_alert_sent
{ {
# Nope # Nope
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Alert->check_alert_sent()", parameter => "set_by" }}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Alert->check_alert_sent()", parameter => "set_by" }});
return(undef); return("!!error!!");
} }
# Are we setting or clearing? # Are we setting or clearing?
@ -157,7 +157,7 @@ sub check_alert_sent
{ {
# Neither... # Neither...
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0097"}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0097"});
return(undef); return("!!error!!");
} }
# This will get set to '1' if an alert is added or removed. # This will get set to '1' if an alert is added or removed.
@ -218,7 +218,7 @@ WHERE
alert_name => $name, alert_name => $name,
modified_date => $modified_date, modified_date => $modified_date,
}}); }});
return(undef); return("!!error!!");
} }
else else
{ {
@ -282,7 +282,7 @@ AND
This registers an alert to be sent later. This registers an alert to be sent later.
If anything goes wrong, C<< undef >> will be returned. If anything goes wrong, C<< !!error!! >> will be returned.
=cut =cut
sub register_alert sub register_alert
@ -313,17 +313,17 @@ sub register_alert
if (not $set_by) if (not $set_by)
{ {
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Alert->register_alert()", parameter => "set_by" }}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Alert->register_alert()", parameter => "set_by" }});
return(undef); return("!!error!!");
} }
if (not $message_key) if (not $message_key)
{ {
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Alert->register_alert()", parameter => "message_key" }}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Alert->register_alert()", parameter => "message_key" }});
return(undef); return("!!error!!");
} }
if (($header) && (not $title_key)) if (($header) && (not $title_key))
{ {
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0101"}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0101"});
return(undef); return("!!error!!");
} }
# zero-pad sort numbers so that they sort properly. # zero-pad sort numbers so that they sort properly.

@ -6,13 +6,19 @@ package AN::Tools::Convert;
use strict; use strict;
use warnings; use warnings;
use Data::Dumper; use Data::Dumper;
use Math::BigInt;
our $VERSION = "3.0.0"; our $VERSION = "3.0.0";
my $THIS_FILE = "Convert.pm"; my $THIS_FILE = "Convert.pm";
### Methods; ### Methods;
# add_commas
# bytes_to_human_readable
# cidr # cidr
# hostname_to_ip # hostname_to_ip
# human_readable_to_bytes
# round
=pod =pod
@ -68,6 +74,404 @@ sub parent
# Public methods # # Public methods #
############################################################################################################# #############################################################################################################
=head2 add_commas
This takes an integer and inserts commas to make it more readable by people.
If the input string isn't a string of digits, it is simply returned as-is.
Parameters;
=head3 number (required)
This is the number to add commas to.
=cut
sub add_commas
{
my $self = shift;
my $parameter = shift;
my $an = $self->parent;
# Now see if the user passed the values in a hash reference or directly.
my $number = defined $parameter->{number} ? $parameter->{number} : "";
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { number => $number }});
# Remove any existing commands or leading '+' signs.
$number =~ s/,//g;
$number =~ s/^\+//g;
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { number => $number }});
# Split on the left-most period.
my ($whole, $decimal) = split/\./, $number, 2;
$whole = "" if not defined $whole;
$decimal = "" if not defined $decimal;
# Now die if either number has a non-digit character in it.
if (($whole =~ /\D/) or ($decimal =~ /\D/))
{
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { number => $number }});
return ($number);
}
local($_) = $whole ? $whole : "";
1 while s/^(-?\d+)(\d{3})/$1,$2/;
$whole = $_;
# Put it together
$number = $decimal ? "$whole.$decimal" : $whole;
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { number => $number }});
return ($number);
}
=head2 bytes_to_human_readable
This takes a number of bytes and converts it to a a human-readable format. Optionally, you can request the human readable size be returned using specific units.
If anything goes wrong, C<< !!error!! >> is returned.
* Base2 Notation;
B<Term> B<Factor> C<Bytes>
Yobiabyte (YiB) 2^80 1,208,925,819,614,629,174,706,176
Zebiabyte (ZiB) 2^70 1,180,591,620,717,411,303,424
Exbibyte (EiB) 2^60 1,152,921,504,606,846,976
Pebibyte (PiB) 2^50 1,125,899,906,842,624
Tebibyte (TiB) 2^40 1,099,511,627,776
Gibibyte (GiB) 2^30 1,073,741,824
Mebibyte (MiB) 2^20 1,048,576
Kibibyte (KiB) 2^10 1,024
Byte (B) 2^1 1
* Base10 Notation;
B<Term> B<Factor> C<Bytes>
Yottabyte (YB) 10^24 1,000,000,000,000,000,000,000,000
Zettabyte (ZB) 10^21 1,000,000,000,000,000,000,000
Exabyte (EB) 10^18 1,000,000,000,000,000,000
Petabyte (PB) 10^15 1,000,000,000,000,000
Terabyte (TB) 10^12 1,000,000,000,000
Gigabyte (GB) 10^9 1,000,000,000
Megabyte (MB) 10^6 1,000,000
Kilobyte (KB) 10^3 1,000
Byte (B) 1 1
Parameters;
=head3 base2 (optional)
This can be set to C<< 1 >> to return the units in base2 notation, or set to C<< 0 >> to return in base10 notation. The default is controlled by c<< sys::use_base2 >>, which is set to C<< 1 >> by default.
The suffix will use C<< XiB >> when base2 notation is used and C<< XB >> will be returned for base10.
=head3 bytes (required)
This is the number of bytes that will be converted. This can be a signed integer.
=head3 unit (optional)
This is a letter
=cut
sub bytes_to_human_readable
{
my $self = shift;
my $parameter = shift;
my $an = $self->parent;
# Now see if the user passed the values in a hash reference or directly.
my $size = defined $parameter->{'bytes'} ? $parameter->{'bytes'} : 0;
my $unit = defined $parameter->{unit} ? uc($parameter->{unit}) : "";
my $base2 = defined $parameter->{base2} ? $parameter->{base2} : $an->data->{sys}{use_base2};
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
size => $size,
unit => $unit,
}});
# Expand exponential numbers.
if ($size =~ /(\d+)e\+(\d+)/)
{
my $base = $1;
my $exp = $2;
$size = $base;
for (1..$exp)
{
$size .= "0";
}
}
# Setup my variables.
my $suffix = "";
my $human_readable_size = $size;
# Store and strip the sign
my $sign = "";
if ($human_readable_size =~ /^-/)
{
$sign = "-";
$human_readable_size =~ s/^-//;
}
$human_readable_size =~ s/,//g;
$human_readable_size =~ s/^\+//g;
# Die if either the 'time' or 'float' has a non-digit character in it.
if ($human_readable_size =~ /\D/)
{
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0116", variables => {
method => "Convert->bytes_to_human_readable()",
parameter => "hostnmae",
value => $human_readable_size,
}});
return ("!!error!!");
}
# Do the math.
if ($an->data->{sys}{use_base2})
{
# Has the user requested a certain unit to use?
if ($unit)
{
# Yup
if ($unit =~ /Y/i)
{
# Yebibyte
$human_readable_size = sprintf("%.3f", ($human_readable_size /= (2 ** 80)));
$suffix = "YiB";
}
elsif ($unit =~ /Z/i)
{
# Zebibyte
$human_readable_size = sprintf("%.3f", ($human_readable_size /= (2 ** 70)));
$suffix = "ZiB";
}
elsif ($unit =~ /E/i)
{
# Exbibyte
$human_readable_size = sprintf("%.3f", ($human_readable_size /= (2 ** 60)));
$suffix = "EiB";
}
elsif ($unit =~ /P/i)
{
# Pebibyte
$human_readable_size = sprintf("%.3f", ($human_readable_size /= (2 ** 50)));
$suffix = "PiB";
}
elsif ($unit =~ /T/i)
{
# Tebibyte
$human_readable_size = sprintf("%.2f", ($human_readable_size /= (2 ** 40)));
$suffix = "TiB";
}
elsif ($unit =~ /G/i)
{
# Gibibyte
$human_readable_size = sprintf("%.2f", ($human_readable_size /= (2 ** 30)));
$suffix = "GiB";
}
elsif ($unit =~ /M/i)
{
# Mebibyte
$human_readable_size = sprintf("%.2f", ($human_readable_size /= (2 ** 20)));
$suffix = "MiB";
}
elsif ($unit =~ /K/i)
{
# Kibibyte
$human_readable_size = sprintf("%.1f", ($human_readable_size /= (2 ** 10)));
$suffix = "KiB";
}
else
{
$suffix = "B";
}
}
else
{
# Nope, use the most efficient.
if ($human_readable_size >= (2 ** 80))
{
# Yebibyte
$human_readable_size = sprintf("%.3f", ($human_readable_size /= (2 ** 80)));
$suffix = "YiB";
}
elsif ($human_readable_size >= (2 ** 70))
{
# Zebibyte
$human_readable_size = sprintf("%.3f", ($human_readable_size /= (2 ** 70)));
$suffix = "ZiB";
}
elsif ($human_readable_size >= (2 ** 60))
{
# Exbibyte
$human_readable_size = sprintf("%.3f", ($human_readable_size /= (2 ** 60)));
$suffix = "EiB";
}
elsif ($human_readable_size >= (2 ** 50))
{
# Pebibyte
$human_readable_size = sprintf("%.3f", ($human_readable_size /= (2 ** 50)));
$suffix = "PiB";
}
elsif ($human_readable_size >= (2 ** 40))
{
# Tebibyte
$human_readable_size = sprintf("%.2f", ($human_readable_size /= (2 ** 40)));
$suffix = "TiB";
}
elsif ($human_readable_size >= (2 ** 30))
{
# Gibibyte
$human_readable_size = sprintf("%.2f", ($human_readable_size /= (2 ** 30)));
$suffix = "GiB";
}
elsif ($human_readable_size >= (2 ** 20))
{
# Mebibyte
$human_readable_size = sprintf("%.2f", ($human_readable_size /= (2 ** 20)));
$suffix = "MiB";
}
elsif ($human_readable_size >= (2 ** 10))
{
# Kibibyte
$human_readable_size = sprintf("%.1f", ($human_readable_size /= (2 ** 10)));
$suffix = "KiB";
}
else
{
$suffix = "B";
}
}
}
else
{
# Has the user requested a certain unit to use?
if ($unit)
{
# Yup
if ($unit =~ /Y/i)
{
# Yottabyte
$human_readable_size = sprintf("%.3f", ($human_readable_size /= (10 ** 24)));
$suffix = "YB";
}
elsif ($unit =~ /Z/i)
{
# Zettabyte
$human_readable_size = sprintf("%.3f", ($human_readable_size /= (10 ** 21)));
$suffix = "ZB";
}
elsif ($unit =~ /E/i)
{
# Exabyte
$human_readable_size = sprintf("%.3f", ($human_readable_size /= (10 ** 18)));
$suffix = "EB";
}
elsif ($unit =~ /P/i)
{
# Petabyte
$human_readable_size = sprintf("%.3f", ($human_readable_size /= (10 ** 15)));
$suffix = "PB";
}
elsif ($unit =~ /T/i)
{
# Terabyte
$human_readable_size = sprintf("%.2f", ($human_readable_size /= (10 ** 12)));
$suffix = "TB";
}
elsif ($unit =~ /G/i)
{
# Gigabyte
$human_readable_size = sprintf("%.2f", ($human_readable_size /= (10 ** 9)));
$suffix = "GB";
}
elsif ($unit =~ /M/i)
{
# Megabyte
$human_readable_size = sprintf("%.2f", ($human_readable_size /= (10 ** 6)));
$suffix = "MB";
}
elsif ($unit =~ /K/i)
{
# Kilobyte
$human_readable_size = sprintf("%.1f", ($human_readable_size /= (10 ** 3)));
$suffix = "KB";
}
else
{
$suffix = "b";
}
}
else
{
# Nope, use the most efficient.
if ($human_readable_size >= (10 ** 24))
{
# Yottabyte
$human_readable_size = sprintf("%.3f", ($human_readable_size /= (10 ** 24)));
$suffix = "YB";
}
elsif ($human_readable_size >= (10 ** 21))
{
# Zettabyte
$human_readable_size = sprintf("%.3f", ($human_readable_size /= (10 ** 21)));
$suffix = "ZB";
}
elsif ($human_readable_size >= (10 ** 18))
{
# Exabyte
$human_readable_size = sprintf("%.3f", ($human_readable_size /= (10 ** 18)));
$suffix = "EB";
}
elsif ($human_readable_size >= (10 ** 15))
{
# Petabyte
$human_readable_size = sprintf("%.3f", ($human_readable_size /= (10 ** 15)));
$suffix = "PB";
}
elsif ($human_readable_size >= (10 ** 12))
{
# Terabyte
$human_readable_size = sprintf("%.2f", ($human_readable_size /= (10 ** 12)));
$suffix = "TB";
}
elsif ($human_readable_size >= (10 ** 9))
{
# Gigabyte
$human_readable_size = sprintf("%.2f", ($human_readable_size /= (10 ** 9)));
$suffix = "GB";
}
elsif ($human_readable_size >= (10 ** 6))
{
# Megabyte
$human_readable_size = sprintf("%.2f", ($human_readable_size /= (10 ** 6)));
$suffix = "MB";
}
elsif ($human_readable_size >= (10 ** 3))
{
# Kilobyte
$human_readable_size = sprintf("%.1f", ($human_readable_size /= (10 ** 3)));
$suffix = "KB";
}
else
{
$suffix = "b";
}
}
}
# If needed, insert commas
$human_readable_size = $an->Convert->add_commas({number => $human_readable_size});
# Restore the sign.
if ($sign)
{
$human_readable_size = $sign.$human_readable_size;
}
$human_readable_size .= " ".$suffix;
return($human_readable_size);
}
=head2 cidr =head2 cidr
This takes an IPv4 CIDR notation and returns the dotted-decimal subnet, or the reverse. This takes an IPv4 CIDR notation and returns the dotted-decimal subnet, or the reverse.
@ -231,3 +635,322 @@ sub hostname_to_ip
return($ip); return($ip);
} }
=head2 human_readable_to_bytes
This takes a "human readable" size with an ISO suffix and converts it back to a base byte size as accurately as possible.
It looks for the C<< i >> in the suffix to determine if the size is base2 or base10. This can be overridden with the optional C<< base2 >> or C<< base10 >> parameters.
If there is a problem, C<< !!error!! >> is returned.
Parameters;
=head3 base2 (optional)
This tells the method to interpret the human-readable suffix as base2 notation, even if it is in the format C<< XB >> instead of C<< XiB >>.
=head3 base10 (optional)
This tells the method to interpret the human-readable suffix as base10 notation, even if it is in the format C<< XiB >> instead of C<< XB >>.
=head3 size (required)
This is the size being converted. It can be a signed integer or real number (with a decimal). If this parameter includes the size suffix, you can skip setting the c<< type >> parameter and this method will break it off automatically.
=head3 type (optional)
This is the unit type that represents the C<< size >> value. This does not need to be used if the C<< size >> parameter already has the suffix.
This value is examined for C<< XiB >> or C<< XB >> notation to determine if the size should be interpreted as a base2 or base10 value when neither C<< base2 >> or C<< base10 >> parameters are set.
=cut
sub human_readable_to_bytes
{
my $self = shift;
my $parameter = shift;
my $an = $self->parent;
my $base2 = defined $parameter->{base2} ? $parameter->{base2} : 0;
my $base10 = defined $parameter->{base10} ? $parameter->{base10} : 0;
my $size = defined $parameter->{size} ? $parameter->{size} : 0;
my $type = defined $parameter->{type} ? $parameter->{type} : 0;
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
base2 => $base2,
base10 => $base10,
size => $size,
type => $type,
}});
# Start cleaning up the variables.
my $value = $size;
$size =~ s/ //g;
$type =~ s/ //g;
# Store and strip the sign, if passed
my $sign = "";
if ($size =~ /^-/)
{
$sign = "-";
$size =~ s/^-//;
}
elsif ($size =~ /^\+/)
{
$sign = "+";
$size =~ s/^\+//;
}
# Strip any commas
$size =~ s/,//g;
# If I don't have a passed type, see if there is a letter or letters after the size to hack off.
if ((not $type) && ($size =~ /[a-zA-Z]$/))
{
# There was
($size, $type) = ($size =~ /^(.*\d)(\D+)/);
}
# Make the type lower close for simplicity.
$type = lc($type);
# Make sure that 'size' is now an integer or float.
if ($size !~ /\d+[\.\d+]?/)
{
# Something illegal was passed.
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0117", variables => {
size => $size,
sign => $sign,
type => $type,
}});
return("!!error!!");
}
# If 'type' is still blank, set it to 'b'.
$type = "b" if not $type;
# If the type is already bytes, make sure the size is an integer and return.
if ($type eq "b")
{
# Something illegal was passed.
if ($size =~ /\D/)
{
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0118", variables => {
size => $size,
sign => $sign,
type => $type,
}});
return("!!error!!");
}
return ($sign.$size);
}
# If the "type" is "Xib" or if '$base2' is set, make sure we're running in Base2 notation. Conversly,
# if the type is "Xb" or if '$base10' is set, make sure that we're running in Base10 notation. In
# either case, shorten the 'type' to just the first letter to make the next sanity check simpler.
if ((not $base2) && (not $base10))
{
if ($type =~ /^(\w)ib$/)
{
# Make sure we're running in Base2.
$type = $1;
$base2 = 1;
$base10 = 0;
}
elsif ($type =~ /^(\w)b$/)
{
# Make sure we're running in Base2.
$type = $1;
$base2 = 0;
$base10 = 1;
}
}
# Check if we have a valid type.
if (($type ne "p") &&
($type ne "e") &&
($type ne "z") &&
($type eq "y") &&
($type ne "t") &&
($type ne "g") &&
($type ne "m") &&
($type ne "k"))
{
# Poop
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0119", variables => {
value => $value,
size => $size,
type => $type,
}});
return("!!error!!");
}
# Now the magic... lame magic, true, but still.
my $bytes = 0;
if ($base10)
{
if ($type eq "y") { $bytes = Math::BigInt->new('10')->bpow('24')->bmul($size); } # Yottabyte
elsif ($type eq "z") { $bytes = Math::BigInt->new('10')->bpow('21')->bmul($size); } # Zettabyte
elsif ($type eq "e") { $bytes = Math::BigInt->new('10')->bpow('18')->bmul($size); } # Exabyte
elsif ($type eq "p") { $bytes = Math::BigInt->new('10')->bpow('15')->bmul($size); } # Petabyte
elsif ($type eq "t") { $bytes = ($size * (10 ** 12)) } # Terabyte
elsif ($type eq "g") { $bytes = ($size * (10 ** 9)) } # Gigabyte
elsif ($type eq "m") { $bytes = ($size * (10 ** 6)) } # Megabyte
elsif ($type eq "k") { $bytes = ($size * (10 ** 3)) } # Kilobyte
}
else
{
if ($type eq "y") { $bytes = Math::BigInt->new('2')->bpow('80')->bmul($size); } # Yobibyte
elsif ($type eq "z") { $bytes = Math::BigInt->new('2')->bpow('70')->bmul($size); } # Zibibyte
elsif ($type eq "e") { $bytes = Math::BigInt->new('2')->bpow('60')->bmul($size); } # Exbibyte
elsif ($type eq "p") { $bytes = Math::BigInt->new('2')->bpow('50')->bmul($size); } # Pebibyte
elsif ($type eq "t") { $bytes = ($size * (2 ** 40)) } # Tebibyte
elsif ($type eq "g") { $bytes = ($size * (2 ** 30)) } # Gibibyte
elsif ($type eq "m") { $bytes = ($size * (2 ** 20)) } # Mebibyte
elsif ($type eq "k") { $bytes = ($size * (2 ** 10)) } # Kibibyte
}
# Last, round off the byte size if it is a float.
if ($bytes =~ /\./)
{
$bytes = $an->Convert->round({
number => $bytes,
places => 0
});
}
if ($sign)
{
$bytes = $sign.$bytes;
}
return ($bytes);
}
=head2 round
This takes a number and rounds it to a given number of places after the decimal (defaulting to an even integer). This does financial-type rounding.
If C<< -- >> is passed in, the same is returned. Any other problems will cause C<< !!error!! >> to be returned.
Parameters;
=head3 number (required)
This is the number being rounded.
=head3 places (optional)
This is an integer representing how many places to round the number to. The default is C<< 0 >>, rounding the number to the closest integer.
=cut
sub round
{
my $self = shift;
my $parameter = shift;
my $an = $self->parent;
# Setup my numbers.
my $number = $parameter->{number} ? $parameter->{number} : 0;
my $places = $parameter->{places} ? $parameter->{places} : 0;
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
number => $number,
places => $places,
}});
# Return if the user passed a double-dash.
return('--') if $number eq "--";
# Make a copy of the passed number that I can manipulate.
my $rounded_number = $number;
# Take out any commas.
$rounded_number =~ s/,//g;
# If there is a decimal place in the number, do the smart math. Otherwise, just pad the number with
# the requested number of zeros after the decimal place.
if ( $rounded_number =~ /\./ )
{
# Split up the number.
my ($real, $decimal) = split/\./, $rounded_number, 2;
# If there is anything other than one ',' and digits, error.
if (($real =~ /\D/) or ($decimal =~ /\D/))
{
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0120", variables => { number => $number }});
return ("!!error!!");
}
# If the number is already equal to the requested number of places after the decimal, just
# return. If it is less, pad the needed number of zeros. Otherwise, start rounding.
if ( length($decimal) == $places )
{
# Equal, return.
return $rounded_number;
}
elsif ( length($decimal) < $places )
{
# Less, pad.
$rounded_number = sprintf("%.${places}f", $rounded_number);
}
else
{
# Greater than; I need to round the number. Start by getting the number of places I
# need to round.
my $round_diff = length($decimal) - $places;
# This keeps track of whether the next (left) digit needs to be incremented.
my $increase = 0;
# Now loop the number of times needed to round to the requested number of places.
for (1..$round_diff)
{
# Reset 'increase'.
$increase = 0;
# Make sure I am dealing with a digit.
if ($decimal =~ /(\d)$/)
{
my $last_digit = $1;
$decimal =~ s/$last_digit$//;
if ($last_digit > 4)
{
$increase = 1;
if ($decimal eq "")
{
$real++;
}
else
{
$decimal++;
}
}
}
}
if ($places == 0 )
{
$rounded_number = $real;
}
else
{
$rounded_number = $real.".".$decimal;
}
}
}
else
{
# This is a whole number so just pad 0s as needed.
$rounded_number = sprintf("%.${places}f", $rounded_number);
}
# Return the number.
return ($rounded_number);
}
# =head3
#
# Private Functions;
#
# =cut
#############################################################################################################
# Private functions #
#############################################################################################################

@ -12,6 +12,8 @@ our $VERSION = "3.0.0";
my $THIS_FILE = "Database.pm"; my $THIS_FILE = "Database.pm";
### Methods; ### Methods;
# archive_databases
# check_lock_age
# configure_pgsql # configure_pgsql
# connect # connect
# disconnect # disconnect
@ -21,10 +23,12 @@ my $THIS_FILE = "Database.pm";
# insert_or_update_hosts # insert_or_update_hosts
# insert_or_update_states # insert_or_update_states
# insert_or_update_variables # insert_or_update_variables
# lock_file
# locking # locking
# mark_active # mark_active
# query # query
# read_variable # read_variable
# resync_databases
# write # write
# _find_behind_database # _find_behind_database
# _mark_database_as_behind # _mark_database_as_behind
@ -84,13 +88,84 @@ sub parent
# Public methods # # Public methods #
############################################################################################################# #############################################################################################################
=head2 archive_databases
NOTE: Not implemented yet.
=cut
sub archive_databases
{
my $self = shift;
my $parameter = shift;
my $an = $self->parent;
return(0);
}
=head2 check_lock_age
This checks to see if 'sys::database::local_lock_active' is set. If it is, its age is checked and if the age is >50% of sys::database::locking_reap_age, it will renew the lock.
=cut
sub check_lock_age
{
my $self = shift;
my $parameter = shift;
my $an = $self->parent;
# Make sure we've got the 'sys::database::local_lock_active' and 'reap_age' variables set.
if ((not defined $an->data->{sys}{database}{local_lock_active}) or ($an->data->{sys}{database}{local_lock_active} =~ /\D/))
{
$an->data->{sys}{database}{local_lock_active} = 0;
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sys::database::local_lock_active" => $an->data->{sys}{database}{local_lock_active} }});
}
if ((not $an->data->{sys}{database}{locking_reap_age}) or ($an->data->{sys}{database}{locking_reap_age} =~ /\D/))
{
$an->data->{sys}{database}{locking_reap_age} = 300;
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sys::database::local_lock_active" => $an->data->{sys}{database}{local_lock_active} }});
}
# If I have an active lock, check its age and also update the ScanCore lock file.
my $renewed = 0;
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sys::database::local_lock_active" => $an->data->{sys}{database}{local_lock_active} }});
if ($an->data->{sys}{database}{local_lock_active})
{
my $current_time = time;
my $lock_age = $current_time - $an->data->{sys}{database}{local_lock_active};
my $half_reap_age = int($an->data->{sys}{database}{locking_reap_age} / 2);
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
current_time => $current_time,
lock_age => $lock_age,
half_reap_age => $half_reap_age,
}});
if ($lock_age > $half_reap_age)
{
# Renew the lock.
$an->Database->locking({renew => 1});
$renewed = 1;
# Update the lock age
$an->data->{sys}{database}{local_lock_active} = time;
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sys::database::local_lock_active" => $an->data->{sys}{database}{local_lock_active} }});
# Update the lock file
my $lock_file_age = $an->Database->lock_file({'do' => "set"});
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { lock_file_age => $lock_file_age }});
}
}
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { renewed => $renewed }});
return($renewed);
}
=head2 configure_pgsql =head2 configure_pgsql
This configures the local database server. Specifically, it checks to make sure the daemon is running and starts it if not. It also checks the 'pg_hba.conf' configuration to make sure it is set properly to listen on this machine's IP addresses and interfaces. This configures the local database server. Specifically, it checks to make sure the daemon is running and starts it if not. It also checks the 'pg_hba.conf' configuration to make sure it is set properly to listen on this machine's IP addresses and interfaces.
If the system is already configured, this method will do nothing, so it is safe to call it at any time. If the system is already configured, this method will do nothing, so it is safe to call it at any time.
If there is a problem, C<< undef >> is returned. If there is a problem, C<< !!error!! >> is returned.
Parameters; Parameters;
@ -111,7 +186,7 @@ sub configure_pgsql
if (not $id) if (not $id)
{ {
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->configure_pgsql()", parameter => "id" }}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->configure_pgsql()", parameter => "id" }});
return(undef); return("!!error!!");
} }
# If we're not running with root access, return. # If we're not running with root access, return.
@ -120,7 +195,7 @@ sub configure_pgsql
# This is a minor error as it will be hit by every unpriviledged program that connects to the # This is a minor error as it will be hit by every unpriviledged program that connects to the
# database(s). # database(s).
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, priority => "alert", key => "log_0113"}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, priority => "alert", key => "log_0113"});
return(undef); return("!!error!!");
} }
# First, is it running? # First, is it running?
@ -141,7 +216,7 @@ sub configure_pgsql
{ {
# Failed... # Failed...
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0050"}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0050"});
return(undef); return("!!error!!");
} }
else else
{ {
@ -263,7 +338,7 @@ sub configure_pgsql
{ {
# Failed to start # Failed to start
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0094"}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0094"});
return(undef); return("!!error!!");
} }
} }
elsif (($update_postgresql_file) or ($update_pg_hba_file)) elsif (($update_postgresql_file) or ($update_pg_hba_file))
@ -320,7 +395,7 @@ sub configure_pgsql
{ {
# No database user defined # No database user defined
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0099", variables => { id => $id }}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0099", variables => { id => $id }});
return(undef); return("!!error!!");
} }
my $user_list = $an->System->call({shell_call => $an->data->{path}{exe}{su}." - postgres -c \"".$an->data->{path}{exe}{psql}." template1 -c 'SELECT usename, usesysid FROM pg_catalog.pg_user;'\"", source => $THIS_FILE, line => __LINE__}); my $user_list = $an->System->call({shell_call => $an->data->{path}{exe}{su}." - postgres -c \"".$an->data->{path}{exe}{psql}." template1 -c 'SELECT usename, usesysid FROM pg_catalog.pg_user;'\"", source => $THIS_FILE, line => __LINE__});
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { user_list => $user_list }}); $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { user_list => $user_list }});
@ -357,7 +432,7 @@ sub configure_pgsql
if (not $user_exists) if (not $user_exists)
{ {
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0096", variables => { user => $scancore_user }}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0096", variables => { user => $scancore_user }});
return(undef); return("!!error!!");
} }
# Update/set the passwords. # Update/set the passwords.
@ -418,7 +493,7 @@ sub configure_pgsql
if (not $database_exists) if (not $database_exists)
{ {
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0109", variables => { database => $scancore_database }}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0109", variables => { database => $scancore_database }});
return(undef); return("!!error!!");
} }
} }
@ -896,8 +971,22 @@ sub connect
# Mark that we're not active. # Mark that we're not active.
$an->Database->mark_active({set => 1}); $an->Database->mark_active({set => 1});
# Archive old data.
$an->Database->archive_databases({});
# Sync the database, if needed.
$an->Database->resync_databases({tables => [
"hosts",
"host_variable",
"alerts",
"variables",
"updated",
"alert_sent",
"states",
]});
# Add ourselves to the database, if needed. # Add ourselves to the database, if needed.
$an->Database->insert_or_update_hosts(); $an->Database->insert_or_update_hosts;
return($connections); return($connections);
} }
@ -1469,7 +1558,7 @@ This updates (or inserts) a record in the 'variables' table. The C<< state_uuid
Unlike the other methods of this type, this method can be told to update the 'variable_value' only. This is so because the section, description and default columns rarely ever change. If this is set and the variable name is new, an INSERT will be done the same as if it weren't set, with the unset columns set to NULL. Unlike the other methods of this type, this method can be told to update the 'variable_value' only. This is so because the section, description and default columns rarely ever change. If this is set and the variable name is new, an INSERT will be done the same as if it weren't set, with the unset columns set to NULL.
If there is an error, C<< undef >> is returned. If there is an error, C<< !!error!! >> is returned.
Parameters; Parameters;
@ -1544,7 +1633,7 @@ sub insert_or_update_variables
{ {
# Neither given, throw an error and return. # Neither given, throw an error and return.
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0037"}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0037"});
return(undef); return("!!error!!");
} }
# If we have a variable UUID but not a name, read the variable name. If we don't have a UUID, see if # If we have a variable UUID but not a name, read the variable name. If we don't have a UUID, see if
@ -1771,7 +1860,44 @@ WHERE
return($variable_uuid); return($variable_uuid);
} }
=head2 lock_file
This reads, sets or updates the database lock file timestamp.
=cut
sub lock_file
{
my $self = shift;
my $parameter = shift;
my $an = $self->parent;
my $do = $parameter->{'do'} ? $parameter->{'do'} : "get";
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'do' => $do }});
my $lock_time = 0;
if ($do eq "set")
{
$lock_time = time;
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { lock_time => $lock_time }});
$an->Storage->write_file({
file => $an->data->{path}{'lock'}{database},
body => $lock_time,
overwrite => 1,
});
}
else
{
# Read the lock file's time stamp, if the file exists.
if (-e $an->data->{path}{'lock'}{database})
{
$lock_time = $an->Storage->read_file({file => $an->data->{path}{'lock'}{database}});
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { lock_time => $lock_time }});
}
}
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { lock_time => $lock_time }});
return($lock_time);
}
=head2 locking =head2 locking
@ -1823,7 +1949,6 @@ sub locking
source_uuid => $source_uuid, source_uuid => $source_uuid,
}}); }});
### TODO: Left off here
my $set = 0; my $set = 0;
my $variable_name = "lock_request"; my $variable_name = "lock_request";
my $variable_value = $source_name."::".$source_uuid."::".time; my $variable_value = $source_name."::".$source_uuid."::".time;
@ -1874,10 +1999,10 @@ sub locking
variable_value => "", variable_value => "",
update_value_only => 1, update_value_only => 1,
}); });
$an->data->{sys}{local_lock_active} = 0; $an->data->{sys}{database}{local_lock_active} = 0;
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
variable_uuid => $variable_uuid, variable_uuid => $variable_uuid,
"sys::local_lock_active" => $an->data->{sys}{local_lock_active}, "sys::local_lock_active" => $an->data->{sys}{database}{local_lock_active},
}}); }});
# Log that the lock has been released. # Log that the lock has been released.
@ -1904,10 +2029,10 @@ sub locking
$set = 1; $set = 1;
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { set => $set }}); $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { set => $set }});
} }
$an->data->{sys}{local_lock_active} = time; $an->data->{sys}{database}{local_lock_active} = time;
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
variable_uuid => $variable_uuid, variable_uuid => $variable_uuid,
"sys::local_lock_active" => $an->data->{sys}{local_lock_active}, "sys::local_lock_active" => $an->data->{sys}{database}{local_lock_active},
}}); }});
# Log that we've renewed the lock. # Log that we've renewed the lock.
@ -1992,11 +2117,11 @@ sub locking
if ($variable_uuid) if ($variable_uuid)
{ {
$set = 1; $set = 1;
$an->data->{sys}{local_lock_active} = time; $an->data->{sys}{database}{local_lock_active} = time;
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
set => $set, set => $set,
variable_uuid => $variable_uuid, variable_uuid => $variable_uuid,
"sys::local_lock_active" => $an->data->{sys}{local_lock_active}, "sys::local_lock_active" => $an->data->{sys}{database}{local_lock_active},
}}); }});
# Log that we've got the lock. # Log that we've got the lock.
@ -2056,7 +2181,7 @@ sub mark_active
This performs a query and returns an array reference of array references (from C<< DBO->fetchall_arrayref >>). The first array contains all the returned rows and each row is an array reference of columns in that row. This performs a query and returns an array reference of array references (from C<< DBO->fetchall_arrayref >>). The first array contains all the returned rows and each row is an array reference of columns in that row.
If an error occurs, C<< undef >> will be returned. If an error occurs, C<< !!error!! >> will be returned.
For example, given the query; For example, given the query;
@ -2095,7 +2220,7 @@ Parameters;
By default, the local database will be queried (if run on a machine with a database). Otherwise, the first database successfully connected to will be used for queries (as stored in C<< $an->data->{sys}{read_db_id} >>). By default, the local database will be queried (if run on a machine with a database). Otherwise, the first database successfully connected to will be used for queries (as stored in C<< $an->data->{sys}{read_db_id} >>).
If you want to read from a specific database, though, you can set this parameter to the ID of the database (C<< database::<id>::host). If you specify a read from a database that isn't available, C<< undef >> will be returned. If you want to read from a specific database, though, you can set this parameter to the ID of the database (C<< database::<id>::host). If you specify a read from a database that isn't available, C<< !!error!! >> will be returned.
=head3 line (optional) =head3 line (optional)
@ -2144,13 +2269,13 @@ sub query
{ {
# No database to talk to... # No database to talk to...
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0072"}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0072"});
return(undef); return("!!error!!");
} }
elsif (not defined $an->data->{cache}{db_fh}{$id}) elsif (not defined $an->data->{cache}{db_fh}{$id})
{ {
# Database handle is gone. # Database handle is gone.
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0073", variables => { id => $id }}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0073", variables => { id => $id }});
return(undef); return("!!error!!");
} }
if (not $query) if (not $query)
{ {
@ -2158,15 +2283,14 @@ sub query
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0084", variables => { $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0084", variables => {
server => $say_server, server => $say_server,
}}); }});
return(undef); return("!!error!!");
} }
### TODO: If I am still alive check if any locks need to be renewed. # If I am still alive check if any locks need to be renewed.
#$an->Database->check_lock_age; $an->Database->check_lock_age;
### TODO: Do I need to log the transaction? # Do I need to log the transaction?
#if ($an->Log->db_transactions()) if ($an->data->{sys}{database}{log_transactions})
if (1)
{ {
$an->Log->entry({source => $source, line => $line, secure => $secure, level => 2, key => "log_0074", variables => { $an->Log->entry({source => $source, line => $line, secure => $secure, level => 2, key => "log_0074", variables => {
id => $id, id => $id,
@ -2202,7 +2326,7 @@ This reads a variable from the C<< variables >> table. Be sure to only use the r
The method returns an array reference containing, in order, the variable's value, database UUID and last modified date stamp. The method returns an array reference containing, in order, the variable's value, database UUID and last modified date stamp.
If anything goes wrong, C<< undef >> is returned. If the variable didn't exist in the database, an empty string will be returned for the UUID, value and modified date. If anything goes wrong, C<< !!error!! >> is returned. If the variable didn't exist in the database, an empty string will be returned for the UUID, value and modified date.
Parameters; Parameters;
@ -2236,7 +2360,7 @@ sub read_variable
{ {
# Throw an error and exit. # Throw an error and exit.
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0036"}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0036"});
return(undef, undef, undef); return("!!error!!", "!!error!!", "!!error!!");
} }
# If we don't have a UUID, see if we can find one for the given SMTP server name. # If we don't have a UUID, see if we can find one for the given SMTP server name.
@ -2302,6 +2426,32 @@ AND
return($variable_value, $variable_uuid, $modified_date); return($variable_value, $variable_uuid, $modified_date);
} }
=head2 resync_databases
NOTE: Not implemented yet.
This will resync the database data on this and peer database(s) if needed.
=cut
sub resync_databases
{
my $self = shift;
my $parameter = shift;
my $an = $self->parent;
# Get a list if tables. Note that we'll only sync a given table with peers that have the same table.
my $table_array = ref($parameter->{tables}) eq "ARRAY" ? $parameter->{tables} : [];
# Show tables;
# SELECT table_schema, table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema') ORDER BY table_name ASC, table_schema DESC;
# Show columns;
# SELECT table_catalog, table_schema, table_name, column_name, column_default, is_nullable, data_type FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'alerts';
# psql -E scancore <<-- LOVE <3
return(0);
}
=head2 write =head2 write
@ -2338,11 +2488,11 @@ sub write
{ {
# No query # No query
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0085", variables => { server => $say_server }}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0085", variables => { server => $say_server }});
return(undef); return("!!error!!");
} }
# TODO: If I am still alive check if any locks need to be renewed. # If I am still alive check if any locks need to be renewed.
#$an->Database->check_lock_age; $an->Database->check_lock_age;
# This array will hold either just the passed DB ID or all of them, if no ID was specified. # This array will hold either just the passed DB ID or all of them, if no ID was specified.
my @db_ids; my @db_ids;
@ -2508,7 +2658,7 @@ sub write
This returns the most up to date database ID, the time it was last updated and an array or DB IDs that are behind. This returns the most up to date database ID, the time it was last updated and an array or DB IDs that are behind.
If there is a problem, C<< undef >> is returned. If there is a problem, C<< !!error!! >> is returned.
Parameters; Parameters;
@ -2538,7 +2688,7 @@ sub _find_behind_databases
if (not $source) if (not $source)
{ {
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->_find_behind_databases()", parameter => "source" }}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->_find_behind_databases()", parameter => "source" }});
return(undef); return("!!error!!");
} }
# Look at all the databases and find the most recent time stamp (and the ID of the DB). # Look at all the databases and find the most recent time stamp (and the ID of the DB).

@ -629,7 +629,7 @@ This reads in a file and returns the contents of the file as a single string var
my $body = $an->Storage->read_file({file => "/tmp/foo"}); my $body = $an->Storage->read_file({file => "/tmp/foo"});
If it fails to find the file, or the file is not readable, 'C<< undef >>' is returned. If it fails to find the file, or the file is not readable, 'C<< !!error!! >>' is returned.
Parameters; Parameters;
@ -651,17 +651,17 @@ sub read_file
if (not $file) if (not $file)
{ {
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Storage->read_file()", parameter => "file" }}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Storage->read_file()", parameter => "file" }});
return(undef); return("!!error!!");
} }
elsif (not -e $file) elsif (not -e $file)
{ {
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0021", variables => { file => $file }}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0021", variables => { file => $file }});
return(undef); return("!!error!!");
} }
elsif (not -r $file) elsif (not -r $file)
{ {
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0022", variables => { file => $file }}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0022", variables => { file => $file }});
return(undef); return("!!error!!");
} }
my $shell_call = $file; my $shell_call = $file;

@ -273,7 +273,7 @@ sub determine_host_type
This method enables a daemon (so that it starts when the OS boots). The return code from the start request will be returned. This method enables a daemon (so that it starts when the OS boots). The return code from the start request will be returned.
If the return code for the enable command wasn't read, C<< undef >> is returned. If the return code for the enable command wasn't read, C<< !!error!! >> is returned.
Parameters; Parameters;
@ -638,18 +638,18 @@ sub remote_call
{ {
# No shell call # No shell call
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Systeme->remote_call()", parameter => "shell_call" }}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Systeme->remote_call()", parameter => "shell_call" }});
return(undef); return("!!error!!");
} }
if (not $target) if (not $target)
{ {
# No target # No target
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Systeme->remote_call()", parameter => "target" }}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Systeme->remote_call()", parameter => "target" }});
return(undef); return("!!error!!");
} }
if (not $user) if (not $user)
{ {
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Systeme->remote_call()", parameter => "user" }}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Systeme->remote_call()", parameter => "user" }});
return(undef); return("!!error!!");
} }
# If the user didn't pass a port, but there is an entry in 'hosts::<host>::port', use it. # If the user didn't pass a port, but there is an entry in 'hosts::<host>::port', use it.
@ -695,7 +695,7 @@ sub remote_call
if (($port !~ /^\d+$/) or ($port < 0) or ($port > 65536)) if (($port !~ /^\d+$/) or ($port < 0) or ($port > 65536))
{ {
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0058", variables => { port => $port }}); $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0058", variables => { port => $port }});
return(undef); return("!!error!!");
} }
# If the target is a host name, convert it to an IP. # If the target is a host name, convert it to an IP.
@ -946,7 +946,7 @@ sub remote_call
This method reloads a daemon (typically to pick up a change in configuration). The return code from the start request will be returned. This method reloads a daemon (typically to pick up a change in configuration). The return code from the start request will be returned.
If the return code for the reload command wasn't read, C<< undef >> is returned. If it did reload, C<< 0 >> is returned. If the reload failed, a non-0 return code will be returned. If the return code for the reload command wasn't read, C<< !!error!! >> is returned. If it did reload, C<< 0 >> is returned. If the reload failed, a non-0 return code will be returned.
Parameters; Parameters;
@ -985,7 +985,7 @@ sub reload_daemon
This method starts a daemon. The return code from the start request will be returned. This method starts a daemon. The return code from the start request will be returned.
If the return code for the start command wasn't read, C<< undef >> is returned. If the return code for the start command wasn't read, C<< !!error!! >> is returned.
Parameters; Parameters;
@ -1025,7 +1025,7 @@ sub start_daemon
This method stops a daemon. The return code from the stop request will be returned. This method stops a daemon. The return code from the stop request will be returned.
If the return code for the stop command wasn't read, C<< undef >> is returned. If the return code for the stop command wasn't read, C<< !!error!! >> is returned.
Parameters; Parameters;

@ -183,6 +183,16 @@ The database connection error was:
<key name="log_0111">[ Warning ] - Failed to reload the Postgres server. Please check the system logs for details. The updated configuration is probably not active yet.</key> <key name="log_0111">[ Warning ] - Failed to reload the Postgres server. Please check the system logs for details. The updated configuration is probably not active yet.</key>
<key name="log_0112">Reloaded the PostgreSQL database server.</key> <key name="log_0112">Reloaded the PostgreSQL database server.</key>
<key name="log_0113"><![CDATA[[ Note ] - The 'Database->configure_pgsql() method was called but the parent program is not running with root priviledges. Returning without doing anything.]]>.</key> <key name="log_0113"><![CDATA[[ Note ] - The 'Database->configure_pgsql() method was called but the parent program is not running with root priviledges. Returning without doing anything.]]>.</key>
<key name="log_0114"><![CDATA[The program: [#!data!path::exe::an-report-memory!#] must be called with '--program <name>', but no program name was read in.]]></key>
<key name="log_0115">#!variable!program!# has started.</key>
<key name="log_0116"><![CDATA[The method: [#!variable!method!#] was passed the parameter: [#!variable!parameter!#] with the value: [#!variable!value!#], which is invalid.]]></key>
<key name="log_0117"><![CDATA[The method 'Convert->human_readable_to_bytes()' was passed the byte size: [#!variable!size!#] in the string: [sign: #!variable!sign!#, size: #!variable!size!#, type: #!variable!type!#] contains an illegal value. Sizes can only be integers or real numbers. It may also have commas in it which will be removed automatically.]]></key>
<key name="log_0118"><![CDATA[The method 'Convert->human_readable_to_bytes()' was passed the byte size: [#!variable!size!#] in the string: [sign: #!variable!sign!#, size: #!variable!size!#, type: #!variable!type!#] appears to be a byte size already but the size does not seem to be an integer. Byte sizes can only be signed integers. It may also have commas in it which will be removed automatically.]]></key>
<key name="log_0119"><![CDATA[The method 'Convert->human_readable_to_bytes()' method was called with the value: [#!variable!value!#] which we split into the size: [#!variable!size!#] and type: [#!variable!type!#]. The type appears to be invalid.]]></key>
<key name="log_0120"><![CDATA[The method 'Convert->round()' was passed the number: [#!variable!number!#] which contains an illegal value. Only digits and one decimal place are allowed.]]></key>
<key name="log_0121">Current memory used by: [#!variable!program_name!#] is approximately: [#!variable!bytes!#] bytes (#!variable!hr_size!#).</key>
<key name="log_0122">The 'smaps' proc file for the process ID: [#!variable!pid!#] was not found. Did the program just close?</key>
<key name="log_0123"><![CDATA[[ Error ] - Asked 'pgrep' to return the PIDs (process IDs) of the program: [#!variable!program!#] and a non-digit value was returned in: [#!variable!line!#]. This should not have happened.]]></key>
<!-- Test words. Do NOT change unless you update 't/Words.t' or tests will needlessly fail. --> <!-- Test words. Do NOT change unless you update 't/Words.t' or tests will needlessly fail. -->
<key name="t_0000">Test</key> <key name="t_0000">Test</key>

@ -18,7 +18,7 @@ database::2::ping_before_connect = 1
# This puts a limit on how many queries (writes, generally) to make in a single batch transaction. This is # This puts a limit on how many queries (writes, generally) to make in a single batch transaction. This is
# useful when doing very large transacions, like resync'ing a large table, by limiting how long a given # useful when doing very large transacions, like resync'ing a large table, by limiting how long a given
# transaction can take and how much memory is used. # transaction can take and how much memory is used.
sys::database::maximum_batch_size = 25000 #sys::database::maximum_batch_size = 25000
# By default, we try to determine the host type using the host name. The rules used for this can be seen in # By default, we try to determine the host type using the host name. The rules used for this can be seen in
# 'perldoc AN::Tools::System -> determine_host_type'. If you are using non-standard host names, or for some # 'perldoc AN::Tools::System -> determine_host_type'. If you are using non-standard host names, or for some

Loading…
Cancel
Save