From 2652cb152f849998f9c4eaff85b0a29259423063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?= <2031761+viniciusferrao@users.noreply.github.com> Date: Mon, 14 Sep 2026 23:15:14 -0300 Subject: [PATCH] feat(openeuler): use native NetworkManager configuration Reuse NetworkManager for persistent routes, bond setup and connection properties on openEuler. Preserve ifcfg handling where the connection still uses it. Propagate route failures to local callers. --- xCAT-server/lib/xcat/plugins/route.pm | 32 +++++++++++++++++++++++++++ xCAT/postscripts/configbond | 19 +++++++++++++++- xCAT/postscripts/configeth | 6 ++--- xCAT/postscripts/confignetwork | 2 +- xCAT/postscripts/nicutils.sh | 24 +++++++++++--------- xCAT/postscripts/routeop | 13 +++++++++++ xCAT/postscripts/xcatlib.sh | 25 +++++++++++++++++++++ 7 files changed, 106 insertions(+), 15 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/route.pm b/xCAT-server/lib/xcat/plugins/route.pm index 6f09dda18..25007efd3 100644 --- a/xCAT-server/lib/xcat/plugins/route.pm +++ b/xCAT-server/lib/xcat/plugins/route.pm @@ -597,6 +597,30 @@ sub route_exists { return 0; } +sub run_routeop { + my ($callback, $op, $net, $mask, $gw_ip, $ifname) = @_; + my $installdir = xCAT::TableUtils->getInstallDir(); + my $host = hostname(); + my $result = eval { + xCAT::Utils::runcmd3(command => [ + "$installdir/postscripts/routeop", $op, $net, $mask, + $gw_ip // '', $ifname // '' + ]); + }; + if (!$result) { + $callback->({ error => ["$host: Unable to run routeop: $@"] }); + return 1; + } + if ($result->{output}) { + $callback->({ data => [map { "$host: $_" } split(/\n/, $result->{output})] }); + } + if ($result->{exitcode}) { + $callback->({ error => ["$host: routeop failed with exit code $result->{exitcode}: " . ($result->{errors} // '')] }); + return 1; + } + return 0; +} + # sets the route with given parameters sub set_route { my $callback = shift; @@ -606,6 +630,10 @@ sub set_route { my $gw = shift; my $ifname = shift; + if (xCAT::Utils->isLinux() && xCAT::Utils->osver() =~ /^openeuler/) { + return run_routeop($callback, "add", $net, $mask, $gw_ip, $ifname); + } + my $host = hostname(); #print "set_route get called\n"; @@ -694,6 +722,10 @@ sub delete_route { my $gw = shift; my $ifname = shift; + if (xCAT::Utils->isLinux() && xCAT::Utils->osver() =~ /^openeuler/) { + return run_routeop($callback, "delete", $net, $mask, $gw_ip, $ifname); + } + my $host = hostname(); #print "delete_route get called\n"; diff --git a/xCAT/postscripts/configbond b/xCAT/postscripts/configbond index af5a921e8..0ab708c48 100755 --- a/xCAT/postscripts/configbond +++ b/xCAT/postscripts/configbond @@ -68,7 +68,7 @@ str_cfg_dir='' str_temp='' if [ "$str_os_type" = "linux" ];then str_temp=`echo $OSVER | grep -E '(sles|suse)'` - if [ -f "/etc/redhat-release" ];then + if [ -f "/etc/redhat-release" ] || xcat_is_openeuler "$OSVER"; then str_os_type="redhat" str_cfg_dir="/etc/sysconfig/network-scripts" elif [ -f "/etc/SuSE-release" -o -n "$str_temp" ];then @@ -191,6 +191,23 @@ fi showmsg "IP information for $str_bond_name: IP=$str_bond_ip; network=$str_bond_net; netmask=$str_bond_mask" +if xcat_is_openeuler "$OSVER"; then + . "$str_dir_name/nicutils.sh" + check_NetworkManager_or_network_service + if [ $? -ne 1 ]; then + showmsg "NetworkManager must be active to configure a bond on openEuler" "error" + exit 1 + fi + networkmanager_active=1 + str_bond_ports=$(IFS=,; echo "${array_bond_slaves[*]}") + str_bond_options=${array_bond_opts[*]} + create_bond_interface_nmcli "bondname=$str_bond_name" \ + "slave_ports=$str_bond_ports" "slave_type=ethernet" \ + "_ipaddr=$str_bond_ip" "_netmask=$str_bond_mask" \ + "_bonding_opts=${str_bond_options// /,}" + exit $? +fi + # Create bond config file str_master_file="${str_cfg_dir}/ifcfg-${str_bond_name}" diff --git a/xCAT/postscripts/configeth b/xCAT/postscripts/configeth index 079a732a6..319b7c5bd 100755 --- a/xCAT/postscripts/configeth +++ b/xCAT/postscripts/configeth @@ -543,7 +543,7 @@ function configipv4(){ do name="${array_extra_param_names[$i]}" value="${array_extra_param_values[$i]}" - if xcat_is_el9_or_later "$OSVER"; then + if xcat_uses_nm_keyfile "$OSVER" "$con_name"; then # Best-effort: apply as a native NetworkManager property if one exists. # Arbitrary ifcfg-style keys (e.g. CONNECTED_MODE) have no NM setting and # are (re)persisted into the keyfile [user] section after ALL IPs are @@ -1220,7 +1220,7 @@ elif [ "$1" = "-s" ];then do name="${array_extra_param_names[$i]}" value="${array_extra_param_values[$i]}" - if xcat_is_el9_or_later "$OSVER"; then + if xcat_uses_nm_keyfile "$OSVER" "$con_name"; then nmcli con modify $con_name $name $value else echo "$i: name=$name value=$value" @@ -1732,7 +1732,7 @@ fi # in-memory model and drops anything NM does not model, so an earlier write would be lost. # On EL10 (keyfile-only) there is no ifcfg file to hold these. We do NOT reload after, so # the file keeps the section; NM tolerates an unknown [user] section in keyfile mode. -if [ "$str_os_type" = "redhat" ] && [ "$networkmanager_active" = "1" ] && xcat_is_el9_or_later "$OSVER"; then +if [ "$str_os_type" = "redhat" ] && [ "$networkmanager_active" = "1" ] && xcat_uses_nm_keyfile "$OSVER" "$con_name"; then # Resolve the connection's keyfile by UUID -- NM may name it "-.nmconnection" # (not the plain ".nmconnection") when a same-named file already exists. ep_con="xcat-${str_nic_name}" diff --git a/xCAT/postscripts/confignetwork b/xCAT/postscripts/confignetwork index f2586d456..95763efdf 100755 --- a/xCAT/postscripts/confignetwork +++ b/xCAT/postscripts/confignetwork @@ -38,7 +38,7 @@ is_redhat=0 is_debian=0 is_sles=0 str_temp=`echo $OSVER | grep -E '(sles|suse)'` -if [ -f "/etc/redhat-release" ];then +if [ -f "/etc/redhat-release" ] || xcat_is_openeuler "$OSVER"; then is_redhat=1 nwdir="/etc/sysconfig/network-scripts" elif [ -f "/etc/SuSE-release" -o -n "$str_temp" ];then diff --git a/xCAT/postscripts/nicutils.sh b/xCAT/postscripts/nicutils.sh index c70615ab7..6768bd025 100755 --- a/xCAT/postscripts/nicutils.sh +++ b/xCAT/postscripts/nicutils.sh @@ -1841,7 +1841,7 @@ function add_extra_params_nmcli { con_name=$2 rc=0 - if ! xcat_is_el9_or_later "$OSVER"; then + if ! xcat_uses_nm_keyfile "$OSVER" "$con_name"; then str_conf_file="/etc/sysconfig/network-scripts/ifcfg-${con_name}" str_conf_file_1="/etc/sysconfig/network-scripts/ifcfg-${con_name}-1" if [ -f $str_conf_file_1 ]; then @@ -1862,7 +1862,7 @@ function add_extra_params_nmcli { if [ -n "$name" -a -n "$value" ]; then # For RHEL 9, use nmcli directly, otherwise use ifcfg scheme. - if xcat_is_el9_or_later "$OSVER"; then + if xcat_uses_nm_keyfile "$OSVER" "$con_name"; then nmcli con modify "$con_name" "$name" "$value" rc+=$? else @@ -1881,7 +1881,7 @@ function add_extra_params_nmcli { i=$((i+1)) done - if ! xcat_is_el9_or_later "$OSVER"; then + if ! xcat_uses_nm_keyfile "$OSVER" "$con_name"; then $nmcli con reload $str_conf_file fi return $rc @@ -2170,6 +2170,8 @@ function create_bond_interface_nmcli { key=$(echo "$1" | $cut -s -d= -f1) if [ "$key" = "bondname" ] || \ [ "$key" = "_ipaddr" ] || \ + [ "$key" = "_netmask" ] || \ + [ "$key" = "_bonding_opts" ] || \ [ "$key" = "slave_ports" ] || \ [ "$key" = "next_nic" ] || \ [ "$key" = "slave_type" ]; then @@ -2180,12 +2182,12 @@ function create_bond_interface_nmcli { if [ "$slave_type" = "ethernet" ]; then slave_type="Ethernet" # - "802.3ad" mode requires a switch that is 802.3ad compliant. - _bonding_opts="mode=802.3ad,miimon=100" + _bonding_opts=${_bonding_opts:-mode=802.3ad,miimon=100} elif [ "$slave_type" = "infiniband" ]; then slave_type="Infiniband" - _bonding_opts="mode=1,miimon=100,fail_over_mac=1" + _bonding_opts=${_bonding_opts:-mode=1,miimon=100,fail_over_mac=1} else - _bonding_opts="mode=active-backup" + _bonding_opts=${_bonding_opts:-mode=active-backup} fi if [ -n "$_ipaddr" ]; then # query "nicnetworks" table about its target "xcatnet" @@ -2199,10 +2201,12 @@ function create_bond_interface_nmcli { fi # Query mask value from "networks" table - _netmask=$(get_network_attr $xcatnet mask) - if [ $? -ne 0 ]; then - log_error "No valid netmask get for $bondname" - return 1 + if [ -z "$_netmask" ]; then + _netmask=$(get_network_attr $xcatnet mask) + if [ $? -ne 0 ]; then + log_error "No valid netmask get for $bondname" + return 1 + fi fi # Calculate prefix based on mask diff --git a/xCAT/postscripts/routeop b/xCAT/postscripts/routeop index 8cf93e33b..5add370d0 100755 --- a/xCAT/postscripts/routeop +++ b/xCAT/postscripts/routeop @@ -1048,6 +1048,19 @@ rm_persistent_route() +if command -v xcat_is_openeuler >/dev/null 2>&1 && xcat_is_openeuler "$OSVER"; then + case "$op" in + add|delete|replace) + nmcli_persistent_route "$op" "$net" "$mask" "$gw" "$ifname" + route_rc=$? + [ $route_rc -eq 0 ] || exit $route_rc + route_dev=$(route_ifname "$net" "$gw" "$ifname") + nmcli device reapply "$route_dev" + exit $? + ;; + esac +fi + if [ "$op" = "add" ]; then result=$(route_exists $net $mask $gw) if [ "$result" = "0" ]; then diff --git a/xCAT/postscripts/xcatlib.sh b/xCAT/postscripts/xcatlib.sh index b06838589..df43b2520 100755 --- a/xCAT/postscripts/xcatlib.sh +++ b/xCAT/postscripts/xcatlib.sh @@ -23,6 +23,31 @@ xcat_is_el9_or_later() [[ "$1" =~ ^(rhel|rhels|alma|almalinux|rocky|centos|ol)(9|1[0-9]) ]] } +xcat_is_openeuler() +{ + case "$1" in + openeuler*) return 0 ;; + ?*) return 1 ;; + esac + grep -Eq '^ID="?openEuler"?$' /etc/os-release 2>/dev/null +} + +xcat_uses_nm_keyfile() +{ + xcat_is_el9_or_later "$1" && return 0 + [ "$networkmanager_active" = "1" ] && xcat_is_openeuler "$1" || return 1 + local uuid + local filename + uuid=$(nmcli -g connection.uuid connection show "$2" 2>/dev/null) + [ -n "$uuid" ] || return 1 + filename=$(nmcli -t -f UUID,FILENAME connection show 2>/dev/null | sed -n "s/^$uuid://p") + case "$filename" in + /etc/NetworkManager/system-connections/*|/run/NetworkManager/system-connections/*|/var/run/NetworkManager/system-connections/*) + return 0 ;; + *) return 1 ;; + esac +} + function debianpreconf(){ #create the config sub dir if [ ! -d "/etc/network/interfaces.d" ];then