Added extra checks to Network->wait_for_bonds()

* Added a default timeout of 180 seconds, and updated
  anvil-configure-host to reduce this to 60 seconds while configuring
  the host.
* Added a check for interfaces configured under a bond. If none are
  found, the bond is ignored.
* Updated Storage->update_config() to take the new 'append' attribute to
  allow adding a variable if it wasn't found already in the config.
* Added the new 'network::wait_for_bonds::timeout' variable to enable
  changing the default timeout for Network->wait_for_bonds().

Signed-off-by: digimer <mkelly@alteeve.ca>
main
digimer 10 months ago
parent d5ceca3dc6
commit 6a193bf710
  1. 1
      Anvil/Tools/Get.pm
  2. 94
      Anvil/Tools/Network.pm
  3. 21
      Anvil/Tools/Storage.pm
  4. 6
      anvil.conf
  5. 1
      share/words.xml
  6. 16
      tools/anvil-configure-host

@ -2898,6 +2898,7 @@ sub switches
# Lastly, if there's a anvil.debug file, set logging to '-vv --log-secure' # Lastly, if there's a anvil.debug file, set logging to '-vv --log-secure'
if (-e $anvil->data->{path}{configs}{'anvil.debug'}) if (-e $anvil->data->{path}{configs}{'anvil.debug'})
{ {
# Set defaults, then see if we should override from the body.
$anvil->data->{switches}{v} = ""; $anvil->data->{switches}{v} = "";
$anvil->data->{switches}{v} = ""; $anvil->data->{switches}{v} = "";
$anvil->data->{switches}{vv} = "#!SET!#"; $anvil->data->{switches}{vv} = "#!SET!#";

@ -4517,9 +4517,9 @@ B<< Note >>: This method only works on Network Manager based systems.
Parameters; Parameters;
=head3 timeout (optional, default '0') =head3 timeout (optional, default '180')
By default, this method will wait forever. If you want to set a timeout, set this as a number of seconds. If the timeout expires and any bonds are still not up, the method will return C<< 1 >>. By default, this method will wait for three minutes. If you want to set a timeout, set this as a number of seconds. If the timeout expires and any bonds are still not up, the method will return C<< 1 >>. If this is set to C<< 0 >>, it will wait forever.
=cut =cut
sub wait_for_bonds sub wait_for_bonds
@ -4530,11 +4530,18 @@ sub wait_for_bonds
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3; my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Network->wait_for_bonds()" }}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Network->wait_for_bonds()" }});
my $timeout = defined $parameter->{timeout} ? $parameter->{timeout} : 0; my $timeout = defined $parameter->{timeout} ? $parameter->{timeout} : 180;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
timeout => $timeout, timeout => $timeout,
}}); }});
# If timeout wasn't set, but network::wait_for_bonds::timeout is set, use it.
if ((exists $anvil->data->{network}{wait_for_bonds}{timeout}) && ($anvil->data->{network}{wait_for_bonds}{timeout} =~ /^\d+$/))
{
$timeout = $anvil->data->{network}{wait_for_bonds}{timeout};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { timeout => $timeout }});
}
my $directory = $anvil->data->{path}{directories}{NetworkManager}; my $directory = $anvil->data->{path}{directories}{NetworkManager};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { directory => $directory }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { directory => $directory }});
@ -4561,16 +4568,22 @@ sub wait_for_bonds
my $file_body = $anvil->Storage->read_file({debug => $debug, file => $full_path}); my $file_body = $anvil->Storage->read_file({debug => $debug, file => $full_path});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { file_body => $file_body }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { file_body => $file_body }});
my $is_bond = 0; my $type = "";
my $interface_name = ""; my $interface_name = "";
my $parent_bond = "";
foreach my $line (split/\n/, $file_body) foreach my $line (split/\n/, $file_body)
{ {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { line => $line }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { line => $line }});
if ($line =~ /^type=bond/) if ($line =~ /^type=(.*)$/)
{ {
$is_bond = 1; $type = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { is_bond => $is_bond }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { type => $type }});
}
if ($line =~ /^master=(.*)$/)
{
$parent_bond = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { parent_bond => $parent_bond }});
} }
if ($line =~ /^interface-name=(.*)$/) if ($line =~ /^interface-name=(.*)$/)
{ {
@ -4584,17 +4597,53 @@ sub wait_for_bonds
} }
} }
if (($is_bond) && ($interface_name)) if (($type eq "bond") && ($interface_name))
{
$anvil->data->{network}{bond}{$interface_name}{ready} = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"network::bond::${interface_name}::ready" => $anvil->data->{network}{bond}{$interface_name}{ready},
}});
}
if (($type eq "ethernet") && ($parent_bond))
{ {
$anvil->data->{network}{watch_bond}{$interface_name}{ready} = 0; $anvil->data->{network}{ethernet}{$interface_name}{parent_bond} = $parent_bond;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"network::watch_bond::${interface_name}::ready" => $anvil->data->{network}{watch_bond}{$interface_name}{ready}, "network::ethernet::${interface_name}::parent_bond" => $anvil->data->{network}{ethernet}{$interface_name}{parent_bond},
}}); }});
} }
} }
closedir(DIRECTORY); closedir(DIRECTORY);
my $bond_count = keys %{$anvil->data->{network}{watch_bond}}; # We only want to watch bonds with interfaces configured to use it.
foreach my $bond_name (sort {$a cmp $b} keys %{$anvil->data->{network}{bond}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { bond_name => $bond_name }});
# We've got a primary, is it (or any interface) configured for this bond yet?
my $interface_found = 0;
foreach my $interface_name (sort {$a cmp $b} keys %{$anvil->data->{network}{ethernet}})
{
my $parent_bond = $anvil->data->{network}{ethernet}{$interface_name}{parent_bond};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { interface_name => $interface_name }});
if ($parent_bond eq $bond_name)
{
# We've got an interface.
$interface_found = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { interface_found => $interface_found }});
}
}
if (not $interface_found)
{
# Ignore this bond.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0845", variables => { bond_name => $bond_name }});
delete $anvil->data->{network}{bond}{$bond_name};
next;
}
}
my $bond_count = keys %{$anvil->data->{network}{bond}};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { bond_count => $bond_count }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { bond_count => $bond_count }});
if (not $bond_count) if (not $bond_count)
{ {
@ -4603,14 +4652,18 @@ sub wait_for_bonds
my $waiting = 1; my $waiting = 1;
my $end_time = $timeout ? time + $timeout : 0; my $end_time = $timeout ? time + $timeout : 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { end_time => $end_time }}); my $duration = $end_time ? $timeout - time : 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
end_time => $end_time,
duration => $duration,
}});
while($waiting) while($waiting)
{ {
$waiting = 0; $waiting = 0;
foreach my $interface_name (sort {$a cmp $b} keys %{$anvil->data->{network}{watch_bond}}) foreach my $interface_name (sort {$a cmp $b} keys %{$anvil->data->{network}{bond}})
{ {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { interface_name => $interface_name }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { interface_name => $interface_name }});
next if $anvil->data->{network}{watch_bond}{$interface_name}{ready}; next if $anvil->data->{network}{bond}{$interface_name}{ready};
my $proc_file = $anvil->data->{path}{directories}{bonds}."/".$interface_name; my $proc_file = $anvil->data->{path}{directories}{bonds}."/".$interface_name;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { proc_file => $proc_file }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { proc_file => $proc_file }});
@ -4639,9 +4692,9 @@ sub wait_for_bonds
if ($mii_status eq "up") if ($mii_status eq "up")
{ {
# This bond is ready. # This bond is ready.
$anvil->data->{network}{watch_bond}{$interface_name}{ready} = 1; $anvil->data->{network}{bond}{$interface_name}{ready} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"network::watch_bond::${interface_name}::ready" => $anvil->data->{network}{watch_bond}{$interface_name}{ready}, "network::bond::${interface_name}::ready" => $anvil->data->{network}{bond}{$interface_name}{ready},
}}); }});
} }
else else
@ -4655,13 +4708,20 @@ sub wait_for_bonds
} }
} }
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { waiting => $waiting }});
if ($waiting) if ($waiting)
{ {
if (($end_time) && ($end_time > time)) $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { end_time => $end_time }});
if ($end_time)
{
if (time > $end_time)
{ {
# We're done. # We're done.
return(1); return(1);
} }
my $time_left = $end_time - time;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { time_left => $time_left }});
}
# Sleep for a minute # Sleep for a minute
sleep 2; sleep 2;

