* Created the new tools/striker-purge-host tool which purges all data about a host from the database.

* Updated Database->get_hosts() to store 'host_key' and 'host_uuid' data.
* Created Database->get_ssh_keys().
* Fixed a couple bugs where Get->host_type() now returns 'striker' but tests checked for 'dashboard'.

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 5 years ago
parent 0b2eb88f39
commit 7d907c15ff
  1. 145
      Anvil/Tools/Database.pm
  2. 42
      Anvil/Tools/System.pm
  3. 11
      share/words.xml
  4. 324
      tools/striker-purge-host
  5. 2
      tools/test.pl

@ -32,6 +32,7 @@ my $THIS_FILE = "Database.pm";
# get_manifests
# get_notifications
# get_recipients
# get_ssh_keys
# get_upses
# initialize
# insert_or_update_anvils
@ -293,6 +294,8 @@ sub archive_database
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.
This method takes no parameters.
=cut
sub check_lock_age
{
@ -357,6 +360,8 @@ If the system is already configured, this method will do nothing, so it is safe
If the method completes, C<< 0 >> is returned. If this method is called without C<< root >> access, it returns C<< 1 >> without doing anything. If there is a problem, C<< !!error!! >> is returned.
This method takes no parameters.
=cut
sub configure_pgsql
{
@ -1332,7 +1337,7 @@ sub connect
$anvil->Database->mark_active({debug => $debug, set => 1});
# Sync the database, if needed.
$anvil->Database->resync_databases({debug => 3});
$anvil->Database->resync_databases({debug => $debug});
# Add ourselves to the database, if needed.
$anvil->Database->insert_or_update_hosts({debug => $debug});
@ -1346,6 +1351,8 @@ sub connect
This cleanly closes any open file handles to all connected databases and clears some internal database related variables.
This method takes no parameters.
=cut
sub disconnect
{
@ -1393,6 +1400,8 @@ sub disconnect
This returns a list of users listening to alerts for a given host, along with their alert level.
This method takes no parameters.
=cut
sub get_recipients
{
@ -1402,11 +1411,6 @@ sub get_recipients
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Database->get_recipients()" }});
my $host_uuid = defined $parameter->{host_uuid} ? $parameter->{host_uuid} : $anvil->Get->host_uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
host_uuid => $host_uuid,
}});
### TODO: Read in 'notifications'
my $query = "
SELECT
@ -1814,12 +1818,16 @@ Each anonymous hash is structured as:
host_uuid => $host_uuid,
host_name => $host_name,
host_type => $host_type,
host_key => $host_key,
host_ipmi => $host_ipmi,
modified_date => $modified_date,
It also sets the variables;
hosts::host_uuid::<host_uuid>::host_name = <host_name>;
hosts::host_uuid::<host_uuid>::host_type = <host_type; node, dr or dashboard>
hosts::host_uuid::<host_uuid>::host_key = <Machine's public key / fingerprint>
hosts::host_uuid::<host_uuid>::host_ipmi = <If equiped, this is how to log into the host's IPMI BMC>
hosts::host_uuid::<host_uuid>::anvil_name = <anvil_name if associated with an anvil>
And to simplify look-ups by UUID or name;
@ -1829,6 +1837,8 @@ And to simplify look-ups by UUID or name;
To prevent some cases of recursion, C<< hosts::loaded >> is set on successful load, and if this is set, this method immediately returns with C<< 0 >>.
This method takes no parameters.
=cut
sub get_hosts
{
@ -1838,6 +1848,11 @@ sub get_hosts
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Database->get_hosts()" }});
# Delete any data from past scans.
delete $anvil->data->{hosts}{host_uuid};
delete $anvil->data->{sys}{hosts}{by_uuid};
delete $anvil->data->{sys}{hosts}{by_name};
# Load anvils. If a host is registered with an Anvil!, we'll note it.
$anvil->Database->get_anvils({debug => $debug});
@ -1846,6 +1861,8 @@ SELECT
host_uuid,
host_name,
host_type,
host_key,
host_ipmi,
modified_date
FROM
hosts
@ -1861,14 +1878,18 @@ FROM
}});
foreach my $row (@{$results})
{
my $host_uuid = $row->[0];
my $host_name = $row->[1];
my $host_type = $row->[2];
my $modified_date = $row->[3];
my $host_uuid = $row->[0];
my $host_name = $row->[1];
my $host_type = defined $row->[2] ? $row->[2] : "";
my $host_key = defined $row->[3] ? $row->[3] : "";
my $host_ipmi = $row->[4];
my $modified_date = $row->[5];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
host_uuid => $host_uuid,
host_name => $host_name,
host_type => $host_type,
host_key => $host_key,
host_ipmi => $host_ipmi,
modified_date => $modified_date,
}});
@ -1883,16 +1904,22 @@ FROM
host_uuid => $host_uuid,
host_name => $host_name,
host_type => $host_type,
host_key => $host_key,
host_ipmi => $host_ipmi,
modified_date => $modified_date,
};
# Record the data in the hash, too.
$anvil->data->{hosts}{host_uuid}{$host_uuid}{host_name} = $host_name;
$anvil->data->{hosts}{host_uuid}{$host_uuid}{host_type} = $host_type;
$anvil->data->{hosts}{host_uuid}{$host_uuid}{host_key} = $host_key;
$anvil->data->{hosts}{host_uuid}{$host_uuid}{host_ipmi} = $host_ipmi;
$anvil->data->{hosts}{host_uuid}{$host_uuid}{anvil_name} = $anvil_name;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"hosts::host_uuid::${host_uuid}::host_name" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_name},
"hosts::host_uuid::${host_uuid}::host_type" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_type},
"hosts::host_uuid::${host_uuid}::host_key" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_key},
"hosts::host_uuid::${host_uuid}::host_ipmi" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_ipmi},
"hosts::host_uuid::${host_uuid}::anvil_name" => $anvil->data->{hosts}{host_uuid}{$host_uuid}{anvil_name},
}});
@ -1915,6 +1942,8 @@ FROM
This gathers up all the known information about all known hosts.
This method takes no parameters.
=cut
sub get_hosts_info
{
@ -2010,6 +2039,8 @@ Parameters;
This is the C<< job_uuid >> of the job being retrieved.
This method takes no parameters.
=cut
sub get_job_details
{
@ -2132,6 +2163,8 @@ Jobs that reached 100% within this number of seconds ago will be included. If th
This is the host that we're getting a list of jobs from.
This method takes no parameters.
=cut
sub get_jobs
{
@ -2270,6 +2303,8 @@ NOTE: This returns nothing if the local machine is not found as a configured dat
# Get the local UUID
my $local_uuid = $anvil->Database->get_local_uuid;
This method takes no parameters.
=cut
sub get_local_uuid
{
@ -2340,6 +2375,8 @@ sub get_local_uuid
This gets the list of configured mail servers.
This method takes no parameters.
=cut
sub get_mail_servers
{
@ -2632,6 +2669,94 @@ FROM
}
=head2 get_ssh_keys
This loads all known user's SSH public keys and all known machine's public keys into the data hash. On success, this method returns C<< 0 >>. If any problems occur, C<< 1 >> is returned.
ssh_keys::ssh_key_uuid::<ssh_key_uuid>::ssh_key_host_uuid = <Host UUID the user is from>
ssh_keys::ssh_key_uuid::<ssh_key_uuid>::ssh_key_user_name = <The user's name>
ssh_keys::ssh_key_uuid::<ssh_key_uuid>::ssh_key_public_key = <The SSH public key>
And:
ssh_keys::ssh_key_host_uuid::<ssh_key_host_uuid>::ssh_key_uuid = <UUID of ssh_keys column>
ssh_keys::ssh_key_host_uuid::<ssh_key_host_uuid>::ssh_key_user_name = <The user's name>
ssh_keys::ssh_key_host_uuid::<ssh_key_host_uuid>::ssh_key_public_key = <The SSH public key>
This method takes no parameters.
=cut
sub get_ssh_keys
{
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->initialize()" }});
# Delete any data from past scans.
delete $anvil->data->{ssh_keys}{ssh_key_uuid};
delete $anvil->data->{sys}{ssh_keys}{by_uuid};
delete $anvil->data->{sys}{ssh_keys}{by_name};
my $query = "
SELECT
ssh_key_uuid,
ssh_key_host_uuid,
ssh_key_user_name,
ssh_key_public_key,
modified_date
FROM
ssh_keys
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, 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 => $debug, list => {
results => $results,
count => $count,
}});
foreach my $row (@{$results})
{
my $ssh_key_uuid = $row->[0];
my $ssh_key_host_uuid = $row->[1];
my $ssh_key_user_name = $row->[2];
my $ssh_key_public_key = $row->[3];
my $modified_date = $row->[4];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
ssh_key_uuid => $ssh_key_uuid,
ssh_key_host_uuid => $ssh_key_host_uuid,
ssh_key_user_name => $ssh_key_user_name,
ssh_key_public_key => $ssh_key_public_key,
modified_date => $modified_date,
}});
# Record the data in the hash, too.
$anvil->data->{ssh_keys}{ssh_key_uuid}{$ssh_key_uuid}{ssh_key_host_uuid} = $ssh_key_host_uuid;
$anvil->data->{ssh_keys}{ssh_key_uuid}{$ssh_key_uuid}{ssh_key_user_name} = $ssh_key_user_name;
$anvil->data->{ssh_keys}{ssh_key_uuid}{$ssh_key_uuid}{ssh_key_public_key} = $ssh_key_public_key;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"ssh_keys::ssh_key_uuid::${ssh_key_uuid}::ssh_key_host_uuid" => $anvil->data->{ssh_keys}{ssh_key_uuid}{$ssh_key_uuid}{ssh_key_host_uuid},
"ssh_keys::ssh_key_uuid::${ssh_key_uuid}::ssh_key_user_name" => $anvil->data->{ssh_keys}{ssh_key_uuid}{$ssh_key_uuid}{ssh_key_user_name},
"ssh_keys::ssh_key_uuid::${ssh_key_uuid}::ssh_key_public_key" => $anvil->data->{ssh_keys}{ssh_key_uuid}{$ssh_key_uuid}{ssh_key_public_key},
}});
$anvil->data->{ssh_keys}{ssh_key_host_uuid}{$ssh_key_host_uuid}{ssh_key_uuid} = $ssh_key_uuid;
$anvil->data->{ssh_keys}{ssh_key_host_uuid}{$ssh_key_host_uuid}{ssh_key_user_name} = $ssh_key_user_name;
$anvil->data->{ssh_keys}{ssh_key_host_uuid}{$ssh_key_host_uuid}{ssh_key_public_key} = $ssh_key_public_key;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"ssh_keys::ssh_key_host_uuid::${ssh_key_host_uuid}::ssh_key_uuid" => $anvil->data->{ssh_keys}{ssh_key_host_uuid}{$ssh_key_host_uuid}{ssh_key_uuid},
"ssh_keys::ssh_key_host_uuid::${ssh_key_host_uuid}::ssh_key_user_name" => $anvil->data->{ssh_keys}{ssh_key_host_uuid}{$ssh_key_host_uuid}{ssh_key_user_name},
"ssh_keys::ssh_key_host_uuid::${ssh_key_host_uuid}::ssh_key_public_key" => $anvil->data->{ssh_keys}{ssh_key_host_uuid}{$ssh_key_host_uuid}{ssh_key_public_key},
}});
}
return(0);
}
=head2 get_upses
This loads the known UPSes (uninterruptible power supplies) into the C<< anvil::data >> hash at:

