From e71c7d49668d007b284339e68e7507020c31791d Mon Sep 17 00:00:00 2001 From: Digimer Date: Thu, 4 Mar 2021 23:28:39 -0500 Subject: [PATCH] * Finished getting tools/striker-auto-initialize-all to merge the built Strikers. * Fixed a bug in Remote->call() where the output of the call not ending in a newline wasn't having the return code parsed off properly. Signed-off-by: Digimer --- Anvil/Tools/Network.pm | 16 +-- Anvil/Tools/Remote.pm | 9 +- share/words.xml | 3 + tools/striker-auto-initialize-all | 147 ++++++++++++++++++++-- tools/striker-auto-initialize-all.example | 4 +- 5 files changed, 154 insertions(+), 25 deletions(-) diff --git a/Anvil/Tools/Network.pm b/Anvil/Tools/Network.pm index 203f39fa..6543d71a 100644 --- a/Anvil/Tools/Network.pm +++ b/Anvil/Tools/Network.pm @@ -1205,22 +1205,22 @@ C<< Note >>: IP addresses that have been deleted will be marked so by C<< ip >> The loaded data will be stored as: -* C<< network::::interface::::ip >> - If an IP address is set -* C<< network::::interface::::subnet_mask >> - If an IP is set -* C<< network::::interface::::mac >> - Always set. -* C<< network::::interface::::default_gateway >> = C<< 0 >> if not the default gateway, C<< 1 >> if so. -* C<< network::::interface::::gateway >> = If the default gateway, this is the gateway IP address. -* C<< network::::interface::::dns >> = If the default gateway, this is the comma-separated list of active DNS servers. +* C<< network::::interface::::ip >> - If an IP address is set +* C<< network::::interface::::subnet_mask >> - If an IP is set +* C<< network::::interface::::mac >> - Always set. +* C<< network::::interface::::default_gateway >> = C<< 0 >> if not the default gateway, C<< 1 >> if so. +* C<< network::::interface::::gateway >> = If the default gateway, this is the gateway IP address. +* C<< network::::interface::::dns >> = If the default gateway, this is the comma-separated list of active DNS servers. Parameters; =head3 clear (optional, default '1') -When set, any previously known information is cleared. Specifically, the C<< network::> >> hash is deleted prior to the load. To prevent this, set this to C<< 0 >>. +When set, any previously known information is cleared. Specifically, the C<< network::> >> hash is deleted prior to the load. To prevent this, set this to C<< 0 >>. =head3 host (optional, default is 'host_uuid' value) -This is the optional C<< target >> string to use in the hash where the data is stored. +This is the optional C<< host >> string to use in the hash where the data is stored. =head3 host_uuid (optional, default 'sys::host_uuid') diff --git a/Anvil/Tools/Remote.pm b/Anvil/Tools/Remote.pm index da6ca4ba..06cd674d 100644 --- a/Anvil/Tools/Remote.pm +++ b/Anvil/Tools/Remote.pm @@ -385,7 +385,7 @@ sub call # In case the user is using ports in /etc/ssh/ssh_config, we'll want to check for an entry. $anvil->System->read_ssh_config({deubg => $debug}); - $anvil->data->{hosts}{$target}{port} = "" if not defined $anvil->data->{hosts}{$target}{port}; + $anvil->data->{hosts}{$target}{port} = 22 if not defined $anvil->data->{hosts}{$target}{port}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "hosts::${target}::port" => $anvil->data->{hosts}{$target}{port} }}); if ($anvil->data->{hosts}{$target}{port} =~ /^\d+$/) { @@ -693,9 +693,9 @@ sub call ### but it's here just in case. # If the output of the shell call doesn't end in a newline, the return_code:X # could be appended. This catches those cases and removes it. - $return_code = $1; - $line =~ s/return_code:\d+$//; - $output .= $line."\n"; + $return_code = $1; + $line =~ s/return_code:\d+$//; + $clean_output .= $line."\n"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { line => $line, output => $output, @@ -709,6 +709,7 @@ sub call } $clean_output =~ s/\n$//; $output = $clean_output; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { output => $output }}); # Have we been asked to close the connection? if ($close) diff --git a/share/words.xml b/share/words.xml index 04643a31..7ade7d47 100644 --- a/share/words.xml +++ b/share/words.xml @@ -687,6 +687,9 @@ It should be provisioned in the next minute or two. Successfully connected to Striker: [#!variable!number!#] using the IP: [#!variable!ip!#]! No connection to Striker: [#!variable!number!#] via the IP: [#!variable!ip!#]. Failed to connect Striker: [#!variable!number!#] over any IPs. Sleeping a bit and then trying again. + Waiting now for the peer Striker: [#!variable!number!#] with host UUID: [#!variable!peer_host_uuid!#] to show up in our database. + The peer Striker: [#!variable!number!#] with host name: [#!variable!peer_host_name!#] has successfully peered with us! + The peer Striker: [#!variable!number!#] with host UUID: [#!variable!peer_host_uuid!#] has not yet started using our database. Waiting a bit before checking again... Starting: [#!variable!program!#]. diff --git a/tools/striker-auto-initialize-all b/tools/striker-auto-initialize-all index 42c11c17..509300e7 100755 --- a/tools/striker-auto-initialize-all +++ b/tools/striker-auto-initialize-all @@ -10,6 +10,7 @@ use strict; use warnings; use Anvil::Tools; use Data::Dumper; +use NetAddr::IP; $| = 1; @@ -22,7 +23,6 @@ if (($running_directory =~ /^\./) && ($ENV{PWD})) =cut -Striker initialization; # At this point, the Striker should be coming up at the IP. Once both/all Strikers are up, update their anvil.conf to add each other's UUID database entry. # FROM ONE STRIKER; job_uuid | job_host_uuid | job_command | job_data | job_picked_up_by | job_picked_up_at | job_updated | job_name | job_progress | job_title | job_description | job_status | modified_date @@ -166,11 +166,13 @@ sub merge_peer_striker $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { network => $network }}); foreach my $network_number (sort {$a cmp $b} keys %{$anvil->data->{striker}{$striker_number}{network}{$network}}) { - my $ip = $anvil->data->{striker}{$striker_number}{network}{$network}{$network_number}{ip}; - push @{$peer_ips}, $ip; + my $ip = $anvil->data->{striker}{$striker_number}{network}{$network}{$network_number}{ip}; + my $subnet_mask = $anvil->data->{striker}{$striker_number}{network}{$network}{$network_number}{subnet_mask}; + push @{$peer_ips}, $ip."/".$subnet_mask; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { network_number => $network_number, ip => $ip, + subnet_mask => $subnet_mask, }}); foreach my $link_number (sort {$a cmp $b} keys %{$anvil->data->{striker}{$striker_number}{network}{$network}{$network_number}{'link'}}) { @@ -212,26 +214,111 @@ AND ### Add the peer. # First, wait for access. my $waiting = 1; + my $joining = 0; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0227", variables => { number => $striker_number }}); while ($waiting) { - foreach my $ip (@{$peer_ips}) + foreach my $network (@{$peer_ips}) { - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ip => $ip }}); - my $access = $anvil->Remote->test_access({ - target => $ip, - password => $anvil->data->{base}{password}{desired}, + next if not $waiting; + my ($ip, $subnet_mask) = ($network =~ /^(.*?)\/(.*)$/); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + ip => $ip, + subnet_mask => $subnet_mask, + }}); + + # Try to read the host uuid. + my $file = $anvil->data->{path}{data}{host_uuid}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file => $file }}); + my $shell_call = " +if [ -e ".$file." ]; +then + cat ".$file."; +else + echo 0; +fi; +"; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0166", variables => { + shell_call => $shell_call, + target => $ip, + remote_user => "root", + }}); + my ($host_uuid, $error, $return_code) = $anvil->Remote->call({ + shell_call => $shell_call, + target => $ip, + password => $anvil->data->{base}{password}{desired}, }); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { access => $access }}); - if ($access) + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + host_uuid => $host_uuid, + error => $error, + return_code => $return_code, + }}); + if (($host_uuid) && ($anvil->Validate->uuid({uuid => $host_uuid}))) { # Success! $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0228", variables => { number => $striker_number, ip => $ip, }}); - exit(0); + + $peer_host_uuid = $host_uuid; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { peer_host_uuid => $peer_host_uuid }}); + + # Find the IP we used to reach the peer. + my $our_ip = ""; + $anvil->Network->load_ips({ + host => "local", + host_uuid => $anvil->Get->host_uuid(), + }); + foreach my $interface_name (sort {$a cmp $b} keys %{$anvil->data->{network}{'local'}{interface}}) + { + my $local_ip = $anvil->data->{network}{'local'}{interface}{$interface_name}{ip}; + my $local_subnet_mask = $anvil->data->{network}{'local'}{interface}{$interface_name}{subnet_mask}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + interface_name => $interface_name, + local_ip => $local_ip, + local_subnet_mask => $local_subnet_mask, + }}); + next if $local_subnet_mask ne $subnet_mask; + + # See if this IP is in the same subnet. + my $first = NetAddr::IP->new($local_ip."/".$local_subnet_mask); + my $second = NetAddr::IP->new($ip."/".$subnet_mask); + if ($second->within($first)) + { + # Found the IP to tell the peer to use + $our_ip = $local_ip; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { our_ip => $our_ip }}); + last; + } + } + + if (not $our_ip) + { + # wtf; + die; + } + + # Register a job and then wait for it to show up in our database. + my $job_data = "password=".$anvil->data->{base}{password}{desired}."\n"; + $job_data .= "peer_job_command=".$anvil->data->{path}{exe}{'striker-manage-peers'}." --add --host-uuid ".$anvil->Get->host_uuid." --host ".$our_ip." --port 5432 --ping 1"; + my $job_command = $anvil->data->{path}{exe}{'striker-manage-peers'}." --add --host-uuid ".$host_uuid." --host ".$ip." --port 5432 --ping 1"; + $waiting = 0; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + job_command => $job_command, + job_data => $anvil->Log->is_secure($job_data), + waiting => $waiting, + }}); + my ($job_uuid) = $anvil->Database->insert_or_update_jobs({ + job_command => $job_command, + job_data => $job_data, + job_name => "striker-peer::remove", + job_title => "job_0013", + job_description => "job_0014", + job_progress => 0, + }); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }}); } else { @@ -250,8 +337,46 @@ AND } } } + + # Now wait until the peer is in our database. + my $peer_host_name = ""; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0231", variables => { + number => $striker_number, + peer_host_uuid => $peer_host_uuid, + }}); + until ($peer_host_name) + { + my $query = "SELECT host_name FROM hosts WHERE host_uuid = ".$anvil->Database->quote($peer_host_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, + }}); + if ($count) + { + $peer_host_name = $results->[0]->[0]; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0232", variables => { + number => $striker_number, + peer_host_name => $peer_host_name, + }}); + } + else + { + # Sleep for a bit. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0233", variables => { + number => $striker_number, + peer_host_uuid => $peer_host_uuid, + }}); + sleep 5; + } + } } + # By here, the peer(s) are joined. + return(0); } diff --git a/tools/striker-auto-initialize-all.example b/tools/striker-auto-initialize-all.example index ddefe3f5..204d6bac 100644 --- a/tools/striker-auto-initialize-all.example +++ b/tools/striker-auto-initialize-all.example @@ -49,7 +49,7 @@ striker::2::network::ifn::1::ip = 192.168.122.252 striker::2::network::ifn::1::subnet_mask = 255.255.255.0 striker::2::network::ifn::1::link::1::mac = 52:54:00:41:1f:7d striker::2::network::ifn::1::link::2::mac = 52:54:00:33:f7:de -striker::2::network::bcn::1::ip = 192.168.122.252 -striker::2::network::bcn::1::subnet_mask = 255.255.255.0 +striker::2::network::bcn::1::ip = 10.201.4.2 +striker::2::network::bcn::1::subnet_mask = 255.255.0.0 striker::2::network::bcn::1::link::1::mac = 52:54:00:b8:34:a7 striker::2::network::bcn::1::link::2::mac = 52:54:00:30:f9:db