From 46f4dfe4ee69749ee9a282d0186111a110ae0906 Mon Sep 17 00:00:00 2001 From: Harinadh Saladi Date: Mon, 1 Jun 2026 17:45:40 +0000 Subject: [PATCH 1/2] New validation for CSCwr51759 --- aci-preupgrade-validation-script.py | 113 ++++++++++++++++++ docs/docs/validations.md | 24 +++- .../test_vns_rscifatt_cleanup_check.py | 78 ++++++++++++ .../vnsRsCIfAttN_match.json | 18 +++ .../vnsRsCIfAttN_missing_cons.json | 10 ++ .../vnsRsCIfAtt_empty.json | 1 + .../vnsRsCIfAtt_match.json | 18 +++ 7 files changed, 261 insertions(+), 1 deletion(-) create mode 100644 tests/checks/vns_rscifatt_cleanup_check/test_vns_rscifatt_cleanup_check.py create mode 100644 tests/checks/vns_rscifatt_cleanup_check/vnsRsCIfAttN_match.json create mode 100644 tests/checks/vns_rscifatt_cleanup_check/vnsRsCIfAttN_missing_cons.json create mode 100644 tests/checks/vns_rscifatt_cleanup_check/vnsRsCIfAtt_empty.json create mode 100644 tests/checks/vns_rscifatt_cleanup_check/vnsRsCIfAtt_match.json diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index da1b4b9..7c6ef37 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -6410,6 +6410,118 @@ def svccore_excessive_data_check(**kwargs): return Result(result=ERROR, msg="Error occurred while fetching svccore object counts: {}".format(str(e)), doc_url=doc_url) +@check_wrapper(check_title="Cleanup vnsRsCIfAtt usage in services") +def vns_rscifatt_cleanup_check(tversion, **kwargs): + result = PASS + headers = ["Tenant", "Device Name", "Cluster Interface", "Missing Concrete Interface", "vnsRsCIfAtt DN"] + data = [] + recommended_action = ( + "Mo vnsRsCIfAtt is deprecated >=6.0(3d). Before upgrade, under Services, add the missing concrete interface as vnsRsCIfAttN under the same cluster interface" + ) + doc_url = "https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#cleanup-vnsrscifatt-usage-in-services" + + if not tversion: + return Result(result=MANUAL, msg=TVER_MISSING, doc_url=doc_url) + + if tversion.older_than("6.0(3d)"): + return Result(result=NA, msg=VER_NOT_AFFECTED, doc_url=doc_url) + + vnsRsCIfAtts = icurl("class", "vnsRsCIfAtt.json?rsp-prop-include=config-only") + if not vnsRsCIfAtts: + return Result(result=PASS, msg="No user-configured vnsRsCIfAtt payload found.", doc_url=doc_url) + + vnsRsCIfAttNs = icurl("class", "vnsRsCIfAttN.json?rsp-prop-include=config-only") + + def get_target_dn(relation_attributes): + target_dn = relation_attributes["tDn"].strip() if "tDn" in relation_attributes else "" + if target_dn: + return target_dn + if "dn" not in relation_attributes: + return "" + relation_dn = relation_attributes["dn"] + target_dn_match = re.search(r"\[(.*)\]$", relation_dn) + return target_dn_match.group(1).strip() if target_dn_match else "" + + def get_parent_dn(relation_dn): + relation_dn = relation_dn.strip() + if "/rscIfAtt-[" in relation_dn: + return relation_dn.split("/rscIfAtt-[", 1)[0] + if "/rscIfAttN-[" in relation_dn: + return relation_dn.split("/rscIfAttN-[", 1)[0] + return relation_dn.rsplit("/", 1)[0] if "/" in relation_dn else "" + + def parse_relation_context(relation_dn): + tenant_name = "" + device_name = "" + logical_interface = "" + concrete_interface = "" + + dn_match = re.search( + r"uni/tn-(?P[^/]+)/lDevVip-(?P[^/]+)/lIf-(?P[^/]+)/" + r"rscIfAtt-\[.*?/cIf-\[(?P[^\]]+)\]\]", + relation_dn, + ) + if dn_match: + tenant_name = dn_match.group("tenant") + device_name = dn_match.group("device") + logical_interface = dn_match.group("lif") + concrete_interface = dn_match.group("cif") + return tenant_name, device_name, logical_interface, concrete_interface + + old_relation_dn_by_key = {} + for vnsRsCIfAtt in vnsRsCIfAtts: + if "vnsRsCIfAtt" not in vnsRsCIfAtt: + continue + if "attributes" not in vnsRsCIfAtt["vnsRsCIfAtt"]: + continue + relation_attributes = vnsRsCIfAtt["vnsRsCIfAtt"]["attributes"] + if "dn" not in relation_attributes: + continue + + relation_dn = relation_attributes["dn"].strip() + if not relation_dn: + continue + target_dn = get_target_dn(relation_attributes) + if not target_dn: + continue + relation_key = (get_parent_dn(relation_dn), target_dn) + old_relation_dn_by_key[relation_key] = relation_dn + + if not old_relation_dn_by_key: + return Result(result=PASS, msg="No user-configured vnsRsCIfAtt payload found.", doc_url=doc_url) + + new_relation_keys = set() + for vnsRsCIfAttN in vnsRsCIfAttNs: + if "vnsRsCIfAttN" not in vnsRsCIfAttN: + continue + if "attributes" not in vnsRsCIfAttN["vnsRsCIfAttN"]: + continue + relation_attributes = vnsRsCIfAttN["vnsRsCIfAttN"]["attributes"] + if "dn" not in relation_attributes: + continue + + relation_dn = relation_attributes["dn"].strip() + if not relation_dn: + continue + target_dn = get_target_dn(relation_attributes) + if not target_dn: + continue + relation_key = (get_parent_dn(relation_dn), target_dn) + new_relation_keys.add(relation_key) + + for relation_key in sorted(old_relation_dn_by_key.keys()): + if relation_key in new_relation_keys: + continue + missing_dn = old_relation_dn_by_key[relation_key] + tenant_name, device_name, logical_interface, concrete_interface = parse_relation_context(missing_dn) + data.append([tenant_name, device_name, logical_interface, concrete_interface, missing_dn]) + + if data: + result = FAIL_O + + return Result(result=result, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url) + + # ---- Script Execution ---- @@ -6581,6 +6693,7 @@ class CheckManager: rogue_ep_coop_exception_mac_check, n9k_c9408_model_lem_count_check, inband_management_policy_misconfig_check, + vns_rscifatt_cleanup_check, ] ssh_checks = [ # General diff --git a/docs/docs/validations.md b/docs/docs/validations.md index 82f2211..55d93ef 100644 --- a/docs/docs/validations.md +++ b/docs/docs/validations.md @@ -203,6 +203,7 @@ Items | Defect | This Script [N9K-C9408 with more than 5 N9K-X9400-16W LEMs][d31] | CSCws82819 | :white_check_mark: | :no_entry_sign: [Multi-Pod Modular Spine Bootscript File][d32] | CSCwr66848 | :white_check_mark: | :no_entry_sign: [Inband Management Policy Misconfiguration][d33]| CSCwd40071 | :white_check_mark: | :no_entry_sign: +[Cleanup vnsRsCIfAtt usage in services][d34] | CSCwr51759 | :white_check_mark: | :no_entry_sign: [d1]: #ep-announce-compatibility [d2]: #eventmgr-db-size-defect-susceptibility @@ -237,6 +238,7 @@ Items | Defect | This Script [d31]: #n9k-c9408-with-more-than-5-n9k-x9400-16w-lems [d32]: #multi-pod-modular-spine-bootscript-file [d33]: #inband-management-policy-misconfiguration +[d34]: #cleanup-vnsrscifatt-usage-in-services ## General Check Details @@ -2770,6 +2772,25 @@ This issue happens only when the target version is specifically 6.1(4h). To avoid this issue, change the target version to another version. Or verify that the `bootscript` file exists in the bootflash of each modular spine switch prior to upgrading to 6.1(4h). If the file is missing, you have to do clean reboot on the impacted spine to ensure that `/bootflash/bootscript` gets created again. In case you already upgraded your spine and you are experiencing the traffic impact due to this issue, clean reboot of the spine will restore the traffic. +### Cleanup vnsRsCIfAtt usage in services + +Due to [CSCwr51759][70], when targeting 6.0(3)+, having only `vnsRsCIfAtt` without the corresponding `vnsRsCIfAttN` under the same `vnsLIf` can leave service graph interface attachment in an inconsistent state. + +Impact: + +Upgrade can be outage-risky for service graph traffic if stale legacy-only interface attachment relations remain. + +How this check works: + +It compares configured `vnsRsCIfAtt` and `vnsRsCIfAttN` relations by the same cluster interface parent (`vnsLIf`) and same concrete interface target (`tDn`). + +If any `vnsRsCIfAtt` relation exists without a matching `vnsRsCIfAttN` for the same concrete interface target (`tDn`), the upgrade is outage-risky and should be treated as affected. + +Suggestion: + +Before the upgrade, add the missing `vnsRsCIfAttN` relation under the same cluster interface (`vnsLIf`) with the same concrete interface target (`tDn`). + + ### Inband Management Policy Misconfiguration Due to the defect [CSCwh80837][67], starting from version 6.0(4c), mgmtRsInBStNode policy get modified in leaf/spine during Apic upgrade. @@ -2867,4 +2888,5 @@ This check will verify the count of the `svccoreCtrlr` Managed Object and raise [66]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwr66848 [67]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwh80837 [68]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwd40071 -[69]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCws84232 \ No newline at end of file +[69]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCws84232 +[70]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwr51759 \ No newline at end of file diff --git a/tests/checks/vns_rscifatt_cleanup_check/test_vns_rscifatt_cleanup_check.py b/tests/checks/vns_rscifatt_cleanup_check/test_vns_rscifatt_cleanup_check.py new file mode 100644 index 0000000..0b43f86 --- /dev/null +++ b/tests/checks/vns_rscifatt_cleanup_check/test_vns_rscifatt_cleanup_check.py @@ -0,0 +1,78 @@ +import os +import pytest +import importlib +from helpers.utils import read_data + +script = importlib.import_module("aci-preupgrade-validation-script") + +dir = os.path.dirname(os.path.abspath(__file__)) + +test_function = "vns_rscifatt_cleanup_check" + +# icurl queries +vnsRsCIfAtt_api = "vnsRsCIfAtt.json?rsp-prop-include=config-only" +vnsRsCIfAttN_api = "vnsRsCIfAttN.json?rsp-prop-include=config-only" + + +@pytest.mark.parametrize( + "icurl_outputs, tversion, expected_result, expected_data", + [ + # Target version missing + ( + {}, + None, + script.MANUAL, + [], + ), + # Target version is not affected (< 6.0(3d)) + ( + {}, + "6.0(2h)", + script.NA, + [], + ), + # No user-configured vnsRsCIfAtt payload + ( + { + vnsRsCIfAtt_api: read_data(dir, "vnsRsCIfAtt_empty.json"), + }, + "6.1(5e)", + script.PASS, + [], + ), + # All vnsRsCIfAtt relations have matching vnsRsCIfAttN relations + ( + { + vnsRsCIfAtt_api: read_data(dir, "vnsRsCIfAtt_match.json"), + vnsRsCIfAttN_api: read_data(dir, "vnsRsCIfAttN_match.json"), + }, + "6.1(5e)", + script.PASS, + [], + ), + # One vnsRsCIfAtt relation (cons) missing in vnsRsCIfAttN + ( + { + vnsRsCIfAtt_api: read_data(dir, "vnsRsCIfAtt_match.json"), + vnsRsCIfAttN_api: read_data(dir, "vnsRsCIfAttN_missing_cons.json"), + }, + "6.1(5e)", + script.FAIL_O, + [ + [ + "CSCwj49418", + "test", + "intf-cons", + "cons", + "uni/tn-CSCwj49418/lDevVip-test/lIf-intf-cons/rscIfAtt-[uni/tn-CSCwj49418/lDevVip-test/cDev-cdev/cIf-[cons]]", + ] + ], + ), + ], +) +def test_logic(run_check, mock_icurl, tversion, expected_result, expected_data): + result = run_check( + tversion=script.AciVersion(tversion) if tversion else None, + ) + assert result.result == expected_result + assert result.data == expected_data diff --git a/tests/checks/vns_rscifatt_cleanup_check/vnsRsCIfAttN_match.json b/tests/checks/vns_rscifatt_cleanup_check/vnsRsCIfAttN_match.json new file mode 100644 index 0000000..2344730 --- /dev/null +++ b/tests/checks/vns_rscifatt_cleanup_check/vnsRsCIfAttN_match.json @@ -0,0 +1,18 @@ +[ + { + "vnsRsCIfAttN": { + "attributes": { + "dn": "uni/tn-CSCwj49418/lDevVip-test/lIf-intf-prov/rscIfAttN-[uni/tn-CSCwj49418/lDevVip-test/cDev-cdev/cIf-[prov]]", + "tDn": "uni/tn-CSCwj49418/lDevVip-test/cDev-cdev/cIf-[prov]" + } + } + }, + { + "vnsRsCIfAttN": { + "attributes": { + "dn": "uni/tn-CSCwj49418/lDevVip-test/lIf-intf-cons/rscIfAttN-[uni/tn-CSCwj49418/lDevVip-test/cDev-cdev/cIf-[cons]]", + "tDn": "uni/tn-CSCwj49418/lDevVip-test/cDev-cdev/cIf-[cons]" + } + } + } +] diff --git a/tests/checks/vns_rscifatt_cleanup_check/vnsRsCIfAttN_missing_cons.json b/tests/checks/vns_rscifatt_cleanup_check/vnsRsCIfAttN_missing_cons.json new file mode 100644 index 0000000..25de6eb --- /dev/null +++ b/tests/checks/vns_rscifatt_cleanup_check/vnsRsCIfAttN_missing_cons.json @@ -0,0 +1,10 @@ +[ + { + "vnsRsCIfAttN": { + "attributes": { + "dn": "uni/tn-CSCwj49418/lDevVip-test/lIf-intf-prov/rscIfAttN-[uni/tn-CSCwj49418/lDevVip-test/cDev-cdev/cIf-[prov]]", + "tDn": "uni/tn-CSCwj49418/lDevVip-test/cDev-cdev/cIf-[prov]" + } + } + } +] diff --git a/tests/checks/vns_rscifatt_cleanup_check/vnsRsCIfAtt_empty.json b/tests/checks/vns_rscifatt_cleanup_check/vnsRsCIfAtt_empty.json new file mode 100644 index 0000000..fe51488 --- /dev/null +++ b/tests/checks/vns_rscifatt_cleanup_check/vnsRsCIfAtt_empty.json @@ -0,0 +1 @@ +[] diff --git a/tests/checks/vns_rscifatt_cleanup_check/vnsRsCIfAtt_match.json b/tests/checks/vns_rscifatt_cleanup_check/vnsRsCIfAtt_match.json new file mode 100644 index 0000000..a9b0696 --- /dev/null +++ b/tests/checks/vns_rscifatt_cleanup_check/vnsRsCIfAtt_match.json @@ -0,0 +1,18 @@ +[ + { + "vnsRsCIfAtt": { + "attributes": { + "dn": "uni/tn-CSCwj49418/lDevVip-test/lIf-intf-prov/rscIfAtt-[uni/tn-CSCwj49418/lDevVip-test/cDev-cdev/cIf-[prov]]", + "tDn": "uni/tn-CSCwj49418/lDevVip-test/cDev-cdev/cIf-[prov]" + } + } + }, + { + "vnsRsCIfAtt": { + "attributes": { + "dn": "uni/tn-CSCwj49418/lDevVip-test/lIf-intf-cons/rscIfAtt-[uni/tn-CSCwj49418/lDevVip-test/cDev-cdev/cIf-[cons]]", + "tDn": "uni/tn-CSCwj49418/lDevVip-test/cDev-cdev/cIf-[cons]" + } + } + } +] From b9570ad0470f3c4659b4c5390de04dbe39be8c6f Mon Sep 17 00:00:00 2001 From: Harinadh-Saladi Date: Mon, 1 Jun 2026 23:34:02 +0530 Subject: [PATCH 2/2] Updated validations.md --- docs/docs/validations.md | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/docs/docs/validations.md b/docs/docs/validations.md index 55d93ef..96467a4 100644 --- a/docs/docs/validations.md +++ b/docs/docs/validations.md @@ -2772,25 +2772,6 @@ This issue happens only when the target version is specifically 6.1(4h). To avoid this issue, change the target version to another version. Or verify that the `bootscript` file exists in the bootflash of each modular spine switch prior to upgrading to 6.1(4h). If the file is missing, you have to do clean reboot on the impacted spine to ensure that `/bootflash/bootscript` gets created again. In case you already upgraded your spine and you are experiencing the traffic impact due to this issue, clean reboot of the spine will restore the traffic. -### Cleanup vnsRsCIfAtt usage in services - -Due to [CSCwr51759][70], when targeting 6.0(3)+, having only `vnsRsCIfAtt` without the corresponding `vnsRsCIfAttN` under the same `vnsLIf` can leave service graph interface attachment in an inconsistent state. - -Impact: - -Upgrade can be outage-risky for service graph traffic if stale legacy-only interface attachment relations remain. - -How this check works: - -It compares configured `vnsRsCIfAtt` and `vnsRsCIfAttN` relations by the same cluster interface parent (`vnsLIf`) and same concrete interface target (`tDn`). - -If any `vnsRsCIfAtt` relation exists without a matching `vnsRsCIfAttN` for the same concrete interface target (`tDn`), the upgrade is outage-risky and should be treated as affected. - -Suggestion: - -Before the upgrade, add the missing `vnsRsCIfAttN` relation under the same cluster interface (`vnsLIf`) with the same concrete interface target (`tDn`). - - ### Inband Management Policy Misconfiguration Due to the defect [CSCwh80837][67], starting from version 6.0(4c), mgmtRsInBStNode policy get modified in leaf/spine during Apic upgrade. @@ -2818,6 +2799,19 @@ Administrators may be unable to access or operate the APIC GUI, potentially impa This check will verify the count of the `svccoreCtrlr` Managed Object and raise and alarm with the bug if object count found more than 240. Remove the content or objects of `svccoreCtrlr` or `svccoreNode`. Contact Cisco TAC or upgrade to a release containing the fix for CSCws84232 before proceeding with an upgrade. +### Cleanup vnsRsCIfAtt usage in services + +Due to [CSCwr51759][70], when targeting 6.0(3)+, having only `vnsRsCIfAtt` without the corresponding `vnsRsCIfAttN` under the same `vnsLIf` can leave service graph interface attachment in an inconsistent state. + +Impact: + +If any `vnsRsCIfAtt` relation exists without a matching `vnsRsCIfAttN` for the same concrete interface target (`tDn`), the upgrade is outage-risky and should be treated as affected. + +Suggestion: + +Before the upgrade, add the missing `vnsRsCIfAttN` relation under the same cluster interface (`vnsLIf`) with the same concrete interface target (`tDn`). + + [0]: https://github.com/datacenter/ACI-Pre-Upgrade-Validation-Script [1]: https://www.cisco.com/c/dam/en/us/td/docs/Website/datacenter/apicmatrix/index.html @@ -2889,4 +2883,4 @@ This check will verify the count of the `svccoreCtrlr` Managed Object and raise [67]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwh80837 [68]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwd40071 [69]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCws84232 -[70]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwr51759 \ No newline at end of file +[70]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwr51759