redfish-python-sdk 1.2.0__tar.gz → 1.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {redfish_python_sdk-1.2.0/redfish_python_sdk.egg-info → redfish_python_sdk-1.2.3}/PKG-INFO +8 -5
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/README.md +7 -4
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/pyproject.toml +1 -1
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3/redfish_python_sdk.egg-info}/PKG-INFO +8 -5
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_python_sdk.egg-info/SOURCES.txt +22 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/__init__.py +3 -1
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/client.py +132 -2
- redfish_python_sdk-1.2.3/redfish_sdk/exceptions.py +200 -0
- redfish_python_sdk-1.2.3/redfish_sdk/http_client.py +673 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/managers/_log_helpers.py +40 -7
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/managers/chassis.py +48 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/managers/event.py +3 -0
- redfish_python_sdk-1.2.3/redfish_sdk/managers/log_collect_strategies/__init__.py +66 -0
- redfish_python_sdk-1.2.3/redfish_sdk/managers/log_collect_strategies/base.py +476 -0
- redfish_python_sdk-1.2.3/redfish_sdk/managers/log_collect_strategies/inspur.py +150 -0
- redfish_python_sdk-1.2.3/redfish_sdk/managers/log_collect_strategies/lenovo.py +247 -0
- redfish_python_sdk-1.2.3/redfish_sdk/managers/log_collect_strategies/registry.py +72 -0
- redfish_python_sdk-1.2.3/redfish_sdk/managers/log_collect_strategies/smoothcompute.py +163 -0
- redfish_python_sdk-1.2.3/redfish_sdk/managers/log_collect_strategies/xfusion.py +41 -0
- redfish_python_sdk-1.2.3/redfish_sdk/managers/log_collect_strategies/zte.py +305 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/managers/managers.py +255 -1
- redfish_python_sdk-1.2.3/redfish_sdk/managers/oem_extractors/__init__.py +65 -0
- redfish_python_sdk-1.2.3/redfish_sdk/managers/oem_extractors/base.py +166 -0
- redfish_python_sdk-1.2.3/redfish_sdk/managers/oem_extractors/h3c.py +28 -0
- redfish_python_sdk-1.2.3/redfish_sdk/managers/oem_extractors/inspur.py +50 -0
- redfish_python_sdk-1.2.3/redfish_sdk/managers/oem_extractors/lenovo.py +28 -0
- redfish_python_sdk-1.2.3/redfish_sdk/managers/oem_extractors/nettrix.py +36 -0
- redfish_python_sdk-1.2.3/redfish_sdk/managers/oem_extractors/registry.py +69 -0
- redfish_python_sdk-1.2.3/redfish_sdk/managers/oem_extractors/xfusion.py +30 -0
- redfish_python_sdk-1.2.3/redfish_sdk/managers/oem_extractors/zte.py +29 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/managers/update_strategies/vendor_detect.py +3 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/drive.py +4 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/event.py +5 -0
- redfish_python_sdk-1.2.3/redfish_sdk/models/log_collect.py +227 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/logs.py +4 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/managers.py +4 -1
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/oem.py +31 -29
- redfish_python_sdk-1.2.3/redfish_sdk/models/task.py +101 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/thermal.py +1 -0
- redfish_python_sdk-1.2.3/tests/test_exception_hints_mock.py +102 -0
- redfish_python_sdk-1.2.3/tests/test_http_retry_mock.py +198 -0
- redfish_python_sdk-1.2.3/tests/test_log_collect_mock.py +1791 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/tests/test_models.py +81 -0
- redfish_python_sdk-1.2.3/tests/test_oem_extractors.py +294 -0
- redfish_python_sdk-1.2.0/redfish_sdk/exceptions.py +0 -56
- redfish_python_sdk-1.2.0/redfish_sdk/http_client.py +0 -452
- redfish_python_sdk-1.2.0/redfish_sdk/models/task.py +0 -54
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/LICENSE +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_python_sdk.egg-info/dependency_links.txt +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_python_sdk.egg-info/requires.txt +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_python_sdk.egg-info/top_level.txt +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/managers/__init__.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/managers/account.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/managers/registries.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/managers/session.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/managers/systems.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/managers/task.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/managers/update.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/managers/update_strategies/__init__.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/managers/update_strategies/base.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/managers/update_strategies/h3c.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/managers/update_strategies/inspur.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/managers/update_strategies/lenovo.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/managers/update_strategies/nettrix.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/managers/update_strategies/registry.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/managers/update_strategies/xfusion.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/managers/update_strategies/zte.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/__init__.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/account.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/chassis.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/check.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/common.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/fru.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/gpu.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/memory.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/network_adapter.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/pcie_device.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/power.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/processor.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/registry.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/resource_key.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/root.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/session.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/storage.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/systems.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_sdk/models/update.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/setup.cfg +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/tests/test_client_mock.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/tests/test_log_entries_mock.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/tests/test_models_mock.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/tests/test_offline_json.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/tests/test_real_bmc.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/tests/test_sdk_mock.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/tests/test_update_strategies.py +0 -0
- {redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/tests/test_v1_1_apis_mock.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: redfish-python-sdk
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.3
|
|
4
4
|
Summary: A Python SDK for interacting with Redfish-compliant BMC endpoints
|
|
5
5
|
Author: RedNote Infrastructure
|
|
6
6
|
License: BSD 3-Clause License
|
|
@@ -63,11 +63,14 @@ Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
|
63
63
|
Requires-Dist: ruff>=0.4.0; extra == "dev"
|
|
64
64
|
Dynamic: license-file
|
|
65
65
|
|
|
66
|
-
#
|
|
66
|
+
# redfish-python-sdk
|
|
67
|
+
**redfish-python-sdk** is a typed, high-level Python SDK for managing
|
|
68
|
+
multi-vendor BMCs and bare-metal servers through the DMTF Redfish API.
|
|
67
69
|
|
|
68
70
|
[](https://pypi.org/project/redfish-python-sdk/)
|
|
69
71
|
[](https://pypi.org/project/redfish-python-sdk/)
|
|
70
72
|
[](https://github.com/rednote-infra/redfish-python-sdk/blob/main/LICENSE)
|
|
73
|
+
[](https://pepy.tech/projects/redfish-python-sdk)
|
|
71
74
|
|
|
72
75
|
[English](README.md) | [中文](README_zh.md)
|
|
73
76
|
|
|
@@ -97,11 +100,11 @@ pip install redfish-python-sdk
|
|
|
97
100
|
pip install git+https://github.com/rednote-infra/redfish-python-sdk.git
|
|
98
101
|
|
|
99
102
|
# Install a specific version
|
|
100
|
-
pip install redfish-python-sdk==1.
|
|
101
|
-
pip install git+https://github.com/rednote-infra/redfish-python-sdk.git@v1.
|
|
103
|
+
pip install redfish-python-sdk==1.2.3
|
|
104
|
+
pip install git+https://github.com/rednote-infra/redfish-python-sdk.git@v1.2.3
|
|
102
105
|
|
|
103
106
|
# In requirements.txt
|
|
104
|
-
# redfish-python-sdk>=1.
|
|
107
|
+
# redfish-python-sdk>=1.2.3
|
|
105
108
|
```
|
|
106
109
|
|
|
107
110
|
## Quick Start
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
#
|
|
1
|
+
# redfish-python-sdk
|
|
2
|
+
**redfish-python-sdk** is a typed, high-level Python SDK for managing
|
|
3
|
+
multi-vendor BMCs and bare-metal servers through the DMTF Redfish API.
|
|
2
4
|
|
|
3
5
|
[](https://pypi.org/project/redfish-python-sdk/)
|
|
4
6
|
[](https://pypi.org/project/redfish-python-sdk/)
|
|
5
7
|
[](https://github.com/rednote-infra/redfish-python-sdk/blob/main/LICENSE)
|
|
8
|
+
[](https://pepy.tech/projects/redfish-python-sdk)
|
|
6
9
|
|
|
7
10
|
[English](README.md) | [中文](README_zh.md)
|
|
8
11
|
|
|
@@ -32,11 +35,11 @@ pip install redfish-python-sdk
|
|
|
32
35
|
pip install git+https://github.com/rednote-infra/redfish-python-sdk.git
|
|
33
36
|
|
|
34
37
|
# Install a specific version
|
|
35
|
-
pip install redfish-python-sdk==1.
|
|
36
|
-
pip install git+https://github.com/rednote-infra/redfish-python-sdk.git@v1.
|
|
38
|
+
pip install redfish-python-sdk==1.2.3
|
|
39
|
+
pip install git+https://github.com/rednote-infra/redfish-python-sdk.git@v1.2.3
|
|
37
40
|
|
|
38
41
|
# In requirements.txt
|
|
39
|
-
# redfish-python-sdk>=1.
|
|
42
|
+
# redfish-python-sdk>=1.2.3
|
|
40
43
|
```
|
|
41
44
|
|
|
42
45
|
## Quick Start
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: redfish-python-sdk
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.3
|
|
4
4
|
Summary: A Python SDK for interacting with Redfish-compliant BMC endpoints
|
|
5
5
|
Author: RedNote Infrastructure
|
|
6
6
|
License: BSD 3-Clause License
|
|
@@ -63,11 +63,14 @@ Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
|
63
63
|
Requires-Dist: ruff>=0.4.0; extra == "dev"
|
|
64
64
|
Dynamic: license-file
|
|
65
65
|
|
|
66
|
-
#
|
|
66
|
+
# redfish-python-sdk
|
|
67
|
+
**redfish-python-sdk** is a typed, high-level Python SDK for managing
|
|
68
|
+
multi-vendor BMCs and bare-metal servers through the DMTF Redfish API.
|
|
67
69
|
|
|
68
70
|
[](https://pypi.org/project/redfish-python-sdk/)
|
|
69
71
|
[](https://pypi.org/project/redfish-python-sdk/)
|
|
70
72
|
[](https://github.com/rednote-infra/redfish-python-sdk/blob/main/LICENSE)
|
|
73
|
+
[](https://pepy.tech/projects/redfish-python-sdk)
|
|
71
74
|
|
|
72
75
|
[English](README.md) | [中文](README_zh.md)
|
|
73
76
|
|
|
@@ -97,11 +100,11 @@ pip install redfish-python-sdk
|
|
|
97
100
|
pip install git+https://github.com/rednote-infra/redfish-python-sdk.git
|
|
98
101
|
|
|
99
102
|
# Install a specific version
|
|
100
|
-
pip install redfish-python-sdk==1.
|
|
101
|
-
pip install git+https://github.com/rednote-infra/redfish-python-sdk.git@v1.
|
|
103
|
+
pip install redfish-python-sdk==1.2.3
|
|
104
|
+
pip install git+https://github.com/rednote-infra/redfish-python-sdk.git@v1.2.3
|
|
102
105
|
|
|
103
106
|
# In requirements.txt
|
|
104
|
-
# redfish-python-sdk>=1.
|
|
107
|
+
# redfish-python-sdk>=1.2.3
|
|
105
108
|
```
|
|
106
109
|
|
|
107
110
|
## Quick Start
|
{redfish_python_sdk-1.2.0 → redfish_python_sdk-1.2.3}/redfish_python_sdk.egg-info/SOURCES.txt
RENAMED
|
@@ -21,6 +21,23 @@ redfish_sdk/managers/session.py
|
|
|
21
21
|
redfish_sdk/managers/systems.py
|
|
22
22
|
redfish_sdk/managers/task.py
|
|
23
23
|
redfish_sdk/managers/update.py
|
|
24
|
+
redfish_sdk/managers/log_collect_strategies/__init__.py
|
|
25
|
+
redfish_sdk/managers/log_collect_strategies/base.py
|
|
26
|
+
redfish_sdk/managers/log_collect_strategies/inspur.py
|
|
27
|
+
redfish_sdk/managers/log_collect_strategies/lenovo.py
|
|
28
|
+
redfish_sdk/managers/log_collect_strategies/registry.py
|
|
29
|
+
redfish_sdk/managers/log_collect_strategies/smoothcompute.py
|
|
30
|
+
redfish_sdk/managers/log_collect_strategies/xfusion.py
|
|
31
|
+
redfish_sdk/managers/log_collect_strategies/zte.py
|
|
32
|
+
redfish_sdk/managers/oem_extractors/__init__.py
|
|
33
|
+
redfish_sdk/managers/oem_extractors/base.py
|
|
34
|
+
redfish_sdk/managers/oem_extractors/h3c.py
|
|
35
|
+
redfish_sdk/managers/oem_extractors/inspur.py
|
|
36
|
+
redfish_sdk/managers/oem_extractors/lenovo.py
|
|
37
|
+
redfish_sdk/managers/oem_extractors/nettrix.py
|
|
38
|
+
redfish_sdk/managers/oem_extractors/registry.py
|
|
39
|
+
redfish_sdk/managers/oem_extractors/xfusion.py
|
|
40
|
+
redfish_sdk/managers/oem_extractors/zte.py
|
|
24
41
|
redfish_sdk/managers/update_strategies/__init__.py
|
|
25
42
|
redfish_sdk/managers/update_strategies/base.py
|
|
26
43
|
redfish_sdk/managers/update_strategies/h3c.py
|
|
@@ -40,6 +57,7 @@ redfish_sdk/models/drive.py
|
|
|
40
57
|
redfish_sdk/models/event.py
|
|
41
58
|
redfish_sdk/models/fru.py
|
|
42
59
|
redfish_sdk/models/gpu.py
|
|
60
|
+
redfish_sdk/models/log_collect.py
|
|
43
61
|
redfish_sdk/models/logs.py
|
|
44
62
|
redfish_sdk/models/managers.py
|
|
45
63
|
redfish_sdk/models/memory.py
|
|
@@ -58,9 +76,13 @@ redfish_sdk/models/task.py
|
|
|
58
76
|
redfish_sdk/models/thermal.py
|
|
59
77
|
redfish_sdk/models/update.py
|
|
60
78
|
tests/test_client_mock.py
|
|
79
|
+
tests/test_exception_hints_mock.py
|
|
80
|
+
tests/test_http_retry_mock.py
|
|
81
|
+
tests/test_log_collect_mock.py
|
|
61
82
|
tests/test_log_entries_mock.py
|
|
62
83
|
tests/test_models.py
|
|
63
84
|
tests/test_models_mock.py
|
|
85
|
+
tests/test_oem_extractors.py
|
|
64
86
|
tests/test_offline_json.py
|
|
65
87
|
tests/test_real_bmc.py
|
|
66
88
|
tests/test_sdk_mock.py
|
|
@@ -28,6 +28,7 @@ Quick start:
|
|
|
28
28
|
"""
|
|
29
29
|
from .client import RedfishClient
|
|
30
30
|
from .exceptions import (
|
|
31
|
+
LogCollectFailedError,
|
|
31
32
|
RedfishAuthError,
|
|
32
33
|
RedfishConnectionError,
|
|
33
34
|
RedfishException,
|
|
@@ -55,7 +56,7 @@ from .models.managers import (
|
|
|
55
56
|
from .models.resource_key import RedfishResource
|
|
56
57
|
from .models.systems import BootOption
|
|
57
58
|
|
|
58
|
-
__version__ = "1.2.
|
|
59
|
+
__version__ = "1.2.3"
|
|
59
60
|
__author__ = "RedNote Infrastructure"
|
|
60
61
|
|
|
61
62
|
__all__ = [
|
|
@@ -67,6 +68,7 @@ __all__ = [
|
|
|
67
68
|
"RedfishConnectionError",
|
|
68
69
|
"RedfishTimeoutError",
|
|
69
70
|
"RedfishValidationError",
|
|
71
|
+
"LogCollectFailedError",
|
|
70
72
|
# Models commonly used at API boundary.
|
|
71
73
|
"BootOption",
|
|
72
74
|
"DnsService",
|
|
@@ -117,6 +117,9 @@ class RedfishClient:
|
|
|
117
117
|
connect_timeout: int = 10,
|
|
118
118
|
read_timeout: int = 30,
|
|
119
119
|
scheme: str = "https",
|
|
120
|
+
retry_5xx: int = 0,
|
|
121
|
+
retry_on_read_timeout: bool = False,
|
|
122
|
+
retry_backoff: float = 1.0,
|
|
120
123
|
):
|
|
121
124
|
"""
|
|
122
125
|
Initialize the Redfish Client.
|
|
@@ -132,6 +135,15 @@ class RedfishClient:
|
|
|
132
135
|
connect_timeout: TCP connection timeout in seconds (default 10)
|
|
133
136
|
read_timeout: HTTP response read timeout in seconds (default 30)
|
|
134
137
|
scheme: URL scheme — "https" (default) or "http"
|
|
138
|
+
retry_5xx: Extra retries when the BMC returns a 5xx (default 0 —
|
|
139
|
+
no retry). GET/HEAD retry on 500/502/503/504; POST/PATCH/DELETE
|
|
140
|
+
retry only on 503/504 to minimise double-write risk. Useful
|
|
141
|
+
against overloaded / flaky BMCs (e.g. AMI MegaRAC firmware
|
|
142
|
+
that intermittently returns Base.1.x.InternalError).
|
|
143
|
+
retry_on_read_timeout: When True, also retry on read timeouts
|
|
144
|
+
(default False). Same idempotency rule as ``retry_5xx``.
|
|
145
|
+
retry_backoff: Base seconds between retries (linear back-off:
|
|
146
|
+
attempt ``n`` sleeps ``retry_backoff * n``). Default 1.0s.
|
|
135
147
|
"""
|
|
136
148
|
self._http_client = RedfishHttpClient(
|
|
137
149
|
host=host,
|
|
@@ -142,6 +154,9 @@ class RedfishClient:
|
|
|
142
154
|
connect_timeout=connect_timeout,
|
|
143
155
|
read_timeout=read_timeout,
|
|
144
156
|
scheme=scheme,
|
|
157
|
+
retry_5xx=retry_5xx,
|
|
158
|
+
retry_on_read_timeout=retry_on_read_timeout,
|
|
159
|
+
retry_backoff=retry_backoff,
|
|
145
160
|
)
|
|
146
161
|
|
|
147
162
|
# Root service cache
|
|
@@ -391,9 +406,20 @@ class RedfishClient:
|
|
|
391
406
|
return root.systems.odata_id
|
|
392
407
|
|
|
393
408
|
def _get_task_service(self) -> TaskService:
|
|
394
|
-
"""
|
|
409
|
+
"""
|
|
410
|
+
Get the TaskService resource.
|
|
411
|
+
|
|
412
|
+
Prefers the standard ``TaskService`` root link (present on every
|
|
413
|
+
DMTF-conformant BMC we've seen). Falls back to the non-standard
|
|
414
|
+
``Tasks`` link some SDK-internal models also expose, and finally to
|
|
415
|
+
the well-known path so a very stripped-down BMC still works.
|
|
416
|
+
"""
|
|
395
417
|
root = self._get_root()
|
|
396
|
-
|
|
418
|
+
link = getattr(root, "task_service", None) or getattr(root, "tasks", None)
|
|
419
|
+
odata_id = getattr(link, "odata_id", None) if link is not None else None
|
|
420
|
+
if not odata_id:
|
|
421
|
+
odata_id = "/redfish/v1/TaskService"
|
|
422
|
+
return self._http_client.get(odata_id, TaskService)
|
|
397
423
|
|
|
398
424
|
def _get_update_service(self) -> UpdateService:
|
|
399
425
|
"""Get the UpdateService resource."""
|
|
@@ -914,6 +940,110 @@ class RedfishClient:
|
|
|
914
940
|
"""
|
|
915
941
|
return self._managers.log_entries(log_id, manager_id)
|
|
916
942
|
|
|
943
|
+
# ------------------------------------------------------------------
|
|
944
|
+
# Out-of-band diagnostic log collection + download
|
|
945
|
+
# ------------------------------------------------------------------
|
|
946
|
+
|
|
947
|
+
def collect_diagnostic_data(
|
|
948
|
+
self,
|
|
949
|
+
diagnostic_data_type: Optional[str] = None,
|
|
950
|
+
log_id: Optional[str] = None,
|
|
951
|
+
manager_id: str = "1",
|
|
952
|
+
oem_params: Optional[dict] = None,
|
|
953
|
+
) -> Task:
|
|
954
|
+
"""
|
|
955
|
+
Trigger ``#LogService.CollectDiagnosticData`` to generate an
|
|
956
|
+
out-of-band diagnostic log bundle.
|
|
957
|
+
|
|
958
|
+
Automatically detects the server vendor and builds the vendor-specific
|
|
959
|
+
request body; the action target is discovered dynamically from the
|
|
960
|
+
LogService ``Actions`` block.
|
|
961
|
+
|
|
962
|
+
Args:
|
|
963
|
+
diagnostic_data_type: ``DiagnosticDataType`` value; ``None`` uses
|
|
964
|
+
the vendor default (OEM when available, else ``Manager``).
|
|
965
|
+
log_id: Log service ID. ``None`` auto-selects the sole service.
|
|
966
|
+
manager_id: Manager ID (default "1").
|
|
967
|
+
oem_params: Optional dict shallow-merged into the request body.
|
|
968
|
+
|
|
969
|
+
Returns:
|
|
970
|
+
A :class:`Task` referencing the asynchronous collection.
|
|
971
|
+
"""
|
|
972
|
+
return self._managers.collect_diagnostic_data(
|
|
973
|
+
diagnostic_data_type, log_id, manager_id, oem_params
|
|
974
|
+
)
|
|
975
|
+
|
|
976
|
+
def download_diagnostic_data(
|
|
977
|
+
self,
|
|
978
|
+
task_or_entry,
|
|
979
|
+
output_path: Optional[str] = None,
|
|
980
|
+
) -> "bytes | str":
|
|
981
|
+
"""
|
|
982
|
+
Download the artifact produced by a diagnostic-data collection.
|
|
983
|
+
|
|
984
|
+
Args:
|
|
985
|
+
task_or_entry: A completed :class:`Task` or a :class:`LogEntry`
|
|
986
|
+
carrying ``AdditionalDataURI``.
|
|
987
|
+
output_path: When provided, stream the bundle to this path and
|
|
988
|
+
return the absolute file path; otherwise return ``bytes``.
|
|
989
|
+
|
|
990
|
+
Returns:
|
|
991
|
+
The file bytes, or the absolute written path.
|
|
992
|
+
"""
|
|
993
|
+
return self._managers.download_diagnostic_data(task_or_entry, output_path)
|
|
994
|
+
|
|
995
|
+
def collect_and_download_diagnostic_data(
|
|
996
|
+
self,
|
|
997
|
+
output_path: str,
|
|
998
|
+
diagnostic_data_type: Optional[str] = None,
|
|
999
|
+
log_id: Optional[str] = None,
|
|
1000
|
+
manager_id: str = "1",
|
|
1001
|
+
poll_interval: int = 5,
|
|
1002
|
+
timeout: int = 1800,
|
|
1003
|
+
*,
|
|
1004
|
+
reuse_existing: bool = True,
|
|
1005
|
+
max_retries: int = 0,
|
|
1006
|
+
retry_backoff: int = 30,
|
|
1007
|
+
) -> str:
|
|
1008
|
+
"""
|
|
1009
|
+
One-click helper: trigger collection, wait for the task, then download.
|
|
1010
|
+
|
|
1011
|
+
Reuses a prior matching collection when available (``reuse_existing``,
|
|
1012
|
+
default True) and can retry a failed collection up to ``max_retries``
|
|
1013
|
+
times (default 0 — no retry). See
|
|
1014
|
+
:meth:`ManagersManager.collect_and_download_diagnostic_data` for the
|
|
1015
|
+
full behaviour contract.
|
|
1016
|
+
|
|
1017
|
+
Args:
|
|
1018
|
+
output_path: Destination file path for the downloaded bundle.
|
|
1019
|
+
diagnostic_data_type: See :meth:`collect_diagnostic_data`.
|
|
1020
|
+
log_id: See :meth:`collect_diagnostic_data`.
|
|
1021
|
+
manager_id: Manager ID (default "1").
|
|
1022
|
+
poll_interval: Task poll interval in seconds (default 5).
|
|
1023
|
+
timeout: Max wait in seconds (default 1800 — bundles are slow).
|
|
1024
|
+
reuse_existing: Reuse a matching prior task on the BMC when
|
|
1025
|
+
available (default True).
|
|
1026
|
+
max_retries: Extra retries on failure (default 0).
|
|
1027
|
+
retry_backoff: Seconds between retries (default 30).
|
|
1028
|
+
|
|
1029
|
+
Returns:
|
|
1030
|
+
The absolute path of the downloaded file.
|
|
1031
|
+
|
|
1032
|
+
Raises:
|
|
1033
|
+
LogCollectFailedError: When the collection ultimately fails.
|
|
1034
|
+
"""
|
|
1035
|
+
return self._managers.collect_and_download_diagnostic_data(
|
|
1036
|
+
output_path,
|
|
1037
|
+
diagnostic_data_type,
|
|
1038
|
+
log_id,
|
|
1039
|
+
manager_id,
|
|
1040
|
+
poll_interval,
|
|
1041
|
+
timeout,
|
|
1042
|
+
reuse_existing=reuse_existing,
|
|
1043
|
+
max_retries=max_retries,
|
|
1044
|
+
retry_backoff=retry_backoff,
|
|
1045
|
+
)
|
|
1046
|
+
|
|
917
1047
|
def get_network_protocol(self, manager_id: str = "1") -> NetworkProtocol:
|
|
918
1048
|
"""
|
|
919
1049
|
Get network protocol configuration for a BMC manager.
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Custom exceptions for the Redfish Python SDK.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class RedfishException(Exception):
|
|
7
|
+
"""
|
|
8
|
+
Base exception for all Redfish SDK errors.
|
|
9
|
+
|
|
10
|
+
Raised when a Redfish API call returns a non-successful HTTP status code.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
def __init__(self, status_code: int, message: str, body: str = ""):
|
|
14
|
+
self.status_code = status_code
|
|
15
|
+
self.message = message
|
|
16
|
+
self.body = body
|
|
17
|
+
super().__init__(f"[HTTP {status_code}] {message}")
|
|
18
|
+
|
|
19
|
+
def __repr__(self) -> str:
|
|
20
|
+
return f"RedfishException(status_code={self.status_code}, message={self.message!r})"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class RedfishNotFoundError(RedfishException):
|
|
24
|
+
"""Raised when a resource is not found (HTTP 404)."""
|
|
25
|
+
|
|
26
|
+
def __init__(self, path: str):
|
|
27
|
+
super().__init__(404, f"Resource not found: {path}")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class RedfishAuthError(RedfishException):
|
|
31
|
+
"""Raised when authentication fails (HTTP 401 / 403)."""
|
|
32
|
+
|
|
33
|
+
def __init__(self, status_code: int = 401):
|
|
34
|
+
super().__init__(status_code, "Authentication failed. Check username and password.")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class RedfishConnectionError(RedfishException):
|
|
38
|
+
"""
|
|
39
|
+
Raised when unable to connect to the BMC.
|
|
40
|
+
|
|
41
|
+
The message includes a category-specific troubleshooting hint derived
|
|
42
|
+
from the underlying ``cause`` so operators can quickly tell apart
|
|
43
|
+
"wrong IP / host down" from "wrong port / Redfish disabled" from
|
|
44
|
+
"TLS / DNS" issues.
|
|
45
|
+
|
|
46
|
+
Attributes:
|
|
47
|
+
host: The BMC host that failed to connect.
|
|
48
|
+
cause: The underlying transport exception (usually from ``requests``
|
|
49
|
+
/ ``urllib3``).
|
|
50
|
+
reason: One of ``"refused"``, ``"unreachable"``, ``"dns"``,
|
|
51
|
+
``"tls"``, ``"other"`` — a coarse category derived from ``cause``.
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
def __init__(self, host: str, cause: Exception = None):
|
|
55
|
+
self.host = host
|
|
56
|
+
self.cause = cause
|
|
57
|
+
self.reason = _classify_connection_cause(cause)
|
|
58
|
+
hint = _connection_hint(host, self.reason)
|
|
59
|
+
super().__init__(
|
|
60
|
+
0,
|
|
61
|
+
f"Unable to connect to host: {host}. Cause: {cause}. {hint}",
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class RedfishTimeoutError(RedfishException):
|
|
66
|
+
"""
|
|
67
|
+
Raised when a request times out.
|
|
68
|
+
|
|
69
|
+
Timeout usually means the BMC accepted the TCP connection but is too slow
|
|
70
|
+
to respond (e.g. mid-collection, or under heavy load). It's distinct from
|
|
71
|
+
:class:`RedfishConnectionError`, which means the TCP handshake itself
|
|
72
|
+
never succeeded.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
def __init__(self, host: str):
|
|
76
|
+
self.host = host
|
|
77
|
+
super().__init__(
|
|
78
|
+
0,
|
|
79
|
+
f"Request timed out connecting to: {host}. "
|
|
80
|
+
f"Hint: the BMC accepted the TCP connection but did not respond "
|
|
81
|
+
f"within the read timeout — it may be busy (e.g. running a "
|
|
82
|
+
f"diagnostic collection) or overloaded. Consider raising "
|
|
83
|
+
f"``read_timeout`` on RedfishClient, or retrying later.",
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class RedfishValidationError(RedfishException):
|
|
88
|
+
"""Raised for invalid input parameters (e.g., unsupported reset type)."""
|
|
89
|
+
|
|
90
|
+
def __init__(self, message: str):
|
|
91
|
+
super().__init__(400, message)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class LogCollectFailedError(RedfishException):
|
|
95
|
+
"""
|
|
96
|
+
Raised when out-of-band diagnostic-data collection fails on the BMC.
|
|
97
|
+
|
|
98
|
+
Carries the full BMC context so the caller can diagnose without having to
|
|
99
|
+
re-query the BMC: the terminal task state/status, the complete list of
|
|
100
|
+
BMC messages, and (when available) the history of progress snapshots
|
|
101
|
+
observed while polling.
|
|
102
|
+
|
|
103
|
+
Attributes:
|
|
104
|
+
task_id: Task or synthetic-task identifier the collection ran under.
|
|
105
|
+
task_state: Terminal ``TaskState`` reported by the BMC.
|
|
106
|
+
task_status: Terminal ``TaskStatus`` reported by the BMC.
|
|
107
|
+
messages: Full ``Messages`` list from the BMC (each entry retains its
|
|
108
|
+
``MessageId`` / ``Message`` / ``Severity`` / ``Resolution`` fields).
|
|
109
|
+
progress_history: Optional list of intermediate progress snapshots
|
|
110
|
+
captured during polling — useful for vendors (e.g. ZTE) whose
|
|
111
|
+
progress endpoint replaces earlier state on each poll.
|
|
112
|
+
"""
|
|
113
|
+
|
|
114
|
+
def __init__(
|
|
115
|
+
self,
|
|
116
|
+
message: str,
|
|
117
|
+
*,
|
|
118
|
+
task_id: str = "",
|
|
119
|
+
task_state: str = "",
|
|
120
|
+
task_status: str = "",
|
|
121
|
+
messages: list = None,
|
|
122
|
+
progress_history: list = None,
|
|
123
|
+
):
|
|
124
|
+
super().__init__(500, message)
|
|
125
|
+
self.task_id = task_id
|
|
126
|
+
self.task_state = task_state
|
|
127
|
+
self.task_status = task_status
|
|
128
|
+
self.messages = messages or []
|
|
129
|
+
self.progress_history = progress_history or []
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
# ---------------------------------------------------------------------------
|
|
133
|
+
# Internal helpers for RedfishConnectionError diagnosis
|
|
134
|
+
# ---------------------------------------------------------------------------
|
|
135
|
+
|
|
136
|
+
# Substrings observed in the string form of common transport failures.
|
|
137
|
+
# Ordered so the most specific matches win when combined into a single blob.
|
|
138
|
+
_CAUSE_MARKERS = (
|
|
139
|
+
("refused", ("connection refused", "econnrefused", "errno 61", "errno 111")),
|
|
140
|
+
("unreachable", (
|
|
141
|
+
"no route to host", "network is unreachable", "host is down",
|
|
142
|
+
"ehostunreach", "enetunreach",
|
|
143
|
+
)),
|
|
144
|
+
("dns", (
|
|
145
|
+
"name or service not known", "nodename nor servname",
|
|
146
|
+
"temporary failure in name resolution", "getaddrinfo failed",
|
|
147
|
+
)),
|
|
148
|
+
("tls", (
|
|
149
|
+
"ssl", "certificate", "handshake failed", "wrong version number",
|
|
150
|
+
)),
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def _classify_connection_cause(cause) -> str:
|
|
155
|
+
"""
|
|
156
|
+
Categorise a low-level connection failure so callers can display a
|
|
157
|
+
targeted hint. Returns one of: ``refused`` / ``unreachable`` / ``dns``
|
|
158
|
+
/ ``tls`` / ``other``.
|
|
159
|
+
"""
|
|
160
|
+
if cause is None:
|
|
161
|
+
return "other"
|
|
162
|
+
blob = f"{cause!r} {cause}".lower()
|
|
163
|
+
for reason, markers in _CAUSE_MARKERS:
|
|
164
|
+
for m in markers:
|
|
165
|
+
if m in blob:
|
|
166
|
+
return reason
|
|
167
|
+
return "other"
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def _connection_hint(host: str, reason: str) -> str:
|
|
171
|
+
"""Return a one-line, action-oriented hint for the given failure reason."""
|
|
172
|
+
if reason == "refused":
|
|
173
|
+
return (
|
|
174
|
+
f"Hint: {host} accepted routing (host is up) but no service is "
|
|
175
|
+
f"listening on the requested TCP port. Check: 1) the IP is a BMC "
|
|
176
|
+
f"address (not a host OS address); 2) the BMC Redfish/HTTPS "
|
|
177
|
+
f"service is enabled; 3) the port matches your RedfishClient "
|
|
178
|
+
f"``scheme``/port (Redfish default is 443 for https)."
|
|
179
|
+
)
|
|
180
|
+
if reason == "unreachable":
|
|
181
|
+
return (
|
|
182
|
+
f"Hint: {host} is not routable from this machine. Check network "
|
|
183
|
+
f"connectivity (VPN / firewall / VLAN / subnet)."
|
|
184
|
+
)
|
|
185
|
+
if reason == "dns":
|
|
186
|
+
return (
|
|
187
|
+
f"Hint: could not resolve host name {host!r}. Check DNS or use "
|
|
188
|
+
f"the raw IP address instead."
|
|
189
|
+
)
|
|
190
|
+
if reason == "tls":
|
|
191
|
+
return (
|
|
192
|
+
f"Hint: TLS/SSL handshake failed with {host}. BMC self-signed "
|
|
193
|
+
f"certificates are expected — RedfishClient defaults to "
|
|
194
|
+
f"``verify_ssl=False``. If you enabled verification, provide a "
|
|
195
|
+
f"trust store; otherwise check the server's TLS version."
|
|
196
|
+
)
|
|
197
|
+
return (
|
|
198
|
+
f"Hint: unclassified connection failure to {host}. Verify basic "
|
|
199
|
+
f"connectivity with ``ping`` / ``nc -zv {host} 443``."
|
|
200
|
+
)
|