From 18431a14fc208af6d04806d2af0e04fc68dd850a Mon Sep 17 00:00:00 2001 From: Priyanka Date: Fri, 20 Mar 2026 16:34:31 +0530 Subject: [PATCH 01/13] Added N9300 switch memory check --- aci-preupgrade-validation-script.py | 96 +++++++++++++++- docs/docs/validations.md | 8 ++ .../fabricNode_non_n9300.json | 13 +++ .../fabricNode_one.json | 13 +++ .../fabricNode_two.json | 24 ++++ .../procMemUsage_all_gt24gb.json | 20 ++++ .../procMemUsage_gt24gb.json | 11 ++ .../procMemUsage_lt24gb.json | 11 ++ .../procMemUsage_mixed.json | 20 ++++ .../procMemUsage_node201_gt24gb.json | 11 ++ .../test_n9300_switch_memory_24g_check.py | 105 ++++++++++++++++++ 11 files changed, 327 insertions(+), 5 deletions(-) create mode 100644 tests/checks/n9300_switch_memory_24g_check/fabricNode_non_n9300.json create mode 100644 tests/checks/n9300_switch_memory_24g_check/fabricNode_one.json create mode 100644 tests/checks/n9300_switch_memory_24g_check/fabricNode_two.json create mode 100644 tests/checks/n9300_switch_memory_24g_check/procMemUsage_all_gt24gb.json create mode 100644 tests/checks/n9300_switch_memory_24g_check/procMemUsage_gt24gb.json create mode 100644 tests/checks/n9300_switch_memory_24g_check/procMemUsage_lt24gb.json create mode 100644 tests/checks/n9300_switch_memory_24g_check/procMemUsage_mixed.json create mode 100644 tests/checks/n9300_switch_memory_24g_check/procMemUsage_node201_gt24gb.json create mode 100644 tests/checks/n9300_switch_memory_24g_check/test_n9300_switch_memory_24g_check.py diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index f29c66b..65ffddd 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -950,9 +950,7 @@ def start(self, timeout=5.0): timeout (float): How long we wait for the thread start event. 5.0 sec by default. """ - _active_limbo_lock = threading._active_limbo_lock - _limbo = threading._limbo - _start_new_thread = threading._start_new_thread + _start_new_thread = getattr(threading, "_start_new_thread", None) # Python2 uses name mangling if hasattr(self, "_Thread__initialized"): @@ -968,6 +966,18 @@ def start(self, timeout=5.0): if self._started.is_set(): raise RuntimeError("threads can only be started once") + # Python 3.14+ no longer exposes threading._start_new_thread. + # In that case, defer to Thread.start() to keep internal join handles valid. + if _start_new_thread is None: + super(CustomThread, self).start() + self._started.wait(timeout) + if not self._started.is_set(): + raise RuntimeError("can't start new thread") + return + + _active_limbo_lock = threading._active_limbo_lock + _limbo = threading._limbo + with _active_limbo_lock: _limbo[self] = self try: @@ -1493,11 +1503,19 @@ def get_row(widths, values, spad=" ", lpad=""): def prints(objects, sep=' ', end='\n'): with open(RESULT_FILE, 'a') as f: - print(objects, sep=sep, end=end, file=sys.stdout) + stdout_ok = True + try: + print(objects, sep=sep, end=end, file=sys.stdout) + except (OSError, ValueError): + stdout_ok = False if end == "\r": end = "\n" # easier to read with \n in a log file print(objects, sep=sep, end=end, file=f) - sys.stdout.flush() + if stdout_ok: + try: + sys.stdout.flush() + except (OSError, ValueError): + pass f.flush() @@ -5877,6 +5895,73 @@ def isis_database_byte_check(tversion, **kwargs): return Result(result=result, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url) +@check_wrapper(check_title='N9300 Switch Memory') +def n9300_switch_memory_check(tversion, fabric_nodes, **kwargs): + result = PASS + headers = ["NodeId", "Name", "Model", "Memory Detected (GB)"] + data = [] + recommended_action = 'Increase the switch memory to at least 24GB before proceeding with the Cisco ACI software upgrade.' + doc_url = 'https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#n9300-switch-memory' + min_memory_kb = 24 * 1024 * 1024 + + if not tversion: + return Result(result=MANUAL, msg=TVER_MISSING) + + if tversion.major_version != '6.1': + return Result(result=NA, msg=VER_NOT_AFFECTED) + + proc_mem_query = 'procMemUsage.json' + affected_nodes = [ + node for node in fabric_nodes + if node.get('fabricNode', {}).get('attributes', {}).get('model', '').startswith('N9K-C93') + ] + + if not affected_nodes: + return Result(result=NA, msg='No N9300 switches found. Skipping.') + + proc_mem_mos = icurl('class', proc_mem_query) + node_total_kb = {} + + for memory_mo in proc_mem_mos: + attrs = memory_mo.get('procMemUsage', {}).get('attributes', {}) + total = attrs.get('Total') + mem_dn = attrs.get('dn', '') + if not total or '/memusage-sup' not in mem_dn: + continue + dn_match = re.search(node_regex, mem_dn) + if not dn_match: + continue + try: + total_kb = int(total) + except ValueError: + continue + + node_id = dn_match.group('node') + if node_id not in node_total_kb: + node_total_kb[node_id] = total_kb + + for node in affected_nodes: + node_id = node['fabricNode']['attributes']['id'] + total_kb = node_total_kb.get(node_id) + if total_kb is None: + continue + + memory_in_gb = round(total_kb / 1048576, 2) + if total_kb < min_memory_kb: + result = FAIL_O + data.append([ + node_id, + node['fabricNode']['attributes'].get('name', ''), + node['fabricNode']['attributes'].get('model', ''), + memory_in_gb, + ]) + + if result == PASS: + return Result(result=result) + + return Result(result=result, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url) + + # Subprocess check - cat + acidiag @check_wrapper(check_title='APIC Database Size') def apic_database_size_check(cversion, **kwargs): @@ -6214,6 +6299,7 @@ class CheckManager: pbr_high_scale_check, standby_sup_sync_check, isis_database_byte_check, + n9300_switch_memory_check, configpush_shard_check, auto_firmware_update_on_switch_check, diff --git a/docs/docs/validations.md b/docs/docs/validations.md index f46e03d..0926580 100644 --- a/docs/docs/validations.md +++ b/docs/docs/validations.md @@ -194,6 +194,7 @@ Items | Defect | This Script [ISIS DTEPs Byte Size][d27] | CSCwp15375 | :white_check_mark: | :no_entry_sign: [Policydist configpushShardCont Crash][d28] | CSCwp95515 | :white_check_mark: | :no_entry_sign: [Auto Firmware Update on Switch Discovery][d29] | CSCwe83941 | :white_check_mark: | :no_entry_sign: +[N9300 Switch Memory][d30] | - | :white_check_mark: | :no_entry_sign: [d1]: #ep-announce-compatibility [d2]: #eventmgr-db-size-defect-susceptibility @@ -224,6 +225,7 @@ Items | Defect | This Script [d27]: #isis-dteps-byte-size [d28]: #policydist-configpushshardcont-crash [d29]: #auto-firmware-update-on-switch-discovery +[d30]: #n9300-switch-memory ## General Check Details @@ -2648,6 +2650,12 @@ 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. +### N9300 Switch Memory + +This check applies only when the target upgrade version is 6.1. It reviews `procMemUsage` for N9300-series switches and flags nodes with less than 24GB memory installed. + +If any N9300-series switch is flagged by this check, increase the switch memory to at least 24GB before the upgrade. + ### Auto Firmware Update on Switch Discovery [Auto Firmware Update on Switch Discovery][63] automatically upgrades a new switch to the target firmware version before registering it to the ACI fabric. This feature activates in three scenarios: diff --git a/tests/checks/n9300_switch_memory_24g_check/fabricNode_non_n9300.json b/tests/checks/n9300_switch_memory_24g_check/fabricNode_non_n9300.json new file mode 100644 index 0000000..a82341a --- /dev/null +++ b/tests/checks/n9300_switch_memory_24g_check/fabricNode_non_n9300.json @@ -0,0 +1,13 @@ +[ + { + "fabricNode": { + "attributes": { + "dn": "topology/pod-1/node-201", + "id": "201", + "name": "leaf201", + "model": "N9K-C9508", + "role": "leaf" + } + } + } +] \ No newline at end of file diff --git a/tests/checks/n9300_switch_memory_24g_check/fabricNode_one.json b/tests/checks/n9300_switch_memory_24g_check/fabricNode_one.json new file mode 100644 index 0000000..74a31ad --- /dev/null +++ b/tests/checks/n9300_switch_memory_24g_check/fabricNode_one.json @@ -0,0 +1,13 @@ +[ + { + "fabricNode": { + "attributes": { + "dn": "topology/pod-1/node-101", + "id": "101", + "name": "leaf101", + "model": "N9K-C93180YC-FX3", + "role": "leaf" + } + } + } +] \ No newline at end of file diff --git a/tests/checks/n9300_switch_memory_24g_check/fabricNode_two.json b/tests/checks/n9300_switch_memory_24g_check/fabricNode_two.json new file mode 100644 index 0000000..fad0289 --- /dev/null +++ b/tests/checks/n9300_switch_memory_24g_check/fabricNode_two.json @@ -0,0 +1,24 @@ +[ + { + "fabricNode": { + "attributes": { + "dn": "topology/pod-1/node-101", + "id": "101", + "name": "leaf101", + "model": "N9K-C93180YC-FX3", + "role": "leaf" + } + } + }, + { + "fabricNode": { + "attributes": { + "dn": "topology/pod-1/node-102", + "id": "102", + "name": "leaf102", + "model": "N9K-C9364C", + "role": "leaf" + } + } + } +] \ No newline at end of file diff --git a/tests/checks/n9300_switch_memory_24g_check/procMemUsage_all_gt24gb.json b/tests/checks/n9300_switch_memory_24g_check/procMemUsage_all_gt24gb.json new file mode 100644 index 0000000..dab23d2 --- /dev/null +++ b/tests/checks/n9300_switch_memory_24g_check/procMemUsage_all_gt24gb.json @@ -0,0 +1,20 @@ +[ + { + "procMemUsage": { + "attributes": { + "dn": "topology/pod-1/node-101/sys/procmem/memusage-sup", + "Modname": "sup", + "Total": "32535444" + } + } + }, + { + "procMemUsage": { + "attributes": { + "dn": "topology/pod-1/node-102/sys/procmem/memusage-sup", + "Modname": "sup", + "Total": "28535444" + } + } + } +] \ No newline at end of file diff --git a/tests/checks/n9300_switch_memory_24g_check/procMemUsage_gt24gb.json b/tests/checks/n9300_switch_memory_24g_check/procMemUsage_gt24gb.json new file mode 100644 index 0000000..597db59 --- /dev/null +++ b/tests/checks/n9300_switch_memory_24g_check/procMemUsage_gt24gb.json @@ -0,0 +1,11 @@ +[ + { + "procMemUsage": { + "attributes": { + "dn": "topology/pod-1/node-101/sys/procmem/memusage-sup", + "Modname": "sup", + "Total": "26535444" + } + } + } +] \ No newline at end of file diff --git a/tests/checks/n9300_switch_memory_24g_check/procMemUsage_lt24gb.json b/tests/checks/n9300_switch_memory_24g_check/procMemUsage_lt24gb.json new file mode 100644 index 0000000..d84e82c --- /dev/null +++ b/tests/checks/n9300_switch_memory_24g_check/procMemUsage_lt24gb.json @@ -0,0 +1,11 @@ +[ + { + "procMemUsage": { + "attributes": { + "dn": "topology/pod-1/node-101/sys/procmem/memusage-sup", + "Modname": "sup", + "Total": "22535444" + } + } + } +] \ No newline at end of file diff --git a/tests/checks/n9300_switch_memory_24g_check/procMemUsage_mixed.json b/tests/checks/n9300_switch_memory_24g_check/procMemUsage_mixed.json new file mode 100644 index 0000000..58ece8e --- /dev/null +++ b/tests/checks/n9300_switch_memory_24g_check/procMemUsage_mixed.json @@ -0,0 +1,20 @@ +[ + { + "procMemUsage": { + "attributes": { + "dn": "topology/pod-1/node-101/sys/procmem/memusage-sup", + "Modname": "sup", + "Total": "32535444" + } + } + }, + { + "procMemUsage": { + "attributes": { + "dn": "topology/pod-1/node-102/sys/procmem/memusage-sup", + "Modname": "sup", + "Total": "22535444" + } + } + } +] \ No newline at end of file diff --git a/tests/checks/n9300_switch_memory_24g_check/procMemUsage_node201_gt24gb.json b/tests/checks/n9300_switch_memory_24g_check/procMemUsage_node201_gt24gb.json new file mode 100644 index 0000000..bca2b9f --- /dev/null +++ b/tests/checks/n9300_switch_memory_24g_check/procMemUsage_node201_gt24gb.json @@ -0,0 +1,11 @@ +[ + { + "procMemUsage": { + "attributes": { + "dn": "topology/pod-1/node-201/sys/procmem/memusage-sup", + "Modname": "sup", + "Total": "28535444" + } + } + } +] \ No newline at end of file diff --git a/tests/checks/n9300_switch_memory_24g_check/test_n9300_switch_memory_24g_check.py b/tests/checks/n9300_switch_memory_24g_check/test_n9300_switch_memory_24g_check.py new file mode 100644 index 0000000..8ae92ad --- /dev/null +++ b/tests/checks/n9300_switch_memory_24g_check/test_n9300_switch_memory_24g_check.py @@ -0,0 +1,105 @@ +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 = "n9300_switch_memory_check" + +# icurl queries +proc_mem_query = 'procMemUsage.json' + + +@pytest.mark.parametrize( + "fabric_nodes, icurl_outputs, tversion, expected_result, expected_msg, expected_data", + [ + # Target version missing + ( + read_data(dir, "fabricNode_one.json"), + { + proc_mem_query: read_data(dir, "procMemUsage_gt24gb.json"), + }, + None, + script.MANUAL, + script.TVER_MISSING, + [], + ), + # Target version not affected + ( + read_data(dir, "fabricNode_one.json"), + { + proc_mem_query: read_data(dir, "procMemUsage_gt24gb.json"), + }, + "6.0(3c)", + script.NA, + script.VER_NOT_AFFECTED, + [], + ), + # No nodes returned + ( + [], + {}, + "6.1(2f)", + script.NA, + 'No N9300 switches found. Skipping.', + [], + ), + # Non-N9300 node with >=24GB memory + ( + read_data(dir, "fabricNode_non_n9300.json"), + { + proc_mem_query: read_data(dir, "procMemUsage_node201_gt24gb.json"), + }, + "6.1(2f)", + script.NA, + 'No N9300 switches found. Skipping.', + [], + ), + # N9300 node with >=24GB memory + ( + read_data(dir, "fabricNode_one.json"), + { + proc_mem_query: read_data(dir, "procMemUsage_gt24gb.json"), + }, + "6.1(2f)", + script.PASS, + '', + [], + ), + # Multiple N9300 nodes, all >=24GB memory + ( + read_data(dir, "fabricNode_two.json"), + { + proc_mem_query: read_data(dir, "procMemUsage_all_gt24gb.json"), + }, + "6.1(2f)", + script.PASS, + '', + [], + ), + # N9300 node with <24GB memory + ( + read_data(dir, "fabricNode_two.json"), + { + proc_mem_query: read_data(dir, "procMemUsage_mixed.json"), + }, + "6.1(2f)", + script.FAIL_O, + '', + [["102", "leaf102", "N9K-C9364C", 21.49]], + ), + ], +) +def test_logic(run_check, mock_icurl, fabric_nodes, tversion, expected_result, expected_msg, expected_data): + result = run_check( + tversion=script.AciVersion(tversion) if tversion else None, + fabric_nodes=fabric_nodes, + ) + assert result.result == expected_result + assert result.msg == expected_msg + assert result.data == expected_data \ No newline at end of file From a0e132acf5e88ca5142790afefdcfe32a488145f Mon Sep 17 00:00:00 2001 From: Priyanka Date: Fri, 20 Mar 2026 17:29:45 +0530 Subject: [PATCH 02/13] Remove unrelated thread/prints changes from N9300 check PR --- aci-preupgrade-validation-script.py | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index 65ffddd..b19128c 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -950,7 +950,9 @@ def start(self, timeout=5.0): timeout (float): How long we wait for the thread start event. 5.0 sec by default. """ - _start_new_thread = getattr(threading, "_start_new_thread", None) + _active_limbo_lock = threading._active_limbo_lock + _limbo = threading._limbo + _start_new_thread = threading._start_new_thread # Python2 uses name mangling if hasattr(self, "_Thread__initialized"): @@ -966,18 +968,6 @@ def start(self, timeout=5.0): if self._started.is_set(): raise RuntimeError("threads can only be started once") - # Python 3.14+ no longer exposes threading._start_new_thread. - # In that case, defer to Thread.start() to keep internal join handles valid. - if _start_new_thread is None: - super(CustomThread, self).start() - self._started.wait(timeout) - if not self._started.is_set(): - raise RuntimeError("can't start new thread") - return - - _active_limbo_lock = threading._active_limbo_lock - _limbo = threading._limbo - with _active_limbo_lock: _limbo[self] = self try: @@ -1503,19 +1493,11 @@ def get_row(widths, values, spad=" ", lpad=""): def prints(objects, sep=' ', end='\n'): with open(RESULT_FILE, 'a') as f: - stdout_ok = True - try: - print(objects, sep=sep, end=end, file=sys.stdout) - except (OSError, ValueError): - stdout_ok = False + print(objects, sep=sep, end=end, file=sys.stdout) if end == "\r": end = "\n" # easier to read with \n in a log file print(objects, sep=sep, end=end, file=f) - if stdout_ok: - try: - sys.stdout.flush() - except (OSError, ValueError): - pass + sys.stdout.flush() f.flush() From 827d36e1c8ec09de089daf428dbff9178c6fcf6c Mon Sep 17 00:00:00 2001 From: Priyanka Date: Mon, 23 Mar 2026 18:02:32 +0530 Subject: [PATCH 03/13] Addressed PR comments --- aci-preupgrade-validation-script.py | 8 +---- docs/docs/validations.md | 14 ++++---- .../test_n9300_switch_memory_24g_check.py | 34 ++++--------------- 3 files changed, 15 insertions(+), 41 deletions(-) diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index b19128c..95940cc 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -5882,16 +5882,10 @@ def n9300_switch_memory_check(tversion, fabric_nodes, **kwargs): result = PASS headers = ["NodeId", "Name", "Model", "Memory Detected (GB)"] data = [] - recommended_action = 'Increase the switch memory to at least 24GB before proceeding with the Cisco ACI software upgrade.' + recommended_action = 'Increase the switch memory to at least 24GB on affected N9300-series switches.' doc_url = 'https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#n9300-switch-memory' min_memory_kb = 24 * 1024 * 1024 - if not tversion: - return Result(result=MANUAL, msg=TVER_MISSING) - - if tversion.major_version != '6.1': - return Result(result=NA, msg=VER_NOT_AFFECTED) - proc_mem_query = 'procMemUsage.json' affected_nodes = [ node for node in fabric_nodes diff --git a/docs/docs/validations.md b/docs/docs/validations.md index 0926580..537a289 100644 --- a/docs/docs/validations.md +++ b/docs/docs/validations.md @@ -2650,12 +2650,6 @@ 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. -### N9300 Switch Memory - -This check applies only when the target upgrade version is 6.1. It reviews `procMemUsage` for N9300-series switches and flags nodes with less than 24GB memory installed. - -If any N9300-series switch is flagged by this check, increase the switch memory to at least 24GB before the upgrade. - ### Auto Firmware Update on Switch Discovery [Auto Firmware Update on Switch Discovery][63] automatically upgrades a new switch to the target firmware version before registering it to the ACI fabric. This feature activates in three scenarios: @@ -2675,6 +2669,14 @@ To avoid this risk, consider disabling Auto Firmware Update before upgrading to !!! note This issue occurs because older switch firmware versions are not compatible with switch images 6.0(3) or newer. The APIC version is not a factor. +### N9300 Switch Memory + +This check applies to N9300-series switches only. It reviews `procMemUsage` and flags nodes with less than 24GB memory installed. + +Impact: Running an N9300-series switch with less than 24GB memory can lead to memory pressure and increase the risk of service instability. + +If any N9300-series switch is flagged by this check, increase the switch memory to at least 24GB. + [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 diff --git a/tests/checks/n9300_switch_memory_24g_check/test_n9300_switch_memory_24g_check.py b/tests/checks/n9300_switch_memory_24g_check/test_n9300_switch_memory_24g_check.py index 8ae92ad..72b76de 100644 --- a/tests/checks/n9300_switch_memory_24g_check/test_n9300_switch_memory_24g_check.py +++ b/tests/checks/n9300_switch_memory_24g_check/test_n9300_switch_memory_24g_check.py @@ -18,33 +18,11 @@ @pytest.mark.parametrize( "fabric_nodes, icurl_outputs, tversion, expected_result, expected_msg, expected_data", [ - # Target version missing - ( - read_data(dir, "fabricNode_one.json"), - { - proc_mem_query: read_data(dir, "procMemUsage_gt24gb.json"), - }, - None, - script.MANUAL, - script.TVER_MISSING, - [], - ), - # Target version not affected - ( - read_data(dir, "fabricNode_one.json"), - { - proc_mem_query: read_data(dir, "procMemUsage_gt24gb.json"), - }, - "6.0(3c)", - script.NA, - script.VER_NOT_AFFECTED, - [], - ), # No nodes returned ( [], {}, - "6.1(2f)", + "6.0(3c)", script.NA, 'No N9300 switches found. Skipping.', [], @@ -55,7 +33,7 @@ { proc_mem_query: read_data(dir, "procMemUsage_node201_gt24gb.json"), }, - "6.1(2f)", + "6.0(3c)", script.NA, 'No N9300 switches found. Skipping.', [], @@ -66,7 +44,7 @@ { proc_mem_query: read_data(dir, "procMemUsage_gt24gb.json"), }, - "6.1(2f)", + "6.0(3c)", script.PASS, '', [], @@ -77,7 +55,7 @@ { proc_mem_query: read_data(dir, "procMemUsage_all_gt24gb.json"), }, - "6.1(2f)", + "6.0(3c)", script.PASS, '', [], @@ -88,7 +66,7 @@ { proc_mem_query: read_data(dir, "procMemUsage_mixed.json"), }, - "6.1(2f)", + "6.0(3c)", script.FAIL_O, '', [["102", "leaf102", "N9K-C9364C", 21.49]], @@ -97,7 +75,7 @@ ) def test_logic(run_check, mock_icurl, fabric_nodes, tversion, expected_result, expected_msg, expected_data): result = run_check( - tversion=script.AciVersion(tversion) if tversion else None, + tversion=script.AciVersion(tversion), fabric_nodes=fabric_nodes, ) assert result.result == expected_result From 648e8c3fd7a5e733a7aca9ae809af7ca329c8929 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Tue, 24 Mar 2026 15:30:49 +0530 Subject: [PATCH 04/13] Addressed and updated n9300_switch_memory_check files --- aci-preupgrade-validation-script.py | 148 ++++++++++-------- .../procMemUsage_invalid_total.json | 11 ++ .../procMemUsage_missing_affected_node.json | 11 ++ .../test_n9300_switch_memory_24g_check.py | 22 +++ 4 files changed, 130 insertions(+), 62 deletions(-) create mode 100644 tests/checks/n9300_switch_memory_24g_check/procMemUsage_invalid_total.json create mode 100644 tests/checks/n9300_switch_memory_24g_check/procMemUsage_missing_affected_node.json diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index 95940cc..256a10e 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -5877,67 +5877,6 @@ def isis_database_byte_check(tversion, **kwargs): return Result(result=result, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url) -@check_wrapper(check_title='N9300 Switch Memory') -def n9300_switch_memory_check(tversion, fabric_nodes, **kwargs): - result = PASS - headers = ["NodeId", "Name", "Model", "Memory Detected (GB)"] - data = [] - recommended_action = 'Increase the switch memory to at least 24GB on affected N9300-series switches.' - doc_url = 'https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#n9300-switch-memory' - min_memory_kb = 24 * 1024 * 1024 - - proc_mem_query = 'procMemUsage.json' - affected_nodes = [ - node for node in fabric_nodes - if node.get('fabricNode', {}).get('attributes', {}).get('model', '').startswith('N9K-C93') - ] - - if not affected_nodes: - return Result(result=NA, msg='No N9300 switches found. Skipping.') - - proc_mem_mos = icurl('class', proc_mem_query) - node_total_kb = {} - - for memory_mo in proc_mem_mos: - attrs = memory_mo.get('procMemUsage', {}).get('attributes', {}) - total = attrs.get('Total') - mem_dn = attrs.get('dn', '') - if not total or '/memusage-sup' not in mem_dn: - continue - dn_match = re.search(node_regex, mem_dn) - if not dn_match: - continue - try: - total_kb = int(total) - except ValueError: - continue - - node_id = dn_match.group('node') - if node_id not in node_total_kb: - node_total_kb[node_id] = total_kb - - for node in affected_nodes: - node_id = node['fabricNode']['attributes']['id'] - total_kb = node_total_kb.get(node_id) - if total_kb is None: - continue - - memory_in_gb = round(total_kb / 1048576, 2) - if total_kb < min_memory_kb: - result = FAIL_O - data.append([ - node_id, - node['fabricNode']['attributes'].get('name', ''), - node['fabricNode']['attributes'].get('model', ''), - memory_in_gb, - ]) - - if result == PASS: - return Result(result=result) - - return Result(result=result, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url) - - # Subprocess check - cat + acidiag @check_wrapper(check_title='APIC Database Size') def apic_database_size_check(cversion, **kwargs): @@ -6114,6 +6053,91 @@ def auto_firmware_update_on_switch_check(cversion, tversion, **kwargs): return Result(result=result, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url) + +@check_wrapper(check_title='N9300 Switch Memory') +def n9300_switch_memory_check(tversion, fabric_nodes, **kwargs): + result = PASS + headers = ["NodeId", "Name", "Model", "Memory Detected (GB)"] + data = [] + recommended_action = 'Increase the switch memory to at least 24GB on affected N9300-series switches.' + doc_url = 'https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#n9300-switch-memory' + min_memory_kb = 24 * 1024 * 1024 + + affected_nodes = [ + node for node in fabric_nodes + if node.get('fabricNode', {}).get('attributes', {}).get('model', '').startswith('N9K-C93') + ] + + if not affected_nodes: + return Result(result=NA, msg='No N9300 switches found. Skipping.') + + proc_mem_mos = icurl('class', 'procMemUsage.json') + node_total_kb = {} + parse_errors = [] + + for memory_mo in proc_mem_mos: + attrs = memory_mo.get('procMemUsage', {}).get('attributes', {}) + total = attrs.get('Total') + mem_dn = attrs.get('dn', '') + if not total or '/memusage-sup' not in mem_dn: + continue + dn_match = re.search(node_regex, mem_dn) + if not dn_match: + continue + try: + total_kb = int(total) + except (TypeError, ValueError): + parse_errors.append([mem_dn, total]) + continue + + node_id = dn_match.group('node') + if node_id not in node_total_kb: + node_total_kb[node_id] = total_kb + + if parse_errors: + return Result( + result=ERROR, + msg='Failed to parse procMemUsage Total for one or more nodes.', + headers=['DN', 'Total'], + data=parse_errors, + ) + + missing_nodes = [] + + for node in affected_nodes: + node_id = node['fabricNode']['attributes']['id'] + total_kb = node_total_kb.get(node_id) + if total_kb is None: + missing_nodes.append([ + node_id, + node['fabricNode']['attributes'].get('name', ''), + node['fabricNode']['attributes'].get('model', ''), + ]) + continue + + memory_in_gb = round(total_kb / 1048576, 2) + if total_kb < min_memory_kb: + result = FAIL_O + data.append([ + node_id, + node['fabricNode']['attributes'].get('name', ''), + node['fabricNode']['attributes'].get('model', ''), + memory_in_gb, + ]) + + if missing_nodes: + return Result( + result=ERROR, + msg='Missing procMemUsage data for one or more affected N9300 nodes.', + headers=['NodeId', 'Name', 'Model'], + data=missing_nodes, + ) + + if result == FAIL_O: + return Result(result=result, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url) + + return Result(result=result) + # ---- Script Execution ---- @@ -6275,9 +6299,9 @@ class CheckManager: pbr_high_scale_check, standby_sup_sync_check, isis_database_byte_check, - n9300_switch_memory_check, configpush_shard_check, auto_firmware_update_on_switch_check, + n9300_switch_memory_check, ] ssh_checks = [ diff --git a/tests/checks/n9300_switch_memory_24g_check/procMemUsage_invalid_total.json b/tests/checks/n9300_switch_memory_24g_check/procMemUsage_invalid_total.json new file mode 100644 index 0000000..dc1a4ee --- /dev/null +++ b/tests/checks/n9300_switch_memory_24g_check/procMemUsage_invalid_total.json @@ -0,0 +1,11 @@ +[ + { + "procMemUsage": { + "attributes": { + "dn": "topology/pod-1/node-101/sys/procmem/memusage-sup", + "Modname": "sup", + "Total": "unknown" + } + } + } +] diff --git a/tests/checks/n9300_switch_memory_24g_check/procMemUsage_missing_affected_node.json b/tests/checks/n9300_switch_memory_24g_check/procMemUsage_missing_affected_node.json new file mode 100644 index 0000000..e11293a --- /dev/null +++ b/tests/checks/n9300_switch_memory_24g_check/procMemUsage_missing_affected_node.json @@ -0,0 +1,11 @@ +[ + { + "procMemUsage": { + "attributes": { + "dn": "topology/pod-1/node-201/sys/procmem/memusage-sup", + "Modname": "sup", + "Total": "26535444" + } + } + } +] diff --git a/tests/checks/n9300_switch_memory_24g_check/test_n9300_switch_memory_24g_check.py b/tests/checks/n9300_switch_memory_24g_check/test_n9300_switch_memory_24g_check.py index 72b76de..0f6aa00 100644 --- a/tests/checks/n9300_switch_memory_24g_check/test_n9300_switch_memory_24g_check.py +++ b/tests/checks/n9300_switch_memory_24g_check/test_n9300_switch_memory_24g_check.py @@ -60,6 +60,28 @@ '', [], ), + # Invalid procMemUsage Total value + ( + read_data(dir, "fabricNode_one.json"), + { + proc_mem_query: read_data(dir, "procMemUsage_invalid_total.json"), + }, + "6.0(3c)", + script.ERROR, + 'Failed to parse procMemUsage Total for one or more nodes.', + [["topology/pod-1/node-101/sys/procmem/memusage-sup", "unknown"]], + ), + # Missing procMemUsage data for affected node + ( + read_data(dir, "fabricNode_one.json"), + { + proc_mem_query: read_data(dir, "procMemUsage_missing_affected_node.json"), + }, + "6.0(3c)", + script.ERROR, + 'Missing procMemUsage data for one or more affected N9300 nodes.', + [["101", "leaf101", "N9K-C93180YC-FX3"]], + ), # N9300 node with <24GB memory ( read_data(dir, "fabricNode_two.json"), From a38bdf8d71fb4ae1f5b7028f1a833b8c0d744243 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Wed, 25 Mar 2026 09:20:05 +0530 Subject: [PATCH 05/13] Updated aci-preupgrade-validation-script.py script --- aci-preupgrade-validation-script.py | 121 +++++++++++++--------------- 1 file changed, 58 insertions(+), 63 deletions(-) diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index 256a10e..9ee408a 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -6062,6 +6062,7 @@ def n9300_switch_memory_check(tversion, fabric_nodes, **kwargs): recommended_action = 'Increase the switch memory to at least 24GB on affected N9300-series switches.' doc_url = 'https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#n9300-switch-memory' min_memory_kb = 24 * 1024 * 1024 + msg = '' affected_nodes = [ node for node in fabric_nodes @@ -6069,74 +6070,68 @@ def n9300_switch_memory_check(tversion, fabric_nodes, **kwargs): ] if not affected_nodes: - return Result(result=NA, msg='No N9300 switches found. Skipping.') - - proc_mem_mos = icurl('class', 'procMemUsage.json') - node_total_kb = {} - parse_errors = [] - - for memory_mo in proc_mem_mos: - attrs = memory_mo.get('procMemUsage', {}).get('attributes', {}) - total = attrs.get('Total') - mem_dn = attrs.get('dn', '') - if not total or '/memusage-sup' not in mem_dn: - continue - dn_match = re.search(node_regex, mem_dn) - if not dn_match: - continue - try: - total_kb = int(total) - except (TypeError, ValueError): - parse_errors.append([mem_dn, total]) - continue - - node_id = dn_match.group('node') - if node_id not in node_total_kb: - node_total_kb[node_id] = total_kb - - if parse_errors: - return Result( - result=ERROR, - msg='Failed to parse procMemUsage Total for one or more nodes.', - headers=['DN', 'Total'], - data=parse_errors, - ) - - missing_nodes = [] + result = NA + msg = 'No N9300 switches found. Skipping.' + else: + proc_mem_mos = icurl('class', 'procMemUsage.json') + node_total_kb = {} + parse_errors = [] + + for memory_mo in proc_mem_mos: + attrs = memory_mo.get('procMemUsage', {}).get('attributes', {}) + total = attrs.get('Total') + mem_dn = attrs.get('dn', '') + if not total or '/memusage-sup' not in mem_dn: + continue + dn_match = re.search(node_regex, mem_dn) + if not dn_match: + continue + try: + total_kb = int(total) + except (TypeError, ValueError): + parse_errors.append([mem_dn, total]) + continue - for node in affected_nodes: - node_id = node['fabricNode']['attributes']['id'] - total_kb = node_total_kb.get(node_id) - if total_kb is None: - missing_nodes.append([ - node_id, - node['fabricNode']['attributes'].get('name', ''), - node['fabricNode']['attributes'].get('model', ''), - ]) - continue + node_id = dn_match.group('node') + if node_id not in node_total_kb: + node_total_kb[node_id] = total_kb - memory_in_gb = round(total_kb / 1048576, 2) - if total_kb < min_memory_kb: - result = FAIL_O - data.append([ - node_id, - node['fabricNode']['attributes'].get('name', ''), - node['fabricNode']['attributes'].get('model', ''), - memory_in_gb, - ]) + if parse_errors: + result = ERROR + msg = 'Failed to parse procMemUsage Total for one or more nodes.' + headers = ['DN', 'Total'] + data = parse_errors + else: + missing_nodes = [] + + for node in affected_nodes: + node_id = node['fabricNode']['attributes']['id'] + total_kb = node_total_kb.get(node_id) + if total_kb is None: + missing_nodes.append([ + node_id, + node['fabricNode']['attributes'].get('name', ''), + node['fabricNode']['attributes'].get('model', ''), + ]) + continue - if missing_nodes: - return Result( - result=ERROR, - msg='Missing procMemUsage data for one or more affected N9300 nodes.', - headers=['NodeId', 'Name', 'Model'], - data=missing_nodes, - ) + if total_kb < min_memory_kb: + memory_in_gb = round(total_kb / 1048576, 2) + result = FAIL_O + data.append([ + node_id, + node['fabricNode']['attributes'].get('name', ''), + node['fabricNode']['attributes'].get('model', ''), + memory_in_gb, + ]) - if result == FAIL_O: - return Result(result=result, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url) + if missing_nodes: + result = ERROR + msg = 'Missing procMemUsage data for one or more affected N9300 nodes.' + headers = ['NodeId', 'Name', 'Model'] + data = missing_nodes - return Result(result=result) + return Result(result=result, msg=msg, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url) # ---- Script Execution ---- From 477dd2415d5da309589a74aba41ff5c15ad02580 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Thu, 9 Apr 2026 17:10:14 +0530 Subject: [PATCH 06/13] Move n9300_switch_memory_check to bottom of check definitions --- aci-preupgrade-validation-script.py | 162 ++++++++++++++-------------- 1 file changed, 81 insertions(+), 81 deletions(-) diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index 1f2f056..78b84bf 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -6092,86 +6092,6 @@ def auto_firmware_update_on_switch_check(cversion, tversion, **kwargs): return Result(result=result, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url) -@check_wrapper(check_title='N9300 Switch Memory') -def n9300_switch_memory_check(tversion, fabric_nodes, **kwargs): - result = PASS - headers = ["NodeId", "Name", "Model", "Memory Detected (GB)"] - data = [] - recommended_action = 'Increase the switch memory to at least 24GB on affected N9300-series switches.' - doc_url = 'https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#n9300-switch-memory' - min_memory_kb = 24 * 1024 * 1024 - msg = '' - - affected_nodes = [ - node for node in fabric_nodes - if node.get('fabricNode', {}).get('attributes', {}).get('model', '').startswith('N9K-C93') - ] - - if not affected_nodes: - result = NA - msg = 'No N9300 switches found. Skipping.' - else: - proc_mem_mos = icurl('class', 'procMemUsage.json') - node_total_kb = {} - parse_errors = [] - - for memory_mo in proc_mem_mos: - attrs = memory_mo.get('procMemUsage', {}).get('attributes', {}) - total = attrs.get('Total') - mem_dn = attrs.get('dn', '') - if not total or '/memusage-sup' not in mem_dn: - continue - dn_match = re.search(node_regex, mem_dn) - if not dn_match: - continue - try: - total_kb = int(total) - except (TypeError, ValueError): - parse_errors.append([mem_dn, total]) - continue - - node_id = dn_match.group('node') - if node_id not in node_total_kb: - node_total_kb[node_id] = total_kb - - if parse_errors: - result = ERROR - msg = 'Failed to parse procMemUsage Total for one or more nodes.' - headers = ['DN', 'Total'] - data = parse_errors - else: - missing_nodes = [] - - for node in affected_nodes: - node_id = node['fabricNode']['attributes']['id'] - total_kb = node_total_kb.get(node_id) - if total_kb is None: - missing_nodes.append([ - node_id, - node['fabricNode']['attributes'].get('name', ''), - node['fabricNode']['attributes'].get('model', ''), - ]) - continue - - if total_kb < min_memory_kb: - memory_in_gb = round(total_kb / 1048576, 2) - result = FAIL_O - data.append([ - node_id, - node['fabricNode']['attributes'].get('name', ''), - node['fabricNode']['attributes'].get('model', ''), - memory_in_gb, - ]) - - if missing_nodes: - result = ERROR - msg = 'Missing procMemUsage data for one or more affected N9300 nodes.' - headers = ['NodeId', 'Name', 'Model'] - data = missing_nodes - - return Result(result=result, msg=msg, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url) - - @check_wrapper(check_title='Rogue EP Exception List missing on switches') def rogue_ep_coop_exception_mac_check(cversion, tversion, **kwargs): result = PASS @@ -6373,6 +6293,86 @@ def multipod_modular_spine_bootscript_check(tversion, fabric_nodes, username, pa return Result(result=result, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url) +@check_wrapper(check_title='N9300 Switch Memory') +def n9300_switch_memory_check(tversion, fabric_nodes, **kwargs): + result = PASS + headers = ["NodeId", "Name", "Model", "Memory Detected (GB)"] + data = [] + recommended_action = 'Increase the switch memory to at least 24GB on affected N9300-series switches.' + doc_url = 'https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#n9300-switch-memory' + min_memory_kb = 24 * 1024 * 1024 + msg = '' + + affected_nodes = [ + node for node in fabric_nodes + if node.get('fabricNode', {}).get('attributes', {}).get('model', '').startswith('N9K-C93') + ] + + if not affected_nodes: + result = NA + msg = 'No N9300 switches found. Skipping.' + else: + proc_mem_mos = icurl('class', 'procMemUsage.json') + node_total_kb = {} + parse_errors = [] + + for memory_mo in proc_mem_mos: + attrs = memory_mo.get('procMemUsage', {}).get('attributes', {}) + total = attrs.get('Total') + mem_dn = attrs.get('dn', '') + if not total or '/memusage-sup' not in mem_dn: + continue + dn_match = re.search(node_regex, mem_dn) + if not dn_match: + continue + try: + total_kb = int(total) + except (TypeError, ValueError): + parse_errors.append([mem_dn, total]) + continue + + node_id = dn_match.group('node') + if node_id not in node_total_kb: + node_total_kb[node_id] = total_kb + + if parse_errors: + result = ERROR + msg = 'Failed to parse procMemUsage Total for one or more nodes.' + headers = ['DN', 'Total'] + data = parse_errors + else: + missing_nodes = [] + + for node in affected_nodes: + node_id = node['fabricNode']['attributes']['id'] + total_kb = node_total_kb.get(node_id) + if total_kb is None: + missing_nodes.append([ + node_id, + node['fabricNode']['attributes'].get('name', ''), + node['fabricNode']['attributes'].get('model', ''), + ]) + continue + + if total_kb < min_memory_kb: + memory_in_gb = round(total_kb / 1048576, 2) + result = FAIL_O + data.append([ + node_id, + node['fabricNode']['attributes'].get('name', ''), + node['fabricNode']['attributes'].get('model', ''), + memory_in_gb, + ]) + + if missing_nodes: + result = ERROR + msg = 'Missing procMemUsage data for one or more affected N9300 nodes.' + headers = ['NodeId', 'Name', 'Model'] + data = missing_nodes + + return Result(result=result, msg=msg, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url) + + # ---- Script Execution ---- @@ -6540,9 +6540,9 @@ class CheckManager: isis_database_byte_check, configpush_shard_check, auto_firmware_update_on_switch_check, - n9300_switch_memory_check, rogue_ep_coop_exception_mac_check, n9k_c9408_model_lem_count_check, + n9300_switch_memory_check, ] ssh_checks = [ # General From 039c1b9232780aa6b0d50fda8a828ebf5b7b8536 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Thu, 9 Apr 2026 17:52:00 +0530 Subject: [PATCH 07/13] Moved N9300 Switch Memory to general checks section in docs --- docs/docs/validations.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/validations.md b/docs/docs/validations.md index 0c7950a..ba2888a 100644 --- a/docs/docs/validations.md +++ b/docs/docs/validations.md @@ -37,6 +37,7 @@ Items | This Script [Fabric Link Redundancy][g17] | :white_check_mark: | :no_entry_sign: [APIC Database Size][g18] | :white_check_mark: | :no_entry_sign: [APIC downgrade compatibility when crossing 6.2 release][g19]| :white_check_mark: | :no_entry_sign: +[N9300 Switch Memory][g20] | :white_check_mark: | :no_entry_sign: [g1]: #compatibility-target-aci-version [g2]: #compatibility-cimc-version @@ -57,6 +58,7 @@ Items | This Script [g17]: #fabric-link-redundancy [g18]: #apic-database-size [g19]: #apic-downgrade-compatibility-when-crossing-62-release +[g20]: #n9300-switch-memory ### Fault Checks Items | Faults | This Script | APIC built-in @@ -198,7 +200,6 @@ Items | Defect | This Script [Rogue EP Exception List missing on switches][d30] | CSCwp64296 | :white_check_mark: | :no_entry_sign: [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: -[N9300 Switch Memory][d33] | - | :white_check_mark: | :no_entry_sign: [d1]: #ep-announce-compatibility [d2]: #eventmgr-db-size-defect-susceptibility @@ -232,7 +233,6 @@ Items | Defect | This Script [d30]: #rogue-ep-exception-list-missing-on-switches [d31]: #n9k-c9408-with-more-than-5-n9k-x9400-16w-lems [d32]: #multi-pod-modular-spine-bootscript-file -[d33]: #n9300-switch-memory ## General Check Details From 910f105c17973eaf08705d67992e33e338824237 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Thu, 9 Apr 2026 19:03:17 +0530 Subject: [PATCH 08/13] Moved N9300 memory check to general checks section --- aci-preupgrade-validation-script.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index 78b84bf..9b204db 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -6464,6 +6464,7 @@ class CheckManager: validate_32_64_bit_image_check, fabric_link_redundancy_check, apic_downgrade_compat_warning_check, + n9300_switch_memory_check, # Faults apic_disk_space_faults_check, @@ -6542,7 +6543,6 @@ class CheckManager: auto_firmware_update_on_switch_check, rogue_ep_coop_exception_mac_check, n9k_c9408_model_lem_count_check, - n9300_switch_memory_check, ] ssh_checks = [ # General From 66861f716ccaf7d620b848ca4f0fdb22b7198e43 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Tue, 14 Apr 2026 15:26:29 +0530 Subject: [PATCH 09/13] Updated N9300 memory check and threshold to 32GB --- aci-preupgrade-validation-script.py | 12 +- docs/docs/validations.md | 6 +- .../procMemUsage_all_gt24gb.json | 4 +- .../procMemUsage_gt24gb.json | 2 +- .../procMemUsage_mixed.json | 2 +- .../test_n9300_switch_memory_24g_check.py | 31 +++-- .../fabricNode_non_n9300.json | 0 .../fabricNode_one.json | 0 .../fabricNode_two.json | 0 .../procMemUsage_all_gt32gb.json | 20 +++ .../procMemUsage_gt32gb.json} | 2 +- .../procMemUsage_invalid_total.json | 0 .../procMemUsage_lt32gb.json | 11 ++ .../procMemUsage_missing_affected_node.json | 0 .../procMemUsage_mixed.json | 20 +++ .../procMemUsage_node201_gt32gb.json} | 0 .../test_n9300_switch_memory_32g_check.py | 116 ++++++++++++++++++ 17 files changed, 202 insertions(+), 24 deletions(-) rename tests/checks/{n9300_switch_memory_24g_check => n9300_switch_memory_32g_check}/fabricNode_non_n9300.json (100%) rename tests/checks/{n9300_switch_memory_24g_check => n9300_switch_memory_32g_check}/fabricNode_one.json (100%) rename tests/checks/{n9300_switch_memory_24g_check => n9300_switch_memory_32g_check}/fabricNode_two.json (100%) create mode 100644 tests/checks/n9300_switch_memory_32g_check/procMemUsage_all_gt32gb.json rename tests/checks/{n9300_switch_memory_24g_check/procMemUsage_lt24gb.json => n9300_switch_memory_32g_check/procMemUsage_gt32gb.json} (84%) rename tests/checks/{n9300_switch_memory_24g_check => n9300_switch_memory_32g_check}/procMemUsage_invalid_total.json (100%) create mode 100644 tests/checks/n9300_switch_memory_32g_check/procMemUsage_lt32gb.json rename tests/checks/{n9300_switch_memory_24g_check => n9300_switch_memory_32g_check}/procMemUsage_missing_affected_node.json (100%) create mode 100644 tests/checks/n9300_switch_memory_32g_check/procMemUsage_mixed.json rename tests/checks/{n9300_switch_memory_24g_check/procMemUsage_node201_gt24gb.json => n9300_switch_memory_32g_check/procMemUsage_node201_gt32gb.json} (100%) create mode 100644 tests/checks/n9300_switch_memory_32g_check/test_n9300_switch_memory_32g_check.py diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index 9b204db..454c3f9 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -6294,23 +6294,23 @@ def multipod_modular_spine_bootscript_check(tversion, fabric_nodes, username, pa @check_wrapper(check_title='N9300 Switch Memory') -def n9300_switch_memory_check(tversion, fabric_nodes, **kwargs): +def n9300_switch_memory_check(fabric_nodes, **kwargs): result = PASS headers = ["NodeId", "Name", "Model", "Memory Detected (GB)"] data = [] - recommended_action = 'Increase the switch memory to at least 24GB on affected N9300-series switches.' + recommended_action = 'Increase the switch memory to at least 32GB on affected N9K-C93180YC-FX3 switches.' doc_url = 'https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#n9300-switch-memory' - min_memory_kb = 24 * 1024 * 1024 + min_memory_kb = 32 * 1024 * 1024 msg = '' affected_nodes = [ node for node in fabric_nodes - if node.get('fabricNode', {}).get('attributes', {}).get('model', '').startswith('N9K-C93') + if node.get('fabricNode', {}).get('attributes', {}).get('model', '') == 'N9K-C93180YC-FX3' ] if not affected_nodes: result = NA - msg = 'No N9300 switches found. Skipping.' + msg = 'No N9K-C93180YC-FX3 switches found. Skipping.' else: proc_mem_mos = icurl('class', 'procMemUsage.json') node_total_kb = {} @@ -6366,7 +6366,7 @@ def n9300_switch_memory_check(tversion, fabric_nodes, **kwargs): if missing_nodes: result = ERROR - msg = 'Missing procMemUsage data for one or more affected N9300 nodes.' + msg = 'Missing procMemUsage data for one or more affected N9K-C93180YC-FX3 nodes.' headers = ['NodeId', 'Name', 'Model'] data = missing_nodes diff --git a/docs/docs/validations.md b/docs/docs/validations.md index ba2888a..f61ad03 100644 --- a/docs/docs/validations.md +++ b/docs/docs/validations.md @@ -2729,11 +2729,11 @@ To avoid this risk, consider disabling Auto Firmware Update before upgrading to ### N9300 Switch Memory -This check applies to N9300-series switches only. It reviews `procMemUsage` and flags nodes with less than 24GB memory installed. +This check applies to N9K-C93180YC-FX3 switches only. It reviews `procMemUsage` and flags nodes with less than 32GB memory installed. This check is not version dependent and runs for all upgrade versions. -Impact: Running an N9300-series switch with less than 24GB memory can lead to memory pressure and increase the risk of service instability. +Impact: Running an N9K-C93180YC-FX3 switch with less than 32GB memory can lead to memory pressure and increase the risk of service instability. -If any N9300-series switch is flagged by this check, increase the switch memory to at least 24GB. +If any N9K-C93180YC-FX3 switch is flagged by this check, upgrade the switch memory to at least 32GB. ### Rogue EP Exception List missing on switches diff --git a/tests/checks/n9300_switch_memory_24g_check/procMemUsage_all_gt24gb.json b/tests/checks/n9300_switch_memory_24g_check/procMemUsage_all_gt24gb.json index dab23d2..3599e1a 100644 --- a/tests/checks/n9300_switch_memory_24g_check/procMemUsage_all_gt24gb.json +++ b/tests/checks/n9300_switch_memory_24g_check/procMemUsage_all_gt24gb.json @@ -4,7 +4,7 @@ "attributes": { "dn": "topology/pod-1/node-101/sys/procmem/memusage-sup", "Modname": "sup", - "Total": "32535444" + "Total": "33554432" } } }, @@ -13,7 +13,7 @@ "attributes": { "dn": "topology/pod-1/node-102/sys/procmem/memusage-sup", "Modname": "sup", - "Total": "28535444" + "Total": "33554432" } } } diff --git a/tests/checks/n9300_switch_memory_24g_check/procMemUsage_gt24gb.json b/tests/checks/n9300_switch_memory_24g_check/procMemUsage_gt24gb.json index 597db59..6f1d221 100644 --- a/tests/checks/n9300_switch_memory_24g_check/procMemUsage_gt24gb.json +++ b/tests/checks/n9300_switch_memory_24g_check/procMemUsage_gt24gb.json @@ -4,7 +4,7 @@ "attributes": { "dn": "topology/pod-1/node-101/sys/procmem/memusage-sup", "Modname": "sup", - "Total": "26535444" + "Total": "33554432" } } } diff --git a/tests/checks/n9300_switch_memory_24g_check/procMemUsage_mixed.json b/tests/checks/n9300_switch_memory_24g_check/procMemUsage_mixed.json index 58ece8e..252adfa 100644 --- a/tests/checks/n9300_switch_memory_24g_check/procMemUsage_mixed.json +++ b/tests/checks/n9300_switch_memory_24g_check/procMemUsage_mixed.json @@ -4,7 +4,7 @@ "attributes": { "dn": "topology/pod-1/node-101/sys/procmem/memusage-sup", "Modname": "sup", - "Total": "32535444" + "Total": "33554432" } } }, diff --git a/tests/checks/n9300_switch_memory_24g_check/test_n9300_switch_memory_24g_check.py b/tests/checks/n9300_switch_memory_24g_check/test_n9300_switch_memory_24g_check.py index 0f6aa00..c0256c6 100644 --- a/tests/checks/n9300_switch_memory_24g_check/test_n9300_switch_memory_24g_check.py +++ b/tests/checks/n9300_switch_memory_24g_check/test_n9300_switch_memory_24g_check.py @@ -24,32 +24,32 @@ {}, "6.0(3c)", script.NA, - 'No N9300 switches found. Skipping.', + 'No N9K-C93180YC-FX3 switches found. Skipping.', [], ), - # Non-N9300 node with >=24GB memory + # Non-N9K-C93180YC-FX3 node ( read_data(dir, "fabricNode_non_n9300.json"), { - proc_mem_query: read_data(dir, "procMemUsage_node201_gt24gb.json"), + proc_mem_query: read_data(dir, "procMemUsage_node201_gt32gb.json"), }, "6.0(3c)", script.NA, - 'No N9300 switches found. Skipping.', + 'No N9K-C93180YC-FX3 switches found. Skipping.', [], ), - # N9300 node with >=24GB memory + # N9K-C93180YC-FX3 node with >=32GB memory ( read_data(dir, "fabricNode_one.json"), { - proc_mem_query: read_data(dir, "procMemUsage_gt24gb.json"), + proc_mem_query: read_data(dir, "procMemUsage_gt32gb.json"), }, "6.0(3c)", script.PASS, '', [], ), - # Multiple N9300 nodes, all >=24GB memory + # Multiple nodes, only N9K-C93180YC-FX3 checked, all >=32GB ( read_data(dir, "fabricNode_two.json"), { @@ -79,19 +79,30 @@ }, "6.0(3c)", script.ERROR, - 'Missing procMemUsage data for one or more affected N9300 nodes.', + 'Missing procMemUsage data for one or more affected N9K-C93180YC-FX3 nodes.', [["101", "leaf101", "N9K-C93180YC-FX3"]], ), - # N9300 node with <24GB memory + # N9K-C93180YC-FX3 node with <32GB memory ( read_data(dir, "fabricNode_two.json"), { proc_mem_query: read_data(dir, "procMemUsage_mixed.json"), }, "6.0(3c)", + script.PASS, + '', + [], + ), + # N9K-C93180YC-FX3 node with <32GB memory (fail case) + ( + read_data(dir, "fabricNode_one.json"), + { + proc_mem_query: read_data(dir, "procMemUsage_lt32gb.json"), + }, + "6.0(3c)", script.FAIL_O, '', - [["102", "leaf102", "N9K-C9364C", 21.49]], + [["101", "leaf101", "N9K-C93180YC-FX3", 25.31]], ), ], ) diff --git a/tests/checks/n9300_switch_memory_24g_check/fabricNode_non_n9300.json b/tests/checks/n9300_switch_memory_32g_check/fabricNode_non_n9300.json similarity index 100% rename from tests/checks/n9300_switch_memory_24g_check/fabricNode_non_n9300.json rename to tests/checks/n9300_switch_memory_32g_check/fabricNode_non_n9300.json diff --git a/tests/checks/n9300_switch_memory_24g_check/fabricNode_one.json b/tests/checks/n9300_switch_memory_32g_check/fabricNode_one.json similarity index 100% rename from tests/checks/n9300_switch_memory_24g_check/fabricNode_one.json rename to tests/checks/n9300_switch_memory_32g_check/fabricNode_one.json diff --git a/tests/checks/n9300_switch_memory_24g_check/fabricNode_two.json b/tests/checks/n9300_switch_memory_32g_check/fabricNode_two.json similarity index 100% rename from tests/checks/n9300_switch_memory_24g_check/fabricNode_two.json rename to tests/checks/n9300_switch_memory_32g_check/fabricNode_two.json diff --git a/tests/checks/n9300_switch_memory_32g_check/procMemUsage_all_gt32gb.json b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_all_gt32gb.json new file mode 100644 index 0000000..3599e1a --- /dev/null +++ b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_all_gt32gb.json @@ -0,0 +1,20 @@ +[ + { + "procMemUsage": { + "attributes": { + "dn": "topology/pod-1/node-101/sys/procmem/memusage-sup", + "Modname": "sup", + "Total": "33554432" + } + } + }, + { + "procMemUsage": { + "attributes": { + "dn": "topology/pod-1/node-102/sys/procmem/memusage-sup", + "Modname": "sup", + "Total": "33554432" + } + } + } +] \ No newline at end of file diff --git a/tests/checks/n9300_switch_memory_24g_check/procMemUsage_lt24gb.json b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_gt32gb.json similarity index 84% rename from tests/checks/n9300_switch_memory_24g_check/procMemUsage_lt24gb.json rename to tests/checks/n9300_switch_memory_32g_check/procMemUsage_gt32gb.json index d84e82c..6f1d221 100644 --- a/tests/checks/n9300_switch_memory_24g_check/procMemUsage_lt24gb.json +++ b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_gt32gb.json @@ -4,7 +4,7 @@ "attributes": { "dn": "topology/pod-1/node-101/sys/procmem/memusage-sup", "Modname": "sup", - "Total": "22535444" + "Total": "33554432" } } } diff --git a/tests/checks/n9300_switch_memory_24g_check/procMemUsage_invalid_total.json b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_invalid_total.json similarity index 100% rename from tests/checks/n9300_switch_memory_24g_check/procMemUsage_invalid_total.json rename to tests/checks/n9300_switch_memory_32g_check/procMemUsage_invalid_total.json diff --git a/tests/checks/n9300_switch_memory_32g_check/procMemUsage_lt32gb.json b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_lt32gb.json new file mode 100644 index 0000000..1f35621 --- /dev/null +++ b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_lt32gb.json @@ -0,0 +1,11 @@ +[ + { + "procMemUsage": { + "attributes": { + "dn": "topology/pod-1/node-101/sys/procmem/memusage-sup", + "Modname": "sup", + "Total": "26535444" + } + } + } +] diff --git a/tests/checks/n9300_switch_memory_24g_check/procMemUsage_missing_affected_node.json b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_missing_affected_node.json similarity index 100% rename from tests/checks/n9300_switch_memory_24g_check/procMemUsage_missing_affected_node.json rename to tests/checks/n9300_switch_memory_32g_check/procMemUsage_missing_affected_node.json diff --git a/tests/checks/n9300_switch_memory_32g_check/procMemUsage_mixed.json b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_mixed.json new file mode 100644 index 0000000..252adfa --- /dev/null +++ b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_mixed.json @@ -0,0 +1,20 @@ +[ + { + "procMemUsage": { + "attributes": { + "dn": "topology/pod-1/node-101/sys/procmem/memusage-sup", + "Modname": "sup", + "Total": "33554432" + } + } + }, + { + "procMemUsage": { + "attributes": { + "dn": "topology/pod-1/node-102/sys/procmem/memusage-sup", + "Modname": "sup", + "Total": "22535444" + } + } + } +] \ No newline at end of file diff --git a/tests/checks/n9300_switch_memory_24g_check/procMemUsage_node201_gt24gb.json b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_node201_gt32gb.json similarity index 100% rename from tests/checks/n9300_switch_memory_24g_check/procMemUsage_node201_gt24gb.json rename to tests/checks/n9300_switch_memory_32g_check/procMemUsage_node201_gt32gb.json diff --git a/tests/checks/n9300_switch_memory_32g_check/test_n9300_switch_memory_32g_check.py b/tests/checks/n9300_switch_memory_32g_check/test_n9300_switch_memory_32g_check.py new file mode 100644 index 0000000..27d5fd6 --- /dev/null +++ b/tests/checks/n9300_switch_memory_32g_check/test_n9300_switch_memory_32g_check.py @@ -0,0 +1,116 @@ +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 = "n9300_switch_memory_check" + +# icurl queries +proc_mem_query = 'procMemUsage.json' + + +@pytest.mark.parametrize( + "fabric_nodes, icurl_outputs, tversion, expected_result, expected_msg, expected_data", + [ + # No nodes returned + ( + [], + {}, + "6.0(3c)", + script.NA, + 'No N9K-C93180YC-FX3 switches found. Skipping.', + [], + ), + # Non-N9K-C93180YC-FX3 node + ( + read_data(dir, "fabricNode_non_n9300.json"), + { + proc_mem_query: read_data(dir, "procMemUsage_node201_gt32gb.json"), + }, + "6.0(3c)", + script.NA, + 'No N9K-C93180YC-FX3 switches found. Skipping.', + [], + ), + # N9K-C93180YC-FX3 node with >=32GB memory + ( + read_data(dir, "fabricNode_one.json"), + { + proc_mem_query: read_data(dir, "procMemUsage_gt32gb.json"), + }, + "6.0(3c)", + script.PASS, + '', + [], + ), + # Multiple nodes, only N9K-C93180YC-FX3 checked, all >=32GB + ( + read_data(dir, "fabricNode_two.json"), + { + proc_mem_query: read_data(dir, "procMemUsage_all_gt32gb.json"), + }, + "6.0(3c)", + script.PASS, + '', + [], + ), + # Invalid procMemUsage Total value + ( + read_data(dir, "fabricNode_one.json"), + { + proc_mem_query: read_data(dir, "procMemUsage_invalid_total.json"), + }, + "6.0(3c)", + script.ERROR, + 'Failed to parse procMemUsage Total for one or more nodes.', + [["topology/pod-1/node-101/sys/procmem/memusage-sup", "unknown"]], + ), + # Missing procMemUsage data for affected node + ( + read_data(dir, "fabricNode_one.json"), + { + proc_mem_query: read_data(dir, "procMemUsage_missing_affected_node.json"), + }, + "6.0(3c)", + script.ERROR, + 'Missing procMemUsage data for one or more affected N9K-C93180YC-FX3 nodes.', + [["101", "leaf101", "N9K-C93180YC-FX3"]], + ), + # N9K-C93180YC-FX3 node with <32GB memory + ( + read_data(dir, "fabricNode_two.json"), + { + proc_mem_query: read_data(dir, "procMemUsage_mixed.json"), + }, + "6.0(3c)", + script.PASS, + '', + [], + ), + # N9K-C93180YC-FX3 node with <32GB memory (fail case) + ( + read_data(dir, "fabricNode_one.json"), + { + proc_mem_query: read_data(dir, "procMemUsage_lt32gb.json"), + }, + "6.0(3c)", + script.FAIL_O, + '', + [["101", "leaf101", "N9K-C93180YC-FX3", 25.31]], + ), + ], +) +def test_logic(run_check, mock_icurl, fabric_nodes, tversion, expected_result, expected_msg, expected_data): + result = run_check( + tversion=script.AciVersion(tversion), + fabric_nodes=fabric_nodes, + ) + assert result.result == expected_result + assert result.msg == expected_msg + assert result.data == expected_data \ No newline at end of file From eca626476aabc13a35bc13013d3a6d1d7012127d Mon Sep 17 00:00:00 2001 From: Priyanka Date: Tue, 14 Apr 2026 16:33:27 +0530 Subject: [PATCH 10/13] Fixed N9300 memory threshold to decimal 32GB --- aci-preupgrade-validation-script.py | 4 ++-- .../procMemUsage_all_gt32gb.json | 4 ++-- .../n9300_switch_memory_32g_check/procMemUsage_gt32gb.json | 2 +- .../n9300_switch_memory_32g_check/procMemUsage_lt32gb.json | 2 +- .../procMemUsage_missing_affected_node.json | 2 +- .../n9300_switch_memory_32g_check/procMemUsage_mixed.json | 2 +- .../procMemUsage_node201_gt32gb.json | 2 +- .../test_n9300_switch_memory_32g_check.py | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index 454c3f9..7ae16d4 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -6300,7 +6300,7 @@ def n9300_switch_memory_check(fabric_nodes, **kwargs): data = [] recommended_action = 'Increase the switch memory to at least 32GB on affected N9K-C93180YC-FX3 switches.' doc_url = 'https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#n9300-switch-memory' - min_memory_kb = 32 * 1024 * 1024 + min_memory_kb = 32 * 1000 * 1000 msg = '' affected_nodes = [ @@ -6355,7 +6355,7 @@ def n9300_switch_memory_check(fabric_nodes, **kwargs): continue if total_kb < min_memory_kb: - memory_in_gb = round(total_kb / 1048576, 2) + memory_in_gb = round(total_kb / 1000000, 2) result = FAIL_O data.append([ node_id, diff --git a/tests/checks/n9300_switch_memory_32g_check/procMemUsage_all_gt32gb.json b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_all_gt32gb.json index 3599e1a..c3aef55 100644 --- a/tests/checks/n9300_switch_memory_32g_check/procMemUsage_all_gt32gb.json +++ b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_all_gt32gb.json @@ -4,7 +4,7 @@ "attributes": { "dn": "topology/pod-1/node-101/sys/procmem/memusage-sup", "Modname": "sup", - "Total": "33554432" + "Total": "32676092" } } }, @@ -13,7 +13,7 @@ "attributes": { "dn": "topology/pod-1/node-102/sys/procmem/memusage-sup", "Modname": "sup", - "Total": "33554432" + "Total": "32676092" } } } diff --git a/tests/checks/n9300_switch_memory_32g_check/procMemUsage_gt32gb.json b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_gt32gb.json index 6f1d221..5597a51 100644 --- a/tests/checks/n9300_switch_memory_32g_check/procMemUsage_gt32gb.json +++ b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_gt32gb.json @@ -4,7 +4,7 @@ "attributes": { "dn": "topology/pod-1/node-101/sys/procmem/memusage-sup", "Modname": "sup", - "Total": "33554432" + "Total": "32676092" } } } diff --git a/tests/checks/n9300_switch_memory_32g_check/procMemUsage_lt32gb.json b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_lt32gb.json index 1f35621..5f50d60 100644 --- a/tests/checks/n9300_switch_memory_32g_check/procMemUsage_lt32gb.json +++ b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_lt32gb.json @@ -4,7 +4,7 @@ "attributes": { "dn": "topology/pod-1/node-101/sys/procmem/memusage-sup", "Modname": "sup", - "Total": "26535444" + "Total": "16000000" } } } diff --git a/tests/checks/n9300_switch_memory_32g_check/procMemUsage_missing_affected_node.json b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_missing_affected_node.json index e11293a..f8b2209 100644 --- a/tests/checks/n9300_switch_memory_32g_check/procMemUsage_missing_affected_node.json +++ b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_missing_affected_node.json @@ -4,7 +4,7 @@ "attributes": { "dn": "topology/pod-1/node-201/sys/procmem/memusage-sup", "Modname": "sup", - "Total": "26535444" + "Total": "32676092" } } } diff --git a/tests/checks/n9300_switch_memory_32g_check/procMemUsage_mixed.json b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_mixed.json index 252adfa..b7c74c0 100644 --- a/tests/checks/n9300_switch_memory_32g_check/procMemUsage_mixed.json +++ b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_mixed.json @@ -4,7 +4,7 @@ "attributes": { "dn": "topology/pod-1/node-101/sys/procmem/memusage-sup", "Modname": "sup", - "Total": "33554432" + "Total": "32676092" } } }, diff --git a/tests/checks/n9300_switch_memory_32g_check/procMemUsage_node201_gt32gb.json b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_node201_gt32gb.json index bca2b9f..db65e8c 100644 --- a/tests/checks/n9300_switch_memory_32g_check/procMemUsage_node201_gt32gb.json +++ b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_node201_gt32gb.json @@ -4,7 +4,7 @@ "attributes": { "dn": "topology/pod-1/node-201/sys/procmem/memusage-sup", "Modname": "sup", - "Total": "28535444" + "Total": "32676092" } } } diff --git a/tests/checks/n9300_switch_memory_32g_check/test_n9300_switch_memory_32g_check.py b/tests/checks/n9300_switch_memory_32g_check/test_n9300_switch_memory_32g_check.py index 27d5fd6..5f56edb 100644 --- a/tests/checks/n9300_switch_memory_32g_check/test_n9300_switch_memory_32g_check.py +++ b/tests/checks/n9300_switch_memory_32g_check/test_n9300_switch_memory_32g_check.py @@ -102,7 +102,7 @@ "6.0(3c)", script.FAIL_O, '', - [["101", "leaf101", "N9K-C93180YC-FX3", 25.31]], + [["101", "leaf101", "N9K-C93180YC-FX3", 16.0]], ), ], ) From 40dc8ec66dc254adf891d8618d364794f15766e3 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Wed, 15 Apr 2026 12:11:44 +0530 Subject: [PATCH 11/13] Added manual check when nodes fail and others have missing memory data --- aci-preupgrade-validation-script.py | 15 +++++++++++- .../fabricNode_two_fx3.json | 24 +++++++++++++++++++ .../procMemUsage_fail_and_missing.json | 11 +++++++++ .../test_n9300_switch_memory_32g_check.py | 16 +++++++++++++ 4 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 tests/checks/n9300_switch_memory_32g_check/fabricNode_two_fx3.json create mode 100644 tests/checks/n9300_switch_memory_32g_check/procMemUsage_fail_and_missing.json diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index 7ae16d4..907ba4f 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -6364,7 +6364,20 @@ def n9300_switch_memory_check(fabric_nodes, **kwargs): memory_in_gb, ]) - if missing_nodes: + if missing_nodes and data: + result = MANUAL + msg = ( + 'Some N9K-C93180YC-FX3 nodes have insufficient memory and others are missing ' + 'procMemUsage data. Please manually verify the memory on all affected nodes.\n' + 'Nodes with insufficient memory: {}\n' + 'Nodes with missing data: {}'.format( + ', '.join(str(row[0]) for row in data), + ', '.join(str(row[0]) for row in missing_nodes), + ) + ) + headers = ['NodeId', 'Name', 'Model', 'Memory Detected (GB)'] + data = data + [row + ['N/A'] for row in missing_nodes] + elif missing_nodes: result = ERROR msg = 'Missing procMemUsage data for one or more affected N9K-C93180YC-FX3 nodes.' headers = ['NodeId', 'Name', 'Model'] diff --git a/tests/checks/n9300_switch_memory_32g_check/fabricNode_two_fx3.json b/tests/checks/n9300_switch_memory_32g_check/fabricNode_two_fx3.json new file mode 100644 index 0000000..dfc8a77 --- /dev/null +++ b/tests/checks/n9300_switch_memory_32g_check/fabricNode_two_fx3.json @@ -0,0 +1,24 @@ +[ + { + "fabricNode": { + "attributes": { + "dn": "topology/pod-1/node-101", + "id": "101", + "name": "leaf101", + "model": "N9K-C93180YC-FX3", + "role": "leaf" + } + } + }, + { + "fabricNode": { + "attributes": { + "dn": "topology/pod-1/node-102", + "id": "102", + "name": "leaf102", + "model": "N9K-C93180YC-FX3", + "role": "leaf" + } + } + } +] diff --git a/tests/checks/n9300_switch_memory_32g_check/procMemUsage_fail_and_missing.json b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_fail_and_missing.json new file mode 100644 index 0000000..5f50d60 --- /dev/null +++ b/tests/checks/n9300_switch_memory_32g_check/procMemUsage_fail_and_missing.json @@ -0,0 +1,11 @@ +[ + { + "procMemUsage": { + "attributes": { + "dn": "topology/pod-1/node-101/sys/procmem/memusage-sup", + "Modname": "sup", + "Total": "16000000" + } + } + } +] diff --git a/tests/checks/n9300_switch_memory_32g_check/test_n9300_switch_memory_32g_check.py b/tests/checks/n9300_switch_memory_32g_check/test_n9300_switch_memory_32g_check.py index 5f56edb..212248c 100644 --- a/tests/checks/n9300_switch_memory_32g_check/test_n9300_switch_memory_32g_check.py +++ b/tests/checks/n9300_switch_memory_32g_check/test_n9300_switch_memory_32g_check.py @@ -104,6 +104,22 @@ '', [["101", "leaf101", "N9K-C93180YC-FX3", 16.0]], ), + # One FX3 node fails memory check, another FX3 node has missing procMemUsage data + ( + read_data(dir, "fabricNode_two_fx3.json"), + { + proc_mem_query: read_data(dir, "procMemUsage_fail_and_missing.json"), + }, + "6.0(3c)", + script.MANUAL, + ( + 'Some N9K-C93180YC-FX3 nodes have insufficient memory and others are missing ' + 'procMemUsage data. Please manually verify the memory on all affected nodes.\n' + 'Nodes with insufficient memory: 101\n' + 'Nodes with missing data: 102' + ), + [["101", "leaf101", "N9K-C93180YC-FX3", 16.0], ["102", "leaf102", "N9K-C93180YC-FX3", "N/A"]], + ), ], ) def test_logic(run_check, mock_icurl, fabric_nodes, tversion, expected_result, expected_msg, expected_data): From ff689706f9a87bcb8131f3ce4648fb9026396bb8 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Wed, 15 Apr 2026 13:48:26 +0530 Subject: [PATCH 12/13] Cleared recommended_action for ERROR results --- aci-preupgrade-validation-script.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index 907ba4f..873f76a 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -6340,6 +6340,7 @@ def n9300_switch_memory_check(fabric_nodes, **kwargs): msg = 'Failed to parse procMemUsage Total for one or more nodes.' headers = ['DN', 'Total'] data = parse_errors + recommended_action = '' else: missing_nodes = [] @@ -6382,6 +6383,7 @@ def n9300_switch_memory_check(fabric_nodes, **kwargs): msg = 'Missing procMemUsage data for one or more affected N9K-C93180YC-FX3 nodes.' headers = ['NodeId', 'Name', 'Model'] data = missing_nodes + recommended_action = '' return Result(result=result, msg=msg, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url) From a4f4f4560a3604a8557f313cc0681e48cdd5258c Mon Sep 17 00:00:00 2001 From: Priyanka Date: Thu, 16 Apr 2026 11:03:47 +0530 Subject: [PATCH 13/13] Updated memory check result to MANUAL --- aci-preupgrade-validation-script.py | 7 ++++++- .../test_n9300_switch_memory_32g_check.py | 7 +++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index 873f76a..5c7f215 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -6357,7 +6357,7 @@ def n9300_switch_memory_check(fabric_nodes, **kwargs): if total_kb < min_memory_kb: memory_in_gb = round(total_kb / 1000000, 2) - result = FAIL_O + result = MANUAL data.append([ node_id, node['fabricNode']['attributes'].get('name', ''), @@ -6384,6 +6384,11 @@ def n9300_switch_memory_check(fabric_nodes, **kwargs): headers = ['NodeId', 'Name', 'Model'] data = missing_nodes recommended_action = '' + elif data: + msg = ( + 'One or more N9K-C93180YC-FX3 switches have less than 32GB of memory. ' + 'An outage is not guaranteed but can occur. Please verify and upgrade the memory on affected nodes.' + ) return Result(result=result, msg=msg, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url) diff --git a/tests/checks/n9300_switch_memory_32g_check/test_n9300_switch_memory_32g_check.py b/tests/checks/n9300_switch_memory_32g_check/test_n9300_switch_memory_32g_check.py index 212248c..699f649 100644 --- a/tests/checks/n9300_switch_memory_32g_check/test_n9300_switch_memory_32g_check.py +++ b/tests/checks/n9300_switch_memory_32g_check/test_n9300_switch_memory_32g_check.py @@ -100,8 +100,11 @@ proc_mem_query: read_data(dir, "procMemUsage_lt32gb.json"), }, "6.0(3c)", - script.FAIL_O, - '', + script.MANUAL, + ( + 'One or more N9K-C93180YC-FX3 switches have less than 32GB of memory. ' + 'An outage is not guaranteed but can occur. Please verify and upgrade the memory on affected nodes.' + ), [["101", "leaf101", "N9K-C93180YC-FX3", 16.0]], ), # One FX3 node fails memory check, another FX3 node has missing procMemUsage data