@ -22,6 +22,7 @@ my $THIS_FILE = "System.pm";
# change_shell_user_password
# check_daemon
# check_if_configured
# check_ssh_keys
# check_memory
# check_storage
# disable_daemon
@ -643,8 +644,9 @@ sub check_ssh_keys
my $users = $anvil->Get->host_type eq "node" ? ["root", "admin", "hacluster"] : ["root", "admin"];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { users => \@{$users} }});
# Get a list of machine host keys and user public keys from other machines.
#get_other_keys($anvil);
# Load the host keys and the SSH keys
$anvil->Database->get_hosts({debug => $debug});
$anvil->Database->get_ssh_keys({debug => $debug});
# Users to check:
foreach my $user (@{$users})
@ -672,11 +674,6 @@ sub check_ssh_keys
group => $user,
mode => "0700",
});
if (not -e $ssh_directory)
{
# Failed ?
next;
}
}
my $ssh_private_key_file = $user_home."/.ssh/id_rsa";
@ -753,10 +750,33 @@ sub check_ssh_keys
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { authorized_keys_file_body => $authorized_keys_file_body }});
}
### Walk through each host we now know of. As we we do, loop through the old file body to see
### if it exists. If it does, and the key has changed, update the line with the new key. If
### it isn't found, add it. Once we check the old body for this entry, change the "old" body
### to the new one, then repeat the process.
# Walk through the Striker dashboards we use. If we're a Node or DR host, walk through our
# peers as well. As we we do, loop through the old file body to see if it exists. If it does,
# and the key has changed, update the line with the new key. If it isn't found, add it. Once
# we check the old body for this entry, change the "old" body to the new one, then repeat the
# process.
my $trusted_host_uuids = [];
if ($anvil->Get->host_type eq "striker")
{
# Add all known machines
}
else
{
# Add dashboard (using postgres connection info), the UUID is the host UUID.
foreach my $uuid (sort {$a cmp $b} keys %{$anvil->data->{database}})
{
# Periodically, autovivication causes and empty key to appear.
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { uuid => $uuid }});
next if ((not $uuid) or (not $anvil->Validate->is_uuid({uuid => $uuid})));
push @{$trusted_host_uuids}, $uuid;
}
# Now add our peers.
}
my $peers = [];
# Look at all the hosts I know about (other than myself) and see if any of the machine or
# user keys either don't exist or have changed.

