Skip to content

Commit

Permalink
Extension proposition
Browse files Browse the repository at this point in the history
  • Loading branch information
volodymyrkatkalov committed Aug 22, 2024
1 parent 7963747 commit 45e2ab2
Showing 1 changed file with 142 additions and 29 deletions.
171 changes: 142 additions & 29 deletions tests/microos/network_bonding.pm
Original file line number Diff line number Diff line change
Expand Up @@ -11,45 +11,158 @@ use strict;
use warnings;
use testapi;
use power_action_utils "power_action";
use serial_terminal qw(select_serial_terminal);

sub check_connectivity {
my ($bond_name) = @_;
my $ping_host = "conncheck.opensuse.org";
my $ping_command = "ping -c1 -I $bond_name $ping_host";
assert_script_run $ping_command;
}

sub get_nics {
my ($bond_name) = @_;
my @devices;

foreach my $line (split('\n', script_output('nmcli -g DEVICE conn show'))) {
# Skip empty lines
next if $line =~ /^\s*$/;

# Skip the loopback device and the bond interface
next if $line eq 'lo';
next if $line eq $bond_name;

# Add valid device names to the array
push @devices, $line;
}

return @devices;
}

sub delete_existing_connections {
my $output = script_output('nmcli -g DEVICE,UUID conn show');
my %seen_uuids; # Hash to keep track of processed UUIDs

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

my ($device, $uuid) = split /:/, $line;

# Skip loopback device
next if defined $device && $device eq 'lo';

# Check if the UUID has been seen before, then skip to the next iteration
if ($seen_uuids{$uuid}) {
next;
}

# Mark the UUID as seen by incrementing its value in the hash
$seen_uuids{$uuid} = 1;

# Delete the connection if UUID is present and not already processed
script_run "nmcli con delete uuid '$uuid'";
}
}

sub create_bond {
my ($bond_name, $bond_mode, $miimon) = @_;
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 1";
}

sub add_devices_to_bond {
my ($bond_name, @devices) = @_;
foreach my $device (@devices) {
assert_script_run "nmcli con add type ethernet ifname $device master $bond_name";
}
}

sub test_failover {
my $device = shift;
# disable one child eth, other should keep bond0 alive
my ($bond_mode, $bond_name, $device, $description, $delay, $nics_ref) = @_;
my @nics_status = map { [$_, $_ eq $device ? 0 : 1] } @$nics_ref;

record_info("Testing Failover for Mode: $bond_mode", "NIC: $device");

assert_script_run "ip link set dev $device down";
sleep $delay;
script_run 'ip a';
# networking should be still good
assert_script_run 'ping -c1 -I bond0 conncheck.opensuse.org';
# bring back up device

# Validate bond mode and NIC statuses (the downed NIC should be "down")
validate_bond_mode_and_slaves($bond_name, $description, \@nics_status);

check_connectivity $bond_name;

assert_script_run "ip link set dev $device up";
}

sub run {
my ($self) = @_;
select_console 'root-console';
my @devices;
# many device can share the same id, so we'll use hash keys to dedup
my %connections;
# remove existing NM-managed connections (except loopback).
foreach (split('\n', script_output 'nmcli -g DEVICE,UUID conn show --active')) {
next if /^lo:/; # skip loopback device
my @item = split /:/;
push @devices, $item[0];
$connections{$item[1]} = 1;
sub validate_bond_mode_and_slaves {
my ($bond_name, $description, $devices_ref) = @_;

assert_script_run "cat /proc/net/bonding/$bond_name | grep 'Mode:' | grep '$description'";

foreach my $device_info (@$devices_ref) {
my ($device, $status_up) = @$device_info;

my $expected_status = $status_up ? 'up' : 'down';

assert_script_run "grep -A 1 'Slave Interface: $device' /proc/net/bonding/$bond_name | grep 'MII Status: $expected_status'";
}
assert_script_run "nmcli con delete '$_'" for keys %connections;
# create a new bonding interface and connect the two ethernet
assert_script_run "nmcli con add type bond ifname bond0 con-name bond0";
assert_script_run "nmcli con add type ethernet ifname $_ master bond0" for @devices;
# bring up bond interface
assert_script_run "nmcli con up bond0";
# reboot to ensure connection properly comes up at start
}

sub test_bonding_mode {
my ($self, $nics_ref, $miimon, $bond_name, $bond_mode, $description, $run_failover) = @_;
my @nics = @$nics_ref;

select_serial_terminal;

delete_existing_connections;

create_bond($bond_name, $bond_mode, $miimon);
add_devices_to_bond($bond_name, @nics);

assert_script_run "nmcli con up $bond_name";

power_action('reboot', textmode => 1);
$self->wait_boot;
select_console 'root-console';
# first connectivity check
assert_script_run 'ping -c1 -I bond0 conncheck.opensuse.org';
# check device failover
test_failover $_ for @devices;
select_serial_terminal;
check_connectivity $bond_name;

# Validate that all NICs are "up"
validate_bond_mode_and_slaves($bond_name, $description, [map { [$_, 1] } @nics]);

# Testing failover for each NIC
$run_failover && test_failover($bond_mode, $bond_name, $_, $description, (($miimon / 1000) + 5), \@nics) for @nics;

delete_existing_connections;
}

sub run {
my ($self) = @_;

my $bond_name = "bond0";
my $miimon = 200;
my @nics = get_nics($bond_name);

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

my @bond_modes = (
['balance-rr', 'load balancing (round-robin)', 1],
['active-backup', 'fault-tolerance (active-backup)', 1],
['balance-xor', 'load balancing (xor)', 0],
['broadcast', 'fault-tolerance (broadcast)', 1],

# For mode=802.3ad|balance-tlb|balance-alb the switch must have support for mode and it has to be enabled on the switch
# ['802.3ad', '802.3ad', 1],
# ['balance-tlb', 'balance-tlb', 1],
# ['balance-alb', 'balance-alb', 1]
);

foreach my $mode_info (@bond_modes) {
my ($bond_mode, $description, $run_failover) = @$mode_info;
record_info("Testing Bonding Mode: $bond_mode", $description);
test_bonding_mode($self, \@nics, $miimon, $bond_name, $bond_mode, $description, $run_failover);
}
}

1;

0 comments on commit 45e2ab2

Please sign in to comment.