From 0a488a62766524fba9975796a365bfe3391e9e68 Mon Sep 17 00:00:00 2001 From: Morten Brekkevold Date: Wed, 11 Oct 2023 14:24:39 +0200 Subject: [PATCH] Raise exception on insane interface data This changes the code flow based on comments from @stveit: Processing a single interface where the collected data is incomplete will raise an exception, while when processing multiple interfaces, single interfaces with issues are just logged and otherwise ignored to not interrupt the flow. --- src/zino/tasks/linkstatetask.py | 15 ++++++++++++--- tests/tasks/test_linkstatetask.py | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/zino/tasks/linkstatetask.py b/src/zino/tasks/linkstatetask.py index 44c0ef7ea..6f2e2af8a 100644 --- a/src/zino/tasks/linkstatetask.py +++ b/src/zino/tasks/linkstatetask.py @@ -49,13 +49,15 @@ async def run(self): def _update_interfaces(self, new_attrs: SparseWalkResponse): for index, row in new_attrs.items(): - self._update_single_interface(row) + try: + self._update_single_interface(row) + except CollectedInterfaceDataIsNotSaneError as error: + _logger.error(error) def _update_single_interface(self, row: dict[str, Any]): data = BaseInterfaceRow(*(row.get(attr) for attr in BASE_POLL_LIST)) if not data.is_sane(): - _logger.info("%s: skipping unknown interface for lack of complete data set: %r", self.device.name, data) - return + raise CollectedInterfaceDataIsNotSaneError(self.device.name, data) port = self._get_or_create_port(data.index) port.ifdescr = data.descr @@ -140,3 +142,10 @@ def _update_ifalias(self, port: Port, data: BaseInterfaceRow): class MissingInterfaceTableData(Exception): def __init__(self, router, port, variable): super().__init__(f"No {variable} from {router} for port {port}") + + +class CollectedInterfaceDataIsNotSaneError(Exception): + def __init__(self, device: str, interface: BaseInterfaceRow): + self.device = device + self.interface = interface + super().__init__(f"Collected interface data from {device} is not sane enough to process: {interface!r}") diff --git a/tests/tasks/test_linkstatetask.py b/tests/tasks/test_linkstatetask.py index cc5d930ff..a093c4b01 100644 --- a/tests/tasks/test_linkstatetask.py +++ b/tests/tasks/test_linkstatetask.py @@ -1,10 +1,12 @@ import pytest from zino.config.models import PollDevice +from zino.oid import OID from zino.state import ZinoState from zino.statemodels import Port from zino.tasks.linkstatetask import ( BaseInterfaceRow, + CollectedInterfaceDataIsNotSaneError, LinkStateTask, MissingInterfaceTableData, ) @@ -58,6 +60,22 @@ def test_when_interface_state_is_missing_update_state_should_raise_exception(sel with pytest.raises(MissingInterfaceTableData): task_with_dummy_device._update_state(data=row, port=port, row=empty_state_row) + def test_when_interface_data_is_empty_update_single_interface_should_raise_exception(self, task_with_dummy_device): + with pytest.raises(CollectedInterfaceDataIsNotSaneError): + task_with_dummy_device._update_single_interface({}) + + def test_when_interface_data_is_empty_update_interfaces_should_keep_processing(self, task_with_dummy_device): + assert ( + task_with_dummy_device._update_interfaces( + { + OID(".1"): {}, + OID(".2"): {}, + OID(".3"): {}, + } + ) + is None + ) + class TestBaseInterfaceRow: def test_when_index_is_missing_is_sane_should_return_false(self):