@ -4202,7 +4202,7 @@ sub push_file
=head2 read_config =head2 read_config
This method is used to read 'Anvil::Tools' style configuration files. These configuration files are in the format: This method is used to read C<< Anvil::Tools >> style configuration files. These configuration files are in the format:
# This is a comment for the 'a::b::c' variable # This is a comment for the 'a::b::c' variable
a::b::c = x a::b::c = x
@ -5228,6 +5228,10 @@ B<< Note >>: If the variable is not found, it is treated like an error and C<< 1
Parameters; Parameters;
=head3 append (optional, default 0)
If set to C<< 1 >>, and if the variable is not found, it will be appended to the end of the config file.
=head3 port (optional, default 22) =head3 port (optional, default 22)
If C<< target >> is set, this is the TCP port number used to connect to the remote machine. If C<< target >> is set, this is the TCP port number used to connect to the remote machine.
@ -5267,6 +5271,7 @@ sub update_config
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3; my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Storage->update_config()" }}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Storage->update_config()" }});
my $append = defined $parameter->{append} ? $parameter->{append} : 0;
my $password = defined $parameter->{password} ? $parameter->{password} : ""; my $password = defined $parameter->{password} ? $parameter->{password} : "";
my $port = defined $parameter->{port} ? $parameter->{port} : 22; my $port = defined $parameter->{port} ? $parameter->{port} : 22;
my $secure = defined $parameter->{secure} ? $parameter->{secure} : ""; my $secure = defined $parameter->{secure} ? $parameter->{secure} : "";
@ -5278,6 +5283,7 @@ sub update_config
my $update = 0; my $update = 0;
my $new_file = ""; my $new_file = "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => {
append => $append,
password => $anvil->Log->is_secure($password), password => $anvil->Log->is_secure($password),
port => $port, port => $port,
secure => $secure, secure => $secure,
@ -5342,6 +5348,18 @@ sub update_config
# Did we see the variable? # Did we see the variable?
if (not $seen) if (not $seen)
{
if ($append)
{
# Add the variable to the config file.
$new_file .= $variable."\t=\t".$value."\n";
$update = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 1, list => {
new_file => $new_file,
update => $update,
}});
}
else
{ {
if ($anvil->Network->is_local({host => $target})) if ($anvil->Network->is_local({host => $target}))
{ {
@ -5361,6 +5379,7 @@ sub update_config
return(1); return(1);
} }
} }
}
# Do we need to update the file? # Do we need to update the file?
my $error = 0; my $error = 0;

