Reworked Network->wait_for_bonds() to be ->wait_for_networks()

* Renamed the old ->wait_for_networks() to be ->wait_for_nm_online().
* The new ->wait_for_networks() waits for all interfaces we manage to be
  'activated' before returning.

Signed-off-by: digimer <mkelly@alteeve.ca>
main
digimer 10 months ago
parent fe2806b5df
commit ab0b1a262b
  1. 210
      Anvil/Tools/Network.pm
  2. 4
      anvil.conf
  3. 8
      tools/anvil-configure-host
  4. 2
      tools/anvil-daemon
  5. 2
      tools/scancore

@ -35,8 +35,8 @@ my $THIS_FILE = "Network.pm";
# ping # ping
# read_nmcli # read_nmcli
# reset_connection # reset_connection
# wait_for_bonds
# wait_for_network # wait_for_network
# wait_on_nm_online
# _check_firewalld_conf # _check_firewalld_conf
# _get_existing_zone_interfaces # _get_existing_zone_interfaces
# _get_server_ports # _get_server_ports
@ -4510,9 +4510,11 @@ sub reset_connection
} }
=head2 wait_for_bonds =head2 wait_for_network
This method checks for Network Manager configurations. Any that are found that belong to the Anvil![1] will be watched until their state is C<< activated >>.
This method checks for Network Manager bond configurations. If they're found, this method will hold. When at least one interface in each bond is up, this method returns with C<< 0 >>. If no bonds are found, this also returns with C<< 0 >>. B<<Note>>: 1. Interfaces with device name starting with C<< bcnX_ >>, C<< ifnX_ >>, C<< snX_ >>, or C<< mnX_ >>, where C<< X >> is an integer
B<< Note >>: This method only works on Network Manager based systems. B<< Note >>: This method only works on Network Manager based systems.
@ -4523,13 +4525,13 @@ Parameters;
By default, this method will wait for five 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. By default, this method will wait for five 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_network
{ {
my $self = shift; my $self = shift;
my $parameter = shift; my $parameter = shift;
my $anvil = $self->parent; my $anvil = $self->parent;
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_network()" }});
### TODO: all configured bonds and slaved interfaces should be 'activated' before this returns, even if their cable is out. Wait for this, with a default 300s timeout. ### TODO: all configured bonds and slaved interfaces should be 'activated' before this returns, even if their cable is out. Wait for this, with a default 300s timeout.
my $timeout = defined $parameter->{timeout} ? $parameter->{timeout} : 300; my $timeout = defined $parameter->{timeout} ? $parameter->{timeout} : 300;
@ -4537,15 +4539,19 @@ sub wait_for_bonds
timeout => $timeout, timeout => $timeout,
}}); }});
# If timeout wasn't set, but network::wait_for_bonds::timeout is set, use it. # If timeout wasn't set, but network::wait_for_network::timeout is set, use it.
if ((exists $anvil->data->{network}{wait_for_bonds}{timeout}) && ($anvil->data->{network}{wait_for_bonds}{timeout} =~ /^\d+$/)) if ((exists $anvil->data->{network}{wait_for_network}{timeout}) && ($anvil->data->{network}{wait_for_network}{timeout} =~ /^\d+$/))
{ {
$timeout = $anvil->data->{network}{wait_for_bonds}{timeout}; $timeout = $anvil->data->{network}{wait_for_network}{timeout};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { timeout => $timeout }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { timeout => $timeout }});
} }
my $directory = $anvil->data->{path}{directories}{NetworkManager}; my $short_host_name = $anvil->Get->short_host_name();
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { directory => $directory }}); my $directory = $anvil->data->{path}{directories}{NetworkManager};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
short_host_name => $short_host_name,
directory => $directory,
}});
if (not -d $directory) if (not -d $directory)
{ {
@ -4570,87 +4576,95 @@ 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 $uuid = "";
my $type = ""; my $type = "";
my $interface_name = ""; my $interface_name = "";
my $id = "";
my $parent_bond = ""; 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 }});
# Collect the UUID
if ($line =~ /^uuid=(.*)$/)
{
$uuid = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { uuid => $uuid }});
}
# ethernet, bond, or bridge
if ($line =~ /^type=(.*)$/) if ($line =~ /^type=(.*)$/)
{ {
$type = $1; $type = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { type => $type }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { type => $type }});
} }
# Get the device name
if ($line =~ /^interface-name=(.*)$/)
{
$interface_name = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { interface_name => $interface_name }});
}
if ($line =~ /id=(.*)$/)
{
$id = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { id => $id }});
}
# Find the parent bond, if this is a child interface
if ($line =~ /^master=(.*)$/) if ($line =~ /^master=(.*)$/)
{ {
$parent_bond = $1; $parent_bond = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { parent_bond => $parent_bond }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { parent_bond => $parent_bond }});
} }
if ($line =~ /^interface-name=(.*)$/) }
if ($uuid)
{
# If the interface_name is multiple names, pull our the name we use (if name)
if ((not $interface_name) && ($id))
{ {
$interface_name = $1; $interface_name = $1;
$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 }});
} }
if ((not $interface_name) && ($line =~ /id=(.*)$/))
if ($interface_name =~ /;/)
{ {
$interface_name = $1; $interface_name =~ s/;$//;
$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 }});
foreach my $this_interface_name (split/;/, $interface_name)
{
if (($this_interface_name =~ /^bcn\d+_/) or
($this_interface_name =~ /^ifn\d+_/) or
($this_interface_name =~ /^sn\d+_/) or
($this_interface_name =~ /^mn\d+_/))
{
$interface_name = $this_interface_name;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { interface_name => $interface_name }});
}
}
} }
} next if not $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}{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);
# 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) # Is this an interface we care about?
if (($interface_name =~ /^bcn\d+_/) or
($interface_name =~ /^ifn\d+_/) or
($interface_name =~ /^sn\d+_/) or
($interface_name =~ /^mn\d+_/))
{ {
# We've got an interface. # Watch for this interface
$interface_found = 1; $anvil->data->{network}{watch}{$interface_name}{uuid} = $uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { interface_found => $interface_found }}); $anvil->data->{network}{watch}{$interface_name}{type} = $type;
$anvil->data->{network}{watch}{$interface_name}{ready} = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"network::watch::${interface_name}::uuid" => $anvil->data->{network}{watch}{$interface_name}{uuid},
"network::watch::${interface_name}::type" => $anvil->data->{network}{watch}{$interface_name}{type},
}});
} }
} }
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)
{
return(0);
} }
closedir(DIRECTORY);
my $waiting = 1; my $waiting = 1;
my $end_time = $timeout ? time + $timeout : 0; my $end_time = $timeout ? time + $timeout : 0;
@ -4661,52 +4675,30 @@ sub wait_for_bonds
}}); }});
while($waiting) while($waiting)
{ {
$anvil->Network->read_nmcli({
debug => $debug,
host => $short_host_name,
});
$waiting = 0; $waiting = 0;
foreach my $interface_name (sort {$a cmp $b} keys %{$anvil->data->{network}{bond}}) foreach my $interface_name (sort {$a cmp $b} keys %{$anvil->data->{network}{watch}})
{ {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { interface_name => $interface_name }}); next if $anvil->data->{network}{watch}{$interface_name}{ready};
next if $anvil->data->{network}{bond}{$interface_name}{ready}; my $uuid = $anvil->data->{network}{watch}{$interface_name}{uuid};
my $type = $anvil->data->{network}{watch}{$interface_name}{type};
my $proc_file = $anvil->data->{path}{directories}{bonds}."/".$interface_name; my $state = $anvil->data->{nmcli}{$short_host_name}{uuid}{$uuid}{'state'};
$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 => {
's1:interface_name' => $interface_name,
if (not -f $proc_file) 's2:type' => $type,
{ 's3:uuid' => $uuid,
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0844", variables => { bond_name => $interface_name }}); 's4:state' => $state,
}});
$waiting = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { waiting => $waiting }});
next;
}
my $file_body = $anvil->Storage->read_file({debug => $debug, file => $proc_file});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { file_body => $file_body }});
foreach my $line (split/\n/, $file_body) if (($state eq "activated") or ($state == 1))
{ {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { line => $line }}); $anvil->data->{network}{watch}{$interface_name}{ready} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
if ($line =~ /MII Status: (.*)$/) "network::watch::${interface_name}::ready" => $anvil->data->{network}{watch}{$interface_name}{ready},
{ }});
my $mii_status = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { mii_status => $mii_status }});
if ($mii_status eq "up")
{
# This bond is ready.
$anvil->data->{network}{bond}{$interface_name}{ready} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"network::bond::${interface_name}::ready" => $anvil->data->{network}{bond}{$interface_name}{ready},
}});
}
else
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0844", variables => { bond_name => $interface_name }});
$waiting = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { waiting => $waiting }});
}
last;
}
} }
} }
@ -4726,8 +4718,8 @@ sub wait_for_bonds
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { time_left => $time_left }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { time_left => $time_left }});
} }
# Sleep for a minute # Sleep for a few seconds.
sleep 2; sleep 5;
} }
} }
@ -4735,7 +4727,7 @@ sub wait_for_bonds
} }
=head2 wait_for_network =head2 wait_on_nm_online
This method calls C<< nm-online --wait-for-startup --timeout X >>, which in turn waits for Network Manager to report C<< startup complete >> in the journald logs. The default timeout used here is C<< 120 >> seconds (as opposed to the default of C<< 30 >> used by C<< nm-online >> itself). This method calls C<< nm-online --wait-for-startup --timeout X >>, which in turn waits for Network Manager to report C<< startup complete >> in the journald logs. The default timeout used here is C<< 120 >> seconds (as opposed to the default of C<< 30 >> used by C<< nm-online >> itself).
@ -4756,13 +4748,13 @@ Parameters;
By default, this method will wait for two 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. By default, this method will wait for two 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_network sub wait_on_nm_online
{ {
my $self = shift; my $self = shift;
my $parameter = shift; my $parameter = shift;
my $anvil = $self->parent; my $anvil = $self->parent;
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_network()" }}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Network->wait_on_nm_online()" }});
my $timeout = defined $parameter->{timeout} ? $parameter->{timeout} : 120; my $timeout = defined $parameter->{timeout} ? $parameter->{timeout} : 120;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {

@ -227,6 +227,6 @@ sys::manage::firewall = 1
# During the startup of a machine, Network Manager can take a minute or two before the network is stable. By # 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, anvil-daemon and scancore will pause during startup, waiting for the network to stabilize. By
# default, Network->wait_for_bonds waits for five minutes. During the initial config, we keep this shorter. # default, Network->wait_for_network waits for five minutes. During the initial config, we keep this shorter.
# This value will be updated by anvil-configure-host when the initial configuration completes. # This value will be updated by anvil-configure-host when the initial configuration completes.
network::wait_for_bonds::timeout = 300 network::wait_for_network::timeout = 300

@ -68,10 +68,10 @@ 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. # Make sure that we set the network->wait_on_network() timeout to 60 seconds.
$anvil->Storage->update_config({ $anvil->Storage->update_config({
append => 1, append => 1,
variable => "network::wait_for_bonds::timeout", variable => "network::wait_on_network::timeout",
value => 60, value => 60,
}); });
@ -119,10 +119,10 @@ $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. # Make sure that we set the network->wait_on_network() timeout back to 180.
$anvil->Storage->update_config({ $anvil->Storage->update_config({
append => 1, append => 1,
variable => "network::wait_for_bonds::timeout", variable => "network::wait_on_network::timeout",
value => 180, value => 180,
}); });

@ -71,7 +71,7 @@ $anvil->System->_check_anvil_conf();
$anvil->System->wait_on_dnf(); $anvil->System->wait_on_dnf();
# If we've got bonds, wait for them to be up. Then wait for NetworkManager to be up. # If we've got bonds, wait for them to be up. Then wait for NetworkManager to be up.
$anvil->Network->wait_for_bonds({debug => 2}); $anvil->Network->wait_on_nm_online({debug => 2});
$anvil->Network->wait_for_network({debug => 2}); $anvil->Network->wait_for_network({debug => 2});
# Connect to the database(s). If we have no connections, we'll proceed anyway as one of the 'run_once' tasks # Connect to the database(s). If we have no connections, we'll proceed anyway as one of the 'run_once' tasks

@ -71,7 +71,7 @@ $anvil->Storage->read_config();
$anvil->System->wait_on_dnf(); $anvil->System->wait_on_dnf();
# If we've got bonds, wait for them to be up. Then wait for NetworkManager to be up. # If we've got bonds, wait for them to be up. Then wait for NetworkManager to be up.
$anvil->Network->wait_for_bonds({debug => 2}); $anvil->Network->wait_on_nm_online({debug => 2});
$anvil->Network->wait_for_network({debug => 2}); $anvil->Network->wait_for_network({debug => 2});
# Read switches # Read switches

Loading…
Cancel
Save