Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions aci-preupgrade-validation-script.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change the name accordingly.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated

def vns_rscifatt_cleanup_check(tversion, **kwargs):
Copy link
Copy Markdown

@muthu-ku muthu-ku Jun 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change the proper function name and title

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated name and title

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"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not explainatery enough. please work on it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated recommended action with additional details.

)
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):
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

look for whole DN, not just Tdn. . this seems wrong to me.
you will see one small diff there for RsCifAtt/RsCifAttN --> make sure you cover this while comparing DN.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated by considering full DN.

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<tenant>[^/]+)/lDevVip-(?P<device>[^/]+)/lIf-(?P<lif>[^/]+)/"
r"rscIfAtt-\[.*?/cIf-\[(?P<cif>[^\]]+)\]\]",
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)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dn is the full path of the relationship object, and tDn is the path of the target interface object it is attached to.

No need of check for tDN.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i agree. its not resolved. at all.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comparison now uses full relation DN instead of tDn and handles rscIfAtt vs rscIfAttN differences before matching.

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
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when mo is not configured, vnsRsCIfAttNs will be empty.. above if conditions not needed.


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])
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where is that fault case handled for post upgrade case..

fault : F1690
uni/tn-CSCwj49418/lDevVip-test/lIf-intf-cons/vnsConfIssue-lif-invalid-CIf
Configuration is invalid due to LIf has an invalid CIf

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per below comment added by Lovkesh,

"After doing upgarde from 605h to 615e.

fab3-apic# moquery -c vnsRsCIfAtt | grep dn
fab3-apic# moquery -c vnsRsCIfAttN | grep dn
dn : uni/tn-CSCwj49418/lDevVip-test/lIf-intf-prov/rscIfAttN-[uni/tn-CSCwj49418/lDevVip-test/cDev-cdev/cIf-[prov]]
fab3-apic#

Gui shows cIf-[prov] deleted from concrete device interface.
and fault raised
F1690
Minor
2026-05-29T13:37:55.525+00:00
Raised
uni/tn-CSCwj49418/lDevVip-test/lIf-intf-cons/vnsConfIssue-lif-invalid-CIf
Configuration is invalid due to LIf has an invalid CIf
Config
configuration-failed
ignorable:no, issue:lif-invalid-CIf. this Fault removed asap i attached the cluster interface."

It'll be seen after upgrade to 6.1(5e). But if older mo config is not there in the new mo config, we are recommending cu to add the missing cluster interface in the lower version itself before doing upgrade. Then we will not see the fault post upgradation and that's the reason current check exists what I feel.


if data:
result = FAIL_O

return Result(result=result, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url)


# ---- Script Execution ----


Expand Down Expand Up @@ -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
Expand Down
18 changes: 17 additions & 1 deletion docs/docs/validations.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Copy link
Copy Markdown

@lovkeshsharma702 lovkeshsharma702 Jun 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Check missing vnsRsCIfAttN" ---> change the name

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated !


[d1]: #ep-announce-compatibility
[d2]: #eventmgr-db-size-defect-susceptibility
Expand Down Expand Up @@ -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
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"check-missing-vnsRsCIfAttN"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated


## General Check Details

Expand Down Expand Up @@ -2797,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
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change the name accordingly.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated


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.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrong buug mentioned. Please do the cleanup for bogus info.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when upgrading to 6.0(3) and above, 'vnsRsCIfAtt' get deleted and without creating the corresponding 'vnsRsCIfAttN' under the same vnsLIf. this will leave service graph interface attachment in an inconsistent state

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated !


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.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please update the document as per impact and requirement.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for this ---> 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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.


Suggestion:

Before the upgrade, add the missing `vnsRsCIfAttN` relation under the same cluster interface (`vnsLIf`) with the same concrete interface target (`tDn`).
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

specify the GUI path.. as discussed earlier

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated




[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
Expand Down Expand Up @@ -2867,4 +2882,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
[69]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCws84232
[70]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwr51759
Original file line number Diff line number Diff line change
@@ -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
18 changes: 18 additions & 0 deletions tests/checks/vns_rscifatt_cleanup_check/vnsRsCIfAttN_match.json
Original file line number Diff line number Diff line change
@@ -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]"
}
}
}
]
Original file line number Diff line number Diff line change
@@ -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]"
}
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
18 changes: 18 additions & 0 deletions tests/checks/vns_rscifatt_cleanup_check/vnsRsCIfAtt_match.json
Original file line number Diff line number Diff line change
@@ -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]"
}
}
}
]
Loading