Skip to content

Commit

Permalink
Refactor Universal Network Bonding Test
Browse files Browse the repository at this point in the history
  • Loading branch information
volodymyrkatkalov committed Sep 5, 2024
1 parent bfd6202 commit a256e56
Show file tree
Hide file tree
Showing 3 changed files with 251 additions and 276 deletions.
199 changes: 198 additions & 1 deletion lib/network_utils.pm
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ use warnings;
use testapi;
use mm_network;

our @EXPORT = qw(setup_static_network recover_network can_upload_logs iface ifc_exists ifc_is_up genmac);
use utils qw(validate_script_output_retry);

our @EXPORT = qw(setup_static_network recover_network can_upload_logs iface ifc_exists ifc_is_up genmac cidr_to_netmask set_nics_link_speed_duplex check_connectivity_to_host_with_retry get_nics is_nm_used is_wicked_used delete_all_existing_connections create_bond add_interfaces_to_bond);

=head2 setup_static_network
Expand Down Expand Up @@ -158,4 +160,199 @@ sub genmac {
return lc(join(':', @mac));
}

=head2 cidr_to_netmask
Converts CIDR notation to a netmask string in IPv4 address format.
=cut

sub cidr_to_netmask {
my ($cidr_str) = @_;

$cidr_str =~ /(\d+)/;
my $cidr = $1;

my $binmask = '1' x $cidr . '0' x (32 - $cidr);
my @octets = unpack("C4", pack("B32", $binmask));
return join('.', @octets);
}

=head2 set_nics_link_speed_duplex
Sets the link speed, duplex settings, and autoneg status for specified NICs.
Accepts hash reference containing NICs and their settings.
set_nics_link_speed_duplex({
nics => ['eth0', 'eth1'],
speed => 1000, # Speed in Mbps
duplex => 'full', # Duplex type: 'full' or 'half'
autoneg => 'off' # Auto-negotiation: 'on' or 'off'
});
=cut

sub set_nics_link_speed_duplex {
my ($args_ref) = @_;
my @nics = @{$args_ref->{nics}};
my $speed = $args_ref->{speed} // 1000; # default speed 1000 Mbps if not specified
my $duplex = $args_ref->{duplex} // 'full'; # default to full duplex if not specified
my $autoneg = $args_ref->{autoneg} // 'off'; # default to autoneg off if not specified

for my $nic (@nics) {
record_info("SET $nic", "Setting link speed to $speed, duplex to $duplex, and autoneg to $autoneg");
script_run("ethtool -s $nic speed $speed duplex $duplex autoneg $autoneg");
}
}

=head2 check_connectivity_to_host_with_retry
Checks connectivity from a specified bonding interface to a host.
This function pings a designated host from a specified bonding interface. It uses the function
validate_script_output_retry to retry the ping command multiple times.
check_connectivity_to_host_with_retry('bond0', '192.168.1.1');
=cut

sub check_connectivity_to_host_with_retry {
my ($bond_name, $ping_host) = @_;
my $ping_command = "ping -c1 -I $bond_name $ping_host";

validate_script_output_retry(
$ping_command,
sub { m/1 packets transmitted, 1 received, 0% packet loss,/ }
);
}

=head2 get_nics
Retrieves a list of network interfaces, excluding specified ones and the loopback interface.
This function scans for network interfaces available on the system, optionally ignoring specified interfaces
and always excluding the loopback interface. It's particularly useful for scripts that need to dynamically
determine which network interfaces to operate on, allowing for exclusion of interfaces that are not of interest.
get_nics(['bond0', 'bond1']);
=cut

sub get_nics {
my ($ignore_ref) = @_;
my @ignore = @$ignore_ref;

my $command = "ip -o link show | grep -v 'lo'";

foreach my $iface (@ignore) {
$command .= " | grep -v '$iface'";
}

$command .= " | awk -F: '{print \$2}' | awk '{print \$1}'";

my $result = script_output($command, type_command => 1);

my @nics = split(/\n/, $result);

record_info(scalar(@nics) . " NICs Detected", join(', ', @nics));

return @nics;
}

