From ced0e4a8f4ee827310d6f3363c8ba537741dcb71 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Fri, 20 Mar 2026 16:34:31 +0530 Subject: [PATCH 01/21] Added N9300 switch memory check --- aci-preupgrade-validation-script.py | 95 +++++++++++++++- 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, 325 insertions(+), 6 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 da1b4b9..d1c2f00 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: @@ -1514,14 +1524,19 @@ 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) - sys.stdout.flush() - except OSError: - pass + 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) + if stdout_ok: + try: + sys.stdout.flush() + except (OSError, ValueError): + pass f.flush() @@ -5985,6 +6000,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): @@ -6576,6 +6658,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, rogue_ep_coop_exception_mac_check, diff --git a/docs/docs/validations.md b/docs/docs/validations.md index 82f2211..0206c04 100644 --- a/docs/docs/validations.md +++ b/docs/docs/validations.md @@ -203,6 +203,7 @@ Items | Defect | This Script [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: [Inband Management Policy Misconfiguration][d33]| CSCwd40071 | :white_check_mark: | :no_entry_sign: +[N9300 Switch Memory][d34] | - | :white_check_mark: | :no_entry_sign: [d1]: #ep-announce-compatibility [d2]: #eventmgr-db-size-defect-susceptibility @@ -237,6 +238,7 @@ Items | Defect | This Script [d31]: #n9k-c9408-with-more-than-5-n9k-x9400-16w-lems [d32]: #multi-pod-modular-spine-bootscript-file [d33]: #inband-management-policy-misconfiguration +[d34]: #n9300-switch-memory ## General Check Details @@ -2722,6 +2724,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 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 615b58e6d23573410d36d3d327798989626df274 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Fri, 20 Mar 2026 17:29:45 +0530 Subject: [PATCH 02/21] 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 d1c2f00..c75d206 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: @@ -1524,19 +1514,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 4013a37993e91aa9f9a14c400da041ac37a5a533 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Mon, 23 Mar 2026 18:02:32 +0530 Subject: [PATCH 03/21] Addressed PR comments --- aci-preupgrade-validation-script.py | 8 +---- docs/docs/validations.md | 15 ++++---- .../test_n9300_switch_memory_24g_check.py | 34 ++++--------------- 3 files changed, 15 insertions(+), 42 deletions(-) diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index c75d206..3f26d55 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -5987,16 +5987,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 0206c04..d599889 100644 --- a/docs/docs/validations.md +++ b/docs/docs/validations.md @@ -2724,13 +2724,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: @@ -2750,6 +2743,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. + ### Rogue EP Exception List missing on switches 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 a357301b4924bf159c1d3e4e9aef6de9f67d7e62 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Tue, 24 Mar 2026 15:30:49 +0530 Subject: [PATCH 04/21] 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 3f26d55..5ed7d13 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -5982,67 +5982,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): @@ -6468,6 +6407,91 @@ def svccore_excessive_data_check(**kwargs): return Result(result=ERROR, msg="Error occurred while fetching svccore object counts: {}".format(str(e)), 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 ---- @@ -6634,12 +6658,12 @@ 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, rogue_ep_coop_exception_mac_check, n9k_c9408_model_lem_count_check, inband_management_policy_misconfig_check, + n9300_switch_memory_check, ] ssh_checks = [ # General 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 d392bd7324b838766e98034325a948f750a08856 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Wed, 25 Mar 2026 09:20:05 +0530 Subject: [PATCH 05/21] 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 5ed7d13..30af4f7 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -6415,6 +6415,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 @@ -6422,74 +6423,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 2f4c70363ead7ec0a2d35e081cc4bf3acd1b0bb7 Mon Sep 17 00:00:00 2001 From: GM Date: Fri, 27 Feb 2026 11:08:57 -0500 Subject: [PATCH 06/21] Add arg to define thread limit - to throttle concurrent API calls when required (#355) * add `--max-threads` arg * fix bad descriptor errs/race conditions * update pytests --- aci-preupgrade-validation-script.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index 30af4f7..dc0a3ce 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -1514,11 +1514,14 @@ 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) + try: + print(objects, sep=sep, end=end, file=sys.stdout) + sys.stdout.flush() + except OSError: + pass 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() f.flush() From c6a46d53537e6ca79e7290c605ca7f86632de3b8 Mon Sep 17 00:00:00 2001 From: GM Date: Fri, 27 Feb 2026 11:11:20 -0500 Subject: [PATCH 07/21] 353 the script incorrectly detects vpc and port channel interfaces as cscwh68103 invalid fabricpathep targets (#357) * specific testing for known failure conditions of cscwh68103 as to not catch valid scenarios --- aci-preupgrade-validation-script.py | 1 + 1 file changed, 1 insertion(+) diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index dc0a3ce..3d78f03 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -4820,6 +4820,7 @@ def fabricPathEp_target_check(**kwargs): fex_a = groups.get("fexA") fex_b = groups.get("fexB") path = groups.get("path") + print(path) # CHECK FEX ID(s) of extpath(s) is 101 or greater if fex_a: From 45bcaac5ff23cf346c87061abab7337498a0ae68 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Fri, 27 Feb 2026 13:45:22 -0500 Subject: [PATCH 08/21] print cleanup --- aci-preupgrade-validation-script.py | 1 - 1 file changed, 1 deletion(-) diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index 3d78f03..dc0a3ce 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -4820,7 +4820,6 @@ def fabricPathEp_target_check(**kwargs): fex_a = groups.get("fexA") fex_b = groups.get("fexB") path = groups.get("path") - print(path) # CHECK FEX ID(s) of extpath(s) is 101 or greater if fex_a: From 8f49c4469d929bb8e1ad56b988484c7f335cca43 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Thu, 9 Apr 2026 19:03:17 +0530 Subject: [PATCH 09/21] 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 dc0a3ce..8ac74d8 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -6581,6 +6581,7 @@ class CheckManager: validate_32_64_bit_image_check, fabric_link_redundancy_check, apic_downgrade_compat_warning_check, + n9300_switch_memory_check, svccore_excessive_data_check, # Faults @@ -6661,7 +6662,6 @@ class CheckManager: rogue_ep_coop_exception_mac_check, n9k_c9408_model_lem_count_check, inband_management_policy_misconfig_check, - n9300_switch_memory_check, ] ssh_checks = [ # General From d9ee712945e3c51fcfa95c5d2278a9a809ae7f2a Mon Sep 17 00:00:00 2001 From: Priyanka Date: Tue, 14 Apr 2026 15:26:29 +0530 Subject: [PATCH 10/21] 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 8ac74d8..042ff3a 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -6411,23 +6411,23 @@ def svccore_excessive_data_check(**kwargs): @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 = {} @@ -6483,7 +6483,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 d599889..d8207b9 100644 --- a/docs/docs/validations.md +++ b/docs/docs/validations.md @@ -2745,11 +2745,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 26f397f9b5c88680939176f262b59163a529022b Mon Sep 17 00:00:00 2001 From: Priyanka Date: Tue, 14 Apr 2026 16:33:27 +0530 Subject: [PATCH 11/21] 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 042ff3a..7887e21 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -6417,7 +6417,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 = [ @@ -6472,7 +6472,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 5a60335c185d15dc0e5bb0d23db481a380697f76 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Wed, 15 Apr 2026 12:11:44 +0530 Subject: [PATCH 12/21] 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 7887e21..49e12f2 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -6481,7 +6481,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 ee2cd8dd4c17410659fa938b03c5f0f6a1fba628 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Wed, 15 Apr 2026 13:48:26 +0530 Subject: [PATCH 13/21] 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 49e12f2..0cad952 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -6457,6 +6457,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 = [] @@ -6499,6 +6500,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 83db0bbca369d9e87f86aecbbd1cf20ad92b4f27 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Thu, 16 Apr 2026 11:03:47 +0530 Subject: [PATCH 14/21] 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 0cad952..fc42087 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -6474,7 +6474,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', ''), @@ -6501,6 +6501,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 From 20ceb84dd1e6fbd4ab089394572ad89f61847ceb Mon Sep 17 00:00:00 2001 From: Priyanka Date: Tue, 5 May 2026 18:00:44 +0530 Subject: [PATCH 15/21] refactored parse errors to unformatted_data --- aci-preupgrade-validation-script.py | 100 ++++++++---------- .../test_n9300_switch_memory_32g_check.py | 16 +-- 2 files changed, 51 insertions(+), 65 deletions(-) diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index fc42087..097d1c7 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -6415,6 +6415,8 @@ def n9300_switch_memory_check(fabric_nodes, **kwargs): result = PASS headers = ["NodeId", "Name", "Model", "Memory Detected (GB)"] data = [] + unformatted_headers = ['DN', 'Total'] + unformatted_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 * 1000 * 1000 @@ -6431,7 +6433,6 @@ def n9300_switch_memory_check(fabric_nodes, **kwargs): 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', {}) @@ -6445,69 +6446,62 @@ def n9300_switch_memory_check(fabric_nodes, **kwargs): try: total_kb = int(total) except (TypeError, ValueError): - parse_errors.append([mem_dn, total]) + unformatted_data.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 - recommended_action = '' - 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 + missing_nodes = [] - if total_kb < min_memory_kb: - memory_in_gb = round(total_kb / 1000000, 2) - result = MANUAL - data.append([ - node_id, - node['fabricNode']['attributes'].get('name', ''), - node['fabricNode']['attributes'].get('model', ''), - memory_in_gb, - ]) + 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 and data: + if total_kb < min_memory_kb: + memory_in_gb = round(total_kb / 1000000, 2) 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'] - 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.' + data.append([ + node_id, + node['fabricNode']['attributes'].get('name', ''), + node['fabricNode']['attributes'].get('model', ''), + memory_in_gb, + ]) + + 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'] + 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) + return Result(result=result, msg=msg, headers=headers, data=data, unformatted_headers=unformatted_headers, unformatted_data=unformatted_data, recommended_action=recommended_action, doc_url=doc_url) # ---- Script Execution ---- 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 699f649..1500817 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 @@ -60,17 +60,6 @@ '', [], ), - # 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"), @@ -132,4 +121,7 @@ def test_logic(run_check, mock_icurl, fabric_nodes, tversion, expected_result, e ) assert result.result == expected_result assert result.msg == expected_msg - assert result.data == expected_data \ No newline at end of file + if result.data: + assert result.data == expected_data + else: + assert result.unformatted_data == expected_data \ No newline at end of file From 61651e4fca1597a1e68d5bf9c6ae806e7b6a16f3 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Thu, 21 May 2026 10:59:05 +0530 Subject: [PATCH 16/21] Addressed PR comments --- aci-preupgrade-validation-script.py | 8 ++++---- docs/docs/validations.md | 6 ++++-- .../fabricNode_non_n9300.json | 0 .../fabricNode_one.json | 0 .../fabricNode_two.json | 0 .../fabricNode_two_fx3.json | 0 .../procMemUsage_all_gt32gb.json | 0 .../procMemUsage_fail_and_missing.json | 0 .../procMemUsage_gt32gb.json | 0 .../procMemUsage_invalid_total.json | 0 .../procMemUsage_lt32gb.json | 0 .../procMemUsage_missing_affected_node.json | 0 .../procMemUsage_mixed.json | 0 .../procMemUsage_node201_gt32gb.json | 0 .../test_n9k_c93180yc_fx3_switch_memory_check.py} | 2 +- 15 files changed, 9 insertions(+), 7 deletions(-) rename tests/checks/{n9300_switch_memory_32g_check => n9k_c93180yc_fx3_switch_memory_check}/fabricNode_non_n9300.json (100%) rename tests/checks/{n9300_switch_memory_32g_check => n9k_c93180yc_fx3_switch_memory_check}/fabricNode_one.json (100%) rename tests/checks/{n9300_switch_memory_32g_check => n9k_c93180yc_fx3_switch_memory_check}/fabricNode_two.json (100%) rename tests/checks/{n9300_switch_memory_32g_check => n9k_c93180yc_fx3_switch_memory_check}/fabricNode_two_fx3.json (100%) rename tests/checks/{n9300_switch_memory_32g_check => n9k_c93180yc_fx3_switch_memory_check}/procMemUsage_all_gt32gb.json (100%) rename tests/checks/{n9300_switch_memory_32g_check => n9k_c93180yc_fx3_switch_memory_check}/procMemUsage_fail_and_missing.json (100%) rename tests/checks/{n9300_switch_memory_32g_check => n9k_c93180yc_fx3_switch_memory_check}/procMemUsage_gt32gb.json (100%) rename tests/checks/{n9300_switch_memory_32g_check => n9k_c93180yc_fx3_switch_memory_check}/procMemUsage_invalid_total.json (100%) rename tests/checks/{n9300_switch_memory_32g_check => n9k_c93180yc_fx3_switch_memory_check}/procMemUsage_lt32gb.json (100%) rename tests/checks/{n9300_switch_memory_32g_check => n9k_c93180yc_fx3_switch_memory_check}/procMemUsage_missing_affected_node.json (100%) rename tests/checks/{n9300_switch_memory_32g_check => n9k_c93180yc_fx3_switch_memory_check}/procMemUsage_mixed.json (100%) rename tests/checks/{n9300_switch_memory_32g_check => n9k_c93180yc_fx3_switch_memory_check}/procMemUsage_node201_gt32gb.json (100%) rename tests/checks/{n9300_switch_memory_32g_check/test_n9300_switch_memory_32g_check.py => n9k_c93180yc_fx3_switch_memory_check/test_n9k_c93180yc_fx3_switch_memory_check.py} (98%) diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index 097d1c7..0a86c2e 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -6410,15 +6410,15 @@ def svccore_excessive_data_check(**kwargs): return Result(result=ERROR, msg="Error occurred while fetching svccore object counts: {}".format(str(e)), doc_url=doc_url) -@check_wrapper(check_title='N9300 Switch Memory') -def n9300_switch_memory_check(fabric_nodes, **kwargs): +@check_wrapper(check_title='N9K-C93180YC-FX3 Switch Memory') +def n9k_c93180yc_fx3_switch_memory_check(fabric_nodes, **kwargs): result = PASS headers = ["NodeId", "Name", "Model", "Memory Detected (GB)"] data = [] unformatted_headers = ['DN', 'Total'] unformatted_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' + doc_url = 'https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#n9k-c93180yc-fx3-switch-memory' min_memory_kb = 32 * 1000 * 1000 msg = '' @@ -6595,7 +6595,7 @@ class CheckManager: validate_32_64_bit_image_check, fabric_link_redundancy_check, apic_downgrade_compat_warning_check, - n9300_switch_memory_check, + n9k_c93180yc_fx3_switch_memory_check, svccore_excessive_data_check, # Faults diff --git a/docs/docs/validations.md b/docs/docs/validations.md index d8207b9..862fcf1 100644 --- a/docs/docs/validations.md +++ b/docs/docs/validations.md @@ -39,6 +39,7 @@ Items | This Script [APIC downgrade compatibility when crossing 6.2 release][g19]| :white_check_mark: | :no_entry_sign: [Supported Hardware Compatibility][g20] | :white_check_mark: | :no_entry_sign: [Svccore Excessive Data Check][g21] | :white_check_mark: | :no_entry_sign: +[N9K-C93180YC-FX3 Switch Memory][g22] | :white_check_mark: | :no_entry_sign: [g1]: #compatibility-target-aci-version [g2]: #compatibility-cimc-version @@ -61,6 +62,7 @@ Items | This Script [g19]: #apic-downgrade-compatibility-when-crossing-62-release [g20]: #supported-hardware-compatibility [g21]: #svccore-excessive-data-check +[g22]: #n9k-c93180yc-fx3-switch-memory ### Fault Checks Items | Faults | This Script | APIC built-in @@ -2743,9 +2745,9 @@ 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 +### N9K-C93180YC-FX3 Switch Memory -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. +This check applies to N9K-C93180YC-FX3 switches only. It checks whether the switch is using 16GB or 32GB of memory and flags switches running on 16GB memory. This check is not version dependent and runs for all upgrade versions. Impact: Running an N9K-C93180YC-FX3 switch with less than 32GB memory can lead to memory pressure and increase the risk of service instability. diff --git a/tests/checks/n9300_switch_memory_32g_check/fabricNode_non_n9300.json b/tests/checks/n9k_c93180yc_fx3_switch_memory_check/fabricNode_non_n9300.json similarity index 100% rename from tests/checks/n9300_switch_memory_32g_check/fabricNode_non_n9300.json rename to tests/checks/n9k_c93180yc_fx3_switch_memory_check/fabricNode_non_n9300.json diff --git a/tests/checks/n9300_switch_memory_32g_check/fabricNode_one.json b/tests/checks/n9k_c93180yc_fx3_switch_memory_check/fabricNode_one.json similarity index 100% rename from tests/checks/n9300_switch_memory_32g_check/fabricNode_one.json rename to tests/checks/n9k_c93180yc_fx3_switch_memory_check/fabricNode_one.json diff --git a/tests/checks/n9300_switch_memory_32g_check/fabricNode_two.json b/tests/checks/n9k_c93180yc_fx3_switch_memory_check/fabricNode_two.json similarity index 100% rename from tests/checks/n9300_switch_memory_32g_check/fabricNode_two.json rename to tests/checks/n9k_c93180yc_fx3_switch_memory_check/fabricNode_two.json diff --git a/tests/checks/n9300_switch_memory_32g_check/fabricNode_two_fx3.json b/tests/checks/n9k_c93180yc_fx3_switch_memory_check/fabricNode_two_fx3.json similarity index 100% rename from tests/checks/n9300_switch_memory_32g_check/fabricNode_two_fx3.json rename to tests/checks/n9k_c93180yc_fx3_switch_memory_check/fabricNode_two_fx3.json diff --git a/tests/checks/n9300_switch_memory_32g_check/procMemUsage_all_gt32gb.json b/tests/checks/n9k_c93180yc_fx3_switch_memory_check/procMemUsage_all_gt32gb.json similarity index 100% rename from tests/checks/n9300_switch_memory_32g_check/procMemUsage_all_gt32gb.json rename to tests/checks/n9k_c93180yc_fx3_switch_memory_check/procMemUsage_all_gt32gb.json diff --git a/tests/checks/n9300_switch_memory_32g_check/procMemUsage_fail_and_missing.json b/tests/checks/n9k_c93180yc_fx3_switch_memory_check/procMemUsage_fail_and_missing.json similarity index 100% rename from tests/checks/n9300_switch_memory_32g_check/procMemUsage_fail_and_missing.json rename to tests/checks/n9k_c93180yc_fx3_switch_memory_check/procMemUsage_fail_and_missing.json diff --git a/tests/checks/n9300_switch_memory_32g_check/procMemUsage_gt32gb.json b/tests/checks/n9k_c93180yc_fx3_switch_memory_check/procMemUsage_gt32gb.json similarity index 100% rename from tests/checks/n9300_switch_memory_32g_check/procMemUsage_gt32gb.json rename to tests/checks/n9k_c93180yc_fx3_switch_memory_check/procMemUsage_gt32gb.json diff --git a/tests/checks/n9300_switch_memory_32g_check/procMemUsage_invalid_total.json b/tests/checks/n9k_c93180yc_fx3_switch_memory_check/procMemUsage_invalid_total.json similarity index 100% rename from tests/checks/n9300_switch_memory_32g_check/procMemUsage_invalid_total.json rename to tests/checks/n9k_c93180yc_fx3_switch_memory_check/procMemUsage_invalid_total.json diff --git a/tests/checks/n9300_switch_memory_32g_check/procMemUsage_lt32gb.json b/tests/checks/n9k_c93180yc_fx3_switch_memory_check/procMemUsage_lt32gb.json similarity index 100% rename from tests/checks/n9300_switch_memory_32g_check/procMemUsage_lt32gb.json rename to tests/checks/n9k_c93180yc_fx3_switch_memory_check/procMemUsage_lt32gb.json diff --git a/tests/checks/n9300_switch_memory_32g_check/procMemUsage_missing_affected_node.json b/tests/checks/n9k_c93180yc_fx3_switch_memory_check/procMemUsage_missing_affected_node.json similarity index 100% rename from tests/checks/n9300_switch_memory_32g_check/procMemUsage_missing_affected_node.json rename to tests/checks/n9k_c93180yc_fx3_switch_memory_check/procMemUsage_missing_affected_node.json diff --git a/tests/checks/n9300_switch_memory_32g_check/procMemUsage_mixed.json b/tests/checks/n9k_c93180yc_fx3_switch_memory_check/procMemUsage_mixed.json similarity index 100% rename from tests/checks/n9300_switch_memory_32g_check/procMemUsage_mixed.json rename to tests/checks/n9k_c93180yc_fx3_switch_memory_check/procMemUsage_mixed.json diff --git a/tests/checks/n9300_switch_memory_32g_check/procMemUsage_node201_gt32gb.json b/tests/checks/n9k_c93180yc_fx3_switch_memory_check/procMemUsage_node201_gt32gb.json similarity index 100% rename from tests/checks/n9300_switch_memory_32g_check/procMemUsage_node201_gt32gb.json rename to tests/checks/n9k_c93180yc_fx3_switch_memory_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/n9k_c93180yc_fx3_switch_memory_check/test_n9k_c93180yc_fx3_switch_memory_check.py similarity index 98% rename from tests/checks/n9300_switch_memory_32g_check/test_n9300_switch_memory_32g_check.py rename to tests/checks/n9k_c93180yc_fx3_switch_memory_check/test_n9k_c93180yc_fx3_switch_memory_check.py index 1500817..9ca1c7c 100644 --- a/tests/checks/n9300_switch_memory_32g_check/test_n9300_switch_memory_32g_check.py +++ b/tests/checks/n9k_c93180yc_fx3_switch_memory_check/test_n9k_c93180yc_fx3_switch_memory_check.py @@ -9,7 +9,7 @@ log = logging.getLogger(__name__) dir = os.path.dirname(os.path.abspath(__file__)) -test_function = "n9300_switch_memory_check" +test_function = "n9k_c93180yc_fx3_switch_memory_check" # icurl queries proc_mem_query = 'procMemUsage.json' From d7d4289fddf7438adc371343fcfcac5a801fda38 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Mon, 25 May 2026 12:43:06 +0530 Subject: [PATCH 17/21] Remove old n9300_switch_memory_24g_check test files --- .../procMemUsage_all_gt24gb.json | 20 --- .../procMemUsage_gt24gb.json | 11 -- .../procMemUsage_mixed.json | 20 --- .../test_n9300_switch_memory_24g_check.py | 116 ------------------ 4 files changed, 167 deletions(-) delete mode 100644 tests/checks/n9300_switch_memory_24g_check/procMemUsage_all_gt24gb.json delete mode 100644 tests/checks/n9300_switch_memory_24g_check/procMemUsage_gt24gb.json delete mode 100644 tests/checks/n9300_switch_memory_24g_check/procMemUsage_mixed.json delete mode 100644 tests/checks/n9300_switch_memory_24g_check/test_n9300_switch_memory_24g_check.py 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 deleted file mode 100644 index 3599e1a..0000000 --- a/tests/checks/n9300_switch_memory_24g_check/procMemUsage_all_gt24gb.json +++ /dev/null @@ -1,20 +0,0 @@ -[ - { - "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_gt24gb.json b/tests/checks/n9300_switch_memory_24g_check/procMemUsage_gt24gb.json deleted file mode 100644 index 6f1d221..0000000 --- a/tests/checks/n9300_switch_memory_24g_check/procMemUsage_gt24gb.json +++ /dev/null @@ -1,11 +0,0 @@ -[ - { - "procMemUsage": { - "attributes": { - "dn": "topology/pod-1/node-101/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_mixed.json b/tests/checks/n9300_switch_memory_24g_check/procMemUsage_mixed.json deleted file mode 100644 index 252adfa..0000000 --- a/tests/checks/n9300_switch_memory_24g_check/procMemUsage_mixed.json +++ /dev/null @@ -1,20 +0,0 @@ -[ - { - "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/test_n9300_switch_memory_24g_check.py b/tests/checks/n9300_switch_memory_24g_check/test_n9300_switch_memory_24g_check.py deleted file mode 100644 index c0256c6..0000000 --- a/tests/checks/n9300_switch_memory_24g_check/test_n9300_switch_memory_24g_check.py +++ /dev/null @@ -1,116 +0,0 @@ -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_gt24gb.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 db4dd05be562a90055bde423c76591e77e4489c9 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Mon, 25 May 2026 18:57:17 +0530 Subject: [PATCH 18/21] Updated check for fabricNode attributes --- aci-preupgrade-validation-script.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index 0a86c2e..43a2b64 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -6424,7 +6424,7 @@ def n9k_c93180yc_fx3_switch_memory_check(fabric_nodes, **kwargs): affected_nodes = [ node for node in fabric_nodes - if node.get('fabricNode', {}).get('attributes', {}).get('model', '') == 'N9K-C93180YC-FX3' + if node['fabricNode']['attributes']['model'] == 'N9K-C93180YC-FX3' ] if not affected_nodes: @@ -6461,8 +6461,8 @@ def n9k_c93180yc_fx3_switch_memory_check(fabric_nodes, **kwargs): if total_kb is None: missing_nodes.append([ node_id, - node['fabricNode']['attributes'].get('name', ''), - node['fabricNode']['attributes'].get('model', ''), + node['fabricNode']['attributes']['name'], + node['fabricNode']['attributes']['model'], ]) continue @@ -6471,8 +6471,8 @@ def n9k_c93180yc_fx3_switch_memory_check(fabric_nodes, **kwargs): result = MANUAL data.append([ node_id, - node['fabricNode']['attributes'].get('name', ''), - node['fabricNode']['attributes'].get('model', ''), + node['fabricNode']['attributes']['name'], + node['fabricNode']['attributes']['model'], memory_in_gb, ]) From a5ed4ce1b011ecc3bbf8b9e942d1aac70fdd0416 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Tue, 26 May 2026 11:40:11 +0530 Subject: [PATCH 19/21] Addressed PR comments in validations.md --- docs/docs/validations.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/docs/validations.md b/docs/docs/validations.md index 862fcf1..cac6204 100644 --- a/docs/docs/validations.md +++ b/docs/docs/validations.md @@ -205,7 +205,6 @@ Items | Defect | This Script [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: [Inband Management Policy Misconfiguration][d33]| CSCwd40071 | :white_check_mark: | :no_entry_sign: -[N9300 Switch Memory][d34] | - | :white_check_mark: | :no_entry_sign: [d1]: #ep-announce-compatibility [d2]: #eventmgr-db-size-defect-susceptibility @@ -240,7 +239,6 @@ Items | Defect | This Script [d31]: #n9k-c9408-with-more-than-5-n9k-x9400-16w-lems [d32]: #multi-pod-modular-spine-bootscript-file [d33]: #inband-management-policy-misconfiguration -[d34]: #n9300-switch-memory ## General Check Details @@ -2726,6 +2724,7 @@ 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. + ### 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: From ea26774ee95c743a01b5e5b85fd8897b5856c2ff Mon Sep 17 00:00:00 2001 From: Priyanka Date: Tue, 26 May 2026 13:42:51 +0530 Subject: [PATCH 20/21] Addressed PR comments --- aci-preupgrade-validation-script.py | 2 +- .../test_n9k_c93180yc_fx3_switch_memory_check.py | 13 ++----------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index 43a2b64..9d7b458 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -6595,7 +6595,6 @@ class CheckManager: validate_32_64_bit_image_check, fabric_link_redundancy_check, apic_downgrade_compat_warning_check, - n9k_c93180yc_fx3_switch_memory_check, svccore_excessive_data_check, # Faults @@ -6676,6 +6675,7 @@ class CheckManager: rogue_ep_coop_exception_mac_check, n9k_c9408_model_lem_count_check, inband_management_policy_misconfig_check, + n9k_c93180yc_fx3_switch_memory_check, ] ssh_checks = [ # General diff --git a/tests/checks/n9k_c93180yc_fx3_switch_memory_check/test_n9k_c93180yc_fx3_switch_memory_check.py b/tests/checks/n9k_c93180yc_fx3_switch_memory_check/test_n9k_c93180yc_fx3_switch_memory_check.py index 9ca1c7c..6fecff0 100644 --- a/tests/checks/n9k_c93180yc_fx3_switch_memory_check/test_n9k_c93180yc_fx3_switch_memory_check.py +++ b/tests/checks/n9k_c93180yc_fx3_switch_memory_check/test_n9k_c93180yc_fx3_switch_memory_check.py @@ -16,13 +16,12 @@ @pytest.mark.parametrize( - "fabric_nodes, icurl_outputs, tversion, expected_result, expected_msg, expected_data", + "fabric_nodes, icurl_outputs, expected_result, expected_msg, expected_data", [ # No nodes returned ( [], {}, - "6.0(3c)", script.NA, 'No N9K-C93180YC-FX3 switches found. Skipping.', [], @@ -33,7 +32,6 @@ { proc_mem_query: read_data(dir, "procMemUsage_node201_gt32gb.json"), }, - "6.0(3c)", script.NA, 'No N9K-C93180YC-FX3 switches found. Skipping.', [], @@ -44,7 +42,6 @@ { proc_mem_query: read_data(dir, "procMemUsage_gt32gb.json"), }, - "6.0(3c)", script.PASS, '', [], @@ -55,7 +52,6 @@ { proc_mem_query: read_data(dir, "procMemUsage_all_gt32gb.json"), }, - "6.0(3c)", script.PASS, '', [], @@ -66,7 +62,6 @@ { 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"]], @@ -77,7 +72,6 @@ { proc_mem_query: read_data(dir, "procMemUsage_mixed.json"), }, - "6.0(3c)", script.PASS, '', [], @@ -88,7 +82,6 @@ { proc_mem_query: read_data(dir, "procMemUsage_lt32gb.json"), }, - "6.0(3c)", script.MANUAL, ( 'One or more N9K-C93180YC-FX3 switches have less than 32GB of memory. ' @@ -102,7 +95,6 @@ { 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 ' @@ -114,9 +106,8 @@ ), ], ) -def test_logic(run_check, mock_icurl, fabric_nodes, tversion, expected_result, expected_msg, expected_data): +def test_logic(run_check, mock_icurl, fabric_nodes, expected_result, expected_msg, expected_data): result = run_check( - tversion=script.AciVersion(tversion), fabric_nodes=fabric_nodes, ) assert result.result == expected_result From 2aa34bf8e4eb03ab4a6a45578d8dee00099410f6 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Tue, 26 May 2026 14:09:08 +0530 Subject: [PATCH 21/21] Addressed the PR comments --- 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 9d7b458..add4a89 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -6596,6 +6596,7 @@ class CheckManager: fabric_link_redundancy_check, apic_downgrade_compat_warning_check, svccore_excessive_data_check, + n9k_c93180yc_fx3_switch_memory_check, # Faults apic_disk_space_faults_check, @@ -6675,7 +6676,6 @@ class CheckManager: rogue_ep_coop_exception_mac_check, n9k_c9408_model_lem_count_check, inband_management_policy_misconfig_check, - n9k_c93180yc_fx3_switch_memory_check, ] ssh_checks = [ # General