From 5563e5275ff112bbbe363b0683b77cad6a9fecda Mon Sep 17 00:00:00 2001 From: Afonne-CID Date: Mon, 10 Nov 2025 15:21:49 +0100 Subject: [PATCH] Filter null NIC firmware versions from cache Treat absent firmware package version as non-cacheable to avoid NOT NULL database constraint violation. Closes-Bug: #2130990 Change-Id: Ic2efaa0d53b6923908112c937957a60aa4f1ad9d Signed-off-by: Afonne-CID --- ironic/drivers/modules/redfish/firmware.py | 2 + .../drivers/modules/redfish/test_firmware.py | 58 +++++++++++++++++++ ...re-versions-in-cache-82a68b4df96591f7.yaml | 6 ++ 3 files changed, 66 insertions(+) create mode 100644 releasenotes/notes/filter-null-nic-firmware-versions-in-cache-82a68b4df96591f7.yaml diff --git a/ironic/drivers/modules/redfish/firmware.py b/ironic/drivers/modules/redfish/firmware.py index 711530561d..55d9e38e56 100644 --- a/ironic/drivers/modules/redfish/firmware.py +++ b/ironic/drivers/modules/redfish/firmware.py @@ -180,6 +180,8 @@ class RedfishFirmware(base.FirmwareInterface): for net_adp in chassis.network_adapters.get_members(): for net_adp_ctrl in net_adp.controllers: fw_pkg_v = net_adp_ctrl.firmware_package_version + if not fw_pkg_v: + continue net_adp_fw = {'component': redfish_utils.NIC_COMPONENT_PREFIX + net_adp.identity, 'current_version': fw_pkg_v} nic_list.append(net_adp_fw) diff --git a/ironic/tests/unit/drivers/modules/redfish/test_firmware.py b/ironic/tests/unit/drivers/modules/redfish/test_firmware.py index de024cb162..90243fc7a4 100644 --- a/ironic/tests/unit/drivers/modules/redfish/test_firmware.py +++ b/ironic/tests/unit/drivers/modules/redfish/test_firmware.py @@ -353,6 +353,64 @@ class RedfishFirmwareTestCase(db_base.DbTestCase): 'NetworkAdapters' in str(call)] self.assertEqual(len(debug_calls), 0) + @mock.patch.object(redfish_fw, 'LOG', autospec=True) + @mock.patch.object(redfish_utils, 'get_system', autospec=True) + @mock.patch.object(redfish_utils, 'get_manager', autospec=True) + @mock.patch.object(redfish_utils, 'get_chassis', autospec=True) + @mock.patch.object(objects, 'FirmwareComponentList', autospec=True) + @mock.patch.object(objects, 'FirmwareComponent', spec_set=True, + autospec=True) + def test_retrieve_nic_components_invalid_firmware_version( + self, fw_cmp_mock, fw_cmp_list, chassis_mock, manager_mock, + system_mock, log_mock): + """Test that NIC components with missing versions are skipped.""" + for invalid_version in [None, ""]: + fw_cmp_list.reset_mock() + fw_cmp_mock.reset_mock() + log_mock.reset_mock() + + create_list = [{'component': 'bios', 'current_version': 'v1.0.0'}, + {'component': 'bmc', 'current_version': 'v1.0.0'}] + fw_cmp_list.sync_firmware_components.return_value = ( + create_list, [], [] + ) + + bios_component = {'component': 'bios', + 'current_version': 'v1.0.0', + 'node_id': self.node.id} + + bmc_component = {'component': 'bmc', 'current_version': 'v1.0.0', + 'node_id': self.node.id} + + with task_manager.acquire(self.context, self.node.uuid, + shared=True) as task: + manager_mock.return_value.firmware_version = "v1.0.0" + system_mock.return_value.bios_version = "v1.0.0" + + netadp_ctrl = mock.MagicMock() + netadp_ctrl.firmware_package_version = invalid_version + netadp = mock.MagicMock() + netadp.identity = 'NIC1' + netadp.controllers = [netadp_ctrl] + net_adapters = mock.MagicMock() + net_adapters.get_members.return_value = [netadp] + chassis_mock.return_value.network_adapters = net_adapters + task.driver.firmware.cache_firmware_components(task) + + fw_cmp_list.sync_firmware_components.assert_called_once_with( + task.context, task.node.id, + [{'component': 'bios', 'current_version': 'v1.0.0'}, + {'component': 'bmc', 'current_version': 'v1.0.0'}]) + + fw_cmp_calls = [ + mock.call(task.context, **bios_component), + mock.call().create(), + mock.call(task.context, **bmc_component), + mock.call().create() + ] + fw_cmp_mock.assert_has_calls(fw_cmp_calls) + log_mock.warning.assert_not_called() + @mock.patch.object(redfish_utils, 'LOG', autospec=True) @mock.patch.object(redfish_utils, '_get_connection', autospec=True) def test_missing_updateservice(self, conn_mock, log_mock): diff --git a/releasenotes/notes/filter-null-nic-firmware-versions-in-cache-82a68b4df96591f7.yaml b/releasenotes/notes/filter-null-nic-firmware-versions-in-cache-82a68b4df96591f7.yaml new file mode 100644 index 0000000000..3df16f94b8 --- /dev/null +++ b/releasenotes/notes/filter-null-nic-firmware-versions-in-cache-82a68b4df96591f7.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + NIC firmware components with null or empty firmware package versions + are now filtered out during caching to avoid NOT NULL database + constraint violations.