Add interface name to inventory for inspection hooks

validate-interfaces inspection hook expect each interface
entry in the inventory to include a 'name' field.

The 'identity' attribute from the Redfish EthernetInterface resource is used to populate this field because it provides unique identifier for each interface.

Change-Id: Ide947f410c3d0d0f67a735c18b30f8cb56caa6b3
Signed-off-by: haseeb <syedhaseebahmed12@gmail.com>
This commit is contained in:
haseeb
2025-06-26 14:59:58 +05:30
parent d264de34b0
commit 790f43337d
3 changed files with 90 additions and 32 deletions

View File

@@ -135,9 +135,10 @@ class RedfishInspect(base.InspectInterface):
if system.ethernet_interfaces and system.ethernet_interfaces.summary:
inventory['interfaces'] = []
mac_addresses = list(system.ethernet_interfaces.summary.keys())
for mac_address in mac_addresses:
inventory['interfaces'].append({'mac_address': mac_address})
for eth in system.ethernet_interfaces.get_members():
iface = {'mac_address': eth.mac_address,
'name': eth.identity}
inventory['interfaces'].append(iface)
system_vendor = {}
if system.name:
@@ -205,7 +206,6 @@ class RedfishInspect(base.InspectInterface):
else:
LOG.warning("No port information discovered "
"for node %(node)s", {'node': task.node.uuid})
inspect_utils.store_inspection_data(task.node,
inventory, None, task.context)
return states.MANAGEABLE

View File

@@ -91,11 +91,24 @@ class RedfishInspectTestCase(db_base.DbTestCase):
system_mock.storage.volumes_sizes_bytes = (
2 * units.Gi, units.Gi * 4, units.Gi * 6)
eth_interface_mock1 = mock.Mock()
eth_interface_mock1.identity = 'NIC.Integrated.1-1'
eth_interface_mock1.mac_address = '00:11:22:33:44:55'
eth_interface_mock2 = mock.Mock()
eth_interface_mock2.identity = 'NIC.Integrated.2-1'
eth_interface_mock2.mac_address = '66:77:88:99:AA:BB'
system_mock.ethernet_interfaces.summary = {
'00:11:22:33:44:55': sushy.STATE_ENABLED,
'66:77:88:99:AA:BB': sushy.STATE_DISABLED,
}
ethernet_mock = mock.Mock()
ethernet_mock.get_members.return_value = [eth_interface_mock1,
eth_interface_mock2]
system_mock.ethernet_interfaces = ethernet_mock
system_mock.name = 'System1'
system_mock.serial_number = '123456'
@@ -118,11 +131,13 @@ class RedfishInspectTestCase(db_base.DbTestCase):
task.driver.management.validate(task)
mock_parse_driver_info.assert_called_once_with(task.node)
@mock.patch.object(redfish_utils, 'get_enabled_macs', autospec=True)
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
@mock.patch.object(inspect_utils, 'create_ports_if_not_exist',
autospec=True)
def test_inspect_hardware_ok(self, mock_create_ports_if_not_exist,
mock_get_system):
mock_get_system,
mock_get_enabled_macs):
expected_properties = {
'capabilities': 'boot_mode:uefi',
'cpu_arch': 'x86_64', 'cpus': '8',
@@ -151,8 +166,10 @@ class RedfishInspectTestCase(db_base.DbTestCase):
self.assertEqual(expected_manufacturer,
system_vendor['manufacturer'])
expected_interfaces = [{'mac_address': '00:11:22:33:44:55'},
{'mac_address': '66:77:88:99:AA:BB'}]
expected_interfaces = [{'mac_address': '00:11:22:33:44:55',
'name': 'NIC.Integrated.1-1'},
{'mac_address': '66:77:88:99:AA:BB',
'name': 'NIC.Integrated.2-1'}]
self.assertEqual(expected_interfaces,
inventory['inventory']['interfaces'])
@@ -165,11 +182,13 @@ class RedfishInspectTestCase(db_base.DbTestCase):
self.assertEqual(expected_disks,
inventory["inventory"]['disks'])
@mock.patch.object(redfish_utils, 'get_enabled_macs', autospec=True)
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
@mock.patch.object(inspect_utils, 'create_ports_if_not_exist',
autospec=True)
def test_inspect_port_creation(self, mock_create_ports_if_not_exist,
mock_get_system):
mock_get_system,
mock_get_enabled_macs):
self.init_system_mock(mock_get_system.return_value)
with task_manager.acquire(self.context, self.node.uuid,
@@ -190,8 +209,10 @@ class RedfishInspectTestCase(db_base.DbTestCase):
self.assertRaises(exception.HardwareInspectionFailure,
task.driver.inspect.inspect_hardware, task)
@mock.patch.object(redfish_utils, 'get_enabled_macs', autospec=True)
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
def test_inspect_hardware_ignore_missing_cpu_count(self, mock_get_system):
def test_inspect_hardware_ignore_missing_cpu_count(self, mock_get_system,
mock_get_enabled_macs):
system_mock = self.init_system_mock(mock_get_system.return_value)
system_mock.processors.summary = None, None
@@ -208,8 +229,10 @@ class RedfishInspectTestCase(db_base.DbTestCase):
self.context)
self.assertNotIn('count', inventory['inventory']['cpu'])
@mock.patch.object(redfish_utils, 'get_enabled_macs', autospec=True)
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
def test_inspect_hardware_ignore_missing_cpu_model(self, mock_get_system):
def test_inspect_hardware_ignore_missing_cpu_model(self, mock_get_system,
mock_get_enabled_macs):
system_mock = self.init_system_mock(mock_get_system.return_value)
mock_processor = system_mock.processors.get_members.return_value[0]
mock_processor.model = None
@@ -228,9 +251,10 @@ class RedfishInspectTestCase(db_base.DbTestCase):
self.context)
self.assertNotIn('model', inventory['inventory']['cpu'])
@mock.patch.object(redfish_utils, 'get_enabled_macs', autospec=True)
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
def test_inspect_hardware_ignore_missing_cpu_frequency(self,
mock_get_system):
def test_inspect_hardware_ignore_missing_cpu_frequency(
self, mock_get_system, mock_get_enabled_macs):
system_mock = self.init_system_mock(mock_get_system.return_value)
mock_processor = system_mock.processors.get_members.return_value[0]
mock_processor.max_speed_mhz = None
@@ -249,10 +273,10 @@ class RedfishInspectTestCase(db_base.DbTestCase):
self.context)
self.assertNotIn('frequency', inventory['inventory']['cpu'])
@mock.patch.object(redfish_utils, 'get_enabled_macs', autospec=True)
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
def test_inspect_hardware_ignore_missing_cpu_instruction_set(
self,
mock_get_system):
self, mock_get_system, mock_get_enabled_macs):
system_mock = self.init_system_mock(mock_get_system.return_value)
mock_processor = system_mock.processors.get_members.return_value[0]
mock_processor.instruction_set = None
@@ -271,8 +295,10 @@ class RedfishInspectTestCase(db_base.DbTestCase):
self.context)
self.assertNotIn('architecture', inventory['inventory']['cpu'])
@mock.patch.object(redfish_utils, 'get_enabled_macs', autospec=True)
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
def test_inspect_hardware_ignore_missing_local_gb(self, mock_get_system):
def test_inspect_hardware_ignore_missing_local_gb(self, mock_get_system,
mock_get_enabled_macs):
system_mock = self.init_system_mock(mock_get_system.return_value)
system_mock.simple_storage.disks_sizes_bytes = None
system_mock.storage.volumes_sizes_bytes = None
@@ -287,9 +313,10 @@ class RedfishInspectTestCase(db_base.DbTestCase):
task.driver.inspect.inspect_hardware(task)
self.assertEqual(expected_properties, task.node.properties)
@mock.patch.object(redfish_utils, 'get_enabled_macs', autospec=True)
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
def test_inspect_hardware_ignore_missing_simple_storage_and_storage(
self, mock_get_system):
self, mock_get_system, mock_get_enabled_macs):
system_mock = self.init_system_mock(mock_get_system.return_value)
system_mock.simple_storage = {}
system_mock.storage = {}
@@ -308,9 +335,10 @@ class RedfishInspectTestCase(db_base.DbTestCase):
self.context)
self.assertNotIn('disks', inventory['inventory'])
@mock.patch.object(redfish_utils, 'get_enabled_macs', autospec=True)
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
def test_inspect_hardware_ignore_missing_simple_storage(self,
mock_get_system):
def test_inspect_hardware_ignore_missing_simple_storage(
self, mock_get_system, mock_get_enabled_macs):
system_mock = self.init_system_mock(mock_get_system.return_value)
system_mock.simple_storage = {}
@@ -328,8 +356,10 @@ class RedfishInspectTestCase(db_base.DbTestCase):
self.context)
self.assertIn('disks', inventory['inventory'])
@mock.patch.object(redfish_utils, 'get_enabled_macs', autospec=True)
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
def test_inspect_hardware_ignore_missing_storage(self, mock_get_system):
def test_inspect_hardware_ignore_missing_storage(self, mock_get_system,
mock_get_enabled_macs):
system_mock = self.init_system_mock(mock_get_system.return_value)
system_mock.storage = {}
@@ -358,8 +388,10 @@ class RedfishInspectTestCase(db_base.DbTestCase):
self.assertRaises(exception.HardwareInspectionFailure,
task.driver.inspect.inspect_hardware, task)
@mock.patch.object(redfish_utils, 'get_enabled_macs', autospec=True)
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
def test_inspect_hardware_ignore_missing_memory_mb(self, mock_get_system):
def test_inspect_hardware_ignore_missing_memory_mb(self, mock_get_system,
mock_get_enabled_macs):
system_mock = self.init_system_mock(mock_get_system.return_value)
system_mock.memory_summary.size_gib = None
@@ -394,9 +426,10 @@ class RedfishInspectTestCase(db_base.DbTestCase):
self.context)
self.assertNotIn('interfaces', inventory['inventory'])
@mock.patch.object(redfish_utils, 'get_enabled_macs', autospec=True)
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
def test_inspect_hardware_ignore_missing_cpus(
self, mock_get_system):
self, mock_get_system, mock_get_enabled_macs):
system_mock = self.init_system_mock(mock_get_system.return_value)
system_mock.processors = []
@@ -407,8 +440,10 @@ class RedfishInspectTestCase(db_base.DbTestCase):
self.context)
self.assertNotIn('cpu', inventory['inventory'])
@mock.patch.object(redfish_utils, 'get_enabled_macs', autospec=True)
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
def test_inspect_hardware_preserve_boot_mode(self, mock_get_system):
def test_inspect_hardware_preserve_boot_mode(self, mock_get_system,
mock_get_enabled_macs):
self.init_system_mock(mock_get_system.return_value)
with task_manager.acquire(self.context, self.node.uuid,
@@ -431,8 +466,10 @@ class RedfishInspectTestCase(db_base.DbTestCase):
self.assertEqual(expected_boot_mode,
inventory['inventory']['boot'])
@mock.patch.object(redfish_utils, 'get_enabled_macs', autospec=True)
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
def test_inspect_hardware_ignore_missing_boot_mode(self, mock_get_system):
def test_inspect_hardware_ignore_missing_boot_mode(self, mock_get_system,
mock_get_enabled_macs):
system_mock = self.init_system_mock(mock_get_system.return_value)
system_mock.boot.mode = None
@@ -448,10 +485,13 @@ class RedfishInspectTestCase(db_base.DbTestCase):
self.context)
self.assertNotIn('boot', inventory['inventory'])
@mock.patch.object(redfish_utils, 'get_enabled_macs', autospec=True)
@mock.patch.object(objects.Port, 'list_by_node_id') # noqa
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
def test_inspect_hardware_with_set_port_pxe_enabled(
self, mock_get_system, mock_list_by_node_id):
self, mock_get_system,
mock_list_by_node_id,
mock_get_enabled_macs):
self.init_system_mock(mock_get_system.return_value)
pxe_disabled_port = obj_utils.create_test_port(
@@ -467,10 +507,12 @@ class RedfishInspectTestCase(db_base.DbTestCase):
task.driver.inspect.inspect_hardware(task)
self.assertTrue(port[0].pxe_enabled)
@mock.patch.object(redfish_utils, 'get_enabled_macs', autospec=True)
@mock.patch.object(objects.Port, 'list_by_node_id') # noqa
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
def test_inspect_hardware_with_set_port_pxe_disabled(
self, mock_get_system, mock_list_by_node_id):
self, mock_get_system,
mock_list_by_node_id, mock_get_enabled_macs):
self.init_system_mock(mock_get_system.return_value)
pxe_enabled_port = obj_utils.create_test_port(
@@ -488,12 +530,13 @@ class RedfishInspectTestCase(db_base.DbTestCase):
port = mock_list_by_node_id.return_value
self.assertFalse(port[0].pxe_enabled)
@mock.patch.object(redfish_utils, 'get_enabled_macs', autospec=True)
@mock.patch.object(objects.Port, 'list_by_node_id') # noqa
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
def test_inspect_hardware_with_conf_update_pxe_disabled_false(
self, mock_get_system, mock_list_by_node_id):
self, mock_get_system,
mock_list_by_node_id, mock_get_enabled_macs):
self.init_system_mock(mock_get_system.return_value)
pxe_enabled_port = obj_utils.create_test_port(
self.context, uuid=self.node.uuid,
node_id=self.node.id, address='24:6E:96:70:49:01',
@@ -526,10 +569,12 @@ class RedfishInspectTestCase(db_base.DbTestCase):
ports = objects.Port.list_by_node_id(task.context, self.node.id)
self.assertEqual(1, len(ports))
@mock.patch.object(redfish_utils, 'get_enabled_macs', autospec=True)
@mock.patch.object(objects.Port, 'list_by_node_id') # noqa
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
def test_inspect_hardware_with_empty_pxe_port_macs(
self, mock_get_system, mock_list_by_node_id):
self, mock_get_system,
mock_list_by_node_id, mock_get_enabled_macs):
self.init_system_mock(mock_get_system.return_value)
pxe_enabled_port = obj_utils.create_test_port(
@@ -547,11 +592,13 @@ class RedfishInspectTestCase(db_base.DbTestCase):
self.assertFalse(port[0].pxe_enabled)
self.assertEqual(states.MANAGEABLE, return_value)
@mock.patch.object(redfish_utils, 'get_enabled_macs', autospec=True)
@mock.patch.object(objects.Port, 'list_by_node_id') # noqa
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
@mock.patch.object(inspect.LOG, 'warning', autospec=True)
def test_inspect_hardware_with_none_pxe_port_macs(
self, mock_log, mock_get_system, mock_list_by_node_id):
self, mock_log, mock_get_system,
mock_list_by_node_id, mock_get_enabled_macs):
self.init_system_mock(mock_get_system.return_value)
pxe_enabled_port = obj_utils.create_test_port(
@@ -569,8 +616,10 @@ class RedfishInspectTestCase(db_base.DbTestCase):
self.assertTrue(port[0].pxe_enabled)
mock_log.assert_called_once()
@mock.patch.object(redfish_utils, 'get_enabled_macs', autospec=True)
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
def test_create_port_when_its_state_is_none(self, mock_get_system):
def test_create_port_when_its_state_is_none(self, mock_get_system,
mock_get_enabled_macs):
self.init_system_mock(mock_get_system.return_value)
expected_port_mac_list = ["00:11:22:33:44:55", "24:6e:96:70:49:00"]
with task_manager.acquire(self.context, self.node.uuid,
@@ -580,9 +629,10 @@ class RedfishInspectTestCase(db_base.DbTestCase):
for port in ports:
self.assertIn(port.address, expected_port_mac_list)
@mock.patch.object(redfish_utils, 'get_enabled_macs', autospec=True)
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
def test_inspect_hardware_ignore_missing_system_vendor(self,
mock_get_system):
def test_inspect_hardware_ignore_missing_system_vendor(
self, mock_get_system, mock_get_enabled_macs):
system_mock = self.init_system_mock(mock_get_system.return_value)
system_mock.name = None
system_mock.serial_number = None

View File

@@ -0,0 +1,8 @@
---
fixes:
- |
Include Ethernet interface name(identity attribute) in inventory for inspection hooks
To succeed Redfish inspection flow ensure that the Ethernet interface name is present in the inventory data.
This is required for inspection hooks such as `validate-interfaces` to function correctly.