python-ipmi 0.5.8__py3-none-any.whl → 0.6.1__py3-none-any.whl
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.
- pyipmi/__init__.py +269 -86
- pyipmi/bmc.py +198 -29
- pyipmi/chassis.py +205 -61
- pyipmi/constants.py +35 -0
- pyipmi/dcmi.py +356 -19
- pyipmi/errors.py +34 -22
- pyipmi/event.py +62 -3
- pyipmi/fields.py +41 -30
- pyipmi/fru.py +1107 -122
- pyipmi/helper.py +50 -16
- pyipmi/hpm.py +932 -203
- pyipmi/interfaces/__init__.py +77 -4
- pyipmi/interfaces/aardvark.py +170 -167
- pyipmi/interfaces/base.py +179 -0
- pyipmi/interfaces/ipmb.py +438 -86
- pyipmi/interfaces/ipmbdev.py +71 -158
- pyipmi/interfaces/ipmidev.py +324 -0
- pyipmi/interfaces/ipmitool.py +258 -90
- pyipmi/interfaces/mock.py +38 -16
- pyipmi/interfaces/openipmblink.py +423 -0
- pyipmi/interfaces/rmcp.py +499 -213
- pyipmi/interfaces/rmcpplus.py +735 -0
- pyipmi/interfaces/router.py +319 -0
- pyipmi/ipmitool.py +1120 -429
- pyipmi/lan.py +251 -76
- pyipmi/logger.py +4 -4
- pyipmi/messaging.py +207 -18
- pyipmi/mixin.py +52 -0
- pyipmi/msgs/__init__.py +0 -1
- pyipmi/msgs/constants.py +98 -0
- pyipmi/msgs/dcmi.py +177 -19
- pyipmi/msgs/device_messaging.py +34 -0
- pyipmi/msgs/fru.py +3 -1
- pyipmi/msgs/hpm.py +7 -7
- pyipmi/msgs/message.py +124 -84
- pyipmi/msgs/picmg.py +7 -5
- pyipmi/msgs/registry.py +18 -9
- pyipmi/msgs/sel.py +4 -4
- pyipmi/msgs/sensor.py +19 -0
- pyipmi/msgs/vita.py +0 -1
- pyipmi/picmg.py +523 -85
- pyipmi/sdr.py +598 -105
- pyipmi/sel.py +193 -28
- pyipmi/sensor.py +186 -48
- pyipmi/session.py +58 -34
- pyipmi/state.py +13 -5
- pyipmi/utils.py +64 -56
- pyipmi/version.py +1 -1
- pyipmi/vita.py +281 -0
- python_ipmi-0.6.1.dist-info/METADATA +372 -0
- python_ipmi-0.6.1.dist-info/RECORD +62 -0
- {python_ipmi-0.5.8.dist-info → python_ipmi-0.6.1.dist-info}/WHEEL +1 -1
- pyipmi/emulation.py +0 -395
- python_ipmi-0.5.8.dist-info/METADATA +0 -207
- python_ipmi-0.5.8.dist-info/RECORD +0 -56
- {python_ipmi-0.5.8.dist-info → python_ipmi-0.6.1.dist-info}/entry_points.txt +0 -0
- {python_ipmi-0.5.8.dist-info → python_ipmi-0.6.1.dist-info}/licenses/AUTHORS +0 -0
- {python_ipmi-0.5.8.dist-info → python_ipmi-0.6.1.dist-info}/licenses/COPYING +0 -0
- {python_ipmi-0.5.8.dist-info → python_ipmi-0.6.1.dist-info}/top_level.txt +0 -0
pyipmi/__init__.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
1
|
# Copyright (c) 2014 Kontron Europe GmbH
|
|
3
2
|
#
|
|
4
3
|
# This library is free software; you can redistribute it and/or
|
|
@@ -15,10 +14,39 @@
|
|
|
15
14
|
# License along with this library; if not, write to the Free Software
|
|
16
15
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
"""A pure Python IPMI library.
|
|
18
|
+
|
|
19
|
+
A connection to an IPMI device is an :class:`Ipmi` object, created by
|
|
20
|
+
:func:`create_connection` for an interface (see
|
|
21
|
+
:func:`pyipmi.interfaces.create_interface`).
|
|
22
|
+
The connection sends the requests to its :class:`Target`, the BMC or a
|
|
23
|
+
controller behind it, which is reached over the :class:`Routing` hops of
|
|
24
|
+
the target. The IPMI commands are the methods of :class:`Ipmi`, which
|
|
25
|
+
inherits them from the command groups of the modules, e.g.
|
|
26
|
+
:mod:`pyipmi.bmc` and :mod:`pyipmi.sdr`.
|
|
27
|
+
|
|
28
|
+
Example:
|
|
29
|
+
Print the device ID of a BMC over RMCP+::
|
|
30
|
+
|
|
31
|
+
import pyipmi
|
|
32
|
+
import pyipmi.interfaces
|
|
33
|
+
|
|
34
|
+
interface = pyipmi.interfaces.create_interface('rmcpplus')
|
|
35
|
+
ipmi = pyipmi.create_connection(interface)
|
|
36
|
+
ipmi.session.set_session_type_rmcp('10.0.0.1', port=623)
|
|
37
|
+
ipmi.session.set_auth_type_user('admin', 'admin')
|
|
38
|
+
ipmi.target = pyipmi.Target(ipmb_address=0x20)
|
|
39
|
+
|
|
40
|
+
with ipmi:
|
|
41
|
+
print(ipmi.get_device_id())
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
from __future__ import annotations
|
|
19
45
|
|
|
20
46
|
import time
|
|
21
47
|
import ast
|
|
48
|
+
import warnings
|
|
49
|
+
from typing import Any, Literal
|
|
22
50
|
|
|
23
51
|
from . import bmc
|
|
24
52
|
from . import chassis
|
|
@@ -27,42 +55,58 @@ from . import event
|
|
|
27
55
|
from . import fru
|
|
28
56
|
from . import hpm
|
|
29
57
|
from . import lan
|
|
58
|
+
from . import logger # noqa: F401 - installs the NullHandler
|
|
30
59
|
from . import messaging
|
|
31
60
|
from . import picmg
|
|
32
61
|
from . import sdr
|
|
33
62
|
from . import sel
|
|
34
63
|
from . import sensor
|
|
64
|
+
from . import vita
|
|
35
65
|
from . import msgs
|
|
36
66
|
|
|
37
67
|
from .errors import IpmiTimeoutError, CompletionCodeError, RetryError
|
|
68
|
+
from .msgs import Message
|
|
38
69
|
from .msgs.registry import create_request_by_name
|
|
39
70
|
from .session import Session
|
|
40
71
|
from .utils import check_rsp_completion_code, is_string
|
|
41
72
|
|
|
42
73
|
try:
|
|
43
|
-
from version import __version__
|
|
74
|
+
from .version import __version__
|
|
44
75
|
except ImportError:
|
|
45
76
|
__version__ = 'dev'
|
|
46
77
|
|
|
47
78
|
|
|
48
|
-
def create_connection(interface):
|
|
79
|
+
def create_connection(interface: Any) -> Ipmi:
|
|
80
|
+
"""Create a connection for an interface.
|
|
81
|
+
|
|
82
|
+
The connection gets a new :class:`pyipmi.session.Session` for the
|
|
83
|
+
interface. The target is not set, assign it to :attr:`Ipmi.target`
|
|
84
|
+
before sending requests.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
interface: The interface, e.g. created by
|
|
88
|
+
:func:`pyipmi.interfaces.create_interface`.
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
The connection.
|
|
92
|
+
"""
|
|
49
93
|
session = Session()
|
|
50
94
|
session.interface = interface
|
|
51
95
|
return Ipmi(interface=interface, session=session)
|
|
52
96
|
|
|
53
97
|
|
|
54
|
-
class Requester
|
|
98
|
+
class Requester:
|
|
55
99
|
"""The Requester class.
|
|
56
100
|
|
|
57
101
|
This represents an IPMI device which initiates a request/response
|
|
58
102
|
message exchange.
|
|
59
103
|
"""
|
|
60
104
|
|
|
61
|
-
def __init__(self, ipmb_address):
|
|
105
|
+
def __init__(self, ipmb_address: int) -> None:
|
|
62
106
|
self.ipmb_address = ipmb_address
|
|
63
107
|
|
|
64
108
|
|
|
65
|
-
class NullRequester
|
|
109
|
+
class NullRequester:
|
|
66
110
|
"""The NullRequester class.
|
|
67
111
|
|
|
68
112
|
This requester is used for interfaces which doesn't require a valid
|
|
@@ -70,36 +114,48 @@ class NullRequester(object):
|
|
|
70
114
|
"""
|
|
71
115
|
|
|
72
116
|
@property
|
|
73
|
-
def ipmb_address(self):
|
|
117
|
+
def ipmb_address(self) -> int:
|
|
74
118
|
raise AssertionError('NullRequester does not provide an IPMB address')
|
|
75
119
|
|
|
76
120
|
|
|
77
|
-
class Routing
|
|
78
|
-
"""
|
|
121
|
+
class Routing:
|
|
122
|
+
"""One hop of the path to a target, see :meth:`Target.set_routing`."""
|
|
123
|
+
|
|
124
|
+
def __init__(self, rq_sa: int, rs_sa: int, channel: int | None) -> None:
|
|
125
|
+
"""Initialize the hop.
|
|
79
126
|
|
|
80
|
-
|
|
127
|
+
Args:
|
|
128
|
+
rq_sa: The requester slave address.
|
|
129
|
+
rs_sa: The responder slave address.
|
|
130
|
+
channel: The channel of the bridge to the next hop, None for
|
|
131
|
+
the last hop.
|
|
132
|
+
"""
|
|
81
133
|
self.rq_sa = rq_sa
|
|
82
134
|
self.rs_sa = rs_sa
|
|
83
135
|
self.channel = channel
|
|
84
136
|
|
|
85
|
-
def __str__(self):
|
|
137
|
+
def __str__(self) -> str:
|
|
86
138
|
s = 'Routing: Rq: %s Rs: %s Ch: %s' \
|
|
87
139
|
% (self.rq_sa, self.rs_sa, self.channel)
|
|
88
140
|
return s
|
|
89
141
|
|
|
90
142
|
|
|
91
|
-
class Target
|
|
143
|
+
class Target:
|
|
92
144
|
"""The Target class represents an IPMI target."""
|
|
93
145
|
|
|
94
|
-
routing = None
|
|
95
|
-
ipmb_address = None
|
|
146
|
+
routing: list[Routing] | None = None
|
|
147
|
+
ipmb_address: int | None = None
|
|
96
148
|
|
|
97
|
-
def __init__(self, ipmb_address
|
|
98
|
-
|
|
149
|
+
def __init__(self, ipmb_address: int | None = None,
|
|
150
|
+
routing: str | list[tuple] | None = None) -> None:
|
|
151
|
+
"""Initialize the target.
|
|
99
152
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
153
|
+
Args:
|
|
154
|
+
ipmb_address: The IPMB address of the target, e.g. 0x20 for
|
|
155
|
+
the BMC.
|
|
156
|
+
routing: The path over which the target is reachable, used to
|
|
157
|
+
build the bridged Send Message requests, see
|
|
158
|
+
:meth:`set_routing`.
|
|
103
159
|
"""
|
|
104
160
|
if ipmb_address:
|
|
105
161
|
self.ipmb_address = ipmb_address
|
|
@@ -107,49 +163,61 @@ class Target(object):
|
|
|
107
163
|
if routing:
|
|
108
164
|
self.set_routing(routing)
|
|
109
165
|
|
|
110
|
-
def set_routing_information(self, routing):
|
|
166
|
+
def set_routing_information(self, routing: str | list[tuple]) -> None:
|
|
167
|
+
"""Set the path over which a target is reachable.
|
|
168
|
+
|
|
169
|
+
An alias of :meth:`set_routing`.
|
|
170
|
+
"""
|
|
111
171
|
self.set_routing(routing)
|
|
112
172
|
|
|
113
|
-
def set_routing(self, routing):
|
|
173
|
+
def set_routing(self, routing: str | list[tuple]) -> None:
|
|
114
174
|
"""Set the path over which a target is reachable.
|
|
115
175
|
|
|
116
|
-
|
|
117
|
-
|
|
176
|
+
Each hop of the path is a tuple ``(rq_sa, rs_sa, channel)``: the
|
|
177
|
+
requester address, the responder address and the channel of the
|
|
178
|
+
bridge to the next hop. The channel of the last hop is None.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
routing: The list of hops, or its string representation as
|
|
182
|
+
given on the command line.
|
|
118
183
|
|
|
119
|
-
Example #1
|
|
120
|
-
|
|
121
|
-
routing = [(0x81,0x20,0),(0x20,0x82,None)]
|
|
184
|
+
Example #1, access to an ATCA blade in a chassis (slave 0x81,
|
|
185
|
+
target 0x82)::
|
|
122
186
|
|
|
123
|
-
|
|
124
|
-
slave = 0x81, target = 0x72
|
|
125
|
-
routing = [(0x81,0x20,0),(0x20,0x82,7),(0x20,0x72,None)]
|
|
187
|
+
routing = [(0x81, 0x20, 0), (0x20, 0x82, None)]
|
|
126
188
|
|
|
189
|
+
Example #2, access to an AMC in a uTCA chassis (slave 0x81,
|
|
190
|
+
target 0x72)::
|
|
127
191
|
|
|
128
|
-
|
|
129
|
-
.-------------------. .--------.
|
|
130
|
-
| .-----------| | |
|
|
131
|
-
| ShMC | CM | | MMC |
|
|
132
|
-
channel=0 | | | channel=7 | |
|
|
133
|
-
81 ------------| 0x20 |0x82 0x20 |-------------| 0x72 |
|
|
134
|
-
| | | | |
|
|
135
|
-
| | | | |
|
|
136
|
-
| `-----------| | |
|
|
137
|
-
`-------------------´ `--------´
|
|
138
|
-
`------------´ `---´ `---------------´
|
|
192
|
+
routing = [(0x81, 0x20, 0), (0x20, 0x82, 7), (0x20, 0x72, None)]
|
|
139
193
|
|
|
140
|
-
|
|
194
|
+
uTCA - MCH AMC
|
|
195
|
+
.-------------------. .--------.
|
|
196
|
+
| .-----------| | |
|
|
197
|
+
| ShMC | CM | | MMC |
|
|
198
|
+
channel=0 | | | channel=7 | |
|
|
199
|
+
81 ------------| 0x20 |0x82 0x20 |-------------| 0x72 |
|
|
200
|
+
| | | | |
|
|
201
|
+
| | | | |
|
|
202
|
+
| `-----------| | |
|
|
203
|
+
`-------------------´ `--------´
|
|
204
|
+
`------------´ `---´ `---------------´
|
|
141
205
|
|
|
142
|
-
|
|
143
|
-
|
|
206
|
+
Example #3, access to an AMC in an ATCA AMC carrier (slave 0x81,
|
|
207
|
+
target 0x72)::
|
|
144
208
|
|
|
209
|
+
routing = [(0x81, 0x20, 0), (0x20, 0x8e, 7), (0x20, 0x80, None)]
|
|
145
210
|
"""
|
|
146
211
|
if is_string(routing):
|
|
147
212
|
# if type(routing) in [unicode, str]:
|
|
148
213
|
routing = ast.literal_eval(routing)
|
|
149
214
|
self.routing = [Routing(*route) for route in routing]
|
|
150
215
|
|
|
151
|
-
def __str__(self):
|
|
152
|
-
|
|
216
|
+
def __str__(self) -> str:
|
|
217
|
+
if self.ipmb_address is None:
|
|
218
|
+
string = 'Target: IPMB: none\n'
|
|
219
|
+
else:
|
|
220
|
+
string = 'Target: IPMB: 0x%02x\n' % self.ipmb_address
|
|
153
221
|
if self.routing:
|
|
154
222
|
for route in self.routing:
|
|
155
223
|
string += ' %s\n' % route
|
|
@@ -158,10 +226,33 @@ class Target(object):
|
|
|
158
226
|
|
|
159
227
|
class Ipmi(bmc.Bmc, chassis.Chassis, dcmi.Dcmi, fru.Fru, picmg.Picmg, hpm.Hpm,
|
|
160
228
|
sdr.Sdr, sensor.Sensor, event.Event, sel.Sel, lan.Lan,
|
|
161
|
-
messaging.Messaging):
|
|
229
|
+
messaging.Messaging, vita.Vita):
|
|
230
|
+
"""A connection to an IPMI device.
|
|
162
231
|
|
|
163
|
-
|
|
164
|
-
|
|
232
|
+
The IPMI commands are the methods of this class, which it inherits
|
|
233
|
+
from the command groups, e.g. :meth:`get_device_id` from the one of
|
|
234
|
+
:mod:`pyipmi.bmc`. The requests are sent over the interface to
|
|
235
|
+
the target.
|
|
236
|
+
|
|
237
|
+
The connection is a context manager, which opens the interface and
|
|
238
|
+
establishes the session on entry and closes them on exit. Set up the
|
|
239
|
+
session before, see the example of :mod:`pyipmi`.
|
|
240
|
+
"""
|
|
241
|
+
|
|
242
|
+
def __init__(self, interface: Any = None, target: Target | None = None,
|
|
243
|
+
session: Session | None = None,
|
|
244
|
+
requester: Any = None) -> None:
|
|
245
|
+
"""Initialize the connection.
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
interface: The interface the requests are sent over.
|
|
249
|
+
target: The target of the requests.
|
|
250
|
+
session: The session, a new one if not given. The interface
|
|
251
|
+
of the session is set to ``interface``.
|
|
252
|
+
requester: The requester of the requests, needed by interfaces
|
|
253
|
+
that send the requests on the IPMB, a
|
|
254
|
+
:class:`NullRequester` if not given.
|
|
255
|
+
"""
|
|
165
256
|
self._interface = interface
|
|
166
257
|
|
|
167
258
|
# we need a session, set if not passed
|
|
@@ -172,43 +263,98 @@ class Ipmi(bmc.Bmc, chassis.Chassis, dcmi.Dcmi, fru.Fru, picmg.Picmg, hpm.Hpm,
|
|
|
172
263
|
self._session.interface = interface
|
|
173
264
|
|
|
174
265
|
self._target = target
|
|
175
|
-
self.requester = requester
|
|
266
|
+
self.requester = requester if requester is not None else NullRequester()
|
|
176
267
|
|
|
177
268
|
for base in Ipmi.__bases__:
|
|
178
|
-
base.__init__(self)
|
|
269
|
+
base.__init__(self) # type: ignore[misc]
|
|
179
270
|
|
|
180
|
-
def __enter__(self):
|
|
271
|
+
def __enter__(self) -> Ipmi:
|
|
181
272
|
self.open()
|
|
182
273
|
return self
|
|
183
274
|
|
|
184
|
-
def __exit__(self, exception_type, exception_value,
|
|
275
|
+
def __exit__(self, exception_type: Any, exception_value: Any,
|
|
276
|
+
traceback: Any) -> Literal[False]:
|
|
185
277
|
self.close()
|
|
186
278
|
return False
|
|
187
279
|
|
|
188
|
-
def open(self):
|
|
280
|
+
def open(self) -> None:
|
|
281
|
+
"""Open the interface and establish the session."""
|
|
189
282
|
self.interface.open()
|
|
190
283
|
if self.session is not None:
|
|
191
284
|
self.session.establish()
|
|
192
285
|
|
|
193
|
-
def close(self):
|
|
286
|
+
def close(self) -> None:
|
|
287
|
+
"""Close the session and the interface."""
|
|
194
288
|
if self.session is not None:
|
|
195
289
|
self.session.close()
|
|
196
290
|
self.interface.close()
|
|
197
291
|
|
|
198
|
-
def
|
|
199
|
-
|
|
292
|
+
def is_target_accessible(self) -> bool:
|
|
293
|
+
"""Check if the target answers.
|
|
200
294
|
|
|
201
|
-
|
|
295
|
+
Returns:
|
|
296
|
+
True if the target answers. Depending on the interface, False
|
|
297
|
+
is returned or an exception is raised if it does not.
|
|
298
|
+
"""
|
|
299
|
+
return self.interface.is_target_accessible(self.target)
|
|
300
|
+
|
|
301
|
+
def is_ipmc_accessible(self) -> bool:
|
|
302
|
+
"""Deprecated, the old name of :meth:`is_target_accessible`."""
|
|
303
|
+
warnings.warn('is_ipmc_accessible is deprecated, use '
|
|
304
|
+
'is_target_accessible', DeprecationWarning,
|
|
305
|
+
stacklevel=2)
|
|
306
|
+
return self.is_target_accessible()
|
|
307
|
+
|
|
308
|
+
def wait_until_target_is_accessible(self, timeout: float,
|
|
309
|
+
interval: float = 0.25) -> None:
|
|
310
|
+
"""Wait until the target is accessible.
|
|
311
|
+
|
|
312
|
+
Args:
|
|
313
|
+
timeout: The time to wait in seconds.
|
|
314
|
+
interval: The time between the checks in seconds.
|
|
315
|
+
|
|
316
|
+
Raises:
|
|
317
|
+
IpmiTimeoutError: The target is not accessible after the
|
|
318
|
+
timeout, if the interface raises it, see
|
|
319
|
+
:meth:`is_target_accessible`.
|
|
320
|
+
"""
|
|
202
321
|
start_time = time.time()
|
|
203
322
|
while time.time() < start_time + (timeout):
|
|
204
323
|
try:
|
|
205
|
-
self.
|
|
324
|
+
if self.is_target_accessible():
|
|
325
|
+
return
|
|
206
326
|
except IpmiTimeoutError:
|
|
207
|
-
|
|
327
|
+
pass
|
|
328
|
+
time.sleep(interval)
|
|
208
329
|
|
|
209
|
-
self.
|
|
330
|
+
self.is_target_accessible()
|
|
210
331
|
|
|
211
|
-
def
|
|
332
|
+
def wait_until_ipmb_is_accessible(self, timeout: float,
|
|
333
|
+
interval: float = 0.25) -> None:
|
|
334
|
+
"""Deprecated, use :meth:`wait_until_target_is_accessible`."""
|
|
335
|
+
warnings.warn('wait_until_ipmb_is_accessible is deprecated, use '
|
|
336
|
+
'wait_until_target_is_accessible', DeprecationWarning,
|
|
337
|
+
stacklevel=2)
|
|
338
|
+
self.wait_until_target_is_accessible(timeout, interval)
|
|
339
|
+
|
|
340
|
+
def send_message(self, req: Message, retry: int = 3) -> Message:
|
|
341
|
+
"""Send a request to the target and return the response.
|
|
342
|
+
|
|
343
|
+
The request is sent again if the target is busy. The completion
|
|
344
|
+
code of the response is not checked.
|
|
345
|
+
|
|
346
|
+
Args:
|
|
347
|
+
req: The request message.
|
|
348
|
+
retry: The number of tries.
|
|
349
|
+
|
|
350
|
+
Returns:
|
|
351
|
+
The response message.
|
|
352
|
+
|
|
353
|
+
Raises:
|
|
354
|
+
RetryError: The target is still busy after ``retry`` tries.
|
|
355
|
+
CompletionCodeError: The interface failed with another
|
|
356
|
+
completion code, e.g. of a bridged Send Message request.
|
|
357
|
+
"""
|
|
212
358
|
req.target = self.target
|
|
213
359
|
req.requester = self.requester
|
|
214
360
|
rsp = None
|
|
@@ -221,12 +367,28 @@ class Ipmi(bmc.Bmc, chassis.Chassis, dcmi.Dcmi, fru.Fru, picmg.Picmg, hpm.Hpm,
|
|
|
221
367
|
except CompletionCodeError as e:
|
|
222
368
|
if e.cc == msgs.constants.CC_NODE_BUSY:
|
|
223
369
|
continue
|
|
370
|
+
raise
|
|
224
371
|
else:
|
|
225
372
|
raise RetryError()
|
|
226
373
|
|
|
227
374
|
return rsp
|
|
228
375
|
|
|
229
|
-
def
|
|
376
|
+
def send_message_by_name(self, name: str, *args: Any,
|
|
377
|
+
**kwargs: Any) -> Message:
|
|
378
|
+
"""Send a request by its name and return the response.
|
|
379
|
+
|
|
380
|
+
Args:
|
|
381
|
+
name: The name of the request, e.g. ``'GetDeviceId'``.
|
|
382
|
+
*args: Not used.
|
|
383
|
+
**kwargs: The fields of the request, set as attributes.
|
|
384
|
+
|
|
385
|
+
Returns:
|
|
386
|
+
The response message.
|
|
387
|
+
|
|
388
|
+
Raises:
|
|
389
|
+
CompletionCodeError: The completion code of the response is
|
|
390
|
+
not successful.
|
|
391
|
+
"""
|
|
230
392
|
req = create_request_by_name(name)
|
|
231
393
|
|
|
232
394
|
for key, value in kwargs.items():
|
|
@@ -236,45 +398,66 @@ class Ipmi(bmc.Bmc, chassis.Chassis, dcmi.Dcmi, fru.Fru, picmg.Picmg, hpm.Hpm,
|
|
|
236
398
|
check_rsp_completion_code(rsp)
|
|
237
399
|
return rsp
|
|
238
400
|
|
|
239
|
-
def
|
|
240
|
-
|
|
401
|
+
def send_message_with_name(self, name: str, *args: Any,
|
|
402
|
+
**kwargs: Any) -> Message:
|
|
403
|
+
"""Deprecated, the old name of :meth:`send_message_by_name`."""
|
|
404
|
+
warnings.warn('send_message_with_name is deprecated, use '
|
|
405
|
+
'send_message_by_name', DeprecationWarning,
|
|
406
|
+
stacklevel=2)
|
|
407
|
+
return self.send_message_by_name(name, *args, **kwargs)
|
|
408
|
+
|
|
409
|
+
def send_raw(self, lun: int, netfn: int, raw_bytes: bytes) -> bytes:
|
|
410
|
+
"""Send a raw request to the target and return the raw response.
|
|
241
411
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
412
|
+
Args:
|
|
413
|
+
lun: The logical unit number.
|
|
414
|
+
netfn: The network function.
|
|
415
|
+
raw_bytes: The request, starting with the command ID.
|
|
245
416
|
|
|
246
|
-
Returns
|
|
417
|
+
Returns:
|
|
418
|
+
The response, starting with the completion code.
|
|
247
419
|
"""
|
|
248
420
|
return self.interface.send_and_receive_raw(self.target, lun, netfn,
|
|
249
421
|
raw_bytes)
|
|
250
422
|
|
|
251
|
-
def
|
|
423
|
+
def raw_command(self, lun: int, netfn: int, raw_bytes: bytes) -> bytes:
|
|
424
|
+
"""Deprecated, the old name of :meth:`send_raw`."""
|
|
425
|
+
warnings.warn('raw_command is deprecated, use send_raw',
|
|
426
|
+
DeprecationWarning, stacklevel=2)
|
|
427
|
+
return self.send_raw(lun, netfn, raw_bytes)
|
|
428
|
+
|
|
429
|
+
@property
|
|
430
|
+
def interface(self) -> Any:
|
|
431
|
+
"""The interface the requests are sent over."""
|
|
252
432
|
try:
|
|
253
433
|
return self._interface
|
|
254
434
|
except AttributeError:
|
|
255
|
-
raise RuntimeError('No interface has been set')
|
|
435
|
+
raise RuntimeError('No interface has been set') from None
|
|
436
|
+
|
|
437
|
+
@interface.setter
|
|
438
|
+
def interface(self, interface: Any) -> None:
|
|
439
|
+
self._interface = interface
|
|
256
440
|
|
|
257
|
-
|
|
441
|
+
@property
|
|
442
|
+
def session(self) -> Session:
|
|
443
|
+
"""The session of the connection."""
|
|
258
444
|
try:
|
|
259
445
|
return self._session
|
|
260
446
|
except AttributeError:
|
|
261
|
-
raise RuntimeError('No IPMI session has been set')
|
|
447
|
+
raise RuntimeError('No IPMI session has been set') from None
|
|
448
|
+
|
|
449
|
+
@session.setter
|
|
450
|
+
def session(self, session: Session) -> None:
|
|
451
|
+
self._session = session
|
|
262
452
|
|
|
263
|
-
|
|
453
|
+
@property
|
|
454
|
+
def target(self) -> Target | None:
|
|
455
|
+
"""The target of the requests."""
|
|
264
456
|
try:
|
|
265
457
|
return self._target
|
|
266
458
|
except AttributeError:
|
|
267
|
-
raise RuntimeError('No IPMI target has been set')
|
|
268
|
-
|
|
269
|
-
def _set_interface(self, interface):
|
|
270
|
-
self._interface = interface
|
|
459
|
+
raise RuntimeError('No IPMI target has been set') from None
|
|
271
460
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
def _set_target(self, target):
|
|
461
|
+
@target.setter
|
|
462
|
+
def target(self, target: Target | None) -> None:
|
|
276
463
|
self._target = target
|
|
277
|
-
|
|
278
|
-
target = property(_get_target, _set_target)
|
|
279
|
-
interface = property(_get_interface, _set_interface)
|
|
280
|
-
session = property(_get_session, _set_session)
|