mirror of
https://github.com/hansjone/netx.git
synced 2026-10-16 07:40:45 +08:00
Decouple cutover HF from portrait and tighten ops UI.
Portrait stays on biz-monitor; cutover create/ensure owns purpose=cutover_hf slots with project collect override, multi-interval bindings, window pause, and industrial detail UX. Also expand ZTE collect/config parsers and TextFSM for route/BGP/L2VPN/VRRP coverage. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
a65c9fc420
commit
285c19e5a3
67 changed files with 9510 additions and 723 deletions
|
|
@ -11,6 +11,14 @@ from .pipeline import prefer_fsm
|
|||
|
||||
RULE_KEYS = ("zte_zxros_show_ip_vrf",)
|
||||
|
||||
_VRF_LINE_RE = re.compile(
|
||||
r"^\s*(?P<name>[A-Za-z0-9_./:-]+)\s+"
|
||||
r"(?P<rd>\d+:\d+|<not set>|\S+:\S+)\s*"
|
||||
r"(?:(?P<protocols>ipv4(?:,ipv6)?|ipv6(?:,ipv4)?|ipv4|ipv6)\s*)?"
|
||||
r"(?P<vrf_id>\d+)?\s*$",
|
||||
re.I,
|
||||
)
|
||||
|
||||
|
||||
def _map_fsm_rows(rows: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
||||
out: list[dict[str, Any]] = []
|
||||
|
|
@ -22,11 +30,16 @@ def _map_fsm_rows(rows: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
|||
if name in seen:
|
||||
continue
|
||||
seen.add(name)
|
||||
protocols = row_get(r, "PROTOCOLS", "ADDRESS_FAMILY", "protocols")
|
||||
# Legacy templates may put protocols in INTERFACES
|
||||
if not protocols:
|
||||
protocols = row_get(r, "INTERFACES", "interfaces")
|
||||
out.append(
|
||||
{
|
||||
"vrf_name": name[:128],
|
||||
"rd": row_get(r, "DEFAULT_RD", "RD", "rd")[:64],
|
||||
"protocols": row_get(r, "PROTOCOLS", "ADDRESS_FAMILY", "INTERFACES", "protocols")[:64],
|
||||
"rd": row_get(r, "RD", "DEFAULT_RD", "rd")[:64],
|
||||
"protocols": protocols[:64],
|
||||
"vrf_id": row_get(r, "VRF_ID", "vrf_id")[:32],
|
||||
}
|
||||
)
|
||||
return out
|
||||
|
|
@ -36,16 +49,23 @@ def _hand_parse(*, raw_text: str, **_kw: Any) -> list[dict[str, Any]]:
|
|||
out: list[dict[str, Any]] = []
|
||||
seen: set[str] = set()
|
||||
for line in str(raw_text or "").splitlines():
|
||||
m = re.match(r"^\s*([A-Za-z0-9_./:-]+)\s+(\d+:\d+|<not set>|\S+:\S+)\s*", line)
|
||||
m = _VRF_LINE_RE.match(line)
|
||||
if not m:
|
||||
continue
|
||||
name = m.group(1)
|
||||
name = m.group("name")
|
||||
if name.lower() in ("name", "vrf", "vpn-instance", "total"):
|
||||
continue
|
||||
if name in seen:
|
||||
continue
|
||||
seen.add(name)
|
||||
out.append({"vrf_name": name[:128], "rd": m.group(2)[:64], "protocols": ""})
|
||||
out.append(
|
||||
{
|
||||
"vrf_name": name[:128],
|
||||
"rd": (m.group("rd") or "")[:64],
|
||||
"protocols": (m.group("protocols") or "")[:64],
|
||||
"vrf_id": (m.group("vrf_id") or "")[:32],
|
||||
}
|
||||
)
|
||||
return out
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue