Skip to content

Commit 46f4dfe

Browse files
New validation for CSCwr51759
1 parent 0d28b80 commit 46f4dfe

7 files changed

Lines changed: 261 additions & 1 deletion

File tree

aci-preupgrade-validation-script.py

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6410,6 +6410,118 @@ def svccore_excessive_data_check(**kwargs):
64106410
return Result(result=ERROR, msg="Error occurred while fetching svccore object counts: {}".format(str(e)), doc_url=doc_url)
64116411

64126412

6413+
@check_wrapper(check_title="Cleanup vnsRsCIfAtt usage in services")
6414+
def vns_rscifatt_cleanup_check(tversion, **kwargs):
6415+
result = PASS
6416+
headers = ["Tenant", "Device Name", "Cluster Interface", "Missing Concrete Interface", "vnsRsCIfAtt DN"]
6417+
data = []
6418+
recommended_action = (
6419+
"Mo vnsRsCIfAtt is deprecated >=6.0(3d). Before upgrade, under Services, add the missing concrete interface as vnsRsCIfAttN under the same cluster interface"
6420+
)
6421+
doc_url = "https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#cleanup-vnsrscifatt-usage-in-services"
6422+
6423+
if not tversion:
6424+
return Result(result=MANUAL, msg=TVER_MISSING, doc_url=doc_url)
6425+
6426+
if tversion.older_than("6.0(3d)"):
6427+
return Result(result=NA, msg=VER_NOT_AFFECTED, doc_url=doc_url)
6428+
6429+
vnsRsCIfAtts = icurl("class", "vnsRsCIfAtt.json?rsp-prop-include=config-only")
6430+
if not vnsRsCIfAtts:
6431+
return Result(result=PASS, msg="No user-configured vnsRsCIfAtt payload found.", doc_url=doc_url)
6432+
6433+
vnsRsCIfAttNs = icurl("class", "vnsRsCIfAttN.json?rsp-prop-include=config-only")
6434+
6435+
def get_target_dn(relation_attributes):
6436+
target_dn = relation_attributes["tDn"].strip() if "tDn" in relation_attributes else ""
6437+
if target_dn:
6438+
return target_dn
6439+
if "dn" not in relation_attributes:
6440+
return ""
6441+
relation_dn = relation_attributes["dn"]
6442+
target_dn_match = re.search(r"\[(.*)\]$", relation_dn)
6443+
return target_dn_match.group(1).strip() if target_dn_match else ""
6444+
6445+
def get_parent_dn(relation_dn):
6446+
relation_dn = relation_dn.strip()
6447+
if "/rscIfAtt-[" in relation_dn:
6448+
return relation_dn.split("/rscIfAtt-[", 1)[0]
6449+
if "/rscIfAttN-[" in relation_dn:
6450+
return relation_dn.split("/rscIfAttN-[", 1)[0]
6451+
return relation_dn.rsplit("/", 1)[0] if "/" in relation_dn else ""
6452+
6453+
def parse_relation_context(relation_dn):
6454+
tenant_name = ""
6455+
device_name = ""
6456+
logical_interface = ""
6457+
concrete_interface = ""
6458+
6459+
dn_match = re.search(
6460+
r"uni/tn-(?P<tenant>[^/]+)/lDevVip-(?P<device>[^/]+)/lIf-(?P<lif>[^/]+)/"
6461+
r"rscIfAtt-\[.*?/cIf-\[(?P<cif>[^\]]+)\]\]",
6462+
relation_dn,
6463+
)
6464+
if dn_match:
6465+
tenant_name = dn_match.group("tenant")
6466+
device_name = dn_match.group("device")
6467+
logical_interface = dn_match.group("lif")
6468+
concrete_interface = dn_match.group("cif")
6469+
return tenant_name, device_name, logical_interface, concrete_interface
6470+
6471+
old_relation_dn_by_key = {}
6472+
for vnsRsCIfAtt in vnsRsCIfAtts:
6473+
if "vnsRsCIfAtt" not in vnsRsCIfAtt:
6474+
continue
6475+
if "attributes" not in vnsRsCIfAtt["vnsRsCIfAtt"]:
6476+
continue
6477+
relation_attributes = vnsRsCIfAtt["vnsRsCIfAtt"]["attributes"]
6478+
if "dn" not in relation_attributes:
6479+
continue
6480+
6481+
relation_dn = relation_attributes["dn"].strip()
6482+
if not relation_dn:
6483+
continue
6484+
target_dn = get_target_dn(relation_attributes)
6485+
if not target_dn:
6486+
continue
6487+
relation_key = (get_parent_dn(relation_dn), target_dn)
6488+
old_relation_dn_by_key[relation_key] = relation_dn
6489+
6490+
if not old_relation_dn_by_key:
6491+
return Result(result=PASS, msg="No user-configured vnsRsCIfAtt payload found.", doc_url=doc_url)
6492+
6493+
new_relation_keys = set()
6494+
for vnsRsCIfAttN in vnsRsCIfAttNs:
6495+
if "vnsRsCIfAttN" not in vnsRsCIfAttN:
6496+
continue
6497+
if "attributes" not in vnsRsCIfAttN["vnsRsCIfAttN"]:
6498+
continue
6499+
relation_attributes = vnsRsCIfAttN["vnsRsCIfAttN"]["attributes"]
6500+
if "dn" not in relation_attributes:
6501+
continue
6502+
6503+
relation_dn = relation_attributes["dn"].strip()
6504+
if not relation_dn:
6505+
continue
6506+
target_dn = get_target_dn(relation_attributes)
6507+
if not target_dn:
6508+
continue
6509+
relation_key = (get_parent_dn(relation_dn), target_dn)
6510+
new_relation_keys.add(relation_key)
6511+
6512+
for relation_key in sorted(old_relation_dn_by_key.keys()):
6513+
if relation_key in new_relation_keys:
6514+
continue
6515+
missing_dn = old_relation_dn_by_key[relation_key]
6516+
tenant_name, device_name, logical_interface, concrete_interface = parse_relation_context(missing_dn)
6517+
data.append([tenant_name, device_name, logical_interface, concrete_interface, missing_dn])
6518+
6519+
if data:
6520+
result = FAIL_O
6521+
6522+
return Result(result=result, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url)
6523+
6524+
64136525
# ---- Script Execution ----
64146526

