Skip to content

Commit

Permalink
ncm-network: nmstate improvements and add advance tests
Browse files Browse the repository at this point in the history
- fixed the way bonded interface is recognised
- add more testing for nmstate config interface config
- support to configure dhcp interface.
  • Loading branch information
Abdul Karim authored and Abdul Karim committed Jan 11, 2024
1 parent ec6caaa commit bc4b03b
Show file tree
Hide file tree
Showing 8 changed files with 261 additions and 12 deletions.
26 changes: 17 additions & 9 deletions ncm-network/src/main/perl/nmstate.pm
Original file line number Diff line number Diff line change
Expand Up @@ -310,11 +310,11 @@ sub generate_nmstate_config

my $iface = $net->{interfaces}->{$name};
my $device = $iface->{device} || $name;
my $is_eth = $iface->{set_hwaddr};
my $is_eth = $iface->{hwaddr} ? 1 : 0;
my $eth_bootproto = $iface->{bootproto};
my $is_ip = exists $iface->{ip} ? 1 : 0;
my $is_vlan_eth = exists $iface->{vlan} ? 1 : 0;
my $is_bond_eth = exists $iface->{master} ? 1 : 0;
my $is_partof_bond = exists $iface->{master} ? 1 : 0;
my $iface_changed = 0;

# create hash of interface entries that will be used by nmstate config.
Expand All @@ -323,9 +323,13 @@ sub generate_nmstate_config
$ifaceconfig->{mtu} = $iface->{mtu} if $iface->{mtu};
$ifaceconfig->{'mac-address'} = $iface->{hwaddr} if $iface->{hwaddr};
$ifaceconfig->{'profile-name'} = $name;

