From bb2a2c55951a856353f34a2f1e55d55af92b0568 Mon Sep 17 00:00:00 2001 From: "Lasota, Adrian" Date: Tue, 5 May 2026 11:17:00 +0200 Subject: [PATCH] feat: Enhance DHCP release process with dhclient check and logging Signed-off-by: Lasota, Adrian --- .../network_interface/feature/ip/linux.py | 20 +++++++++++-------- .../test_feature/test_ip/test_ip_linux.py | 16 +++++++++++++++ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/mfd_network_adapter/network_interface/feature/ip/linux.py b/mfd_network_adapter/network_interface/feature/ip/linux.py index 3b62191..2ac24e5 100644 --- a/mfd_network_adapter/network_interface/feature/ip/linux.py +++ b/mfd_network_adapter/network_interface/feature/ip/linux.py @@ -189,17 +189,21 @@ def release_ip(self, ip_version: IPVersion) -> None: :param ip_version: IP version to use """ - # release current lease - cmd = f"dhclient -r {self._interface().name}" - output = self._connection.execute_command(cmd, expected_return_codes={}) - if output.return_code and "dhcpcd not running" not in output.stdout: - raise IPFeatureException( - f"Unknown error msg returned, while releasing IP on {self._interface().name} - {output.stderr}" - ) + dhclient_output = self._connection.execute_command("command -v dhclient", expected_return_codes={0, 1}) + if dhclient_output.return_code == 0: + # release current lease + cmd = f"dhclient -r {self._interface().name}" + output = self._connection.execute_command(cmd, expected_return_codes={}) + if output.return_code and "dhcpcd not running" not in output.stdout.casefold(): + raise IPFeatureException( + f"Unknown error msg returned, while releasing IP on {self._interface().name} - {output.stderr}" + ) + else: + logger.log(level=log_levels.MODULE_DEBUG, msg="dhclient not found, skipping DHCP release step.") # RHEL7 still keeps IP after releasing it, so we need to remove it cmd = f"ip -{ip_version.value} addr flush dev {self._interface().name}" - self._connection.execute_command(cmd) + self._connection.execute_command(add_namespace_call_command(cmd, namespace=self._interface().namespace)) def renew_ip(self) -> None: """Refresh Ip address.""" diff --git a/tests/unit/test_mfd_network_adapter/test_network_interface/test_feature/test_ip/test_ip_linux.py b/tests/unit/test_mfd_network_adapter/test_network_interface/test_feature/test_ip/test_ip_linux.py index 2f2a465..3e9afa6 100644 --- a/tests/unit/test_mfd_network_adapter/test_network_interface/test_feature/test_ip/test_ip_linux.py +++ b/tests/unit/test_mfd_network_adapter/test_network_interface/test_feature/test_ip/test_ip_linux.py @@ -183,6 +183,22 @@ def test_release_ip(self, interface): ] ) + def test_release_ip_dhclient_not_found(self, interface): + interface._connection.execute_command.side_effect = [ + ConnectionCompletedProcess(return_code=1, args="", stdout="", stderr=""), + ConnectionCompletedProcess(return_code=0, args="", stdout="", stderr=""), + ] + interface.ip.release_ip(IPVersion.V4) + interface._connection.execute_command.assert_called_with(f"ip -4 addr flush dev {interface.name}") + + def test_release_ip_raises_on_dhclient_error(self, interface): + interface._connection.execute_command.side_effect = [ + ConnectionCompletedProcess(return_code=0, args="", stdout="", stderr=""), + ConnectionCompletedProcess(return_code=1, args="", stdout="some error", stderr="some error"), + ] + with pytest.raises(IPFeatureException): + interface.ip.release_ip(IPVersion.V4) + def test_renew_ip(self, interface): interface._connection.execute_command.return_value = ConnectionCompletedProcess( return_code=0, args="", stdout="", stderr=""