From 4f2f277bb4c5a358ed33b93a8df1c87f8a514786 Mon Sep 17 00:00:00 2001 From: Alexandra Bara Date: Tue, 19 May 2026 11:13:06 -0500 Subject: [PATCH] exiting with NOT_RAN when cards not present --- .../plugins/inband/nic/nic_collector.py | 42 +++++++++++++------ test/unit/plugin/test_niccli_collector.py | 38 +++++++++++++++++ 2 files changed, 67 insertions(+), 13 deletions(-) diff --git a/nodescraper/plugins/inband/nic/nic_collector.py b/nodescraper/plugins/inband/nic/nic_collector.py index 021fa3e3..c9c0b606 100644 --- a/nodescraper/plugins/inband/nic/nic_collector.py +++ b/nodescraper/plugins/inband/nic/nic_collector.py @@ -354,7 +354,9 @@ class NicCollector(InBandDataCollector[NicDataModel, NicCollectorArgs]): CMD_NICCLI_QOS_TEMPLATE_LEGACY, ] # New (> v233): double-dash options and qos --ets --show - CMD_NICCLI_SUPPORT_RDMA_TEMPLATE_NEW = "niccli --dev {device_num} nvm --getoption support_rdma" + CMD_NICCLI_SUPPORT_RDMA_TEMPLATE_NEW = ( + "niccli --dev {device_num} nvm --getoption support_rdma --scope 0" + ) CMD_NICCLI_PERFORMANCE_PROFILE_TEMPLATE_NEW = ( "niccli --dev {device_num} nvm --getoption performance_profile" ) @@ -471,6 +473,19 @@ def collect_data( card_ids = [c.id for c in legacy_cards] card_list_from_text = [c.model_dump() for c in legacy_cards] + if custom_commands is None and not device_nums and not card_ids: + self._log_event( + category=EventCategory.NETWORK, + description="No Broadcom (niccli) or Pensando (nicctl) NIC hardware detected", + priority=EventPriority.INFO, + ) + self.result.status = ExecutionStatus.NOT_RAN + self.result.message = ( + "No Broadcom (niccli) or Pensando (nicctl) NIC hardware detected; " + "NIC collection skipped" + ) + return self.result, None + # Build full command list (expand placeholders) if custom_commands is not None: commands_to_run: List[str] = [] @@ -486,18 +501,19 @@ def collect_data( else: commands_to_run = [] # niccli list already stored - per_device_templates = _get_niccli_per_device_templates(niccli_version) - for tpl in per_device_templates: - for d in device_nums: - commands_to_run.append(tpl.format(device_num=d)) - # nicctl global (card discovery already done via CMD_NICCTL_CARD_TEXT) - for c in NicCollector.CMD_NICCTL_GLOBAL: - commands_to_run.append(c) - for tpl in NicCollector.CMD_NICCTL_PER_CARD: - for cid in card_ids: - commands_to_run.append(tpl.format(card_id=cid)) - for cmd in NicCollector.CMD_NICCTL_LEGACY_TEXT: - commands_to_run.append(cmd) + if device_nums: + per_device_templates = _get_niccli_per_device_templates(niccli_version) + for tpl in per_device_templates: + for d in device_nums: + commands_to_run.append(tpl.format(device_num=d)) + if card_ids: + for c in NicCollector.CMD_NICCTL_GLOBAL: + commands_to_run.append(c) + for tpl in NicCollector.CMD_NICCTL_PER_CARD: + for cid in card_ids: + commands_to_run.append(tpl.format(card_id=cid)) + for cmd in NicCollector.CMD_NICCTL_LEGACY_TEXT: + commands_to_run.append(cmd) # Run each command and store (artifact-only commands are not added to results / data model). for cmd in commands_to_run: diff --git a/test/unit/plugin/test_niccli_collector.py b/test/unit/plugin/test_niccli_collector.py index c4e5adef..709ed8a3 100644 --- a/test/unit/plugin/test_niccli_collector.py +++ b/test/unit/plugin/test_niccli_collector.py @@ -242,6 +242,44 @@ def test_nic_data_model_with_pensando_nic(collector): assert data.pensando_nic_cards[1].serial_number == "FPL253710E5" +def test_collect_data_not_ran_when_no_nic_hardware(collector, conn_mock): + """Skip collection when discovery finds no Broadcom or Pensando NICs.""" + collector.system_info.os_family = OSFamily.LINUX + collector._run_sut_cmd = MagicMock( + return_value=MagicMock(exit_code=1, stdout="", stderr="not found", command="") + ) + + result, data = collector.collect_data() + + assert result.status == ExecutionStatus.NOT_RAN + assert data is None + assert "skipped" in result.message.lower() + assert collector._run_sut_cmd.call_count <= 4 + + +def test_collect_data_skips_nicctl_commands_when_no_pensando_cards(collector, conn_mock): + """Do not run nicctl global/legacy commands when nicctl show card finds no cards.""" + collector.system_info.os_family = OSFamily.LINUX + commands_run: list[str] = [] + + def run_sut_cmd_side_effect(cmd, **kwargs): + commands_run.append(cmd) + if "niccli" in cmd and ("--list" in cmd or "--list_devices" in cmd or "--listdev" in cmd): + return MagicMock(exit_code=0, stdout=NICCLI_LISTDEV_OUTPUT, stderr="", command=cmd) + if cmd.strip() == "nicctl show card": + return MagicMock(exit_code=1, stdout="", stderr="no card", command=cmd) + return MagicMock(exit_code=0, stdout="", stderr="", command=cmd) + + collector._run_sut_cmd = MagicMock(side_effect=run_sut_cmd_side_effect) + + result, data = collector.collect_data() + + assert result.status == ExecutionStatus.OK + assert data is not None + assert not any(c.startswith("nicctl show card flash") for c in commands_run) + assert not any(c == "nicctl --version" for c in commands_run) + + def test_collect_data_success(collector, conn_mock): """Test successful collection of niccli/nicctl data.""" collector.system_info.os_family = OSFamily.LINUX