From 49682a01d777f07f4944fba6e956ed5fb7b679ef Mon Sep 17 00:00:00 2001 From: Digimer Date: Thu, 3 Sep 2020 01:36:11 -0400 Subject: [PATCH] * Fixed a bug in Database->disconnect() where the database idenitification number wasn't being removed, so connecting again triggered the duplicate DB connection check. * Fixed a bug in Tools->_set_defaults where the order the tables were sync'ed it caused primary/foreign keys would trigger DB errors when resync'ing in some cases. * Created Database->log_connections to make it easier to log which databases are actively in use and other data about the connections. * Fixed bugs in striker-manage-peers that (partly because of the above bugs) failed to connect to new peers properly. Signed-off-by: Digimer --- Anvil/Tools.pm | 2 +- Anvil/Tools/Database.pm | 85 ++++++++++++++++++++++++++++++++++---- Anvil/Tools/Network.pm | 3 ++ notes | 3 +- rpm/SPECS/anvil.spec | 5 ++- share/words.xml | 5 +++ tools/anvil-daemon | 9 ++-- tools/striker-manage-peers | 16 +++---- tools/test.pl | 10 ++--- 9 files changed, 112 insertions(+), 26 deletions(-) diff --git a/Anvil/Tools.pm b/Anvil/Tools.pm index a0e6e82e..47daee68 100644 --- a/Anvil/Tools.pm +++ b/Anvil/Tools.pm @@ -908,9 +908,9 @@ sub _set_defaults "mail_servers", "variables", "jobs", - "network_interfaces", "bonds", "bridges", + "network_interfaces", "ip_addresses", "files", "file_locations", diff --git a/Anvil/Tools/Database.pm b/Anvil/Tools/Database.pm index bf69ae87..292eb382 100644 --- a/Anvil/Tools/Database.pm +++ b/Anvil/Tools/Database.pm @@ -849,6 +849,12 @@ sub connect # This will be set to '1' if either DB needs to be initialized or if the last_updated differs on any node. $anvil->data->{sys}{database}{resync_needed} = 0; + # In case this is called when connections already exist, clear the identifiers. + if (exists $anvil->data->{sys}{database}{identifier}) + { + delete $anvil->data->{sys}{database}{identifier}; + } + # Now setup or however-many connections my $seen_connections = []; my $failed_connections = []; @@ -865,12 +871,18 @@ sub connect next; } + # Make sure values are set. + $anvil->data->{database}{$uuid}{port} = 5432 if not $anvil->data->{database}{$uuid}{port}; + $anvil->data->{database}{$uuid}{name} = $anvil->data->{sys}{database}{name} if not $anvil->data->{database}{$uuid}{name}; + $anvil->data->{database}{$uuid}{user} = $anvil->data->{sys}{database}{user} if not $anvil->data->{database}{$uuid}{user}; + $anvil->data->{database}{$uuid}{password} = "" if not defined $anvil->data->{database}{$uuid}{password}; + my $driver = "DBI:Pg"; - my $host = $anvil->data->{database}{$uuid}{host} ? $anvil->data->{database}{$uuid}{host} : ""; # This should fail - my $port = $anvil->data->{database}{$uuid}{port} ? $anvil->data->{database}{$uuid}{port} : 5432; - my $name = $anvil->data->{database}{$uuid}{name} ? $anvil->data->{database}{$uuid}{name} : $anvil->data->{sys}{database}{name}; - my $user = $anvil->data->{database}{$uuid}{user} ? $anvil->data->{database}{$uuid}{user} : $anvil->data->{sys}{database}{user}; - my $password = $anvil->data->{database}{$uuid}{password} ? $anvil->data->{database}{$uuid}{password} : ""; + my $host = $anvil->data->{database}{$uuid}{host}; # This should fail + my $port = $anvil->data->{database}{$uuid}{port}; + my $name = $anvil->data->{database}{$uuid}{name}; + my $user = $anvil->data->{database}{$uuid}{user}; + my $password = $anvil->data->{database}{$uuid}{password}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host => $host, port => $port, @@ -1093,6 +1105,7 @@ sub connect elsif ($dbh =~ /^DBI::db=HASH/) { # Woot! + $anvil->data->{sys}{database}{connections}++; push @{$successful_connections}, $uuid; $anvil->data->{cache}{database_handle}{$uuid} = $dbh; @@ -1366,7 +1379,6 @@ sub connect $anvil->Database->mark_active({debug => $debug, set => 1}); # Sync the database, if needed. - #$anvil->Database->resync_databases({debug => $debug}); $anvil->Database->resync_databases({debug => $debug}); # Add ourselves to the database, if needed. @@ -1413,6 +1425,7 @@ sub disconnect # Delete the stored DB-related values. delete $anvil->data->{sys}{database}{timestamp}; delete $anvil->data->{sys}{database}{read_uuid}; + delete $anvil->data->{sys}{database}{identifier}; $anvil->Database->read({set => "delete"}); # Delete any database information (reconnects should re-read anvil.conf anyway). @@ -2272,7 +2285,7 @@ AND # This isn't a network we should know about (ie: it might be a stray 'virbrX' # birdge), delete this IP. my $query = "UPDATE ip_addresses SET ip_address_note = 'DELETED' WHERE ip_address_uuid = ".$anvil->Database->quote($ip_address_uuid).";"; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); next; } @@ -9830,6 +9843,62 @@ sub locking } +=head2 log_connections + +This method logs details about open connections to databases. It's generally only used as a debugging tool. + +This method takes no parameters. + +=cut +sub log_connections +{ + my $self = shift; + my $parameter = shift; + my $anvil = $self->parent; + my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Database->locking()" }}); + + # Log how many connections there are. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, key => "log_0132"}); + + # Reading from + my $read_uuid = $anvil->data->{sys}{database}{read_uuid}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { read_uuid => $read_uuid }}); + foreach my $uuid (sort {$a cmp $b} keys %{$anvil->data->{cache}{database_handle}}) + { + my $host = $anvil->data->{database}{$uuid}{host}; + my $port = $anvil->data->{database}{$uuid}{port}; + my $name = $anvil->data->{database}{$uuid}{name}; + my $user = $anvil->data->{database}{$uuid}{user}; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0537", variables => { + name => $name, + user => $user, + host => $host, + port => $port, + }}); + + my $query = "SELECT system_identifier FROM pg_control_system();"; + my $identifier = $anvil->Database->query({uuid => $uuid, debug => ($debug + 1), query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0]; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => ($debug + 1), key => "log_0540", variables => { + uuid => $uuid, + identifier => $identifier, + }}); + + if ($uuid eq $read_uuid) + { + # Reading from this DB + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0538"}); + } + else + { + # Not reading from this DB + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0539"}); + } + } + + return(0); +} + =head2 manage_anvil_conf This adds, removes or updates a database entry in a machine's anvil.conf file. This returns C<< 0 >> on success, C<< 1 >> if there was a problem. @@ -10712,6 +10781,8 @@ sub resync_databases return(0); } + #$anvil->data->{sys}{database}{log_transactions} = 1; + # Archive old data before resync'ing $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0451"}); $anvil->Database->archive_database({debug => $debug}); diff --git a/Anvil/Tools/Network.pm b/Anvil/Tools/Network.pm index 7c7fbc73..b21af6fe 100755 --- a/Anvil/Tools/Network.pm +++ b/Anvil/Tools/Network.pm @@ -1236,6 +1236,7 @@ AND results => $results, count => $count, }}); + next if not $count; $interface_name = $results->[0]->[0]; $interface_mac = $results->[0]->[1]; @@ -1281,6 +1282,7 @@ AND results => $results, count => $count, }}); + next if not $count; $interface_name = $results->[0]->[0]; $interface_mac = $results->[0]->[1]; @@ -1326,6 +1328,7 @@ AND results => $results, count => $count, }}); + next if not $count; $interface_name = $results->[0]->[0]; $interface_mac = $results->[0]->[1]; diff --git a/notes b/notes index a00a42f7..73b6b635 100644 --- a/notes +++ b/notes @@ -179,8 +179,7 @@ Drop; su - postgres -c "dropdb anvil" && su - postgres -c "createdb --owner admin anvil" && su - postgres -c "psql anvil" Reload the DB; -su - postgres -c "dropdb anvil" && su - postgres -c "createdb --owner admin anvil" && su - postgres -c "psql anvil < /anvil.out" -su - postgres -c "psql anvil" +su - postgres -c "dropdb anvil" && su - postgres -c "createdb --owner admin anvil" && su - postgres -c "psql anvil < /anvil.out" && su - postgres -c "psql anvil" diff --git a/rpm/SPECS/anvil.spec b/rpm/SPECS/anvil.spec index dbf0026c..68d2e207 100644 --- a/rpm/SPECS/anvil.spec +++ b/rpm/SPECS/anvil.spec @@ -3,7 +3,7 @@ %define anvilgroup admin Name: anvil Version: 3.0 -Release: 34%{?dist} +Release: 35%{?dist} Summary: Alteeve Anvil! complete package. License: GPLv2+ @@ -373,6 +373,9 @@ fi %changelog +* tbd Madison Kelly 3.0-35 +- Updated source. + * Fri Aug 28 2020 Madison Kelly 3.0-34 - Added 'virt-top' as a requirement on nodes and dr hosts. - Added cyrus-sasl* as requirements to core. diff --git a/share/words.xml b/share/words.xml index c61ef407..f2254138 100644 --- a/share/words.xml +++ b/share/words.xml @@ -388,6 +388,7 @@ Failure! The return code: [#!variable!return_code!#] was received ('0' was expec Update not required, nothing changed. Completed joining the #!string!brand_0002!#. No job was found that needs to be run. + Reconnecting will start a synchonization of the database. This step might take a while to complete, please be patient. Starting: [#!variable!program!#]. @@ -1015,6 +1016,10 @@ The file: [#!variable!file!#] needs to be updated. The difference is: Updating the configuration line from: [#!variable!old_line!#] to: [#!variable!new_line!#]. Starting and enabling the daemon: [#!variable!daemon!#]. Creating the Anvil! alert email spool directory: [#!data!path::directories::alert_emails!#]. + Connected to the database named: [#!variable!name!#] as: [#!variable!user!#@#!variable!host!#:#!variable!port!#]. + This IS the database queries are read from. + This is NOT the database queries are read from. + This host UUID is: [#!variable!uuid!#] and the database identifier is: [#!variable!identifier!#]. The host name: [#!variable!target!#] does not resolve to an IP address. diff --git a/tools/anvil-daemon b/tools/anvil-daemon index ba3e3e19..15ae77e8 100755 --- a/tools/anvil-daemon +++ b/tools/anvil-daemon @@ -1013,7 +1013,7 @@ sub run_jobs my $command = $job_command." --job-uuid ".$job_uuid; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, secure => 0, key => "log_0210", variables => { command => $command }}); ($anvil->data->{jobs}{handles}{$job_uuid}, my $return_code) = $anvil->System->call({ - debug => 2, + debug => 3, background => 1, stdout_file => "/tmp/anvil.job.".$job_uuid.".stdout", stderr_file => "/tmp/anvil.job.".$job_uuid.".stderr", @@ -1058,13 +1058,16 @@ sub update_state_file # Bunch of things happen here, so this allows a single variable to change for logging. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, secure => 0, key => "log_0480"}); - my $log_level = 3; + my $log_level = 2; my $v = "-"; for (1..$log_level) { $v .= "v"; } - my ($states_output, $return_code) = $anvil->System->call({debug => $log_level, shell_call => $anvil->data->{path}{exe}{'anvil-update-states'}." ".$v, source => $THIS_FILE, line => __LINE__}); + my $shell_call = $anvil->data->{path}{exe}{'anvil-update-states'}." ".$v; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { shell_call => $shell_call }}); + + my ($states_output, $return_code) = $anvil->System->call({debug => $log_level, shell_call => $shell_call, source => $THIS_FILE, line => __LINE__}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $log_level, list => { states_output => $states_output, return_code => $return_code, diff --git a/tools/striker-manage-peers b/tools/striker-manage-peers index a79e86be..91e30916 100755 --- a/tools/striker-manage-peers +++ b/tools/striker-manage-peers @@ -223,6 +223,7 @@ sub process_entry if ((not $password) && ($job_uuid)) { # Do we have a database connection? + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sys::database::connections" => $anvil->data->{sys}{database}{connections}}}); if ($anvil->data->{sys}{database}{connections}) { # See if the password is in job_data. @@ -337,7 +338,7 @@ sub process_entry my $left_space = $2; my $right_space = $3; my $value = $4; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "s1:variable" => $variable, "s2:value" => $value, "s3:left_space" => $left_space, @@ -512,6 +513,7 @@ sub process_entry # Now update! $anvil->Storage->write_file({ + debug => 3, secure => 1, file => $anvil->data->{path}{configs}{'anvil.conf'}, body => $new_body, @@ -521,13 +523,17 @@ sub process_entry overwrite => 1, }); update_progress($anvil, 80, "message_0073"); + update_progress($anvil, 82, "job_0131"); # Disconnect (if no connections exist, will still clear out known databases). - $anvil->Database->disconnect; + $anvil->Database->disconnect({debug => 2}); # Re-read the config. sleep 1; - $anvil->Storage->read_config({file => $anvil->data->{path}{configs}{'anvil.conf'}}); + $anvil->Storage->read_config({debug => 3}); + + # Reconnect + $anvil->Database->connect({debug => 3}); } # If I've been asked to have the peer add us, disconnect from the database, re-read the new config @@ -537,10 +543,6 @@ sub process_entry { update_progress($anvil, 85, "message_0074"); - # Reconnect - $anvil->Database->connect; - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0132"}); - # Now loop until we see the peer's host_uuid show up and we have a connection to the peer's # database. my $peer_connected = 0; diff --git a/tools/test.pl b/tools/test.pl index f37eb67c..688be86b 100755 --- a/tools/test.pl +++ b/tools/test.pl @@ -23,12 +23,12 @@ $| = 1; my $anvil = Anvil::Tools->new(); $anvil->Log->level({set => 2}); $anvil->Log->secure({set => 1}); +$anvil->Get->switches; print "Connecting to the database(s);\n"; -$anvil->Database->connect(); +$anvil->Database->connect({debug => 2}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, secure => 0, key => "log_0132"}); -$anvil->Get->switches; - -my ($oldest_message) = $anvil->Email->check_queue({debug => 2}); -print "Oldest message: [".$oldest_message."]\n"; +# +# my ($oldest_message) = $anvil->Email->check_queue({debug => 2}); +# print "Oldest message: [".$oldest_message."]\n";