Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ Installing

pip install redfish

The asynchronous client has an optional ``aiohttp`` dependency:

.. code-block:: console

pip install redfish[aiohttp]

Building from zip file source
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand All @@ -52,6 +58,8 @@ Required external packages:
requests-toolbelt
requests-unixsocket

The optional asynchronous client requires ``aiohttp>=3.9.0``.

If installing from GitHub, you may install the external packages by running:

.. code-block:: console
Expand Down Expand Up @@ -183,6 +191,45 @@ Each of the previous methods allows for the following arguments:
- This can be useful when a particular URI is known to take multiple retries.
- The default value is ``None``, which indicates the object-defined max retry count is used.

Asynchronous client
~~~~~~~~~~~~~~~~~~~

The additive asynchronous API uses ``aiohttp`` and does not change the existing synchronous client. The caller must provide an ``aiohttp.ClientSession`` and remains responsible for closing it. This allows an application to control connection pooling, TLS trust, proxy behavior, and session lifetime in one place.

The asynchronous client supports Redfish session authentication and HTTP Basic authentication. Authentication is explicit: call ``login`` after creating the client and ``logout`` when finished. ``login`` uses Redfish session authentication by default, matching the synchronous client. Redfish authentication requires HTTPS. For compatibility with nonconforming services, session login uses the standard session collection URI and emits a warning if the service root incorrectly responds with HTTP 401.

The asynchronous context manager creates and terminates a Redfish session. It does not close the caller's ``aiohttp.ClientSession``:

.. code-block:: python

import aiohttp

from redfish.aio import AsyncRedfishClient


async def get_service_root():
async with aiohttp.ClientSession() as session:
async with AsyncRedfishClient(
base_url="https://bmc.example",
username="user",
password="password",
session=session,
timeout=10,
) as client:
return await client.get_service_root()

To use HTTP Basic authentication, call ``await client.login(auth="basic")`` and ensure ``await client.logout()`` is called when finished. Basic ``login`` configures the authentication header; the service validates the credentials when the client performs its next request. An existing Redfish session can be supplied with the ``session_key`` argument and, when available, its resource URI with ``session_location``. Supplying the location allows ``logout`` to terminate that session.

If session login reports that the account password must change, ``login`` raises ``RedfishPasswordChangeRequiredError`` with the account URI in ``password_change_uri`` while retaining the restricted session. The caller can use that client to change the password and then call ``logout``. The asynchronous context manager instead cleans up a restricted session before propagating this exception because a failed ``__aenter__`` call cannot return the client to the context body.

If an authenticated ``GET`` or ``HEAD`` receives HTTP 401, the client re-establishes an expired Redfish session once when credentials are available. State-changing requests are never retried automatically. Callers can therefore decide whether it is safe to repeat a failed ``POST``, ``PUT``, ``PATCH``, or ``DELETE``.

Requests do not follow redirects, and advertised resource, action, and session targets are accepted only when they resolve to the configured Redfish origin. Authentication headers provided by the caller cannot replace the client's configured Basic credentials or session token. These rules prevent credentials from being sent to another origin.

``get``, ``head``, ``post``, ``put``, ``patch``, and ``delete`` are coroutines with the same ``path``, ``args``, ``body``, ``headers``, and ``timeout`` concepts as the synchronous methods. The returned response is fully read and cached before the coroutine returns, so it can be inspected after the underlying aiohttp response closes.

The optional request ``timeout`` bounds each HTTP request. TLS verification is controlled entirely by the injected ``ClientSession``. Configure that session with an appropriate CA certificate or SSL context for a Redfish service using a private or self-signed certificate.

Working with tasks
~~~~~~~~~~~~~~~~~~

Expand Down
31 changes: 31 additions & 0 deletions examples/async_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Copyright Notice:
# Copyright 2016-2026 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md

"""Retrieve the service root with the asynchronous Redfish client."""

import asyncio
import os

import aiohttp

from redfish.aio import AsyncRedfishClient


async def main():
"""Retrieve and display the Redfish service root."""
async with aiohttp.ClientSession() as session:
async with AsyncRedfishClient(
base_url=os.environ["REDFISH_BASE_URL"],
username=os.environ["REDFISH_USERNAME"],
password=os.environ["REDFISH_PASSWORD"],
session=session,
timeout=10,
) as client:
service_root = await client.get_service_root()
print(service_root)


if __name__ == "__main__":
asyncio.run(main())
3 changes: 3 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
aiohttp>=3.9.0
multidict>=4.5
yarl>=1.0
jsonpatch<=1.24 ; python_version == '3.4'
jsonpatch ; python_version >= '3.5'
jsonpath_ng
Expand Down
5 changes: 5 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@
'requests-unixsocket'
],
extras_require={
'aiohttp': [
'aiohttp>=3.9.0',
'multidict>=4.5',
'yarl>=1.0'
],
':python_version == "3.4"': [
'jsonpatch<=1.24'
],
Expand Down
33 changes: 33 additions & 0 deletions src/redfish/aio/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Copyright Notice:
# Copyright 2016-2026 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link:
# https://github.com/DMTF/python-redfish-library/blob/main/LICENSE.md

"""Asynchronous Redfish client API."""

from .client import AsyncRedfishClient
from .exceptions import (
RedfishAuthenticationError,
RedfishConnectionError,
RedfishError,
RedfishHTTPError,
RedfishInvalidTargetError,
RedfishPasswordChangeRequiredError,
RedfishProtocolError,
RedfishTimeoutError,
)
from .response import AsyncRestRequest, AsyncRestResponse

__all__ = [
"AsyncRedfishClient",
"AsyncRestRequest",
"AsyncRestResponse",
"RedfishAuthenticationError",
"RedfishConnectionError",
"RedfishError",
"RedfishHTTPError",
"RedfishInvalidTargetError",
"RedfishPasswordChangeRequiredError",
"RedfishProtocolError",
"RedfishTimeoutError",
]
Loading