From df13276464d4d8990b0525c1d5816f38fbd0ad46 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Wed, 14 Oct 2026 09:39:16 -0400 Subject: [PATCH] Fix FEX access untagged fault parsing --- aci-preupgrade-validation-script.py | 14 ++++++-- .../faultInst_PATH_VARIANTS.json | 20 +++++++++++ .../faultInst_UNFORMATTED.json | 11 ++++++ .../test_access_untagged_check.py | 35 +++++++++++++++++++ 4 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 tests/checks/access_untagged_check/faultInst_PATH_VARIANTS.json create mode 100644 tests/checks/access_untagged_check/faultInst_UNFORMATTED.json diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index 284e09b8..0ab86fb9 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -5008,22 +5008,32 @@ def access_untagged_check(**kwargs): doc_url = 'https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations#access-untagged-port-config' faultInsts = icurl('class', 'faultInst.json?&query-target-filter=wcard(faultInst.changeSet,"native-or-untagged-encap-failure")') - fault_dn_regex = r"topology/pod-(?P\d+)/node-(?P[^/]+)/[^/]+/[^/]+/uni/epp/fv-\[uni/tn-(?P[^/]+)/ap-(?P[^/]+)/epg-(?P[^/]+)\]/[^/]+/stpathatt-\[(?P.+)\]/nwissues/fault-F0467" + fault_dn_regex = ( + r"^topology/pod-(?P\d+)/node-\d+/[^/]+/[^/]+/" + r"uni/epp/fv-\[uni/tn-(?P[^/]+)/ap-(?P[^/]+)/" + r"epg-(?P[^\]]+)\]/node-(?P\d+)/" + r"(?Pext)?stpathatt-\[(?P[^\]]+)\]" + r"(?:-extchid-(?P\d+))?/nwissues/fault-F0467$" + ) if faultInsts: fc = faultInsts[0]['faultInst']['attributes']['code'] for faultInst in faultInsts: m = re.search(fault_dn_regex, faultInst['faultInst']['attributes']['dn']) + if m and bool(m.group('fex')) != bool(m.group('fexid')): + m = None if m: podid = m.group('podid') nodeid = m.group('nodeid') port = m.group('port') + if m.group('fexid'): + port = '{} on FEX {}'.format(port, m.group('fexid')) tenant = m.group('tenant') app_profile = m.group('app_profile') epg_name = m.group('epg_name') data.append([fc, podid, nodeid, port, tenant, app_profile, epg_name, recommended_action]) else: - unformatted_data.append(fc, faultInst['faultInst']['attributes']['descr'], recommended_action) + unformatted_data.append([fc, faultInst['faultInst']['attributes']['descr'], recommended_action]) if not data and not unformatted_data: result = PASS diff --git a/tests/checks/access_untagged_check/faultInst_PATH_VARIANTS.json b/tests/checks/access_untagged_check/faultInst_PATH_VARIANTS.json new file mode 100644 index 00000000..59635fa3 --- /dev/null +++ b/tests/checks/access_untagged_check/faultInst_PATH_VARIANTS.json @@ -0,0 +1,20 @@ +[ + { + "faultInst": { + "attributes": { + "code": "F0467", + "descr": "Configuration failed for uni/tn-TENANT-A/ap-APP-A/epg-EPG-A node 101 eth1/10 due to Only One Native or Untagged Encap Allowed on Interface, debug message: ", + "dn": "topology/pod-1/node-101/local/svc-policyelem-id-0/uni/epp/fv-[uni/tn-TENANT-A/ap-APP-A/epg-EPG-A]/node-101/stpathatt-[eth1/10]/nwissues/fault-F0467" + } + } + }, + { + "faultInst": { + "attributes": { + "code": "F0467", + "descr": "Configuration failed for uni/tn-TENANT-B/ap-APP-B/epg-EPG-B node 102 eth1/20 on FEX 110 due to Only One Native or Untagged Encap Allowed on Interface, debug message: ", + "dn": "topology/pod-2/node-102/local/svc-policyelem-id-0/uni/epp/fv-[uni/tn-TENANT-B/ap-APP-B/epg-EPG-B]/node-102/extstpathatt-[eth1/20]-extchid-110/nwissues/fault-F0467" + } + } + } +] diff --git a/tests/checks/access_untagged_check/faultInst_UNFORMATTED.json b/tests/checks/access_untagged_check/faultInst_UNFORMATTED.json new file mode 100644 index 00000000..fb36cf8b --- /dev/null +++ b/tests/checks/access_untagged_check/faultInst_UNFORMATTED.json @@ -0,0 +1,11 @@ +[ + { + "faultInst": { + "attributes": { + "code": "F0467", + "descr": "Configuration failed for a synthetic attachment due to Only One Native or Untagged Encap Allowed on Interface, debug message: ", + "dn": "topology/pod-1/node-101/local/svc-policyelem-id-0/uni/epp/fv-[uni/tn-TENANT-C/ap-APP-C/epg-EPG-C]/node-101/unknownpathatt-[PATH-C]/nwissues/fault-F0467" + } + } + } +] diff --git a/tests/checks/access_untagged_check/test_access_untagged_check.py b/tests/checks/access_untagged_check/test_access_untagged_check.py index f7a6d610..fadd9983 100644 --- a/tests/checks/access_untagged_check/test_access_untagged_check.py +++ b/tests/checks/access_untagged_check/test_access_untagged_check.py @@ -31,3 +31,38 @@ def test_logic(run_check, mock_icurl, expected_result): result = run_check() assert result.result == expected_result + + +def test_standard_and_fex_path_details(run_check, mock_icurl, icurl_outputs): + icurl_outputs[faultInsts] = read_data(dir, "faultInst_PATH_VARIANTS.json") + recommended_action = ( + "Resolve the conflict by removing this config or other configs using this port " + "in Access(untagged) or native mode." + ) + + result = run_check() + + assert result.result == script.FAIL_O + assert result.data == [ + ["F0467", "1", "101", "eth1/10", "TENANT-A", "APP-A", "EPG-A", recommended_action], + ["F0467", "2", "102", "eth1/20 on FEX 110", "TENANT-B", "APP-B", "EPG-B", recommended_action], + ] + assert result.unformatted_data == [] + + +def test_unrecognized_dn_uses_unformatted_details(run_check, mock_icurl, icurl_outputs): + icurl_outputs[faultInsts] = read_data(dir, "faultInst_UNFORMATTED.json") + description = ( + "Configuration failed for a synthetic attachment due to Only One Native or " + "Untagged Encap Allowed on Interface, debug message: " + ) + recommended_action = ( + "Resolve the conflict by removing this config or other configs using this port " + "in Access(untagged) or native mode." + ) + + result = run_check() + + assert result.result == script.FAIL_O + assert result.data == [] + assert result.unformatted_data == [["F0467", description, recommended_action]]