Skip to content

Commit 1098b6c

Browse files
welkinhemonrog2
authored andcommitted
Welkin issue 245 (#263)
* Introduced CSCwp22212 check for stale pconsRA objects --------- Co-authored-by: Gabriel <gmonroy@cisco.com>
1 parent 4a2940e commit 1098b6c

7 files changed

Lines changed: 249 additions & 30 deletions

File tree

aci-preupgrade-validation-script.py

Lines changed: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5101,33 +5101,62 @@ def ave_eol_check(index, total_checks, tversion, **kwargs):
51015101
return result
51025102

51035103

5104-
def configpush_shard_check(index, total_checks, tversion, **kwargs):
5105-
title = 'configpushShardCont headTx'
5106-
result = NA
5104+
def stale_pcons_ra_mo_check(index, total_checks, cversion, tversion, **kwargs):
5105+
title = 'Stale pconsRA Objects'
5106+
result = PASS
51075107
msg = ''
5108-
headers = ["dn", "headTx", "tailTx"]
5108+
headers = ["Stale pconsRA DN", "Non-Existing DN"]
5109+
51095110
data = []
5110-
recommended_action = 'Contact Cisco TAC for Support before upgrade'
5111-
doc_url = 'https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#policydist-configpushshardcont-defect'
5111+
recommended_action = 'Contact Cisco TAC to delete stale pconsRA before upgrading'
5112+
doc_url = 'https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#stale-pconsra-object'
51125113
print_title(title, index, total_checks)
5113-
configpushShardCont = 'configpushShardCont.json'
5114-
if tversion.older_than("6.1(4a)"):
5115-
configpush_sh_cont = icurl('class', configpushShardCont)
5116-
if configpush_sh_cont:
5117-
result = PASS
5118-
for sh_cont in configpush_sh_cont:
5119-
if sh_cont['configpushShardCont']['attributes']['headTx'] != '0' and sh_cont['configpushShardCont']['attributes']['tailTx'] == '0':
5120-
sh_cont_dn = sh_cont['configpushShardCont']['attributes']['dn']
5121-
headtx = sh_cont['configpushShardCont']['attributes']['headTx']
5122-
tailtx = sh_cont['configpushShardCont']['attributes']['tailTx']
5123-
data.append([sh_cont_dn, headtx, tailtx])
5124-
5114+
5115+
if not tversion:
5116+
print_result(title, MANUAL, "Target version not supplied. Skipping.")
5117+
return MANUAL
5118+
5119+
if cversion.older_than("6.0(3d)") and tversion.newer_than("6.0(3c)") and tversion.older_than("6.1(4a)"):
5120+
pcons_rssubtreedep_api = 'pconsRsSubtreeDep.json?query-target-filter=wcard(pconsRsSubtreeDep.tDn,"/instdn-")'
5121+
pcons_rssubtreedep_mo = icurl('class', pcons_rssubtreedep_api)
5122+
pcons_inst_dn_reg = r'registry/class-\d+/instdn-\[(?P<policy_dn>.+?)\]/ra'
5123+
pcons_ra_dn_reg = r'(?P<pcons_ra_dn>.+?)/p...-\['
5124+
5125+
pcons_ra_set = set()
5126+
policy_dn_set = set()
5127+
5128+
for mo in pcons_rssubtreedep_mo:
5129+
pcons_rssubtreedep_tdn = mo['pconsRsSubtreeDep']['attributes']['tDn']
5130+
instdn_found = re.search(pcons_inst_dn_reg, pcons_rssubtreedep_tdn)
5131+
radn_found = re.search(pcons_ra_dn_reg, pcons_rssubtreedep_tdn)
5132+
if instdn_found and radn_found:
5133+
pcons_ra_dn = radn_found.group('pcons_ra_dn')
5134+
policy_dn = instdn_found.group('policy_dn')
5135+
if pcons_ra_dn not in pcons_ra_set:
5136+
pcons_ra_set.add(pcons_ra_dn)
5137+
if policy_dn not in policy_dn_set:
5138+
policy_dn_set.add(policy_dn)
5139+
5140+
for policy_dn in policy_dn_set:
5141+
policy_dn_api = policy_dn + '.json'
5142+
policy_dn_mo = icurl('mo', policy_dn_api)
5143+
if not policy_dn_mo:
5144+
for pcons_ra_dn in pcons_ra_set:
5145+
if policy_dn in pcons_ra_dn:
5146+
pcons_ra_api = pcons_ra_dn + '.json'
5147+
pcons_ra_dn_mo = icurl('mo', pcons_ra_api)
5148+
if pcons_ra_dn_mo:
5149+
data.append([pcons_ra_dn, policy_dn])
5150+
else:
5151+
print_result(title, NA, "Target version not supplied or not applicable. Skipping.")
5152+
return NA
5153+
51255154
if data:
51265155
result = FAIL_O
5127-
5128-
print_result(title, result, msg, headers, data, recommended_action=recommended_action, doc_url=doc_url)
5156+
print_result(title, result, msg, headers, data, recommended_action=recommended_action, doc_url=doc_url)
51295157
return result
51305158

5159+
51315160
if __name__ == "__main__":
51325161
prints(' ==== %s%s, Script Version %s ====\n' % (ts, tz, SCRIPT_VERSION))
51335162
prints('!!!! Check https://github.com/datacenter/ACI-Pre-Upgrade-Validation-Script for Latest Release !!!!\n')
@@ -5243,7 +5272,7 @@ def configpush_shard_check(index, total_checks, tversion, **kwargs):
52435272
pbr_high_scale_check,
52445273
standby_sup_sync_check,
52455274
observer_db_size_check,
5246-
configpush_shard_check,
5275+
stale_pcons_ra_mo_check,
52475276

52485277
]
52495278
summary = {PASS: 0, FAIL_O: 0, FAIL_UF: 0, ERROR: 0, MANUAL: 0, POST: 0, NA: 0, 'TOTAL': len(checks)}

docs/docs/validations.md

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,7 @@ Items | Defect | This Script
184184
[PBR High Scale][d23] | CSCwi66348 | :white_check_mark: | :no_entry_sign: |:no_entry_sign:
185185
[Standby Sup Image Sync][d24] | CSCwi66348 | :white_check_mark: | :no_entry_sign: |:no_entry_sign:
186186
[Observer Database Size][d25] | CSCvw45531 | :white_check_mark: | :no_entry_sign: |:no_entry_sign:
187-
[Policydist configpushShardCont defect][d26] | CSCwp95515 | :white_check_mark: | :no_entry_sign: |:no_entry_sign:
188-
187+
[Stale pconsRA Object][d26] | CSCwp22212 | :white_check_mark: | :no_entry_sign: |:no_entry_sign:
189188

190189
[d1]: #ep-announce-compatibility
191190
[d2]: #eventmgr-db-size-defect-susceptibility
@@ -212,7 +211,7 @@ Items | Defect | This Script
212211
[d23]: #pbr-high-scale
213212
[d24]: #standby-sup-image-sync
214213
[d25]: #observer-database-size
215-
[d26]: #policydist-configpushshardcont-defect
214+
[d26]: #stale-pconsra-object
216215

217216

218217
## General Check Details
@@ -2543,13 +2542,11 @@ This check logs in to each APIC, checks the contents of the `/data2/dbstats/` di
25432542
!!! tip
25442543
Certain high churn logging configurations have been found to grow this DB exceptionally large while on a non-fixed version. 'Contract Permit Logging' is one such configuration.
25452544

2546-
### Policydist configpushShardCont defect
2547-
2548-
Due to [CSCwp95515][57], a configpushShardCont MO in policydist has a non-zero headTx while tailTx is zero. if APIC cluster is upgraded or if config is pushed to a PM shard corresponding to the DN that has the bad properties policydist can crash.
2545+
### Stale pconsRA Object
25492546

2550-
The Policydist component is responsible for policy enforcement and replicating policy actions and maintaining consistency of policy state across all APICs in the cluster.
2547+
Due to [CSCwp22212][57], the existence of stale pconsRA objects within an ACI fabric can cause the APIC Policymanager process to crash after an upgrade to 6.0(3d) and above. This script looks for instances of stale pconsRA objects and flags them for cleanup when found.
25512548

2552-
The script scans for any instance of configpushShardCont that can lead to this defect, contact Cisco TAC to resolve the issue prior to the upgrade.
2549+
TAC must be engaged to cleanup these objects, as they require root access.
25532550

25542551

25552552
[0]: https://github.com/datacenter/ACI-Pre-Upgrade-Validation-Script
@@ -2609,4 +2606,4 @@ The script scans for any instance of configpushShardCont that can lead to this d
26092606
[54]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCvt47850
26102607
[55]: https://www.cisco.com/c/en/us/products/collateral/cloud-systems-management/application-policy-infrastructure-controller-apic/eol-apic-virtual-edge-pod-pb.html
26112608
[56]: https://www.cisco.com/c/en/us/td/docs/dcn/whitepapers/cisco-aci-virtual-edge-migration.html
2612-
[57]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwp95515
2609+
[57]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwp22212
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"totalCount": "1",
3+
"imdata": [
4+
{
5+
"pconsRA": {
6+
"attributes": {
7+
"applyFilter": "yes",
8+
"childAction": "",
9+
"ctx": "uni/infra/attentp-PHY-DOM_AttEntityP",
10+
"deployStatus": "deployed",
11+
"distAll": "no",
12+
"dn": "registry/class-1809/instdn-[uni/phys-PHY-DOM]/ra-[uni/infra/attentp-PHY-DOM_AttEntityP]-6-0-0-0-SubtreeWithRels-mo",
13+
"incrDeploy": "no",
14+
"lcOwn": "local",
15+
"markedForDelete": "no",
16+
"modOnly": "no",
17+
"modTs": "2025-01-23T11:42:00.631+10:00",
18+
"nonDeployable": "no",
19+
"onBehalfOf": "no",
20+
"pendingRelease": "no",
21+
"resolverType": "mo",
22+
"rn": "ra-[uni/infra/attentp-PHY-DOM_AttEntityP]-6-0-0-0-SubtreeWithRels-mo",
23+
"slotId": "0",
24+
"status": "",
25+
"svc": "6",
26+
"systemId": "0",
27+
"systemType": "0",
28+
"updateType": "SubtreeWithRels"
29+
}
30+
}
31+
}
32+
]
33+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"totalCount": "3",
3+
"imdata": [
4+
{
5+
"pconsRsSubtreeDep": {
6+
"attributes": {
7+
"childAction": "",
8+
"dn": "depRegistry/sdep-physDomP/rssubtreeDep-[registry/class-1809/instdn-[uni/phys-PHY-DOM]/ra-[uni/infra/attentp-PHY-DOM_AttEntityP]-6-0-0-0-SubtreeWithRels-mo/pown-[uni/phys-PHY-DOM]]",
9+
"forceResolve": "yes",
10+
"lcOwn": "local",
11+
"modTs": "2025-01-23T11:41:55.730+10:00",
12+
"rType": "mo",
13+
"rn": "rssubtreeDep-[registry/class-1809/instdn-[uni/phys-PHY-DOM]/ra-[uni/infra/attentp-PHY-DOM_AttEntityP]-6-0-0-0-SubtreeWithRels-mo/pown-[uni/phys-PHY-DOM]]",
14+
"state": "unformed",
15+
"stateQual": "none",
16+
"status": "",
17+
"tCl": "pconsAPolDep",
18+
"tDn": "registry/class-1809/instdn-[uni/phys-PHY-DOM]/ra-[uni/infra/attentp-PHY-DOM_AttEntityP]-6-0-0-0-SubtreeWithRels-mo/pown-[uni/phys-PHY-DOM]",
19+
"tType": "mo"
20+
}
21+
}
22+
}
23+
]
24+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"totalCount": "1",
3+
"imdata": [
4+
{
5+
"physDomP": {
6+
"attributes": {
7+
"annotation": "",
8+
"childAction": "",
9+
"configIssues": "",
10+
"dn": "uni/phys-PHY-DOM",
11+
"extMngdBy": "",
12+
"lcOwn": "local",
13+
"modTs": "2025-01-23T11:41:59.855+10:00",
14+
"monPolDn": "uni/fabric/monfab-default",
15+
"name": "PHY-DOM",
16+
"nameAlias": "",
17+
"ownerKey": "",
18+
"ownerTag": "",
19+
"rn": "phys-PHY-DOM",
20+
"status": "",
21+
"uid": "15374",
22+
"userdom": "all"
23+
}
24+
}
25+
}
26+
]
27+
}
28+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"totalCount": "0",
3+
"imdata": [
4+
]
5+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import os
2+
import pytest
3+
import logging
4+
import importlib
5+
import json
6+
from helpers.utils import read_data
7+
8+
script = importlib.import_module("aci-preupgrade-validation-script")
9+
10+
log = logging.getLogger(__name__)
11+
dir = os.path.dirname(os.path.abspath(__file__))
12+
pcons_rs_subtree_dep_api = 'pconsRsSubtreeDep.json?query-target-filter=wcard(pconsRsSubtreeDep.tDn,"/instdn-")'
13+
pcons_ra_api = 'registry/class-1809/instdn-[uni/phys-PHY-DOM]/ra-[uni/infra/attentp-PHY-DOM_AttEntityP]-6-0-0-0-SubtreeWithRels-mo.json'
14+
policy_dn_api = 'uni/phys-PHY-DOM.json'
15+
16+
@pytest.mark.parametrize(
17+
"icurl_outputs, cversion, tversion, expected_result",
18+
[
19+
# MANUAL when tversion not given
20+
(
21+
{
22+
pcons_rs_subtree_dep_api: read_data(dir, 'pconsRsSubtreeDep.json'),
23+
pcons_ra_api: read_data(dir, 'pconsRA.json'),
24+
policy_dn_api: read_data(dir, 'policyDn.json'),
25+
},
26+
"5.3(2a)",
27+
"",
28+
script.MANUAL,
29+
),
30+
# NA when tversion is older than 6.0(3d)
31+
(
32+
{
33+
pcons_rs_subtree_dep_api: read_data(dir, 'pconsRsSubtreeDep.json'),
34+
pcons_ra_api: read_data(dir, 'pconsRA.json'),
35+
policy_dn_api: read_data(dir, 'policyDn.json'),
36+
},
37+
"5.3(2a)",
38+
"6.0(3c)",
39+
script.NA,
40+
),
41+
# NA when tversion is older than 6.0(3d)
42+
(
43+
{
44+
pcons_rs_subtree_dep_api: read_data(dir, 'pconsRsSubtreeDep.json'),
45+
pcons_ra_api: read_data(dir, 'pconsRA.json'),
46+
policy_dn_api: read_data(dir, 'policyDn.json'),
47+
},
48+
"6.1(2a)",
49+
"6.1(3c)",
50+
script.NA,
51+
),
52+
# pass when tversion is 6.0(3d)+ and policy_dn is found.
53+
(
54+
{
55+
pcons_rs_subtree_dep_api: read_data(dir, 'pconsRsSubtreeDep.json'),
56+
pcons_ra_api: read_data(dir, 'pconsRA.json'),
57+
policy_dn_api: read_data(dir, 'policyDn.json')
58+
},
59+
"5.3(2a)",
60+
"6.0(3d)",
61+
script.PASS,
62+
),
63+
# pass when tversion is newer than 6.1(4a).
64+
(
65+
{
66+
pcons_rs_subtree_dep_api: read_data(dir, 'pconsRsSubtreeDep.json'),
67+
pcons_ra_api: read_data(dir, 'pconsRA.json'),
68+
policy_dn_api: read_data(dir, 'policyDn.json')
69+
},
70+
"5.3(2a)",
71+
"6.1(4a)",
72+
script.NA,
73+
),
74+
# FAIL_O when version tversion is older than 6.0(3d) and policy_dn is NOT found (pcons is stale).
75+
(
76+
{
77+
pcons_rs_subtree_dep_api: read_data(dir, 'pconsRsSubtreeDep.json'),
78+
pcons_ra_api: read_data(dir, 'pconsRA.json'),
79+
policy_dn_api: read_data(dir, 'policyDn_empty.json'),
80+
},
81+
"5.3(2a)",
82+
"6.0(3d)",
83+
script.FAIL_O,
84+
),
85+
# FAIL_O when version tversion is older than 6.0(3d) and policy_dn is NOT found (pcons is stale).
86+
(
87+
{
88+
pcons_rs_subtree_dep_api: read_data(dir, 'pconsRsSubtreeDep.json'),
89+
pcons_ra_api: read_data(dir, 'pconsRA.json'),
90+
policy_dn_api: read_data(dir, 'policyDn_empty.json'),
91+
},
92+
"5.3(2a)",
93+
"6.1(3d)",
94+
script.FAIL_O,
95+
),
96+
],
97+
)
98+
def test_logic(mock_icurl, cversion, tversion, expected_result):
99+
cver = script.AciVersion(cversion) if cversion else None
100+
tver = script.AciVersion(tversion) if tversion else None
101+
102+
result = script.stale_pcons_ra_mo_check(1, 1, cver, tver,)
103+
assert result == expected_result

0 commit comments

Comments
 (0)