64156527

@@ -6581,6 +6693,7 @@ class CheckManager:
65816693
rogue_ep_coop_exception_mac_check,
65826694
n9k_c9408_model_lem_count_check,
65836695
inband_management_policy_misconfig_check,
6696+
vns_rscifatt_cleanup_check,
65846697
]
65856698
ssh_checks = [
65866699
# General

docs/docs/validations.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ Items | Defect | This Script
203203
[N9K-C9408 with more than 5 N9K-X9400-16W LEMs][d31] | CSCws82819 | :white_check_mark: | :no_entry_sign:
204204
[Multi-Pod Modular Spine Bootscript File][d32] | CSCwr66848 | :white_check_mark: | :no_entry_sign:
205205
[Inband Management Policy Misconfiguration][d33]| CSCwd40071 | :white_check_mark: | :no_entry_sign:
206+
[Cleanup vnsRsCIfAtt usage in services][d34] | CSCwr51759 | :white_check_mark: | :no_entry_sign:
206207

207208
[d1]: #ep-announce-compatibility
208209
[d2]: #eventmgr-db-size-defect-susceptibility
@@ -237,6 +238,7 @@ Items | Defect | This Script
237238
[d31]: #n9k-c9408-with-more-than-5-n9k-x9400-16w-lems
238239
[d32]: #multi-pod-modular-spine-bootscript-file
239240
[d33]: #inband-management-policy-misconfiguration
241+
[d34]: #cleanup-vnsrscifatt-usage-in-services
240242

241243
## General Check Details
242244

@@ -2770,6 +2772,25 @@ This issue happens only when the target version is specifically 6.1(4h).
27702772
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.
27712773

27722774

2775+
### Cleanup vnsRsCIfAtt usage in services
2776+
2777+
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.
2778+
2779+
Impact:
2780+
2781+
Upgrade can be outage-risky for service graph traffic if stale legacy-only interface attachment relations remain.
2782+
2783+
How this check works:
2784+
2785+
It compares configured `vnsRsCIfAtt` and `vnsRsCIfAttN` relations by the same cluster interface parent (`vnsLIf`) and same concrete interface target (`tDn`).
2786+
2787+
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.
2788+
2789+
Suggestion:
2790+
2791+
Before the upgrade, add the missing `vnsRsCIfAttN` relation under the same cluster interface (`vnsLIf`) with the same concrete interface target (`tDn`).
2792+
2793+
27732794
### Inband Management Policy Misconfiguration
27742795

27752796
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
28672888
[66]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwr66848
28682889
[67]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwh80837
28692890
[68]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwd40071
2870-
[69]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCws84232
2891+
[69]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCws84232
2892+
[70]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwr51759
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import os
2+
import pytest
3+
import importlib
4+
from helpers.utils import read_data
5+
6+
script = importlib.import_module("aci-preupgrade-validation-script")
7+
8+
dir = os.path.dirname(os.path.abspath(__file__))
9+
10+
test_function = "vns_rscifatt_cleanup_check"
11+
12+
# icurl queries
13+
vnsRsCIfAtt_api = "vnsRsCIfAtt.json?rsp-prop-include=config-only"
14+
vnsRsCIfAttN_api = "vnsRsCIfAttN.json?rsp-prop-include=config-only"
15+
16+
17+
@pytest.mark.parametrize(
18+
"icurl_outputs, tversion, expected_result, expected_data",
19+
[
20+
# Target version missing
21+
(
22+
{},
23+
None,
24+
script.MANUAL,
25+
[],
26+
),
27+
# Target version is not affected (< 6.0(3d))
28+
(
29+
{},
30+
"6.0(2h)",
31+
script.NA,
32+
[],
33+
),
34+
# No user-configured vnsRsCIfAtt payload
35+
(
36+
{
37+
vnsRsCIfAtt_api: read_data(dir, "vnsRsCIfAtt_empty.json"),
38+
},
39+
"6.1(5e)",
40+
script.PASS,
41+
[],
42+
),
43+
# All vnsRsCIfAtt relations have matching vnsRsCIfAttN relations
44+
(
45+
{
46+
vnsRsCIfAtt_api: read_data(dir, "vnsRsCIfAtt_match.json"),
47+
vnsRsCIfAttN_api: read_data(dir, "vnsRsCIfAttN_match.json"),
48+
},
49+
"6.1(5e)",
50+
script.PASS,
51+
[],
52+
),
53+
# One vnsRsCIfAtt relation (cons) missing in vnsRsCIfAttN
54+
(
55+
{
56+
vnsRsCIfAtt_api: read_data(dir, "vnsRsCIfAtt_match.json"),
57+
vnsRsCIfAttN_api: read_data(dir, "vnsRsCIfAttN_missing_cons.json"),
58+
},
59+
"6.1(5e)",
60+
script.FAIL_O,
61+
[
62+
[
63+
"CSCwj49418",
64+
"test",
65+
"intf-cons",
66+
"cons",
67+
"uni/tn-CSCwj49418/lDevVip-test/lIf-intf-cons/rscIfAtt-[uni/tn-CSCwj49418/lDevVip-test/cDev-cdev/cIf-[cons]]",
68+
]
69+
],
70+
),
71+
],
72+
)
73+
def test_logic(run_check, mock_icurl, tversion, expected_result, expected_data):
74+
result = run_check(
75+
tversion=script.AciVersion(tversion) if tversion else None,
76+
)
77+
assert result.result == expected_result
78+
assert result.data == expected_data
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[
2+
{
3+
"vnsRsCIfAttN": {
4+
"attributes": {
5+
"dn": "uni/tn-CSCwj49418/lDevVip-test/lIf-intf-prov/rscIfAttN-[uni/tn-CSCwj49418/lDevVip-test/cDev-cdev/cIf-[prov]]",
6+
"tDn": "uni/tn-CSCwj49418/lDevVip-test/cDev-cdev/cIf-[prov]"
7+
}
8+
}
9+
},
10+
{
11+
"vnsRsCIfAttN": {
12+
"attributes": {
13+
"dn": "uni/tn-CSCwj49418/lDevVip-test/lIf-intf-cons/rscIfAttN-[uni/tn-CSCwj49418/lDevVip-test/cDev-cdev/cIf-[cons]]",
14+
"tDn": "uni/tn-CSCwj49418/lDevVip-test/cDev-cdev/cIf-[cons]"
15+
}
16+
}
17+
}
18+
]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[
2+
{
3+
"vnsRsCIfAttN": {
4+
"attributes": {
5+
"dn": "uni/tn-CSCwj49418/lDevVip-test/lIf-intf-prov/rscIfAttN-[uni/tn-CSCwj49418/lDevVip-test/cDev-cdev/cIf-[prov]]",
6+
"tDn": "uni/tn-CSCwj49418/lDevVip-test/cDev-cdev/cIf-[prov]"
7+
}
8+
}
9+
}
10+
]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[]
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[
2+
{
3+
"vnsRsCIfAtt": {
4+
"attributes": {
5+
"dn": "uni/tn-CSCwj49418/lDevVip-test/lIf-intf-prov/rscIfAtt-[uni/tn-CSCwj49418/lDevVip-test/cDev-cdev/cIf-[prov]]",
6+
"tDn": "uni/tn-CSCwj49418/lDevVip-test/cDev-cdev/cIf-[prov]"
7+
}
8+
}
9+
},
10+
{
11+
"vnsRsCIfAtt": {
12+
"attributes": {
13+
"dn": "uni/tn-CSCwj49418/lDevVip-test/lIf-intf-cons/rscIfAtt-[uni/tn-CSCwj49418/lDevVip-test/cDev-cdev/cIf-[cons]]",
14+
"tDn": "uni/tn-CSCwj49418/lDevVip-test/cDev-cdev/cIf-[cons]"
15+
}
16+
}
17+
}
18+
]

0 commit comments

Comments
 (0)