=head2 is_nm_used
Check if NetworkManager service is active.
=cut

sub is_nm_used {
return script_run("systemctl is-active NetworkManager") == 0;
}

=head2 is_wicked_used
Check if wicked service is active.
=cut

sub is_wicked_used {
return script_run("systemctl is-active wicked") == 0;
}

sub delete_all_existing_connections_nm {
my $output = script_output('nmcli -g DEVICE,UUID conn show', type_command => 1);
my %seen_uuids;

foreach my $line (split "\n", $output) {
next if $line =~ /^\s*$/;

my ($device, $uuid) = split /:/, $line;
next if defined $device && $device eq 'lo';
next if exists $seen_uuids{$uuid};

$seen_uuids{$uuid} = 1;
assert_script_run "nmcli con delete uuid '$uuid'";
}
}

sub delete_all_existing_connections_wicked {
assert_script_run "wicked ifdown all";
script_run "rm -f /etc/sysconfig/network/ifcfg-*";
}

sub delete_all_existing_connections {
delete_all_existing_connections_nm() if is_nm_used();
delete_all_existing_connections_wicked() if is_wicked_used();
}

sub create_bond {
my ($bond_name, $options) = @_;
my $bond_mode = $options->{mode};
my $miimon = $options->{miimon} // 200;
my $autoconnect_slaves = $options->{autoconnect_slaves} // 1;

if (is_nm_used()) {
assert_script_run "nmcli con add type bond ifname $bond_name con-name $bond_name bond.options \"mode=$bond_mode, miimon=$miimon\"";
assert_script_run "nmcli connection modify $bond_name connection.autoconnect-slaves $autoconnect_slaves";
}

if (is_wicked_used()) {
# Remove the old configuration file if it exists
script_run "rm -f /etc/sysconfig/network/ifcfg-$bond_name";

assert_script_run "echo 'STARTMODE=auto' > /etc/sysconfig/network/ifcfg-$bond_name";
assert_script_run "echo 'BONDING_MASTER=yes' >> /etc/sysconfig/network/ifcfg-$bond_name";
assert_script_run "echo 'BONDING_SLAVE=no' >> /etc/sysconfig/network/ifcfg-$bond_name";
assert_script_run "echo 'BONDING_MODULE_OPTS=\"mode=$bond_mode miimon=$miimon\"' >> /etc/sysconfig/network/ifcfg-$bond_name";
}
}

sub add_interfaces_to_bond {
my ($bond_name, @interfaces) = @_;
if (is_nm_used()) {
foreach my $interface (@interfaces) {
assert_script_run "nmcli con add type ethernet ifname $interface master $bond_name";
}
}

if (is_wicked_used()) {
my $index = 1;

foreach my $interface (@interfaces) {
# Remove the old configuration file for the interface if it exists
script_run "rm -f /etc/sysconfig/network/ifcfg-$interface";

# Create the new configuration file for the interface
assert_script_run "echo 'BOOTPROTO=static' > /etc/sysconfig/network/ifcfg-$interface";
assert_script_run "echo 'STARTMODE=auto' >> /etc/sysconfig/network/ifcfg-$interface";
assert_script_run "echo 'BONDING_MASTER=no' >> /etc/sysconfig/network/ifcfg-$interface";
assert_script_run "echo 'BONDING_SLAVE=yes' >> /etc/sysconfig/network/ifcfg-$interface";
assert_script_run "echo 'BONDING_MASTER_IF=$bond_name' >> /etc/sysconfig/network/ifcfg-$interface";

# Append slave interfaces to the bond configuration
assert_script_run "echo 'BONDING_SLAVE_$index=$interface' >> /etc/sysconfig/network/ifcfg-$bond_name";
$index++;
}
}
}

1;
Loading

0 comments on commit a256e56

Please sign in to comment.