Merge pull request #233 from ClusterLabs/anvil-tools-dev

Anvil tools dev
main
Digimer 3 years ago committed by GitHub
commit b4362eb643
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 79
      Anvil/Tools/Database.pm
  2. 36
      Anvil/Tools/System.pm
  3. 1
      notes
  4. 35
      scancore-agents/scan-drbd/scan-drbd
  5. 1
      scancore-agents/scan-drbd/scan-drbd.xml
  6. 3
      share/words.xml
  7. 20
      tools/anvil-daemon
  8. 59
      tools/striker-purge-target

@ -16139,7 +16139,6 @@ sub resync_databases
next if $table eq "alert_sent";
next if $table eq "states";
next if $table eq "update";
next if $table eq "oui";
# If the 'schema' is 'public', there is no table in the history schema.
my $schema = $anvil->data->{sys}{database}{table}{$table}{schema} ? $anvil->data->{sys}{database}{table}{$table}{schema} : "public";
@ -16224,10 +16223,59 @@ sub resync_databases
}});
}
### TODO: This can be removed later.
# Look through the bridges, bonds, and network interfaces tables. Look for records in the
# history schema that don't exist in the public schema and purge them.
if ($schema eq "history")
{
foreach my $uuid (sort {$a cmp $b} keys %{$anvil->data->{cache}{database_handle}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { uuid => $uuid }});
my $query = "SELECT DISTINCT ".$uuid_column." FROM history.".$table.";";
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0124", variables => { query => $query }});
my $results = $anvil->Database->query({debug => $debug, uuid => $uuid, query => $query, source => $THIS_FILE, line => __LINE__});
my $count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
results => $results,
count => $count,
}});
foreach my $row (@{$results})
{
my $column_uuid = $row->[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { column_uuid => $column_uuid }});
my $query = "SELECT COUNT(*) FROM ".$table." WHERE ".$uuid_column." = '".$column_uuid."';";
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0124", variables => { query => $query }});
my $count = $anvil->Database->query({debug => $debug, uuid => $uuid, query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { count => $count }});
if (not $count)
{
# Purge it from everywhere.
my $queries = [];
push @{$queries}, "DELETE FROM history.".$table." WHERE ".$uuid_column." = '".$column_uuid."';";
push @{$queries}, "DELETE FROM ".$table." WHERE ".$uuid_column." = '".$column_uuid."';";
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "err", key => "error_0365", variables => {
table => $table,
uuid_column => $uuid_column,
column_uuid => $column_uuid,
}});
# Delete across all DBs.
$anvil->Database->write({debug => $debug, query => $queries, source => $THIS_FILE, line => __LINE__});
}
}
}
}
# Now read in the data from the different databases.
foreach my $uuid (sort {$a cmp $b} keys %{$anvil->data->{cache}{database_handle}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { uuid => $uuid }});
# This will store queries.
$anvil->data->{db_resync}{$uuid}{public}{sql} = [];
$anvil->data->{db_resync}{$uuid}{history}{sql} = [];
@ -16266,7 +16314,7 @@ sub resync_databases
{
$query .= " ORDER BY utc_modified_date DESC;";
}
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0074", variables => {
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0074", variables => {
uuid => $anvil->Database->get_host_from_uuid({short => 1, host_uuid => $uuid}),
query => $query,
}});
@ -16345,7 +16393,7 @@ sub resync_databases
if (($last_record) && ($schema eq "history") && ($last_record eq "${modified_date}::${row_uuid}"))
{
# Duplicate!
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0363", variables => {
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "err", key => "error_0363", variables => {
table => $table,
key => $last_record,
query => $query,
@ -16354,7 +16402,7 @@ sub resync_databases
# Delete this entry.
my $query = "DELETE FROM history.".$table." WHERE history_id = ".$history_id.";";
$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({debug => $debug, uuid => $uuid, query => $query, source => $THIS_FILE, line => __LINE__});
next;
@ -17399,6 +17447,12 @@ sub _age_out_data
# scan_storcli
$to_clean->{table}{scan_storcli_variables}{child_table}{scan_storcli_variables}{uuid_column} = "scan_storcli_variable_uuid";
# Network stuff
$to_clean->{table}{network_interfaces}{child_table}{network_interfaces}{uuid_column} = "network_interface_uuid";
$to_clean->{table}{bridges}{child_table}{bridges}{uuid_column} = "bridge_uuid";
$to_clean->{table}{bonds}{child_table}{bonds}{uuid_column} = "bond_uuid";
$to_clean->{table}{ip_addresses}{child_table}{ip_addresses}{uuid_column} = "ip_address_uuid";
my $vacuum = 0;
foreach my $table (sort {$a cmp $b} keys %{$to_clean->{table}})
{
@ -17979,7 +18033,6 @@ sub _find_behind_databases
{
# We don't sync 'states' or 'oui' as it's transient and sometimes per-DB.
next if $table eq "states";
next if $table eq "oui";
# Does this table exist yet?
my $query = "SELECT COUNT(*) FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND table_schema = 'public' AND table_name = ".$anvil->Database->quote($table).";";
@ -18066,7 +18119,6 @@ ORDER BY
}
}
# Are being asked to trigger a resync?
foreach my $uuid (keys %{$anvil->data->{cache}{database_handle}})
{
@ -18096,7 +18148,6 @@ ORDER BY
next if $table eq "alert_sent";
next if $table eq "states";
next if $table eq "update";
next if $table eq "oui";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"sys::database::table::${table}::last_updated" => $anvil->data->{sys}{database}{table}{$table}{last_updated},
@ -18154,6 +18205,20 @@ ORDER BY
last if $anvil->data->{sys}{database}{resync_needed};
}
# Force resync if requested by command line switch.
$anvil->data->{switches}{'resync-db'} = "" if not defined $anvil->data->{switches}{'resync-db'};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"switches::resync-db" => $anvil->data->{switches}{'resync-db'},
}});
if ($anvil->data->{switches}{'resync-db'})
{
$anvil->data->{sys}{database}{resync_needed} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"sys::database::resync_needed" => $anvil->data->{sys}{database}{resync_needed},
}});
return(0);
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "sys::database::resync_needed" => $anvil->data->{sys}{database}{resync_needed} }});
return(0);
}

