diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index 4b83f4c..5f0983f 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -6026,6 +6026,44 @@ def apic_downgrade_compat_warning_check(cversion, tversion, **kwargs): return Result(result=result, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url) +@check_wrapper(check_title="Inband Mgmt Zero Address") +def inband_mgmt_zero_address_check(cversion, tversion, **kwargs): + result = PASS + headers = ["Inband Mgmt EPG", "Node", "Inband Address", "Inband Gateway"] + data = [] + recommended_action = "Remove the zero address(es) from the Inband EPG before upgrade" + doc_url = "https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#inb-mgmt-zero-addr" + + if not tversion: + return Result(result=MANUAL, msg=TVER_MISSING) + # Misconfig Rejected beginning at 6.0(1g) + if cversion.newer_than("6.0(1g)"): + return Result(result=NA, msg=VER_NOT_AFFECTED) + if tversion.older_than("6.0(4g)"): + return Result(result=NA, msg=VER_NOT_AFFECTED) + # Inband Mmgmt Node + mgmtRsInBStNode_api = icurl("class", "mgmtRsInBStNode.json") + if not mgmtRsInBStNode_api: + return Result(result=NA, msg='No mgmtRsInBStNode MOs') + + inb_mgmt_regex = r'uni/tn-mgmt/mgmtp-default/inb' + inb_mgmt_regex += r'-(?P.+)/rsinBStNode-' + inb_mgmt_regex += r'\[' + node_regex + r'\]' + for mgmtInB in mgmtRsInBStNode_api: + addr = mgmtInB["mgmtRsInBStNode"]["attributes"]["addr"] + gw = mgmtInB["mgmtRsInBStNode"]["attributes"]["gw"] + if addr == "0.0.0.0" or gw == "0.0.0.0": + dn = mgmtInB["mgmtRsInBStNode"]["attributes"]["dn"] + inb_array = re.search(inb_mgmt_regex, dn) + node = inb_array.group("node") + inb_epg =inb_array.group("inbepg") + data.append([inb_epg, node, addr, gw ]) + + if data: + result = FAIL_O + return Result(result=result, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url) + + # ---- Script Execution ---- @@ -6188,6 +6226,7 @@ class CheckManager: standby_sup_sync_check, isis_database_byte_check, configpush_shard_check, + inband_mgmt_zero_address_check, ] ssh_checks = [ diff --git a/docs/docs/validations.md b/docs/docs/validations.md index 68ca1c0..be24932 100644 --- a/docs/docs/validations.md +++ b/docs/docs/validations.md @@ -193,6 +193,7 @@ 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: | +[Inb mgmt Zero Addr][d29] | CSCwd40071 | :white_check_mark: | :no_entry_sign: [d1]: #ep-announce-compatibility [d2]: #eventmgr-db-size-defect-susceptibility @@ -222,6 +223,7 @@ Items | Defect | This Script [d26]: #stale-pconsra-object [d27]: #isis-dteps-byte-size [d28]: #policydist-configpushshardcont-crash +[d29]: #inb-mgmt-zero-addr ## General Check Details @@ -2648,6 +2650,16 @@ 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. +### Inb mgmt Zero Addr + +ACI supports both Out-of-band and Inband Management configuration, these inband management policies can be pushed via REST API calls. + +Due to [CSCwd40071][62], ACI accepts a zero, "0.0.0.0" value in Address or Gateway attributes. +This can cause PolicyElem hap resets when a Node downloads the Policy like during an upgrade, which can lead to problems with data plane. + +Remove any instance of misconfiguration before the upgrade to avoid unexpected issues. + + [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 @@ -2710,3 +2722,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/CSCwd40071 \ No newline at end of file diff --git a/preupgrade_validator_2026-02-23T14-15-24-0600.tgz b/preupgrade_validator_2026-02-23T14-15-24-0600.tgz new file mode 100644 index 0000000..38781df Binary files /dev/null and b/preupgrade_validator_2026-02-23T14-15-24-0600.tgz differ diff --git a/tests/checks/inband_mgmt_zero_address_check/mgmtRsInBStNode-neg.json b/tests/checks/inband_mgmt_zero_address_check/mgmtRsInBStNode-neg.json new file mode 100644 index 0000000..5c551cb --- /dev/null +++ b/tests/checks/inband_mgmt_zero_address_check/mgmtRsInBStNode-neg.json @@ -0,0 +1,89 @@ +[ + { + "mgmtRsInBStNode": { + "attributes": { + "addr": "14.2.107.248/28", + "annotation": "", + "childAction": "", + "configurationMode": "static", + "descr": "", + "dn": "uni/tn-mgmt/mgmtp-default/inb-inb/rsinBStNode-[topology/pod-1/node-104]", + "extMngdBy": "", + "forceResolve": "yes", + "gw": "14.2.107.241", + "lcOwn": "local", + "modTs": "2023-03-09T15:09:10.230-06:00", + "rType": "mo", + "rn": "rsinBStNode-[topology/pod-1/node-104]", + "state": "unformed", + "stateQual": "none", + "status": "", + "tCl": "fabricNode", + "tDn": "topology/pod-1/node-104", + "tType": "mo", + "uid": "17189", + "userdom": ":all:", + "v6Addr": "::", + "v6Gw": "::" + } + } + }, + { + "mgmtRsInBStNode": { + "attributes": { + "addr": "172.29.213.72/24", + "annotation": "", + "childAction": "", + "configurationMode": "static", + "descr": "", + "dn": "uni/tn-mgmt/mgmtp-default/inb-InBand/rsinBStNode-[topology/pod-1/node-204]", + "extMngdBy": "", + "forceResolve": "yes", + "gw": "172.29.213.1", + "lcOwn": "local", + "modTs": "2026-02-03T15:12:34.815-06:00", + "rType": "mo", + "rn": "rsinBStNode-[topology/pod-1/node-204]", + "state": "unformed", + "stateQual": "none", + "status": "", + "tCl": "fabricNode", + "tDn": "topology/pod-1/node-204", + "tType": "mo", + "uid": "23653", + "userdom": ":all:", + "v6Addr": "::", + "v6Gw": "::" + } + } + }, + { + "mgmtRsInBStNode": { + "attributes": { + "addr": "172.29.213.82/24", + "annotation": "", + "childAction": "", + "configurationMode": "static", + "descr": "", + "dn": "uni/tn-mgmt/mgmtp-default/inb-InBand/rsinBStNode-[topology/pod-1/node-305]", + "extMngdBy": "", + "forceResolve": "yes", + "gw": "172.29.213.1", + "lcOwn": "local", + "modTs": "2026-02-03T15:12:34.815-06:00", + "rType": "mo", + "rn": "rsinBStNode-[topology/pod-1/node-305]", + "state": "unformed", + "stateQual": "none", + "status": "", + "tCl": "fabricNode", + "tDn": "topology/pod-1/node-305", + "tType": "mo", + "uid": "23653", + "userdom": ":all:", + "v6Addr": "::", + "v6Gw": "::" + } + } + } + ] \ No newline at end of file diff --git a/tests/checks/inband_mgmt_zero_address_check/mgmtRsInBStNode-pos.json b/tests/checks/inband_mgmt_zero_address_check/mgmtRsInBStNode-pos.json new file mode 100644 index 0000000..7d03945 --- /dev/null +++ b/tests/checks/inband_mgmt_zero_address_check/mgmtRsInBStNode-pos.json @@ -0,0 +1,89 @@ +[ + { + "mgmtRsInBStNode": { + "attributes": { + "addr": "0.0.0.0", + "annotation": "", + "childAction": "", + "configurationMode": "static", + "descr": "", + "dn": "uni/tn-mgmt/mgmtp-default/inb-inb/rsinBStNode-[topology/pod-1/node-104]", + "extMngdBy": "", + "forceResolve": "yes", + "gw": "14.2.107.241", + "lcOwn": "local", + "modTs": "2023-03-09T15:09:10.230-06:00", + "rType": "mo", + "rn": "rsinBStNode-[topology/pod-1/node-104]", + "state": "unformed", + "stateQual": "none", + "status": "", + "tCl": "fabricNode", + "tDn": "topology/pod-1/node-104", + "tType": "mo", + "uid": "17189", + "userdom": ":all:", + "v6Addr": "::", + "v6Gw": "::" + } + } + }, + { + "mgmtRsInBStNode": { + "attributes": { + "addr": "172.29.213.72/24", + "annotation": "", + "childAction": "", + "configurationMode": "static", + "descr": "", + "dn": "uni/tn-mgmt/mgmtp-default/inb-InBand/rsinBStNode-[topology/pod-1/node-204]", + "extMngdBy": "", + "forceResolve": "yes", + "gw": "0.0.0.0", + "lcOwn": "local", + "modTs": "2026-02-03T15:12:34.815-06:00", + "rType": "mo", + "rn": "rsinBStNode-[topology/pod-1/node-204]", + "state": "unformed", + "stateQual": "none", + "status": "", + "tCl": "fabricNode", + "tDn": "topology/pod-1/node-204", + "tType": "mo", + "uid": "23653", + "userdom": ":all:", + "v6Addr": "::", + "v6Gw": "::" + } + } + }, + { + "mgmtRsInBStNode": { + "attributes": { + "addr": "172.29.213.82/24", + "annotation": "", + "childAction": "", + "configurationMode": "static", + "descr": "", + "dn": "uni/tn-mgmt/mgmtp-default/inb-InBand/rsinBStNode-[topology/pod-1/node-305]", + "extMngdBy": "", + "forceResolve": "yes", + "gw": "172.29.213.1", + "lcOwn": "local", + "modTs": "2026-02-03T15:12:34.815-06:00", + "rType": "mo", + "rn": "rsinBStNode-[topology/pod-1/node-305]", + "state": "unformed", + "stateQual": "none", + "status": "", + "tCl": "fabricNode", + "tDn": "topology/pod-1/node-305", + "tType": "mo", + "uid": "23653", + "userdom": ":all:", + "v6Addr": "::", + "v6Gw": "::" + } + } + } + ] \ No newline at end of file diff --git a/tests/checks/inband_mgmt_zero_address_check/test_inband_mgmt_zero_address_check.py b/tests/checks/inband_mgmt_zero_address_check/test_inband_mgmt_zero_address_check.py new file mode 100644 index 0000000..b2b1877 --- /dev/null +++ b/tests/checks/inband_mgmt_zero_address_check/test_inband_mgmt_zero_address_check.py @@ -0,0 +1,85 @@ +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 = "inband_mgmt_zero_address_check" + +# icurl queries +mgmtRsInBStNode = "mgmtRsInBStNode.json" + +@pytest.mark.parametrize( + "icurl_outputs, cver, tver, expected_result", + [ + # Target version missing + ( + { + mgmtRsInBStNode: read_data(dir, "mgmtRsInBStNode-pos.json") + }, + "4.2(7p)", + None, + script.MANUAL, + ), + # Current Version not affected (>=6.0-1g) + # NA Current version not affected + ( + { + mgmtRsInBStNode: read_data(dir, "mgmtRsInBStNode-neg.json") + }, + "6.1(1a)", + "6.0(4g)", + script.NA, + ), + # Target Version not affected (<=6.0-4g) + # NA Current version not affected + ( + { + mgmtRsInBStNode: read_data(dir, "mgmtRsInBStNode-neg.json") + }, + "4.2(7a)", + "5.0(4g)", + script.NA, + ), + # Upgrade within the affected version + # NA Affected version, No mgmtRsInBStNode MOs. + ( + { + mgmtRsInBStNode: [] + }, + "5.1(1g)", + "6.0(4g)", + script.NA, + ), + # PASS Affected version, mgmtRsInBStNode MOs, all with Valid addr and gw values + ( + { + mgmtRsInBStNode: read_data(dir, "mgmtRsInBStNode-neg.json") + }, + "5.1(1g)", + "6.0(4g)", + script.PASS, + ), + # FAIL_O + ( + { + mgmtRsInBStNode: read_data(dir, "mgmtRsInBStNode-pos.json") + }, + "5.1(1g)", + "6.0(4g)", + script.FAIL_O, + ), + ], +) +def test_logic(run_check, mock_icurl, cver, tver, expected_result): + result = run_check( + cversion=script.AciVersion(cver), + tversion=script.AciVersion(tver) if tver else None, + ) + assert result.result == expected_result +