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 9 months ago
parent d5ceca3dc6
commit 6a193bf710
  1. 1
      Anvil/Tools/Get.pm
  2. 100
      Anvil/Tools/Network.pm
  3. 43
      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'
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}{vv} = "#!SET!#";

@ -4517,9 +4517,9 @@ B<< Note >>: This method only works on Network Manager based systems.
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
sub wait_for_bonds
@ -4530,11 +4530,18 @@ sub wait_for_bonds
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()" }});
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 => {
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};
$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});
$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 $parent_bond = "";
foreach my $line (split/\n/, $file_body)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { line => $line }});
if ($line =~ /^type=bond/)
if ($line =~ /^type=(.*)$/)
{
$is_bond = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { is_bond => $is_bond }});
$type = $1;
$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=(.*)$/)
{
@ -4584,17 +4597,53 @@ sub wait_for_bonds
}
}
if (($is_bond) && ($interface_name))
if (($type eq "bond") && ($interface_name))
{
$anvil->data->{network}{watch_bond}{$interface_name}{ready} = 0;
$anvil->data->{network}{bond}{$interface_name}{ready} = 0;
$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},
}});
}
if (($type eq "ethernet") && ($parent_bond))
{
$anvil->data->{network}{ethernet}{$interface_name}{parent_bond} = $parent_bond;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"network::ethernet::${interface_name}::parent_bond" => $anvil->data->{network}{ethernet}{$interface_name}{parent_bond},
}});
}
}
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 }});
if (not $bond_count)
{
@ -4602,15 +4651,19 @@ sub wait_for_bonds
}
my $waiting = 1;
my $end_time = $timeout ? time + $timeout : 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { end_time => $end_time }});
my $end_time = $timeout ? time + $timeout : 0;
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)
{
$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 }});
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;
$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")
{
# 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 => {
"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
@ -4655,12 +4708,19 @@ sub wait_for_bonds
}
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { waiting => $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)
{
# We're done.
return(1);
if (time > $end_time)
{
# We're done.
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

@ -4202,7 +4202,7 @@ sub push_file
=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
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;
=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)
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;
$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 $port = defined $parameter->{port} ? $parameter->{port} : 22;
my $secure = defined $parameter->{secure} ? $parameter->{secure} : "";
@ -5278,6 +5283,7 @@ sub update_config
my $update = 0;
my $new_file = "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => {
append => $append,
password => $anvil->Log->is_secure($password),
port => $port,
secure => $secure,
@ -5343,22 +5349,35 @@ sub update_config
# Did we see the variable?
if (not $seen)
{
if ($anvil->Network->is_local({host => $target}))
if ($append)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0174", variables => {
variable => $variable,
file => $anvil->data->{path}{configs}{'anvil.conf'},
# 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,
}});
return(1);
}
else
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0175", variables => {
variable => $variable,
file => $anvil->data->{path}{configs}{'anvil.conf'},
target => $target,
}});
return(1);
if ($anvil->Network->is_local({host => $target}))
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0174", variables => {
variable => $variable,
file => $anvil->data->{path}{configs}{'anvil.conf'},
}});
return(1);
}
else
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0175", variables => {
variable => $variable,
file => $anvil->data->{path}{configs}{'anvil.conf'},
target => $target,
}});
return(1);
}
}
}

@ -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
# going forward.
#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_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_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. -->
<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});
}
# 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.
$anvil->data->{sys}{net}{always_reconnect} = 1;
$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},
});
# 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.
$anvil->System->maintenance_mode({set => 0, debug => 2});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, 'print' => 1, key => "log_0467"});

Loading…
Cancel
Save