@ -2587,6 +2587,10 @@ Parameters;
This is the name of the daemon to disable. The exact name given is passed to C<< systemctl >>, so please be mindful of appropriate suffixes.
=head3 now (optional, default '0')
If set to C<< 1 >>, the daemon will be stopped as well as disabled
=cut
sub disable_daemon
{
@ -2597,9 +2601,19 @@ sub disable_daemon
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "System->disable_daemon()" }});
my $daemon = defined $parameter->{daemon} ? $parameter->{daemon} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { daemon => $daemon }});
my $now = defined $parameter->{now} ? $parameter->{now} : 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
daemon => $daemon,
now => $now,
}});
my ($output, $return_code) = $anvil->System->call({debug => $debug, shell_call => $anvil->data->{path}{exe}{systemctl}." disable ".$daemon});
my $shell_call = $anvil->data->{path}{exe}{systemctl}." disable ".$daemon;
if ($now)
{
$shell_call = $anvil->data->{path}{exe}{systemctl}." disable --now ".$daemon;
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { shell_call => $shell_call }});
my ($output, $return_code) = $anvil->System->call({debug => $debug, shell_call => $shell_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
output => $output,
return_code => $return_code,
@ -3033,6 +3047,10 @@ Parameters;
This is the name of the daemon to enable. The exact name given is passed to C<< systemctl >>, so please be mindful of appropriate suffixes.
=head3 now (optional, default '0'
If set to c<< 1 >>, the daemon will be started now.
=cut
sub enable_daemon
{
@ -3043,9 +3061,19 @@ sub enable_daemon
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "System->enable_daemon()" }});
my $daemon = defined $parameter->{daemon} ? $parameter->{daemon} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { daemon => $daemon }});
my $now = defined $parameter->{now} ? $parameter->{now} : 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
daemon => $daemon,
now => $now,
}});
my ($output, $return_code) = $anvil->System->call({debug => $debug, shell_call => $anvil->data->{path}{exe}{systemctl}." enable ".$daemon." 2>&1"});
my $shell_call = $anvil->data->{path}{exe}{systemctl}." enable ".$daemon." 2>&1";
if ($now)
{
$shell_call = $anvil->data->{path}{exe}{systemctl}." enable --now ".$daemon." 2>&1";
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { shell_call => $shell_call }});
my ($output, $return_code) = $anvil->System->call({debug => $debug, shell_call => $shell_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
output => $output,
return_code => $return_code,

@ -14,6 +14,7 @@ web -s enable
snmp -S enable -c1 private -a1 writeplus
snmp -S enable -c2 public -a2 writeplus
Anvil! to Anvil! live migration;
1. Create LVs
2. Make sure /etc/hosts is populated

@ -1325,17 +1325,50 @@ WHERE
my $scan_drbd_peer_uuid = $row->[0];
my $scan_drbd_peer_scan_drbd_volume_uuid = $row->[1];
my $scan_drbd_peer_host_name = $row->[2];
my $scan_drbd_peer_connection_state = $row->[3];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
scan_drbd_peer_uuid => $scan_drbd_peer_uuid,
scan_drbd_peer_scan_drbd_volume_uuid => $scan_drbd_peer_scan_drbd_volume_uuid,
scan_drbd_peer_host_name => $scan_drbd_peer_host_name,
scan_drbd_peer_connection_state => $scan_drbd_peer_connection_state,
}});
# It's possible that a DELETED resource no longer has corresponding LVM data. If so, we'll
# purge this record.
if (($scan_drbd_peer_connection_state eq "DELETED") && (not exists $anvil->data->{volume_to_uuid}{$scan_drbd_peer_scan_drbd_volume_uuid}))
{
# Purge it.
my $resource_uuid = $anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_peer_scan_drbd_volume_uuid}{scan_drbd_volume_scan_drbd_resource_uuid};
my $volume_number = $anvil->data->{old}{scan_drbd_volume}{scan_drbd_volume_uuid}{$scan_drbd_peer_scan_drbd_volume_uuid}{scan_drbd_volume_number};
my $resource_name = $anvil->data->{old}{scan_drbd_resource}{scan_drbd_resource_uuid}{$resource_uuid}{scan_drbd_resource_name};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
resource_uuid => $resource_uuid,
volume_number => $volume_number,
resource_name => $resource_name,
}});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_message_0035", variables => {
peer_name => $scan_drbd_peer_host_name,
resource_name => $resource_name,
volume_number => $volume_number,
}});
my $queries = [];
push @{$queries}, "DELETE FROM history.scan_drbd_peers WHERE scan_drbd_peer_uuid = '".$scan_drbd_peer_uuid."';";
push @{$queries}, "DELETE FROM scan_drbd_peers WHERE scan_drbd_peer_uuid = '".$scan_drbd_peer_uuid."';";
foreach my $query (@{$queries})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
}
$anvil->Database->write({query => $queries, source => $THIS_FILE, line => __LINE__});
next;
}
# Store the old data now.
$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{processed} = 0;
$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_scan_drbd_volume_uuid} = $scan_drbd_peer_scan_drbd_volume_uuid;
$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_host_name} = $scan_drbd_peer_host_name;
$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_connection_state} = $row->[3];
$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_connection_state} = $scan_drbd_peer_connection_state;
$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_local_disk_state} = $row->[4];
$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_disk_state} = $row->[5];
$anvil->data->{old}{scan_drbd_peer}{scan_drbd_peer_uuid}{$scan_drbd_peer_uuid}{scan_drbd_peer_local_role} = $row->[6];

