diff --git a/netx_api/biz_state/parsers/zte/isis_adjacency.py b/netx_api/biz_state/parsers/zte/isis_adjacency.py index 30cb5ef..69c214a 100644 --- a/netx_api/biz_state/parsers/zte/isis_adjacency.py +++ b/netx_api/biz_state/parsers/zte/isis_adjacency.py @@ -5,10 +5,11 @@ from __future__ import annotations import re from typing import Any +# MT may be blank (common on IPv4 adjacencies); NSF/AF still follow. _ISIS_ROW_RE = re.compile( r"^(?P\S+)\s+(?P\S+)\s+(?P\S+)\s+(?P\S+)\s+" - r"(?P\S+)\s+(?P\S+)\s+(?P\S+)\s+(?P\S+)\s+" - r"(?P\S+)\s+(?P\S+)\s*$", + r"(?P\S+)\s+(?P\S+)\s+(?P\S+)\s+" + r"(?:(?P\S+)\s+)?(?P\S+)\s+(?P\S+)\s*$", re.I, ) _PROCESS_RE = re.compile(r"(?i)^\s*Process\s+ID\s*:\s*(\d+)\s*$") @@ -51,11 +52,12 @@ def normalize_isis_adjacency( "holds": m.group("holds")[:32], "snpa": m.group("snpa")[:64], "pri": m.group("pri")[:16], - "mt": m.group("mt")[:16], + "mt": (m.group("mt") or "")[:16], "nsf": m.group("nsf")[:32], "af": m.group("af")[:64], } ) return out + normalize_isis_adjacency.RULE_KEYS = RULE_KEYS diff --git a/tests/test_zte_status_parsers.py b/tests/test_zte_status_parsers.py index 296f7fa..e396f1f 100644 --- a/tests/test_zte_status_parsers.py +++ b/tests/test_zte_status_parsers.py @@ -75,6 +75,34 @@ class ZteStatusParserTests(unittest.TestCase): up = [r for r in rows if r["state"].upper() == "UP"] self.assertEqual(len(up), len(rows)) + def test_isis_adjacency_empty_mt_ipv4(self) -> None: + """IPv4 rows often leave MT blank; must still parse NSF/AF.""" + text = """ +Process ID: 0 + +Process ID: 1 +Interface System id State Lev Holds SNPA(802.2) Pri MT NSF AF +smartgroup107 PAG7_6120HS UP L1 26 PPP - Disable IPv4 +smartgroup32766.1 AG4 UP/UP L1L2 27/27 PPP -/- Disable IPv4 +smartgroup4501 C3 UP/UP L1L2 30/30 PPP -/- Disable IPv4 +smartgroup11 MDN-SGI-P-ZM8SP UP L2 24 PPP - M Disable IPv6 +""" + rows = normalize_isis_adjacency(raw_text=text) + self.assertEqual(len(rows), 4) + self.assertTrue(all(r["process_id"] == "1" for r in rows)) + v4 = [r for r in rows if r["af"] == "IPv4"] + self.assertEqual(len(v4), 3) + self.assertTrue(all(r["mt"] == "" for r in v4)) + self.assertEqual(v4[0]["interface"], "smartgroup107") + self.assertEqual(v4[0]["system_id"], "PAG7_6120HS") + self.assertEqual(v4[0]["state"], "UP") + self.assertEqual(v4[0]["nsf"], "Disable") + self.assertEqual(v4[1]["state"], "UP/UP") + self.assertEqual(v4[1]["pri"], "-/-") + v6 = next(r for r in rows if r["af"] == "IPv6") + self.assertEqual(v6["mt"], "M") + self.assertEqual(v6["nsf"], "Disable") + def test_interface_brief(self) -> None: text = _section( self.log,