2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-10-20 14:45:41 +00:00

Merge pull request #7766 from VersatusHPC/refactor/routeop-helper-reuse

refactor(routeop): reuse route classification helpers
This commit is contained in:
Vinícius Ferrão
2026-08-26 11:11:44 -03:00
committed by GitHub
2 changed files with 212 additions and 21 deletions
+197
View File
@@ -0,0 +1,197 @@
#!/usr/bin/env perl
use strict;
use warnings;
use File::Spec;
use File::Temp qw(tempfile);
use FindBin;
use Test::More;
my $repo_root = File::Spec->catdir( $FindBin::Bin, '..', '..' );
my $routeop = File::Spec->catfile( $repo_root, 'xCAT', 'postscripts', 'routeop' );
my $xcatlib = File::Spec->catfile( $repo_root, 'xCAT', 'postscripts', 'xcatlib.sh' );
open( my $routeop_fh, '<', $routeop ) or die "Unable to read $routeop: $!";
my $routeop_source = do { local $/; <$routeop_fh> };
close($routeop_fh);
my ($definitions) =
$routeop_source =~ /\A(.*?)(?=^if \[ "\$op" = "add" \]; then)/ms;
BAIL_OUT('Unable to extract routeop function definitions') unless $definitions;
my ( $runner_fh, $runner ) = tempfile( UNLINK => 1 );
print {$runner_fh} $definitions;
print {$runner_fh} <<'BASH';
case "$ROUTE_TEST_ACTION" in
classify)
if is_ipv6_route "$ROUTE_TEST_NET"; then
printf '%s\n' ipv6
else
printf '%s\n' ipv4
fi
;;
prefix)
source "$ROUTE_TEST_XCATLIB"
ipv4_route_prefix "$ROUTE_TEST_MASK"
;;
route_exists)
source "$ROUTE_TEST_XCATLIB"
uname()
{
printf '%s\n' Linux
}
ip()
{
printf '%s\n' "$*" > "$ROUTE_TEST_LOG"
case "$ROUTE_TEST_SCENARIO" in
ipv4-network)
printf '%s\n' '192.0.2.0/24 via 192.0.2.1 dev eth0 proto static'
;;
ipv4-host)
printf '%s\n' '192.0.2.44 via 192.0.2.1 dev eth0 proto static'
;;
ipv4-default)
printf '%s\n' 'default via 192.0.2.1 dev eth0 proto static'
;;
ipv6-network)
printf '%s\n' '2001:db8::/64 via fe80::1 dev eth0 proto static'
;;
empty)
;;
*)
exit 2
;;
esac
}
if [ "$ROUTE_TEST_GLOBAL_IFNAME" = 1 ]; then
ifname=$ROUTE_TEST_IFNAME
route_exists "$ROUTE_TEST_NET" "$ROUTE_TEST_MASK" "$ROUTE_TEST_GW"
else
route_exists "$ROUTE_TEST_NET" "$ROUTE_TEST_MASK" "$ROUTE_TEST_GW" "$ROUTE_TEST_IFNAME"
fi
;;
*)
exit 2
;;
esac
BASH
close($runner_fh);
sub run_routeop_helper {
my (%environment) = @_;
local %ENV = ( %ENV, %environment, ROUTE_TEST_XCATLIB => $xcatlib );
open(
my $fh,
'-|',
'bash',
'--noprofile',
'--norc',
$runner,
'noop',
'192.0.2.0',
'24',
'0.0.0.0',
'eth0'
) or die "Unable to run routeop helper: $!";
my $output = do { local $/; <$fh> };
close($fh);
my $status = $? >> 8;
chomp $output;
return ( $status, $output );
}
my @classification_cases = (
[ '192.0.2.44', 'ipv4', 'IPv4 host route' ],
[ '198.51.100.0', 'ipv4', 'IPv4 network route' ],
[ 'default', 'ipv4', 'default route' ],
[ '2001:db8::44', 'ipv6', 'IPv6 host route' ],
[ '2001:db8::', 'ipv6', 'IPv6 network route' ],
[ '::1', 'ipv6', 'compressed IPv6 route' ],
[ '::ffff:192.0.2.44', 'ipv6', 'IPv4-mapped IPv6 route' ],
);
foreach my $case (@classification_cases) {
my ( $status, $family ) = run_routeop_helper(
ROUTE_TEST_ACTION => 'classify',
ROUTE_TEST_NET => $case->[0],
);
is( $status, 0, "$case->[2] classification succeeds" );
is( $family, $case->[1], "$case->[2] keeps delimiter classification" );
}
my @prefix_cases = (
[ '0', '0', 'zero prefix' ],
[ '24', '24', 'numeric prefix' ],
[ '255.255.255.0', '24', 'dotted class C mask' ],
[ '255.255.0.0', '16', 'dotted class B mask' ],
);
foreach my $case (@prefix_cases) {
my ( $status, $prefix ) = run_routeop_helper(
ROUTE_TEST_ACTION => 'prefix',
ROUTE_TEST_MASK => $case->[0],
);
is( $status, 0, "$case->[2] conversion succeeds" );
is( $prefix, $case->[1], "$case->[2] keeps its route prefix" );
}
sub route_exists_case {
my (%case) = @_;
my ( $log_fh, $log ) = tempfile( UNLINK => 1 );
close($log_fh);
my ( $status, $exists ) = run_routeop_helper(
ROUTE_TEST_ACTION => 'route_exists',
ROUTE_TEST_SCENARIO => $case{scenario},
ROUTE_TEST_NET => $case{net},
ROUTE_TEST_MASK => $case{mask},
ROUTE_TEST_GW => $case{gateway},
ROUTE_TEST_IFNAME => $case{ifname},
ROUTE_TEST_GLOBAL_IFNAME => $case{global_ifname} // 0,
ROUTE_TEST_LOG => $log,
);
open( my $log_read, '<', $log ) or die "Unable to read route query log: $!";
my $query = do { local $/; <$log_read> };
close($log_read);
chomp $query;
is( $status, 0, "$case{name} check succeeds" );
is( $exists, $case{exists}, "$case{name} existence result" );
is( $query, $case{query}, "$case{name} route query" );
}
my @route_exists_cases = (
# name, scenario, net, mask, gateway, interface, global interface, exists, query
[ 'IPv4 network route', 'ipv4-network', '192.0.2.0', '24', '192.0.2.1', 'eth0', 0, '1', 'route show 192.0.2.0/24' ],
[ 'IPv4 dotted-mask route', 'ipv4-network', '192.0.2.0', '255.255.255.0', '192.0.2.1', 'eth0', 0, '1', 'route show 192.0.2.0/24' ],
[ 'IPv4 host route', 'ipv4-host', '192.0.2.44', '32', '192.0.2.1', 'eth0', 0, '1', 'route show 192.0.2.44/32' ],
[ 'IPv4 route using the global interface', 'ipv4-network', '192.0.2.0', '24', '192.0.2.1', 'eth0', 1, '1', 'route show 192.0.2.0/24' ],
[ 'IPv4 route with a different gateway', 'ipv4-network', '192.0.2.0', '24', '192.0.2.254', 'eth0', 0, '0', 'route show 192.0.2.0/24' ],
[ 'IPv4 route with a different interface', 'ipv4-network', '192.0.2.0', '24', '192.0.2.1', 'eth1', 0, '0', 'route show 192.0.2.0/24' ],
[ 'IPv4 default route', 'ipv4-default', 'default', '0', '192.0.2.1', 'eth0', 0, '1', 'route show default' ],
[ 'IPv6 network route', 'ipv6-network', '2001:db8::', '64', 'fe80::1', 'eth0', 0, '1', '-6 route show 2001:db8::/64' ],
[ 'IPv6 device route', 'ipv6-network', '2001:db8::', '64', '', 'eth0', 0, '1', '-6 route show 2001:db8::/64' ],
[ 'missing IPv6 network route', 'empty', '2001:db8::', '64', 'fe80::1', 'eth0', 0, '0', '-6 route show 2001:db8::/64' ],
);
foreach my $case (@route_exists_cases) {
route_exists_case(
name => $case->[0],
scenario => $case->[1],
net => $case->[2],
mask => $case->[3],
gateway => $case->[4],
ifname => $case->[5],
global_ifname => $case->[6],
exists => $case->[7],
query => $case->[8],
);
}
done_testing();
+15 -21
View File
@@ -141,7 +141,7 @@ route_exists()
os_type=$(uname -s)
# ipv6
if echo $route_net | grep : 2>&1 1>/dev/null
if is_ipv6_route "$route_net"
then
result=`ip -6 route show $route_net/$route_mask`
if [ $? -ne 0 ] || [ -z "$result" ]
@@ -152,14 +152,10 @@ route_exists()
fi
else
if [ "$os_type" = "Linux" ] && command -v ip >/dev/null 2>&1; then
local route_prefix=$route_mask
local route_prefix
local line
if ! echo "$route_prefix" | grep -E "^[0123456789]+$" >/dev/null 2>&1; then
if type v4mask2prefix >/dev/null 2>&1; then
route_prefix=$(v4mask2prefix "$route_mask")
fi
fi
route_prefix=$(ipv4_route_prefix "$route_mask")
if [ "$route_net" = "default" ]; then
result=$(ip route show default 2>/dev/null)
@@ -484,7 +480,7 @@ replace_persistent_route()
case $OS_name in
sles)
filename="/etc/sysconfig/network/routes";
if echo $net | grep : 2>&1 1>/dev/null
if is_ipv6_route "$net"
then
# for ipv6
if [ "$gw" = "" -o "$gw" = "::" ] ; then
@@ -541,7 +537,7 @@ replace_persistent_route()
return $?
fi
if echo $net | grep : 2>&1 1>/dev/null
if is_ipv6_route "$net"
then
# ipv6
filename="/etc/sysconfig/network-scripts/route6-$ifname"
@@ -690,7 +686,7 @@ add_persistent_route()
#echo "sles"
# ipv6 net
filename="/etc/sysconfig/network/routes";
if echo $net | grep : 2>&1 1>/dev/null
if is_ipv6_route "$net"
then
if [ "$gw" = "" -o "$gw" = "::" ] ; then
route="$net/$mask :: - $ifname"
@@ -766,9 +762,8 @@ add_persistent_route()
echo "auto $ifname" > $filename
echo "iface $ifname inet dhcp" >> $filename
fi
echo $net | grep : 2>&1 1>/dev/null
#ipv6
if [ $? -eq 0 ];then
if is_ipv6_route "$net";then
if [ "$gw" = "" -o "$gw" = "::" ] ; then
matchstr="$net/$mask dev $ifname"
else
@@ -851,7 +846,7 @@ add_persistent_route()
return $?
fi
# ipv6 net
if echo $net | grep : 2>&1 1>/dev/null
if is_ipv6_route "$net"
then
if [ "$gw" = "" ] ; then
$gw = "::";
@@ -926,7 +921,7 @@ rm_persistent_route()
#echo "sles"
filename="/etc/sysconfig/network/routes";
# ipv6 net
if echo $net | grep : 2>&1 1>/dev/null
if is_ipv6_route "$net"
then
if [ $gw = "" -o $gw = "::" ] ; then
route="$net/$mask :: - $ifname";
@@ -969,9 +964,8 @@ rm_persistent_route()
fi
filename="/etc/network/interfaces.d/$ifname"
echo $net | grep : 2>&1 1>/dev/null
#ipv6
if [ $? -eq 0 ];then
if is_ipv6_route "$net";then
if [ $gw = "" -o $gw = "::" ] ; then
matchstr="$net/$mask dev $ifname"
else
@@ -1001,7 +995,7 @@ rm_persistent_route()
return $?
fi
#ipv6
if echo $net | grep : 2>&1 1>/dev/null
if is_ipv6_route "$net"
then
filename="/etc/sysconfig/static-routes-ipv6";
# $net/$mask does not work with sed
@@ -1054,7 +1048,7 @@ if [ "$op" = "add" ]; then
result=$(route_exists $net $mask $gw)
if [ "$result" = "0" ]; then
#ipv6
if echo $net | grep : 2>&1 1>/dev/null
if is_ipv6_route "$net"
then
if [ "$(uname -s)" = "Linux" ]; then
if [ "$gw" = "" -o "$gw" = "::" ] ; then
@@ -1096,7 +1090,7 @@ if [ "$op" = "add" ]; then
fi
else
#ipv6
if echo $net | grep : 2>&1 1>/dev/null
if is_ipv6_route "$net"
then
echo "The temporary route ($net/$mask $gw) already exists."
else
@@ -1110,7 +1104,7 @@ elif [ "$op" = "delete" ]; then
result=$(route_exists $net $mask $gw)
if [ "$result" = "1" ]; then
# ipv6
if echo $net | grep : 2>&1 1>/dev/null
if is_ipv6_route "$net"
then
if [ "$(uname -s)" = "Linux" ]; then
if [ "$gw" = "" -o "$gw" = "::" ] ; then
@@ -1159,7 +1153,7 @@ elif [ "$op" = "replace" ]; then
mask=$(v4mask2prefix $mask)
fi
if echo $net | grep : 2>&1 1>/dev/null
if is_ipv6_route "$net"
then # ipv6
if [ "$(uname -s)" = "Linux" ]; then
if [ "$gw" = "" -o "$gw" = "::" ] ; then