From ced0e4a8f4ee827310d6f3363c8ba537741dcb71 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Fri, 20 Mar 2026 16:34:31 +0530 Subject: [PATCH 01/23] 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 da1b4b9e..d1c2f000 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 82f22119..0206c042 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 00000000..a82341a4 --- /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 00000000..74a31ad3 --- /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 00000000..fad02898 --- /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 00000000..dab23d29 --- /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 00000000..597db59c --- /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 00000000..d84e82c0 --- /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 00000000..58ece8e7 --- /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 00000000..bca2b9ff --- /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 00000000..8ae92ad4 --- /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/23] 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 d1c2f000..c75d206e 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/23] 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 c75d206e..3f26d550 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 0206c042..d5998893 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 8ae92ad4..72b76dee 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/23] 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 3f26d550..5ed7d132 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 00000000..dc1a4ee3 --- /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 00000000..e11293a7 --- /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 72b76dee..0f6aa001 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/23] 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 5ed7d132..30af4f78 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/23] 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 30af4f78..dc0a3cef 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/23] 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 dc0a3cef..3d78f03c 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/23] 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 3d78f03c..dc0a3cef 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/23] 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 dc0a3cef..8ac74d85 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/23] 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 8ac74d85..042ff3ae 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 d5998893..d8207b9a 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 dab23d29..3599e1ab 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 597db59c..6f1d2214 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 58ece8e7..252adfaf 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 0f6aa001..c0256c64 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 00000000..3599e1ab --- /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 d84e82c0..6f1d2214 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 00000000..1f356213 --- /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 00000000..252adfaf --- /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 00000000..27d5fd66 --- /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/23] 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 042ff3ae..7887e21e 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 3599e1ab..c3aef55a 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 6f1d2214..5597a511 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 1f356213..5f50d60d 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 e11293a7..f8b22098 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 252adfaf..b7c74c07 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 bca2b9ff..db65e8c6 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 27d5fd66..5f56edb5 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/23] 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 7887e21e..49e12f23 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 00000000..dfc8a77a --- /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 00000000..5f50d60d --- /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 5f56edb5..212248cd 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/23] 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 49e12f23..0cad952f 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/23] 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 0cad952f..fc42087b 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 212248cd..699f6490 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/23] 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 fc42087b..097d1c7c 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 699f6490..15008175 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/23] 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 097d1c7c..0a86c2ec 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 d8207b9a..862fcf15 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 15008175..9ca1c7cb 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/23] 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 3599e1ab..00000000 --- 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 6f1d2214..00000000 --- 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 252adfaf..00000000 --- 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 c0256c64..00000000 --- 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/23] 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 0a86c2ec..43a2b649 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/23] 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 862fcf15..cac6204c 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/23] 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 43a2b649..9d7b4588 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 9ca1c7cb..6fecff03 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/23] 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 9d7b4588..add4a895 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 From 3f0bd8c02f60e99943b1023a75a209f70be09ae4 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Thu, 18 Jun 2026 18:43:33 +0530 Subject: [PATCH 22/23] Addressed PR Comments --- aci-preupgrade-validation-script.py | 94 ++++++------------- docs/docs/validations.md | 13 +-- ...st_n9k_c93180yc_fx3_switch_memory_check.py | 58 +++--------- 3 files changed, 48 insertions(+), 117 deletions(-) diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index add4a895..9983a677 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -6415,8 +6415,6 @@ 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/#n9k-c93180yc-fx3-switch-memory' min_memory_kb = 32 * 1000 * 1000 @@ -6431,77 +6429,45 @@ def n9k_c93180yc_fx3_switch_memory_check(fabric_nodes, **kwargs): result = NA msg = 'No N9K-C93180YC-FX3 switches found. Skipping.' else: - proc_mem_mos = icurl('class', 'procMemUsage.json') - node_total_kb = {} + node_ids = [node['fabricNode']['attributes']['id'] for node in affected_nodes] + node_filter = 'or({})'.format(','.join( + 'wcard(procMemUsage.dn,"node-{}/")'.format(nid) for nid in node_ids + )) + query = 'procMemUsage.json?query-target-filter=and({},wcard(procMemUsage.dn,"memusage-sup"),lt(procMemUsage.Total,"{}"))'.format( + node_filter, min_memory_kb + ) + proc_mem_mos = icurl('class', query) + + node_id_to_attrs = { + node['fabricNode']['attributes']['id']: node['fabricNode']['attributes'] + for node in affected_nodes + } 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) + attrs = memory_mo['procMemUsage']['attributes'] + dn_match = re.search(node_regex, attrs['dn']) if not dn_match: continue - try: - total_kb = int(total) - except (TypeError, ValueError): - 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 - - 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']['name'], - node['fabricNode']['attributes']['model'], - ]) + if node_id not in node_id_to_attrs: continue - - if total_kb < min_memory_kb: - memory_in_gb = round(total_kb / 1000000, 2) - result = MANUAL - data.append([ - node_id, - node['fabricNode']['attributes']['name'], - node['fabricNode']['attributes']['model'], - memory_in_gb, - ]) - - if missing_nodes and data: + memory_in_gb = round(int(attrs['Total']) / 1000000, 2) result = MANUAL + data.append([ + node_id, + node_id_to_attrs[node_id]['name'], + node_id_to_attrs[node_id]['model'], + memory_in_gb, + ]) + + if data: 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.' + 'N9K-C93180YC-FX3 requires a minimum of 32GB RAM for proper operation in ACI mode. ' + 'One or more switches have less than 32GB of memory and may experience service instability. ' + 'Upgrade the switch memory to at least 32GB.' ) - 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) + return Result(result=result, msg=msg, headers=headers, data=data, recommended_action=recommended_action, doc_url=doc_url) # ---- Script Execution ---- @@ -6596,7 +6562,6 @@ 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, @@ -6676,6 +6641,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/docs/docs/validations.md b/docs/docs/validations.md index cac6204c..8b740588 100644 --- a/docs/docs/validations.md +++ b/docs/docs/validations.md @@ -39,7 +39,6 @@ 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 @@ -62,7 +61,6 @@ 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 @@ -205,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: +[N9K-C93180YC-FX3 Switch Memory][d34] | CSCwm42741 | :white_check_mark: | :no_entry_sign: [d1]: #ep-announce-compatibility [d2]: #eventmgr-db-size-defect-susceptibility @@ -239,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]: #n9k-c93180yc-fx3-switch-memory ## General Check Details @@ -2746,11 +2746,11 @@ To avoid this risk, consider disabling Auto Firmware Update before upgrading to ### N9K-C93180YC-FX3 Switch Memory -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. +This check applies to N9K-C93180YC-FX3 switches only. It checks whether the switch has less than 32GB of memory. The minimum RAM requirement for the N9K-C93180YC-FX3 to operate properly in ACI mode is 32GB. 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. +[CSCwm42741][70] tracks this issue. N9K-C93180YC-FX3 switches running in ACI mode with less than 32GB of memory will not perform well and are at risk of service instability. On ACI releases that include the fix for CSCwm42741, a critical fault F4680 (`eqpt-low-memory-device`) is raised on affected switches. -If any N9K-C93180YC-FX3 switch is flagged by this check, upgrade the switch memory to at least 32GB. +If any N9K-C93180YC-FX3 switch is flagged by this check, upgrade the switch memory to at least 32GB before proceeding with the upgrade. ### Rogue EP Exception List missing on switches @@ -2877,4 +2877,5 @@ This check will verify the count of the `svccoreCtrlr` Managed Object and raise [66]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwr66848 [67]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwh80837 [68]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwd40071 -[69]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCws84232 \ No newline at end of file +[69]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCws84232 +[70]: https://bst.cloudapps.cisco.com/bugsearch/bug/CSCwm42741 \ No newline at end of file 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 6fecff03..dcfe0422 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 @@ -11,8 +11,8 @@ test_function = "n9k_c93180yc_fx3_switch_memory_check" -# icurl queries -proc_mem_query = 'procMemUsage.json' +# icurl queries - filtered by affected node IDs and memory threshold +proc_mem_query_node101 = 'procMemUsage.json?query-target-filter=and(or(wcard(procMemUsage.dn,"node-101/")),wcard(procMemUsage.dn,"memusage-sup"),lt(procMemUsage.Total,"32000000"))' @pytest.mark.parametrize( @@ -29,48 +29,26 @@ # Non-N9K-C93180YC-FX3 node ( read_data(dir, "fabricNode_non_n9300.json"), - { - proc_mem_query: read_data(dir, "procMemUsage_node201_gt32gb.json"), - }, + {}, script.NA, 'No N9K-C93180YC-FX3 switches found. Skipping.', [], ), - # N9K-C93180YC-FX3 node with >=32GB memory + # N9K-C93180YC-FX3 node with >=32GB memory - API returns empty (filtered by lt) ( read_data(dir, "fabricNode_one.json"), { - proc_mem_query: read_data(dir, "procMemUsage_gt32gb.json"), + proc_mem_query_node101: [], }, script.PASS, '', [], ), - # Multiple nodes, only N9K-C93180YC-FX3 checked, all >=32GB + # Multiple nodes, only N9K-C93180YC-FX3 checked, all >=32GB - API returns empty ( read_data(dir, "fabricNode_two.json"), { - proc_mem_query: read_data(dir, "procMemUsage_all_gt32gb.json"), - }, - script.PASS, - '', - [], - ), - # Missing procMemUsage data for affected node - ( - read_data(dir, "fabricNode_one.json"), - { - proc_mem_query: read_data(dir, "procMemUsage_missing_affected_node.json"), - }, - 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"), + proc_mem_query_node101: [], }, script.PASS, '', @@ -80,30 +58,16 @@ ( read_data(dir, "fabricNode_one.json"), { - proc_mem_query: read_data(dir, "procMemUsage_lt32gb.json"), + proc_mem_query_node101: read_data(dir, "procMemUsage_lt32gb.json"), }, 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.' + 'N9K-C93180YC-FX3 requires a minimum of 32GB RAM for proper operation in ACI mode. ' + 'One or more switches have less than 32GB of memory and may experience service instability. ' + 'Upgrade the switch memory to at least 32GB.' ), [["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"), - }, - 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, expected_result, expected_msg, expected_data): From c27507078ed69a75c0d4166bbfdf22227795410f Mon Sep 17 00:00:00 2001 From: Priyanka Date: Fri, 19 Jun 2026 12:43:24 +0530 Subject: [PATCH 23/23] Updated the files --- aci-preupgrade-validation-script.py | 8 ++++---- docs/docs/validations.md | 8 ++++---- ...abricNode_non_n9300.json => fabricNode_N9K-C9508.json} | 0 .../test_n9k_c93180yc_fx3_switch_memory_check.py | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) rename tests/checks/n9k_c93180yc_fx3_switch_memory_check/{fabricNode_non_n9300.json => fabricNode_N9K-C9508.json} (100%) diff --git a/aci-preupgrade-validation-script.py b/aci-preupgrade-validation-script.py index 9983a677..da5d15f3 100644 --- a/aci-preupgrade-validation-script.py +++ b/aci-preupgrade-validation-script.py @@ -6410,13 +6410,13 @@ 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='N9K-C93180YC-FX3 Switch Memory') +@check_wrapper(check_title='N9K-C93180YC-FX3 Switch Memory Less Than 32GB') def n9k_c93180yc_fx3_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 32GB on affected N9K-C93180YC-FX3 switches.' - doc_url = 'https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#n9k-c93180yc-fx3-switch-memory' + recommended_action = 'Increase the switch memory to at least 32GB on affected N9K-C93180YC-FX3.' + doc_url = 'https://datacenter.github.io/ACI-Pre-Upgrade-Validation-Script/validations/#n9k-c93180yc-fx3-switch-memory-less-than-32gb' min_memory_kb = 32 * 1000 * 1000 msg = '' @@ -6463,7 +6463,7 @@ def n9k_c93180yc_fx3_switch_memory_check(fabric_nodes, **kwargs): if data: msg = ( 'N9K-C93180YC-FX3 requires a minimum of 32GB RAM for proper operation in ACI mode. ' - 'One or more switches have less than 32GB of memory and may experience service instability. ' + 'One or more switches with less than 32GB of memory may experience service instability. ' 'Upgrade the switch memory to at least 32GB.' ) diff --git a/docs/docs/validations.md b/docs/docs/validations.md index 8b740588..8dda2227 100644 --- a/docs/docs/validations.md +++ b/docs/docs/validations.md @@ -203,7 +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: -[N9K-C93180YC-FX3 Switch Memory][d34] | CSCwm42741 | :white_check_mark: | :no_entry_sign: +[N9K-C93180YC-FX3 Switch Memory Less Than 32GB][d34] | CSCwm42741 | :white_check_mark: | :no_entry_sign: [d1]: #ep-announce-compatibility [d2]: #eventmgr-db-size-defect-susceptibility @@ -238,7 +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]: #n9k-c93180yc-fx3-switch-memory +[d34]: #n9k-c93180yc-fx3-switch-memory-less-than-32gb ## General Check Details @@ -2744,11 +2744,11 @@ 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. -### N9K-C93180YC-FX3 Switch Memory +### N9K-C93180YC-FX3 Switch Memory Less Than 32GB This check applies to N9K-C93180YC-FX3 switches only. It checks whether the switch has less than 32GB of memory. The minimum RAM requirement for the N9K-C93180YC-FX3 to operate properly in ACI mode is 32GB. This check is not version dependent and runs for all upgrade versions. -[CSCwm42741][70] tracks this issue. N9K-C93180YC-FX3 switches running in ACI mode with less than 32GB of memory will not perform well and are at risk of service instability. On ACI releases that include the fix for CSCwm42741, a critical fault F4680 (`eqpt-low-memory-device`) is raised on affected switches. +[CSCwm42741][70] tracks this issue. N9K-C93180YC-FX3 switches running in ACI mode with less than 32GB of memory will not perform well and are at risk of service instability. With fix of CSCwm42741, a critical fault F4680 (`eqpt-low-memory-device`) is raised on affected switches. If any N9K-C93180YC-FX3 switch is flagged by this check, upgrade the switch memory to at least 32GB before proceeding with the upgrade. diff --git a/tests/checks/n9k_c93180yc_fx3_switch_memory_check/fabricNode_non_n9300.json b/tests/checks/n9k_c93180yc_fx3_switch_memory_check/fabricNode_N9K-C9508.json similarity index 100% rename from tests/checks/n9k_c93180yc_fx3_switch_memory_check/fabricNode_non_n9300.json rename to tests/checks/n9k_c93180yc_fx3_switch_memory_check/fabricNode_N9K-C9508.json 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 dcfe0422..56a360c2 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 @@ -26,9 +26,9 @@ 'No N9K-C93180YC-FX3 switches found. Skipping.', [], ), - # Non-N9K-C93180YC-FX3 node + # Non-N9K-C93180YC-FX3 node (N9K-C9508) ( - read_data(dir, "fabricNode_non_n9300.json"), + read_data(dir, "fabricNode_N9K-C9508.json"), {}, script.NA, 'No N9K-C93180YC-FX3 switches found. Skipping.', @@ -63,7 +63,7 @@ script.MANUAL, ( 'N9K-C93180YC-FX3 requires a minimum of 32GB RAM for proper operation in ACI mode. ' - 'One or more switches have less than 32GB of memory and may experience service instability. ' + 'One or more switches with less than 32GB of memory may experience service instability. ' 'Upgrade the switch memory to at least 32GB.' ), [["101", "leaf101", "N9K-C93180YC-FX3", 16.0]],