@ -150,6 +150,7 @@ The global common configuration file: [#!variable!file!#] needs to be updated. T
#!variable!diff!#
====
</key>
<key name="scan_drbd_message_0035">The DRBD peer: [#!variable!peer_name!#] resource: [#!variable!resource_name!#] volume: [#!variable!volume_number!#] was deleted, and the corresponding LVM data no longer exists. Purging this resource's data.</key>
<!-- Units -->
<key name="scan_drbd_unit_0001">Enabled</key>

@ -510,6 +510,7 @@ The output, if any, was;
<key name="error_0362"><![CDATA[The level: [#!variable!level!#] is invalid. Please use '--level <critical,warning,notice,info>' to specify the alert level of the test message.]]></key>
<key name="error_0363">There are two or more entries on the host: [#!variable!host!#] in the history table: [#!variable!table!#]! The duplicate modidied_date and column UUID are: [#!variable!key!#] (time is UTC), and the query that exposed the dupplicate was: [#!variable!query!#]. This is likely caused by two database writes where the 'modified_date' wasn't updated between writes.</key>
<key name="error_0364">[ Error ] - There was a problem purging records. The details of the problem should be in the logs.</key>
<key name="error_0365">The table: [#!variable!table!#] has an entry in the history schema that doesn't have a corresponding record in the public schema. This is likely a resync artifact of a deleted record. Purging the record: [#!variable!uuid_column!#:#!variable!column_uuid!#] from all databases.</key>
<!-- Files templates -->
<!-- NOTE: Translating these files requires an understanding of which lines are translatable -->
@ -2125,6 +2126,7 @@ The file: [#!variable!file!#] needs to be updated. The difference is:
<key name="log_0702">I was asked to update the timestamp, but the returned timestamp matches the last one. Will loop until a new timestamp is returned.</key>
<key name="log_0703">The timestamp has been updated from: [#!variable!old_time!#] to: [#!variable!new_time!#].</key>
<key name="log_0704"><![CDATA[[ Error ] - The method Database->read_state() was called but both the 'state_name' and 'state_uuid' parameters were not passed or both were empty.]]></key>
<key name="log_0705">Forcing the dailing resync and checking to clear records in the history schema no longer in public schema.</key>
<!-- Messages for users (less technical than log entries), though sometimes used for logs, too. -->
<key name="message_0001">The host name: [#!variable!target!#] does not resolve to an IP address.</key>
@ -3222,6 +3224,7 @@ We will sleep a bit and try again.
<key name="warning_0142">[ Warning ] - The command: [#!variable!command!#] is still using our database.</key>
<key name="warning_0143">[ Warning ] - While evaluating database shutdown, the host UUID: [#!variable!host_uuid!#] was not yet found in the database on host: [#!variable!db_uuid!#]. DB shutdown will not happen until all hosts are in all DBs.</key>
<key name="warning_0144">[ Warning ] - While preparing to record the state: [#!variable!state_info!#], the host UUID: [#!variable!host_uuid!#] was not yet found in the database on host: [#!variable!db_uuid!#]. NOT recording the state!</key>
<key name="warning_0145">[ Warning ] - The daemon: [#!variable!daemon!#] was found running. It shouldn't be, and will now be stopped and disabled.</key>
<!-- The entries below here are not sequential, but use a key to find the entry. -->
<!-- Run 'striker-parse-os-list to find new entries. -->

@ -251,7 +251,7 @@ while(1)
check_ram($anvil);
# Disconnect from the database(s) and sleep now.
$anvil->Database->disconnect({debug => 2});
$anvil->Database->disconnect();
sleep(2);
}
@ -698,6 +698,24 @@ sub handle_periodic_tasks
# Now check to see if it's time to run daily tasks.
if ($now_time >= $anvil->data->{timing}{next_daily_check})
{
# Make sure ksm and ksmtuned are disabled.
foreach my $daemon ("ksm.service", "ksmtuned.service")
{
my $status = $anvil->System->check_daemon({daemon => $daemon});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
daemon => $daemon,
status => $status,
}});
if ($status eq "1")
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, priority => "alert", key => "warning_0145", variables => { daemon => $daemon }});
$anvil->System->disable_daemon({
now => 1,
daemon => $daemon,
});
}
}
### NOTE: We call it once/day, but this will also trigger on restart of anvil-daemon. As such, we
### don't use '--force' and let striker-manage-install-target skip the repo update if it happened
### recently enough.

@ -281,6 +281,65 @@ WHERE
}
}
# If deleting an Anvil!, we need to clear any Anvil! references from file_locations and storage groups.
if (($table eq "anvils") && ($anvil->data->{purge}{anvil_uuid}))
{
#
my $query = "DELETE FROM history.file_locations WHERE file_location_anvil_uuid = ".$anvil->Database->quote($anvil->data->{purge}{anvil_uuid}).";";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
push @{$queries}, $query;
$query = "DELETE FROM file_locations WHERE file_location_anvil_uuid = ".$anvil->Database->quote($anvil->data->{purge}{anvil_uuid}).";";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
push @{$queries}, $query;
# Storage groups
$query = "
SELECT
storage_group_member_uuid
FROM
storage_group_members
WHERE
storage_group_member_storage_group_uuid =
(
SELECT
storage_group_uuid
FROM
storage_groups
WHERE
storage_group_anvil_uuid = ".$anvil->Database->quote($anvil->data->{purge}{anvil_uuid})."
)
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
my $count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
results => $results,
count => $count,
}});
foreach my $row (@{$results})
{
my $storage_group_member_uuid = $row->[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { storage_group_member_uuid => $storage_group_member_uuid }});
my $query = "DELETE FROM history.storage_group_members WHERE storage_group_member_uuid = ".$anvil->Database->quote($storage_group_member_uuid).";";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
push @{$queries}, $query;
$query = "DELETE FROM storage_group_members WHERE storage_group_member_uuid = ".$anvil->Database->quote($storage_group_member_uuid).";";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
push @{$queries}, $query;
}
$query = "DELETE FROM history.storage_groups WHERE storage_group_anvil_uuid = ".$anvil->Database->quote($anvil->data->{purge}{anvil_uuid}).";";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
push @{$queries}, $query;
$query = "DELETE FROM storage_groups WHERE storage_group_anvil_uuid = ".$anvil->Database->quote($anvil->data->{purge}{anvil_uuid}).";";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
push @{$queries}, $query;
}
# Just delete the record normally.
if ($anvil->data->{sys}{database}{history_table}{$table})
{

Loading…
Cancel
Save