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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions