Skip to content

Unit tests for osism/tasks/conductor/redfish.py #2225

@berendt

Description

@berendt

Background

Follow-up to #2192 (foundation) and PR #2193 (pytest + Zuul infrastructure). Part of Tier 3 (#2199). osism/tasks/conductor/redfish.py is the Redfish data-collection module: it normalizes raw Redfish payloads and walks Systems / Chassis to extract EthernetInterfaces, NetworkAdapters, and NetworkDeviceFunctions. Small enough to cover in a single test module.

Scope

Add tests/unit/tasks/conductor/test_redfish.py covering all functions in osism/tasks/conductor/redfish.py.

Test targets

_normalize_redfish_data(data)redfish.py:8

Pure function. Build small input dicts inline.

  • None value → key removed from result
  • dict value → JSON-serialized (json.dumps)
  • list value → JSON-serialized
  • bool True"true"; bool False"false"
  • int / floatstr(value)
  • Plain str → kept as-is
  • Mixed input combining all of the above → all keys present except those with None
  • Empty dict → empty dict

get_resources(hostname, resource_type)redfish.py:38

Patch osism.tasks.conductor.redfish._get_ethernet_interfaces, ..._get_network_adapters, ..._get_network_device_functions.

  • resource_type="EthernetInterfaces" → delegates to _get_ethernet_interfaces and returns its result; other helpers not called
  • resource_type="NetworkAdapters" → delegates to _get_network_adapters
  • resource_type="NetworkDeviceFunctions" → delegates to _get_network_device_functions
  • Unknown resource type → returns [], warning logged

_get_ethernet_interfaces(hostname)redfish.py:64

Patch osism.tasks.conductor.redfish.get_redfish_connection. Build a fake connection chain with MagicMock:

conn.get_system_collection().get_members() -> [system]
system.identity = "1"
system.ethernet_interfaces.get_members() -> [iface1, iface2]
iface.identity / iface.name / iface.mac_address / iface.speed_mbps / ...

Cases:

  • Connection unavailable (get_redfish_connection returns None) → returns [], error logged
  • Connection raises top-level exception → returns [], error logged
  • System without ethernet_interfaces attribute → no entries, but no error
  • System with ethernet_interfaces=None → no entries
  • Two systems, each with two interfaces → 4 entries returned, each normalized via _normalize_redfish_data
  • Per-interface exception (e.g. interface.identity raises during attribute access) → that interface skipped, warning logged, others still returned
  • All optional attributes returned via getattr(..., None) (name, description, mac_address, permanent_mac_address, speed_mbps, mtu_size, link_status, interface_enabled)
  • mac_address=None → key removed from result by _normalize_redfish_data

_get_network_adapters(hostname)redfish.py:134

Same shape as _get_ethernet_interfaces but iterates chassis.network_adapters:

  • No connection → [], error logged
  • Top-level exception → [], error logged
  • Chassis without network_adapters → no entries
  • One chassis with two adapters → two entries with id, name, manufacturer, model, part_number, serial_number, firmware_version
  • Per-adapter exception → skipped, warning logged

_get_network_device_functions(hostname)redfish.py:201

Patch get_redfish_connection. Cover the nested loop (Chassis → NetworkAdapters → NetworkDeviceFunctions):

  • No connection → [], error logged
  • Top-level exception → [], error logged
  • Adapter without network_device_functions → outer for adapter in ... is exercised, inner for device_func in ... raises caught by adapter-level except (warning logged), processing continues for next adapter
  • Per-device-function exception → skipped, warning logged
  • Device function with ethernet attribute → mac_address and permanent_mac_address extracted from device_func.ethernet
  • Device function without ethernet → both MACs None (then stripped by normalization)
  • All entries include adapter_id and adapter_name so callers can correlate

Mocking hints

  • MagicMock is sufficient for the Redfish connection chain. Set get_members.return_value=[...] per level.
  • For attribute-not-present cases, use del mock.attribute to make hasattr(...) return False. For attribute-raises cases, set mock.attribute = property(lambda self: 1/0) is overkill — instead, point getattr(...) to a Mock(side_effect=Exception("boom")) for that attribute.
  • _normalize_redfish_data is exercised indirectly in the three loop functions — assert on the returned dicts to confirm normalization happened (e.g. no None values, lists turned into JSON strings).

Definition of Done

  • tests/unit/tasks/conductor/test_redfish.py created
  • All listed cases covered
  • pytest --cov=osism.tasks.conductor.redfish shows 100 %
  • pipenv run pytest tests/unit/tasks/conductor/test_redfish.py passes locally
  • flake8, mypy, python-black remain green
  • Zuul job python-osism-unit-tests passes

Dependencies

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions