Skip to content
56 changes: 56 additions & 0 deletions aci-preupgrade-validation-script.py
Original file line number Diff line number Diff line change
Expand Up @@ -5962,6 +5962,61 @@ def configpush_shard_check(tversion, **kwargs):

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

@check_wrapper(check_title='active_node pres.Listener mo object check')
def active_node_presListener_mo_object_check(tversion, **kwargs):
result = PASS
headers = ["Missing Node ID", "Node Status"]
data = []
fabric_leaf_ids = []
preslistener_leaf_ids = []
recommended_action = 'PresListener objects should be configured for all fabric leaf active nodes before upgrade and target version with the fix for CSCwn81692,version > 6.1(3)'
Comment thread
muthu-ku marked this conversation as resolved.
Outdated
doc_url = 'https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#active_node_presListener_mo_object_check'

url1= 'presListener.json?query-target-filter=wcard(presListener.dn,"4307")'
Comment thread
muthu-ku marked this conversation as resolved.
Outdated
url2='fabricNode.json?query-target-filter=and(wcard(fabricNode.role,"leaf"),wcard(fabricNode.fabricSt,"active"))'
Comment thread
muthu-ku marked this conversation as resolved.
Outdated

presListeners = icurl('class', url1 )
fabric_leaf_data= icurl('class', url2)
Comment thread
muthu-ku marked this conversation as resolved.
Outdated

node_regex = r"uni/infra/nodecfgcont/node-(?P<node>\d+)"
class_regex = r"resregistry/resregistry-(?P<registry>\d+)/class-(?P<class>\d+)"

if not tversion:
return Result(result=MANUAL, msg=TVER_MISSING)

# Only run check if target version < 6.1(3f)
if tversion and tversion.older_than("6.1(3f)"):
Comment thread
muthu-ku marked this conversation as resolved.
Outdated

if fabric_leaf_data :
Comment thread
muthu-ku marked this conversation as resolved.
Outdated
for leaf in fabric_leaf_data:
leaf_id = leaf['fabricNode']['attributes']['id']
fabric_leaf_ids.append(leaf_id)

if presListeners :
Comment thread
muthu-ku marked this conversation as resolved.
Outdated
for presListener_mo in presListeners:
dn = presListener_mo['presListener']['attributes']['dn']
node_match = re.search(node_regex, dn)
class_match = re.search(class_regex, dn)

if class_match and class_match.group("class") == "4307" and node_match:
node = node_match.group("node")
class_id = class_match.group("class")
preslistener_leaf_ids.append(node)

missing_nodes = set(fabric_leaf_ids) - set(preslistener_leaf_ids)

if missing_nodes:
for node_id in sorted(missing_nodes):
data.append([node_id, "active"])
log.warning("Alert ! Some Leaf Nodes missing in PresListener Object \n\n Missing Nodes: {}".format(missing_nodes ))
Comment thread
muthu-ku marked this conversation as resolved.
Outdated
result = FAIL_O
return Result(result=result, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url)
if not fabric_leaf_ids:
return Result(result=FAIL_UF, msg="Could not retrieve any leaf node data")
return Result(result=result, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url)
else:
return Result(result=NA, msg=VER_NOT_AFFECTED)

# ---- Script Execution ----


Expand Down Expand Up @@ -6122,6 +6177,7 @@ class CheckManager:
standby_sup_sync_check,
isis_database_byte_check,
configpush_shard_check,
active_node_presListener_mo_object_check

]
ssh_checks = [
Expand Down
17 changes: 17 additions & 0 deletions docs/docs/validations.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ Items | Defect | This Script
[Stale pconsRA Object][d26] | CSCwp22212 | :warning:{title="Deprecated"} | :no_entry_sign:
[ISIS DTEPs Byte Size][d27] | CSCwp15375 | :white_check_mark: | :no_entry_sign:
[Policydist configpushShardCont Crash][d28] | CSCwp95515 | :white_check_mark: |
[active_node_presListener_mo_object_check][d29] | CSCwn81692 | :white_check_mark: | :no_entry_sign:


[d1]: #ep-announce-compatibility
[d2]: #eventmgr-db-size-defect-susceptibility
Expand Down Expand Up @@ -220,6 +222,7 @@ Items | Defect | This Script
[d26]: #stale-pconsra-object
[d27]: #isis-dteps-byte-size
[d28]: #policydist-configpushshardcont-crash
[d29]: #active_node_presListener_mo_object_check


## General Check Details
Expand Down Expand Up @@ -2604,6 +2607,19 @@ Due to [CSCwp95515][59], upgrading to an affected version while having any `conf
If any instances of `configpushShardCont` are flagged by this script, Cisco TAC must be contacted to identify and resolve the underlying issue before performing the upgrade.


### active_node_presListener_mo_object_check
Comment thread
muthu-ku marked this conversation as resolved.

RCA:
After upgrading the leaf to an affected version, interface configurations are not pushed because the "pres.Listener" object is missing in the APIC.
This occurs due to an incomplete/faulty APIC upgrade.

IMPACT:
If "pres.Listener" is missing after a leaf upgrade or clean reload, leaf ports remain out of service, and infraAccPortP and infraAccBndlGrp cannot program interfaces.

Suggestion:
Verify that all active leaf node objects are present in the "pres.Listener" list (class 4307) and alert if the affected version is detected. If an alert is raised, upgrade to a version that includes the fix for [CSCwn81692][62].


[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
[2]: https://www.cisco.com/c/en/us/support/switches/nexus-9000-series-switches/products-release-notes-list.html
Expand Down Expand Up @@ -2666,3 +2682,4 @@ If any instances of `configpushShardCont` are flagged by this script, Cisco TAC
[59]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwp95515
[60]: https://www.cisco.com/c/en/us/solutions/collateral/data-center-virtualization/application-centric-infrastructure/white-paper-c11-743951.html#Inter
[61]: https://www.cisco.com/c/en/us/solutions/collateral/data-center-virtualization/application-centric-infrastructure/white-paper-c11-743951.html#EnablePolicyCompression
[62]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwn81692
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[
{

"fabricNode": {
"attributes": {
"dn": "topology/pod-1/node-104",
"fabricSt": "active",
"id": "104",
"role": "leaf"
}
}
},
{
"fabricNode": {
"attributes": {
"dn": "topology/pod-1/node-105",
"fabricSt": "active",
"id": "105",
"role": "leaf"
}
}
}

]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[
{
"presListener": {
"attributes": {
"childAction": "",
"dn": "resregistry/resregistry-20/relnholder/rspresClass-[resregistry/resregistry-20/class-4307]/list-[uni/infra/nodecfgcont/node-104]",
"lstDn": "uni/infra/nodecfgcont/node-104"
}
}
},
{
"presListener": {
"attributes": {
"dn": "resregistry/resregistry-20/relnholder/rspresClass-[resregistry/resregistry-20/class-4307]/list-[uni/infra/nodecfgcont/node-105]",
"lstDn": "uni/infra/nodecfgcont/node-105"

}
}
}

]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[
{
"presListener": {
"attributes": {
"dn": "resregistry/resregistry-20/relnholder/rspresClass-[resregistry/resregistry-20/class-4307]/list-[uni/infra/nodecfgcont/node-104]",
"lstDn": "uni/infra/nodecfgcont/node-104"
}
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import os
import pytest
import logging
import importlib
from helpers.utils import read_data

script = importlib.import_module("aci-preupgrade-validation-script")

log = logging.getLogger(__name__)
dir = os.path.dirname(os.path.abspath(__file__))

test_function = "active_node_presListener_mo_object_check"

# icurl queries
presListener = 'presListener.json?query-target-filter=wcard(presListener.dn,"4307")'
fabricNode = 'fabricNode.json?query-target-filter=and(wcard(fabricNode.role,"leaf"),wcard(fabricNode.fabricSt,"active"))'

@pytest.mark.parametrize(
"icurl_outputs, tversion,expected_result",
[
#Check pass case
(
{
presListener: read_data(
dir, "presListener.json"
),
fabricNode: read_data(
dir, "fabricNode.json"
),
},
"6.1(2f)",
script.PASS,
),
#Check with missing nodes
(
{
presListener: read_data(
dir, "presListener_missing_node.json"
),
fabricNode: read_data(
dir, "fabricNode.json"
),
},
"6.1(2f)",
script.FAIL_O
),
#Check with missing nodes on affected version
(
{
presListener: read_data(
dir, "presListener_missing_node.json"
),
fabricNode: read_data(
dir, "fabricNode.json"
),
},
"5.2(8h)",
script.FAIL_O,
),
#Check with empty responses for latest version
(
{
presListener: read_data(
dir, "presListener_empty.json"
),
fabricNode: read_data(
dir, "fabricNode_empty.json"
),
},
"6.1(3h)",
script.NA,
),
#Check with empty responses for affected version
(
{
presListener: read_data(
dir, "presListener_empty.json"
),
fabricNode: read_data(
dir, "fabricNode_empty.json"
),
},
"5.2(8h)",
script.FAIL_UF,
),
# tversion not given
(
{
presListener: read_data(
dir, "presListener_missing_node.json"
),
fabricNode: read_data(
dir, "fabricNode.json"
),
},
None,
script.MANUAL,
),
],
)
def test_logic(run_check,mock_icurl, tversion, expected_result):
result = run_check(tversion=script.AciVersion(tversion) if tversion else None)
assert result.result == expected_result