diff --git a/src/charm.py b/src/charm.py index ebdf53c..a6ad8e0 100755 --- a/src/charm.py +++ b/src/charm.py @@ -20,6 +20,7 @@ import logging import os import subprocess +import shutil from ops.charm import CharmBase from ops.framework import StoredState @@ -133,12 +134,17 @@ def i40e_filter(path: Path) -> bool: ) return + ethtool_cmd = shutil.which("ethtool") + if ethtool_cmd is None: + logger.info("ethtool not found in PATH") + return + for nic in nics: logger.info("Using ethtool(8) to disable FW lldp for %s" % nic) subprocess.run( [ "sudo", - "/usr/sbin/ethtool", + ethtool_cmd, "--set-priv-flags", nic, "disable-fw-lldp", diff --git a/tests/unit/test_charm.py b/tests/unit/test_charm.py index 56e01a3..27763fe 100644 --- a/tests/unit/test_charm.py +++ b/tests/unit/test_charm.py @@ -34,11 +34,13 @@ def test_disable_i40e_lldp_without_i40e_nics( mock_subprocess.assert_not_called() @patch("charm.Path") + @patch("charm.shutil.which") @patch("charm.subprocess.run") @patch("charm.logger") def test_disable_i40e_lldp_with_i40e_nics( - self, mock_logger, mock_subprocess, mock_path + self, mock_logger, mock_subprocess, mock_which, mock_path ): + mock_which.return_value = "/usr/sbin/ethtool" nic_list = ["eth0", "eth1"] mock_nics = [] @@ -77,6 +79,35 @@ def test_disable_i40e_lldp_with_i40e_nics( f"Using ethtool(8) to disable FW lldp for {nic_name}" ) + @patch("charm.Path") + @patch("charm.shutil.which") + @patch("charm.subprocess.run") + @patch("charm.logger") + def test_disable_i40e_lldp_no_ethtool( + self, mock_logger, mock_subprocess, mock_which, mock_path + ): + mock_which.return_value = None + + nic_list = ["eth0", "eth1"] + mock_nics = [] + + for nic_name in nic_list: + mock_nic = MagicMock() + mock_nic.name = nic_name + mock_driver = mock_nic / "device/driver" + mock_driver.resolve.return_value = Path( + "/sys/class/net/{nic_name}/device/driver/i40e" + ) + mock_nics.append(mock_nic) + + mock_path("/sys/class/net").iterdir.return_value = mock_nics + + self.harness.charm.disable_i40e_lldp() + + mock_logger.info.assert_any_call("ethtool not found in PATH") + + mock_subprocess.assert_not_called() + @patch("charm.apt") def test_install(self, _apt): self.harness.charm.on.install.emit() diff --git a/tox.ini b/tox.ini index 17b5573..527e472 100644 --- a/tox.ini +++ b/tox.ini @@ -43,7 +43,7 @@ deps = codespell commands = codespell --skip .git --skip .tox --skip build --skip lib --skip venv --skip .mypy_cache {toxinidir} - ruff {[vars]all_path} + ruff check {[vars]all_path} black --check --diff {[vars]all_path} [testenv:static-{charm,lib}]