@ -224,3 +224,9 @@ sys::manage::firewall = 1
# behavious by setting this to '0'. Be aware of course that you will need to manually update or add entries # behavious by setting this to '0'. Be aware of course that you will need to manually update or add entries
# going forward. # going forward.
#sys::hosts::manage = 0 #sys::hosts::manage = 0
# During the startup of a machine, Network Manager can take a minute or two before the network is stable. By
# default, anvil-daemon and scancore will pause during startup, waiting for the network to stabilize. By
# default, Network->wait_for_bonds waits for three minutes. During the initial config, we keep this shorter.
# This value will be updated by anvil-configure-host when the initial configuration completes.
network::wait_for_bonds::timeout = 60

@ -2725,6 +2725,7 @@ The file: [#!variable!file!#] needs to be updated. The difference is:
<key name="log_0842">Starting the network manager connection: [#!variable!id!#] (uuid: [#!variable!uuid!#]).</key> <key name="log_0842">Starting the network manager connection: [#!variable!id!#] (uuid: [#!variable!uuid!#]).</key>
<key name="log_0843">Creating the: [#!variable!file!#] debug file on: [#!variable!host!#].</key> <key name="log_0843">Creating the: [#!variable!file!#] debug file on: [#!variable!host!#].</key>
<key name="log_0844">The bond interface: [#!variable!bond_name!#] is not ready yet, we'll check again shortly.</key> <key name="log_0844">The bond interface: [#!variable!bond_name!#] is not ready yet, we'll check again shortly.</key>
<key name="log_0845">No interfaces found configured for the bond: [#!variable!bond_name!#], ignoring it.</key>
<!-- Messages for users (less technical than log entries), though sometimes used for logs, too. --> <!-- 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> <key name="message_0001">The host name: [#!variable!target!#] does not resolve to an IP address.</key>

@ -68,6 +68,14 @@ if (($< != 0) && ($> != 0))
$anvil->nice_exit({exit_code => 1}); $anvil->nice_exit({exit_code => 1});
} }
# Make sure that we set the network->wait_for_bonds() timeout to 60 seconds.
$anvil->Storage->update_config({
debug => 2,
append => 1,
variable => "network::wait_for_bonds::timeout",
value => 60,
});
# Because we're working with the network config, we can't reliable use cached connections. # Because we're working with the network config, we can't reliable use cached connections.
$anvil->data->{sys}{net}{always_reconnect} = 1; $anvil->data->{sys}{net}{always_reconnect} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 1, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 1, list => {
@ -113,6 +121,14 @@ $anvil->Job->update_progress({
job_uuid => $anvil->data->{job}{uuid}, job_uuid => $anvil->data->{job}{uuid},
}); });
# Make sure that we set the network->wait_for_bonds() timeout back to 180.
$anvil->Storage->update_config({
debug => 2,
append => 1,
variable => "network::wait_for_bonds::timeout",
value => 180,
});
# Clear maintenance mode. # Clear maintenance mode.
$anvil->System->maintenance_mode({set => 0, debug => 2}); $anvil->System->maintenance_mode({set => 0, debug => 2});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, 'print' => 1, key => "log_0467"}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, 'print' => 1, key => "log_0467"});

Loading…
Cancel
Save