# this will be empty if the interface isnt a bond interface.
# we can use this to determine if this interface is bond interface.
my $bonded_eth = get_bonded_eth($self, $name, $net->{interfaces});
if ($is_eth) {
$ifaceconfig->{type} = "ethernet";
if ($is_bond_eth) {
if ($is_partof_bond) {
# no ipv4 address for bonded eth, plus in nmstate bonded eth is controlled by controller. no config is required.
$ifaceconfig->{ipv4}->{enabled} = "false";
$ifaceconfig->{state} = "up";
Expand All @@ -338,18 +342,17 @@ sub generate_nmstate_config
$ifaceconfig->{type} = "vlan";
$ifaceconfig->{vlan}->{'base-iface'} = $iface->{physdev};
$ifaceconfig->{vlan}->{'id'} = $vlan_id;
} else {
} elsif ($bonded_eth) {
# if bond device
$ifaceconfig->{type} = "bond";
$ifaceconfig->{'link-aggregation'} = $iface->{link_aggregation};
my $bonded_eth = get_bonded_eth($self, $name, $net->{interfaces});
if ($bonded_eth){
$ifaceconfig->{'link-aggregation'}->{port} = $bonded_eth;
}
}

if (defined($eth_bootproto)) {
if ($eth_bootproto eq 'static') {
if (defined($eth_bootproto) or $is_ip) {
if ((defined($eth_bootproto) and $eth_bootproto eq 'static') or $is_ip ) {
$ifaceconfig->{state} = "up";
if ($is_ip) {
# if device has manual ip assigned
Expand Down Expand Up @@ -377,8 +380,13 @@ sub generate_nmstate_config
$self->verbose("no ipv6 entries");
}
}
} elsif (($eth_bootproto eq "none") && (!$is_bond_eth)) {
# no ip on interface and is not a bond eth, assume not managed so disable eth.
} elsif (($eth_bootproto eq "dhcp") && (!$is_partof_bond)) {
# dhcp configuration
$ifaceconfig->{state} = "up";
$ifaceconfig->{ipv4}->{dhcp} = $YTRUE;
$ifaceconfig->{ipv4}->{enabled} = $YTRUE;
} elsif (($eth_bootproto eq "none") && (!$is_partof_bond)) {
# no ip on interface and is not a part of a bonded interface, assume not managed so disable eth.
$ifaceconfig->{ipv4}->{enabled} = "false";
$ifaceconfig->{ipv6}->{enabled} = "false";
$ifaceconfig->{state} = "down";
Expand Down
181 changes: 181 additions & 0 deletions ncm-network/src/test/perl/nmstate_advance.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
use strict;
use warnings;

BEGIN {
*CORE::GLOBAL::sleep = sub {};
}

use Test::More;
use Test::Quattor qw(nmstate_advance);
use Test::MockModule;
use Readonly;

use NCM::Component::nmstate;
my $mock = Test::MockModule->new('NCM::Component::nmstate');
my %executables;
$mock->mock('_is_executable', sub {diag "executables $_[1] ",explain \%executables;return $executables{$_[1]};});

my $cfg = get_config_for_profile('nmstate_advance');
my $cmp = NCM::Component::nmstate->new('network');

Readonly my $ETH0_YML => <<EOF;
# File generated by NCM::Component::nmstate. Do not edit
---
interfaces:
- ipv4:
address:
- ip: 4.3.2.1
prefix-length: 24
dhcp: false
enabled: true
mac-address: 6e:a5:1b:55:77:0a
name: eth0
profile-name: eth0
state: up
type: ethernet
route-rules:
config:
- family: ipv4
ip-to: 1.2.3.4/24
priority: 100
route-table: '4'
- route-table: '4'
state: absent
routes:
config:
- next-hop-interface: eth0
state: absent
- destination: 1.2.3.4/32
next-hop-interface: eth0
- destination: 1.2.3.5/24
next-hop-interface: eth0
- destination: 1.2.3.6/8
next-hop-address: 4.3.2.1
next-hop-interface: eth0
- destination: 1.2.3.7/32
next-hop-address: 4.3.2.2
next-hop-interface: eth0
- destination: 0.0.0.0/0
next-hop-address: 4.3.2.3
next-hop-interface: eth0
table-id: '3'
EOF

Readonly my $VLAN_YML => <<EOF;
# File generated by NCM::Component::nmstate. Do not edit
---
interfaces:
- ipv4:
address:
- ip: 4.3.2.1
prefix-length: 24
dhcp: false
enabled: true
name: eth0.123
profile-name: eth0.123
state: up
type: vlan
vlan:
base-iface: eth0
id: '123'
routes:
config:
- next-hop-interface: eth0.123
state: absent
- destination: 1.2.3.4/32
next-hop-interface: eth0.123
EOF

Readonly my $DHCP_YML => <<EOF;
# File generated by NCM::Component::nmstate. Do not edit
---
interfaces:
- ipv4:
dhcp: true
enabled: true
mac-address: 6e:a5:1b:55:77:0b
name: eth1
profile-name: eth1
state: up
type: ethernet
routes:
config:
- next-hop-interface: eth1
state: absent
EOF

Readonly my $BOND_YML => <<EOF;
# File generated by NCM::Component::nmstate. Do not edit
---
interfaces:
- ipv4:
address:
- ip: 4.3.2.1
prefix-length: 24
dhcp: false
enabled: true
link-aggregation:
port:
- eth2
- eth3
name: bond0
profile-name: bond0
state: up
type: bond
routes:
config:
- next-hop-interface: bond0
state: absent
EOF


Readonly my $RT => <<EOF;
#
# reserved values
#
255 local
254 main
253 default
0 unspec
#
# local
#
#1 inr.ruhep
EOF

Readonly my $RT_NEW => <<EOF;
#
# reserved values
#
255 local
254 main
253 default
0 unspec
#
# local
#
#1 inr.ruhep
3 outside # managed by Quattor
4 space # managed by Quattor
EOF

# File must exist, set with correct content
set_file_contents("/etc/iproute2/rt_tables", $RT);

is($cmp->Configure($cfg), 1, "Component runs correctly with a test profile");

is(get_file_contents("/etc/iproute2/rt_tables"), $RT_NEW, "Exact routing table");

my $eth0yml = get_file_contents("/etc/nmstate/eth0.yml");
is($eth0yml, $ETH0_YML, "Exact eth0 route yml config");

my $dhcpyml = get_file_contents("/etc/nmstate/eth1.yml");
is($dhcpyml, $DHCP_YML, "Exact eth1 dhcp yml config");

my $bondyml = get_file_contents("/etc/nmstate/bond0.yml");
is($bondyml, $BOND_YML, "Exact bond0 yml config");

my $vlanyml = get_file_contents("/etc/nmstate/eth0.123.yml");
is($vlanyml, $VLAN_YML, "Exact eth0.123 vlan yml config");

done_testing();
16 changes: 13 additions & 3 deletions ncm-network/src/test/perl/nmstate_simple.t
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,21 @@ Readonly my $ETH0_YML => <<EOF;
# File generated by NCM::Component::nmstate. Do not edit
---
interfaces:
- link-aggregation:
port: []
- ipv4:
address:
- ip: 4.3.2.1
prefix-length: 24
dhcp: false
enabled: true
mac-address: 6e:a5:1b:55:77:0a
name: eth0
profile-name: eth0
type: bond
state: up
type: ethernet
routes:
config:
- next-hop-interface: eth0
state: absent
EOF

Readonly my $NOTTOREMOVE => <<EOF;
Expand Down
6 changes: 6 additions & 0 deletions ncm-network/src/test/resources/bondinterface.pan
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
structure template bondinterface;

"broadcast" = '4.3.2.255';
"ip" = '4.3.2.1';
"netmask" = '255.255.255.0';
"bootproto" = 'static';
2 changes: 2 additions & 0 deletions ncm-network/src/test/resources/dhcpinterface.pan
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
structure template dhcpinterface;
"bootproto" = 'dhcp';
34 changes: 34 additions & 0 deletions ncm-network/src/test/resources/nmstate_advance.pan
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
object template nmstate_advance;

include 'simple_base_profile';
include 'components/network/config-nmstate';

# additional interface testing for nmstate.
"/system/network/interfaces/eth1" = create("dhcpinterface");
"/hardware/cards/nic/eth1/hwaddr" = "6e:a5:1b:55:77:0b";
"/system/network/interfaces/bond0" = create("bondinterface");
"/hardware/cards/nic/eth2/hwaddr" = "6e:a5:1b:55:77:0c";
"/system/network/interfaces/eth2/master" = "bond0";
"/hardware/cards/nic/eth3/hwaddr" = "6e:a5:1b:55:77:0d";
"/system/network/interfaces/eth3/master" = "bond0";

# routes and rules
prefix "/system/network/routing_table";
"outside" = 3;
"space" = 4;

prefix "/system/network/interfaces/eth0";
"route/0" = dict("address", "1.2.3.4");
"route/1" = dict("address", "1.2.3.5", "netmask", "255.255.255.0");
"route/2" = dict("address", "1.2.3.6", "netmask", "255.0.0.0", "gateway", "4.3.2.1");
"route/3" = dict("address", "1.2.3.7", "prefix", 16, "gateway", "4.3.2.2");
"route/4" = dict("address", "default", "gateway", "4.3.2.3", "table", "outside");

"rule/0" = dict("to", "1.2.3.4/24", "not", true, "table", "space");

# test vlan interface and route on vlan
"/system/network/interfaces/eth0.123" = create("vlaninterface");
"/hardware/cards/nic/eth0/hwaddr" = "6e:a5:1b:55:77:0a";
prefix "/system/network/interfaces/eth0.123";
"physdev" = "eth0";
"route/0" = dict("address", "1.2.3.4");
1 change: 1 addition & 0 deletions ncm-network/src/test/resources/nmstate_simple.pan
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
object template nmstate_simple;

include 'simple_base_profile';
"/hardware/cards/nic/eth0/hwaddr" = "6e:a5:1b:55:77:0a";
# the next include is mainly to the profile, it is not used in the tests
# (unless the component gets specific schema things)
include 'components/network/config-nmstate';
7 changes: 7 additions & 0 deletions ncm-network/src/test/resources/vlaninterface.pan
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
structure template vlaninterface;

"broadcast" = '4.3.2.255';
"ip" = '4.3.2.1';
"netmask" = '255.255.255.0';
"bootproto" = 'static';
"vlan" = true;

0 comments on commit bc4b03b

Please sign in to comment.