@ -33,6 +33,7 @@ Author: Madison Kelly <mkelly@alteeve.ca>
<key name="brand_0006"><![CDATA[<i>Anvil!</i>]]></key>
<key name="brand_0007">Node</key>
<key name="brand_0008">DR Host</key>
<key name="brand_0009">Unknown Type</key>
<!-- Errors -->
<key name="error_0001">There are not enough network interfaces on this machine. You have: [#!variable!interface_count!#] interface(s), and you need at least: [#!variable!required_interfaces_for_single!#] interfaces to connect to the requested networks (one for Back-Channel and one for each Internet-Facing network).</key>
@ -188,6 +189,8 @@ The error was:
<key name="error_0127">I was asked to delete and entry from: [#!variable!table!#] but neither the name or UUID was passed.</key>
<key name="error_0128">The host UUID: [#!variable!uuid!#] was set as the value for: [#!variable!column!#], but that host doesn't appear to exist.</key>
<key name="error_0129">Unable to connect to any database, unable to read the job details.</key>
<key name="error_0130">The answer: [#!variable!answer!#] is invalid. Please try again.</key>
<key name="error_0131">The host UUID: [#!variable!host_uuid!#] was not found. Has it already been purged?</key>
<!-- Table headers -->
<key name="header_0001">Current Network Interfaces and States</key>
@ -1126,6 +1129,14 @@ About to try to download aproximately: [#!variable!packages!#] packages needed t
<key name="message_0166">An isolated, VLAN'ed network used for all inter-machine communication in the #!string!brand_0006!#, as well as communication for foundation pack devices.</key>
<key name="message_0167">An isolated, VLAN'ed network Used for storage replication traffic only.</key>
<key name="message_0168">Connecting to the main site intranet. This is the network (or networks) that guest virtual servers will use to connect to all devices outside the #!string!brand_0006!# system.</key>
<key name="message_0169">Please select the host you want to purge from the database:</key>
<key name="message_0170">#!variable!key!#) #!variable!host_name!# - #!variable!type!# - #!variable!host_uuid!#)</key>
<key name="message_0171">Which machine do you want to purge from the database(s)? </key>
<key name="message_0172">Note: Be sure all databases are online! Otherwise, the purged records could return during the next resync!</key>
<key name="message_0173">Are you sure you want to purge: [#!variable!host_name!# (#!variable!host_uuid!#)]?</key> <!-- Translation note: If you want to accept other characters as confirmation, update 'striker-purge-host', 'sub confirm' in the 'normalize -y' section. -->
<key name="message_0174">Confirmed by switch, proceeding with purge of: [#!variable!host_name!#].</key>
<key name="message_0175">Thank you, proceeding.</key>
<key name="message_0176">The host: [#!variable!host_name!#] has been purged.</key>
<!-- Success messages shown to the user -->
<key name="ok_0001">Saved the mail server information successfully!</key>

@ -0,0 +1,324 @@
#!/usr/bin/perl
#
# This tool is meant to be run from the command line and lets a user purge all information about a given host
# from the databases.
#
# Exit codes;
# 0 = Normal exit.
# 1 = User's answer to which machine to purge was invalid.
# 2 = The passed-in (or selected) host UUID (no longer) exists.
# 3 = User did not confirm to proceed.
# 4 = Runaway loop detected.
#
use strict;
use warnings;
use Anvil::Tools;
use Data::Dumper;
use Curses::UI;
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0];
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0];
if (($running_directory =~ /^\./) && ($ENV{PWD}))
{
$running_directory =~ s/^\./$ENV{PWD}/;
}
# Turn off buffering so that the pinwheel will display while waiting for the SSH call(s) to complete.
$| = 1;
my $anvil = Anvil::Tools->new({debug => 2});
$anvil->Log->secure({set => 1});
$anvil->Log->level({set => 2});
$anvil->Database->connect({debug => 3});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0132"});
# First, ask the user to select a host.
$anvil->data->{switches}{'host-uuid'} = "" if not defined $anvil->data->{switches}{'host-uuid'};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'switches::host-uuid' => $anvil->data->{switches}{'host-uuid'} }});
$anvil->Database->get_hosts();
# Ask the user to pick a host.
pick_host($anvil);
# Ask the user to confirm.
confirm($anvil);
# If we're alive, purge.
purge($anvil);
$anvil->nice_exit({code => 0});
#############################################################################################################
# Functions #
#############################################################################################################
sub purge
{
my ($anvil) = @_;
# Read in all constraints and create a hash of what depends on what, then delete anything referencing
# hosts without any further references. As each delete is done, delete it. Loop until all entries are
# gone.
# Load all the known tables in the DB.
my $query = "SELECT schemaname||'.'||tablename AS table_name FROM pg_catalog.pg_tables WHERE schemaname = 'history' ORDER BY tablename ASC, schemaname ASC;";
$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 => 3, list => {
results => $results,
count => $count,
}});
foreach my $row (@{$results})
{
my $table_name = $row->[0];
$anvil->data->{sql}{history_tables}{$table_name} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "sql::history_tables::${table_name}" => $anvil->data->{sql}{history_tables}{$table_name} }});
}
undef $query;
undef $results;
undef $count;
### NOTE: Credit for this query goes to:
### - https://stackoverflow.com/questions/1152260/postgres-sql-to-list-table-foreign-keys
$query = "
SELECT
tc.table_schema||'.'||tc.table_name AS table,
kcu.column_name,
ccu.table_schema||'.'||ccu.table_name AS foreign_table,
ccu.column_name AS foreign_column_name
FROM
information_schema.table_constraints AS tc
JOIN information_schema.key_column_usage AS kcu
ON tc.constraint_name = kcu.constraint_name
AND tc.table_schema = kcu.table_schema
JOIN information_schema.constraint_column_usage AS ccu
ON ccu.constraint_name = tc.constraint_name
AND ccu.table_schema = tc.table_schema
WHERE
tc.constraint_type = 'FOREIGN KEY'
AND
ccu.column_name = 'host_uuid'
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
$results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
$count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
results => $results,
count => $count,
}});
foreach my $row (@{$results})
{
my $table_name = $row->[0];
my $column_name = $row->[1];
my $foreign_table_name = $row->[2];
my $foreign_column_name = $row->[3];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
's1:table_name' => $table_name,
's2:column_name' => $column_name,
's3:foreign_table_name' => $foreign_table_name,
's4:foreign_column_name' => $foreign_column_name,
}});
if (not exists $anvil->data->{sql}{table}{$table_name})
{
$anvil->data->{sql}{table}{$table_name}{column} = $column_name;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "sql::table::${table_name}::column" => $anvil->data->{sql}{table}{$table_name}{column} }});
}
if (not exists $anvil->data->{sql}{table}{$foreign_table_name})
{
$anvil->data->{sql}{table}{$foreign_table_name}{column} = $foreign_column_name;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "sql::table::${foreign_table_name}::column" => $anvil->data->{sql}{table}{$foreign_table_name}{column} }});
}
$anvil->data->{sql}{table}{$foreign_table_name}{referenced_by}{$table_name} = 1;
}
my $loops = 20;
my $loop = 0;
my $done = 0;
my $queries = [];
until($done)
{
$loop++;
foreach my $table_name (sort {$a cmp $b} keys %{$anvil->data->{sql}{table}})
{
my $count = exists $anvil->data->{sql}{table}{$table_name}{referenced_by} ? keys %{$anvil->data->{sql}{table}{$table_name}{referenced_by}} : 0;
#print "-- Table: [".$table_name."] is referenced by: [".$count."] foreign table(s);\n";
if (not $count)
{
# If there is a corresponding history table, delete it as well.
my $column = $anvil->data->{sql}{table}{$table_name}{column};
my $history_table = $table_name;
$history_table =~ s/^public\./history\./;
if (exists $anvil->data->{sql}{history_tables}{$history_table})
{
push @{$queries}, "DELETE FROM ".$history_table." WHERE ".$column." = ".$anvil->Database->quote($anvil->data->{switches}{'host-uuid'}).";";
}
# Now delete the public table entries.
push @{$queries}, "DELETE FROM ".$table_name." WHERE ".$column." = ".$anvil->Database->quote($anvil->data->{switches}{'host-uuid'}).";";
foreach my $foreign_table_name (sort {$a cmp $b} keys %{$anvil->data->{sql}{table}})
{
if (exists $anvil->data->{sql}{table}{$foreign_table_name}{referenced_by}{$table_name})
{
#print "-- Deleting: [".$foreign_table_name."] reference to: [".$table_name."]\n";
delete $anvil->data->{sql}{table}{$foreign_table_name}{referenced_by}{$table_name};
}
}
#print "-- Deleting hash entry for: [".$table_name."]\n";
delete $anvil->data->{sql}{table}{$table_name};
}
}
my $remaining = keys %{$anvil->data->{sql}{table}};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { remaining => $remaining }});
if (not $remaining)
{
$done = 1;
}
elsif ($loop > $loops)
{
print "Run-away loop detected, aborting!\n";
$anvil->nice_exit({code => 4});
}
}
# Do the deed.
$anvil->Database->write({debug => 2, query => $queries, source => $THIS_FILE, line => __LINE__});
my $host_uuid = $anvil->data->{switches}{'host-uuid'};
print $anvil->Words->string({key => "message_0176", variables => { host_name => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_name} }})."\n";
return(0);
}
sub confirm
{
my ($anvil) = @_;
# Normalize -y
$anvil->data->{switches}{'y'} = "" if not defined $anvil->data->{switches}{'y'};
$anvil->data->{switches}{'yes'} = "" if not defined $anvil->data->{switches}{'yes'};
$anvil->data->{switches}{'Y'} = "" if not defined $anvil->data->{switches}{'Y'};
$anvil->data->{switches}{'Yes'} = "" if not defined $anvil->data->{switches}{'Yes'};
$anvil->data->{switches}{'YES'} = "" if not defined $anvil->data->{switches}{'YES'};
if (not $anvil->data->{switches}{'y'})
{
if ($anvil->data->{switches}{'yes'}) { $anvil->data->{switches}{'y'} = $anvil->data->{switches}{'yes'}; }
elsif ($anvil->data->{switches}{'Y'}) { $anvil->data->{switches}{'y'} = $anvil->data->{switches}{'Y'}; }
elsif ($anvil->data->{switches}{'Yes'}) { $anvil->data->{switches}{'y'} = $anvil->data->{switches}{'Yes'}; }
elsif ($anvil->data->{switches}{'YES'}) { $anvil->data->{switches}{'y'} = $anvil->data->{switches}{'YES'}; }
}
# Ask to confirm, is sane and not -y
my $host_uuid = $anvil->data->{switches}{'host-uuid'};
if (not exists $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_name})
{
print $anvil->Words->string({key => "error_0131", variables => { host_uuid => $host_uuid }})."\n\n";
$anvil->nice_exit({code => 2});
}
else
{
print $anvil->Words->string({key => "message_0172"})."\n\n";
print $anvil->Words->string({key => "message_0173", variables => {
host_name => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_name},
host_uuid => $host_uuid,
}})."\n";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 'switches::y' => $anvil->data->{switches}{'y'} }});
if ($anvil->data->{switches}{'y'} eq "#!SET!#")
{
# Already confirmed.
print $anvil->Words->string({key => "message_0023"})."\n\n";
return(0);
}
print $anvil->Words->string({key => "message_0021"})." ";
chomp(my $answer = <STDIN>);
if ($answer =~ /^y/i)
{
# Proceed.
print $anvil->Words->string({key => "message_0175"})."\n";
}
else
{
# Abort.
print $anvil->Words->string({key => "message_0022"})."\n";
$anvil->nice_exit({code => 3});
}
}
return(0);
}
sub pick_host
{
my ($anvil) = @_;
return(0) if $anvil->data->{switches}{'host-uuid'};
# Get a list of hosts
my $i = 1;
my $select = {};
my $host_length = 0;
my $type_length = 0;
foreach my $host_name (sort {$a cmp $b} keys %{$anvil->data->{sys}{hosts}{by_name}})
{
my $host_uuid = $anvil->data->{sys}{hosts}{by_name}{$host_name};
my $host_type = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_type};
my $anvil_name = defined $anvil->data->{hosts}{host_uuid}{$host_uuid}{anvil_name} ? $anvil->data->{hosts}{host_uuid}{$host_uuid}{anvil_name} : "";
my $say_type = $anvil->Words->string({key => "brand_0009"});
if ($host_type eq "striker") { $say_type = $anvil->Words->string({key => "brand_0003"}); }
elsif ($host_type eq "node") { $say_type = $anvil->Words->string({key => "brand_0007"}); }
elsif ($host_type eq "dr") { $say_type = $anvil->Words->string({key => "brand_0008"}); }
if (length($host_name) > $host_length) { $host_length = length($host_name); }
if (length($say_type) > $type_length) { $type_length = length($say_type); }
# This is used to build the menu.
$select->{$i}{host_uuid} = $host_uuid;
$select->{$i}{host_name} = $host_name;
$select->{$i}{host_type} = $host_type;
$select->{$i}{say_type} = $say_type;
$select->{$i}{anvil_name} = $anvil_name;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
"${i}::host_uuid" => $select->{$i}{host_uuid},
"${i}::host_name" => $select->{$i}{host_name},
"${i}::host_type" => $select->{$i}{host_type},
"${i}::anvil_name" => $select->{$i}{anvil_name},
}});
$i++;
}
my $pad = $i > 9 ? 2 : 1;
print $anvil->Words->string({key => "message_0169"})."\n\n";
foreach my $i (sort {$a cmp $b} keys %{$select})
{
print " ".$anvil->Words->string({key => "message_0170", variables => {
key => sprintf("%".$pad."s", $i),
type => sprintf("%-".$type_length."s", $select->{$i}{say_type}),
host_name => sprintf("%-".$host_length."s", $select->{$i}{host_name}),
host_uuid => $select->{$i}{host_uuid},
}})."\n";
}
print "\n".$anvil->Words->string({key => "message_0171"})." ";
chomp(my $answer = <STDIN>);
if (not exists $select->{$answer}{host_name})
{
print "\n".$anvil->Words->string({key => "error_0130", variables => { answer => $answer }})."\n\n";
$anvil->nice_exit({code => 1});
}
else
{
print "\n";
$anvil->data->{switches}{'host-uuid'} = $select->{$answer}{host_uuid};
}
return(0);
}

@ -25,4 +25,4 @@ $anvil->Database->connect({debug => 3});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0132"});
print "DB Connections: [".$anvil->data->{sys}{database}{connections}."]\n";
$anvil->System->check_ssh_keys({debug => 2});
#$anvil->System->check_ssh_keys({debug => 2});

Loading…
Cancel
Save