python-ipmi 0.5.5__py3-none-any.whl → 0.5.8__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 +32 -9
- pyipmi/bmc.py +16 -1
- pyipmi/errors.py +19 -1
- pyipmi/fields.py +1 -1
- pyipmi/fru.py +73 -49
- pyipmi/helper.py +1 -1
- pyipmi/hpm.py +1 -1
- pyipmi/interfaces/aardvark.py +18 -10
- pyipmi/interfaces/ipmb.py +31 -12
- pyipmi/interfaces/ipmbdev.py +8 -4
- pyipmi/interfaces/ipmitool.py +44 -7
- pyipmi/interfaces/mock.py +6 -0
- pyipmi/interfaces/rmcp.py +22 -6
- pyipmi/ipmitool.py +6 -5
- pyipmi/messaging.py +1 -0
- pyipmi/msgs/bmc.py +6 -7
- pyipmi/msgs/chassis.py +0 -1
- pyipmi/msgs/dcmi.py +0 -2
- pyipmi/msgs/event.py +0 -1
- pyipmi/msgs/fru.py +0 -1
- pyipmi/msgs/hpm.py +0 -1
- pyipmi/msgs/lan.py +0 -1
- pyipmi/msgs/message.py +3 -6
- pyipmi/msgs/picmg.py +0 -2
- pyipmi/msgs/registry.py +0 -1
- pyipmi/msgs/sdr.py +0 -1
- pyipmi/msgs/sel.py +0 -1
- pyipmi/msgs/sensor.py +0 -1
- pyipmi/msgs/vita.py +0 -2
- pyipmi/version.py +1 -1
- {python_ipmi-0.5.5.dist-info → python_ipmi-0.5.8.dist-info}/METADATA +16 -4
- python_ipmi-0.5.8.dist-info/RECORD +56 -0
- {python_ipmi-0.5.5.dist-info → python_ipmi-0.5.8.dist-info}/WHEEL +1 -1
- python_ipmi-0.5.5.dist-info/RECORD +0 -56
- {python_ipmi-0.5.5.dist-info → python_ipmi-0.5.8.dist-info}/entry_points.txt +0 -0
- {python_ipmi-0.5.5.dist-info → python_ipmi-0.5.8.dist-info/licenses}/AUTHORS +0 -0
- {python_ipmi-0.5.5.dist-info → python_ipmi-0.5.8.dist-info/licenses}/COPYING +0 -0
- {python_ipmi-0.5.5.dist-info → python_ipmi-0.5.8.dist-info}/top_level.txt +0 -0
pyipmi/__init__.py
CHANGED
|
@@ -48,11 +48,7 @@ except ImportError:
|
|
|
48
48
|
def create_connection(interface):
|
|
49
49
|
session = Session()
|
|
50
50
|
session.interface = interface
|
|
51
|
-
|
|
52
|
-
ipmi.interface = interface
|
|
53
|
-
ipmi.session = session
|
|
54
|
-
ipmi.requester = NullRequester()
|
|
55
|
-
return ipmi
|
|
51
|
+
return Ipmi(interface=interface, session=session)
|
|
56
52
|
|
|
57
53
|
|
|
58
54
|
class Requester(object):
|
|
@@ -164,14 +160,41 @@ class Ipmi(bmc.Bmc, chassis.Chassis, dcmi.Dcmi, fru.Fru, picmg.Picmg, hpm.Hpm,
|
|
|
164
160
|
sdr.Sdr, sensor.Sensor, event.Event, sel.Sel, lan.Lan,
|
|
165
161
|
messaging.Messaging):
|
|
166
162
|
|
|
167
|
-
def __init__(self)
|
|
168
|
-
|
|
169
|
-
self.
|
|
170
|
-
|
|
163
|
+
def __init__(self, interface=None, target=None, session=Session(),
|
|
164
|
+
requester=NullRequester()):
|
|
165
|
+
self._interface = interface
|
|
166
|
+
|
|
167
|
+
# we need a session, set if not passed
|
|
168
|
+
if session is None:
|
|
169
|
+
session = Session()
|
|
170
|
+
self._session = session
|
|
171
|
+
# session needs an interface
|
|
172
|
+
self._session.interface = interface
|
|
173
|
+
|
|
174
|
+
self._target = target
|
|
175
|
+
self.requester = requester
|
|
171
176
|
|
|
172
177
|
for base in Ipmi.__bases__:
|
|
173
178
|
base.__init__(self)
|
|
174
179
|
|
|
180
|
+
def __enter__(self):
|
|
181
|
+
self.open()
|
|
182
|
+
return self
|
|
183
|
+
|
|
184
|
+
def __exit__(self, exception_type, exception_value, traceback):
|
|
185
|
+
self.close()
|
|
186
|
+
return False
|
|
187
|
+
|
|
188
|
+
def open(self):
|
|
189
|
+
self.interface.open()
|
|
190
|
+
if self.session is not None:
|
|
191
|
+
self.session.establish()
|
|
192
|
+
|
|
193
|
+
def close(self):
|
|
194
|
+
if self.session is not None:
|
|
195
|
+
self.session.close()
|
|
196
|
+
self.interface.close()
|
|
197
|
+
|
|
175
198
|
def is_ipmc_accessible(self):
|
|
176
199
|
return self.interface.is_ipmc_accessible(self.target)
|
|
177
200
|
|
pyipmi/bmc.py
CHANGED
|
@@ -24,6 +24,9 @@ class Bmc(object):
|
|
|
24
24
|
def get_device_id(self):
|
|
25
25
|
return DeviceId(self.send_message_with_name('GetDeviceId'))
|
|
26
26
|
|
|
27
|
+
def get_device_guid(self):
|
|
28
|
+
return DeviceGuid(self.send_message_with_name('GetDeviceGuid'))
|
|
29
|
+
|
|
27
30
|
def cold_reset(self):
|
|
28
31
|
self.send_message_with_name('ColdReset')
|
|
29
32
|
|
|
@@ -86,7 +89,7 @@ class Watchdog(State):
|
|
|
86
89
|
TIMEOUT_ACTION_POWER_CYCLE = 3
|
|
87
90
|
|
|
88
91
|
__properties__ = [
|
|
89
|
-
# (
|
|
92
|
+
# (property, description)
|
|
90
93
|
('timer_use', ''),
|
|
91
94
|
('dont_stop', ''),
|
|
92
95
|
('is_running', ''),
|
|
@@ -121,6 +124,7 @@ class DeviceId(State):
|
|
|
121
124
|
string += ' ipmi: %s' % self.ipmi_version
|
|
122
125
|
string += ' manufacturer: %d' % self.manufacturer_id
|
|
123
126
|
string += ' product: %d' % self.product_id
|
|
127
|
+
string += ' functions: %s' % ','.join(self.supported_functions)
|
|
124
128
|
return string
|
|
125
129
|
|
|
126
130
|
def supports_function(self, name):
|
|
@@ -164,3 +168,14 @@ class DeviceId(State):
|
|
|
164
168
|
self.aux = None
|
|
165
169
|
if rsp.auxiliary is not None:
|
|
166
170
|
self.aux = list(rsp.auxiliary)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
class DeviceGuid(State):
|
|
174
|
+
def __str__(self):
|
|
175
|
+
return 'Device GUID: %s' % self.device_guid_string
|
|
176
|
+
|
|
177
|
+
def _from_response(self, rsp):
|
|
178
|
+
self.device_guid = rsp.device_guid
|
|
179
|
+
self.device_guid_string = \
|
|
180
|
+
'%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-' \
|
|
181
|
+
'%02x%02x%02x%02x%02x%02x' % tuple(reversed(self.device_guid))
|
pyipmi/errors.py
CHANGED
|
@@ -69,7 +69,7 @@ class DescriptionError(Exception):
|
|
|
69
69
|
|
|
70
70
|
|
|
71
71
|
class RetryError(Exception):
|
|
72
|
-
"""
|
|
72
|
+
"""Maximum number of retries exceeded."""
|
|
73
73
|
pass
|
|
74
74
|
|
|
75
75
|
|
|
@@ -90,3 +90,21 @@ class IpmiConnectionError(Exception):
|
|
|
90
90
|
|
|
91
91
|
def __str__(self):
|
|
92
92
|
return "{}".format(self.msg)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class IpmiLongPasswordError(Exception):
|
|
96
|
+
"""Password longer than 20 bytes."""
|
|
97
|
+
def __init__(self, msg=None):
|
|
98
|
+
self.msg = msg
|
|
99
|
+
|
|
100
|
+
def __str__(self):
|
|
101
|
+
return "{}".format(self.msg)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class AuthenticationError(Exception):
|
|
105
|
+
"""Authentication error."""
|
|
106
|
+
def __init__(self, msg=None):
|
|
107
|
+
self.msg = msg
|
|
108
|
+
|
|
109
|
+
def __str__(self):
|
|
110
|
+
return "{}".format(self.msg)
|
pyipmi/fields.py
CHANGED
|
@@ -64,7 +64,7 @@ def _unpack6bitascii(data):
|
|
|
64
64
|
|
|
65
65
|
class TypeLengthString(object):
|
|
66
66
|
"""
|
|
67
|
-
This is the TYPE/LENGTH BYTE FORMAT field
|
|
67
|
+
This is the TYPE/LENGTH BYTE FORMAT field representation according the
|
|
68
68
|
Platform Management FRU Information Storage Definition v1.0.
|
|
69
69
|
|
|
70
70
|
In addition the difference to the 'FRU Information Storage Definition' to
|
pyipmi/fru.py
CHANGED
|
@@ -88,9 +88,9 @@ class Fru(object):
|
|
|
88
88
|
def read_fru_data_full(self, fru_id=0):
|
|
89
89
|
return self.read_fru_data(fru_id=fru_id)
|
|
90
90
|
|
|
91
|
-
def get_fru_inventory_header(self, fru_id=0):
|
|
91
|
+
def get_fru_inventory_header(self, fru_id=0, ignore_checksum=False):
|
|
92
92
|
data = self.read_fru_data(offset=0, count=8, fru_id=fru_id)
|
|
93
|
-
return InventoryCommonHeader(data)
|
|
93
|
+
return InventoryCommonHeader(data, ignore_checksum=ignore_checksum)
|
|
94
94
|
|
|
95
95
|
def _read_fru_area(self, offset, fru_id=0):
|
|
96
96
|
# read the area header
|
|
@@ -99,26 +99,30 @@ class Fru(object):
|
|
|
99
99
|
count = data[1] * 8
|
|
100
100
|
return self.read_fru_data(offset=offset, count=count, fru_id=fru_id)
|
|
101
101
|
|
|
102
|
-
def get_fru_chassis_area(self, fru_id=0):
|
|
103
|
-
header = self.get_fru_inventory_header(fru_id=fru_id
|
|
102
|
+
def get_fru_chassis_area(self, fru_id=0, ignore_checksum=False):
|
|
103
|
+
header = self.get_fru_inventory_header(fru_id=fru_id,
|
|
104
|
+
ignore_checksum=ignore_checksum)
|
|
104
105
|
data = self._read_fru_area(offset=header.chassis_info_area_offset,
|
|
105
106
|
fru_id=fru_id)
|
|
106
|
-
return InventoryChassisInfoArea(data)
|
|
107
|
+
return InventoryChassisInfoArea(data, ignore_checksum=ignore_checksum)
|
|
107
108
|
|
|
108
|
-
def get_fru_board_area(self, fru_id=0):
|
|
109
|
-
header = self.get_fru_inventory_header(fru_id=fru_id
|
|
109
|
+
def get_fru_board_area(self, fru_id=0, ignore_checksum=False):
|
|
110
|
+
header = self.get_fru_inventory_header(fru_id=fru_id,
|
|
111
|
+
ignore_checksum=ignore_checksum)
|
|
110
112
|
data = self._read_fru_area(offset=header.board_info_area_offset,
|
|
111
113
|
fru_id=fru_id)
|
|
112
|
-
return InventoryBoardInfoArea(data)
|
|
114
|
+
return InventoryBoardInfoArea(data, ignore_checksum=ignore_checksum)
|
|
113
115
|
|
|
114
|
-
def get_fru_product_area(self, fru_id=0):
|
|
115
|
-
header = self.get_fru_inventory_header(fru_id=fru_id
|
|
116
|
+
def get_fru_product_area(self, fru_id=0, ignore_checksum=False):
|
|
117
|
+
header = self.get_fru_inventory_header(fru_id=fru_id,
|
|
118
|
+
ignore_checksum=ignore_checksum)
|
|
116
119
|
data = self._read_fru_area(offset=header.product_info_area_offset,
|
|
117
120
|
fru_id=fru_id)
|
|
118
|
-
return InventoryProductInfoArea(data)
|
|
121
|
+
return InventoryProductInfoArea(data, ignore_checksum=ignore_checksum)
|
|
119
122
|
|
|
120
|
-
def get_fru_multirecord_area(self, fru_id=0):
|
|
121
|
-
header = self.get_fru_inventory_header(fru_id=fru_id
|
|
123
|
+
def get_fru_multirecord_area(self, fru_id=0, ignore_checksum=False):
|
|
124
|
+
header = self.get_fru_inventory_header(fru_id=fru_id,
|
|
125
|
+
ignore_checksum=ignore_checksum)
|
|
122
126
|
|
|
123
127
|
# we have to determine the length of the area first
|
|
124
128
|
offset = header.multirecord_area_offset
|
|
@@ -137,31 +141,47 @@ class Fru(object):
|
|
|
137
141
|
# now read the full area
|
|
138
142
|
offset = header.multirecord_area_offset
|
|
139
143
|
data = self.read_fru_data(offset=offset, count=count)
|
|
140
|
-
return InventoryMultiRecordArea(data)
|
|
144
|
+
return InventoryMultiRecordArea(data, ignore_checksum=ignore_checksum)
|
|
141
145
|
|
|
142
|
-
def get_fru_inventory(self, fru_id=0):
|
|
146
|
+
def get_fru_inventory(self, fru_id=0, ignore_checksum=False):
|
|
143
147
|
"""
|
|
144
148
|
Get the full parsed FRU inventory data.
|
|
145
149
|
"""
|
|
146
150
|
fru = FruInventory()
|
|
147
|
-
|
|
151
|
+
|
|
152
|
+
header = self.get_fru_inventory_header(
|
|
153
|
+
fru_id=fru_id,
|
|
154
|
+
ignore_checksum=ignore_checksum
|
|
155
|
+
)
|
|
148
156
|
|
|
149
157
|
if header.chassis_info_area_offset:
|
|
150
|
-
fru.chassis_info_area = self.get_fru_chassis_area(
|
|
158
|
+
fru.chassis_info_area = self.get_fru_chassis_area(
|
|
159
|
+
fru_id=fru_id,
|
|
160
|
+
ignore_checksum=ignore_checksum
|
|
161
|
+
)
|
|
151
162
|
|
|
152
163
|
if header.board_info_area_offset:
|
|
153
|
-
fru.board_info_area = self.get_fru_board_area(
|
|
164
|
+
fru.board_info_area = self.get_fru_board_area(
|
|
165
|
+
fru_id=fru_id,
|
|
166
|
+
ignore_checksum=ignore_checksum
|
|
167
|
+
)
|
|
154
168
|
|
|
155
169
|
if header.product_info_area_offset:
|
|
156
|
-
fru.product_info_area = self.get_fru_product_area(
|
|
170
|
+
fru.product_info_area = self.get_fru_product_area(
|
|
171
|
+
fru_id=fru_id,
|
|
172
|
+
ignore_checksum=ignore_checksum
|
|
173
|
+
)
|
|
157
174
|
|
|
158
175
|
if header.multirecord_area_offset:
|
|
159
|
-
fru.multirecord_area = self.get_fru_multirecord_area(
|
|
176
|
+
fru.multirecord_area = self.get_fru_multirecord_area(
|
|
177
|
+
fru_id=fru_id,
|
|
178
|
+
ignore_checksum=ignore_checksum
|
|
179
|
+
)
|
|
160
180
|
|
|
161
181
|
return fru
|
|
162
182
|
|
|
163
183
|
|
|
164
|
-
def get_fru_inventory_from_file(filename):
|
|
184
|
+
def get_fru_inventory_from_file(filename, ignore_checksum=False):
|
|
165
185
|
try:
|
|
166
186
|
file = open(filename, "rb")
|
|
167
187
|
except IOError:
|
|
@@ -173,7 +193,7 @@ def get_fru_inventory_from_file(filename):
|
|
|
173
193
|
file_data = file.read(file_size)
|
|
174
194
|
data = array.array('B', file_data)
|
|
175
195
|
file.close()
|
|
176
|
-
return FruInventory(data)
|
|
196
|
+
return FruInventory(data, ignore_checksum=ignore_checksum)
|
|
177
197
|
|
|
178
198
|
|
|
179
199
|
CUSTOM_FIELD_END = 0xc1
|
|
@@ -190,18 +210,18 @@ def _decode_custom_fields(data):
|
|
|
190
210
|
|
|
191
211
|
|
|
192
212
|
class FruData(object):
|
|
193
|
-
def __init__(self, data=None):
|
|
213
|
+
def __init__(self, data=None, ignore_checksum=False):
|
|
194
214
|
if data:
|
|
195
215
|
if isinstance(data, str):
|
|
196
216
|
data = [ord(c) for c in data]
|
|
197
217
|
self.data = data
|
|
198
218
|
if hasattr(self, '_from_data'):
|
|
199
|
-
self._from_data(data)
|
|
219
|
+
self._from_data(data, ignore_checksum=ignore_checksum)
|
|
200
220
|
|
|
201
221
|
|
|
202
222
|
class InventoryCommonHeader(FruData):
|
|
203
|
-
def _from_data(self, data):
|
|
204
|
-
if len(data)
|
|
223
|
+
def _from_data(self, data, ignore_checksum=False):
|
|
224
|
+
if len(data) < 8:
|
|
205
225
|
raise DecodingError('InventoryCommonHeader length != 8')
|
|
206
226
|
self.format_version = data[0] & 0x0f
|
|
207
227
|
self.internal_use_area_offset = data[1] * 8 or None
|
|
@@ -209,18 +229,18 @@ class InventoryCommonHeader(FruData):
|
|
|
209
229
|
self.board_info_area_offset = data[3] * 8 or None
|
|
210
230
|
self.product_info_area_offset = data[4] * 8 or None
|
|
211
231
|
self.multirecord_area_offset = data[5] * 8 or None
|
|
212
|
-
if sum(data) % 256 != 0:
|
|
213
|
-
raise DecodingError('InventoryCommonHeader checksum failed')
|
|
232
|
+
if sum(data[:8]) % 256 != 0 and ignore_checksum is False:
|
|
233
|
+
raise DecodingError(f'InventoryCommonHeader checksum failed {sum(data) % 0x10}')
|
|
214
234
|
|
|
215
235
|
|
|
216
236
|
class CommonInfoArea(FruData):
|
|
217
|
-
def _from_data(self, data):
|
|
237
|
+
def _from_data(self, data, ignore_checksum=False):
|
|
218
238
|
self.format_version = data[0] & 0x0f
|
|
219
239
|
if self.format_version != 1:
|
|
220
240
|
raise DecodingError('unsupported format version (%d)' %
|
|
221
241
|
self.format_version)
|
|
222
242
|
self.length = data[1] * 8
|
|
223
|
-
if sum(data[:self.length]) % 256 != 0:
|
|
243
|
+
if sum(data[:self.length]) % 256 != 0 and ignore_checksum is False:
|
|
224
244
|
raise DecodingError('checksum failed')
|
|
225
245
|
|
|
226
246
|
|
|
@@ -249,7 +269,7 @@ class InventoryChassisInfoArea(CommonInfoArea):
|
|
|
249
269
|
TYPE_RAID_CHASSIS = 22
|
|
250
270
|
TYPE_RACK_MOUNT_CHASSIS = 23
|
|
251
271
|
|
|
252
|
-
def _from_data(self, data):
|
|
272
|
+
def _from_data(self, data, ignore_checksum=False):
|
|
253
273
|
CommonInfoArea._from_data(self, data)
|
|
254
274
|
self.type = data[2]
|
|
255
275
|
offset = 3
|
|
@@ -261,8 +281,8 @@ class InventoryChassisInfoArea(CommonInfoArea):
|
|
|
261
281
|
|
|
262
282
|
|
|
263
283
|
class InventoryBoardInfoArea(CommonInfoArea):
|
|
264
|
-
def _from_data(self, data):
|
|
265
|
-
CommonInfoArea._from_data(self, data)
|
|
284
|
+
def _from_data(self, data, ignore_checksum=False):
|
|
285
|
+
CommonInfoArea._from_data(self, data, ignore_checksum=ignore_checksum)
|
|
266
286
|
self.language_code = data[2]
|
|
267
287
|
minutes = data[5] << 16 | data[4] << 8 | data[3]
|
|
268
288
|
self.mfg_date = (datetime.datetime(1996, 1, 1)
|
|
@@ -282,7 +302,7 @@ class InventoryBoardInfoArea(CommonInfoArea):
|
|
|
282
302
|
|
|
283
303
|
|
|
284
304
|
class InventoryProductInfoArea(CommonInfoArea):
|
|
285
|
-
def _from_data(self, data):
|
|
305
|
+
def _from_data(self, data, ignore_checksum=False):
|
|
286
306
|
CommonInfoArea._from_data(self, data)
|
|
287
307
|
self.language_code = data[2]
|
|
288
308
|
offset = 3
|
|
@@ -318,17 +338,17 @@ class FruDataMultiRecord(FruData):
|
|
|
318
338
|
return '%02x: %s' % (self.record_type_id,
|
|
319
339
|
' '.join('%02x' % b for b in self.raw))
|
|
320
340
|
|
|
321
|
-
def _from_data(self, data):
|
|
341
|
+
def _from_data(self, data, ignore_checksum=False):
|
|
322
342
|
if len(data) < 5:
|
|
323
343
|
raise DecodingError('data too short')
|
|
324
344
|
self.record_type_id = data[0]
|
|
325
345
|
self.format_version = data[1] & 0x0f
|
|
326
346
|
self.end_of_list = bool(data[1] & 0x80)
|
|
327
347
|
self.length = data[2]
|
|
328
|
-
if sum(data[:5]) % 256 != 0:
|
|
348
|
+
if sum(data[:5]) % 256 != 0 and ignore_checksum is False:
|
|
329
349
|
raise DecodingError('FruDataMultiRecord header checksum failed')
|
|
330
350
|
self.raw = data[5:5+self.length]
|
|
331
|
-
if (sum(self.raw) + data[3]) % 256 != 0:
|
|
351
|
+
if (sum(self.raw) + data[3]) % 256 != 0 and ignore_checksum is False:
|
|
332
352
|
raise DecodingError('FruDataMultiRecord record checksum failed')
|
|
333
353
|
|
|
334
354
|
@staticmethod
|
|
@@ -386,11 +406,11 @@ class FruPicmgRecord(FruDataMultiRecord):
|
|
|
386
406
|
|
|
387
407
|
return FruPicmgRecord(data)
|
|
388
408
|
|
|
389
|
-
def _from_data(self, data):
|
|
409
|
+
def _from_data(self, data, ignore_checksum=False):
|
|
390
410
|
if len(data) < 10:
|
|
391
411
|
raise DecodingError('data too short')
|
|
392
412
|
data = array.array('B', data)
|
|
393
|
-
FruDataMultiRecord._from_data(self, data)
|
|
413
|
+
FruDataMultiRecord._from_data(self, data, ignore_checksum=ignore_checksum)
|
|
394
414
|
self.manufacturer_id = \
|
|
395
415
|
data[5] | data[6] << 8 | data[7] << 16
|
|
396
416
|
self.picmg_record_type_id = data[8]
|
|
@@ -398,7 +418,7 @@ class FruPicmgRecord(FruDataMultiRecord):
|
|
|
398
418
|
|
|
399
419
|
|
|
400
420
|
class FruPicmgPowerModuleCapabilityRecord(FruPicmgRecord):
|
|
401
|
-
def _from_data(self, data):
|
|
421
|
+
def _from_data(self, data, ignore_checksum=False):
|
|
402
422
|
if len(data) < 12:
|
|
403
423
|
raise DecodingError('data too short')
|
|
404
424
|
FruPicmgRecord._from_data(self, data)
|
|
@@ -407,11 +427,11 @@ class FruPicmgPowerModuleCapabilityRecord(FruPicmgRecord):
|
|
|
407
427
|
|
|
408
428
|
|
|
409
429
|
class InventoryMultiRecordArea(object):
|
|
410
|
-
def __init__(self, data):
|
|
430
|
+
def __init__(self, data, ignore_checksum=False):
|
|
411
431
|
if data:
|
|
412
432
|
self._from_data(data)
|
|
413
433
|
|
|
414
|
-
def _from_data(self, data):
|
|
434
|
+
def _from_data(self, data, ignore_checksum=False):
|
|
415
435
|
self.records = list()
|
|
416
436
|
offset = 0
|
|
417
437
|
while True:
|
|
@@ -423,31 +443,35 @@ class InventoryMultiRecordArea(object):
|
|
|
423
443
|
|
|
424
444
|
|
|
425
445
|
class FruInventory(object):
|
|
426
|
-
def __init__(self, data=None):
|
|
446
|
+
def __init__(self, data=None, ignore_checksum=False):
|
|
427
447
|
self.chassis_info_area = None
|
|
428
448
|
self.board_info_area = None
|
|
429
449
|
self.product_info_area = None
|
|
430
450
|
self.multirecord_area = None
|
|
431
451
|
|
|
432
452
|
if data:
|
|
433
|
-
self._from_data(data)
|
|
453
|
+
self._from_data(data, ignore_checksum=ignore_checksum)
|
|
434
454
|
|
|
435
|
-
def _from_data(self, data):
|
|
455
|
+
def _from_data(self, data, ignore_checksum=False):
|
|
436
456
|
self.raw = data
|
|
437
457
|
self.common_header = InventoryCommonHeader(data[:8])
|
|
438
458
|
|
|
439
459
|
if self.common_header.chassis_info_area_offset:
|
|
440
460
|
self.chassis_info_area = InventoryChassisInfoArea(
|
|
441
|
-
data[self.common_header.chassis_info_area_offset:]
|
|
461
|
+
data[self.common_header.chassis_info_area_offset:],
|
|
462
|
+
ignore_checksum=ignore_checksum)
|
|
442
463
|
|
|
443
464
|
if self.common_header.board_info_area_offset:
|
|
444
465
|
self.board_info_area = InventoryBoardInfoArea(
|
|
445
|
-
data[self.common_header.board_info_area_offset:]
|
|
466
|
+
data[self.common_header.board_info_area_offset:],
|
|
467
|
+
ignore_checksum=ignore_checksum)
|
|
446
468
|
|
|
447
469
|
if self.common_header.product_info_area_offset:
|
|
448
470
|
self.product_info_area = InventoryProductInfoArea(
|
|
449
|
-
data[self.common_header.product_info_area_offset:]
|
|
471
|
+
data[self.common_header.product_info_area_offset:],
|
|
472
|
+
ignore_checksum=ignore_checksum)
|
|
450
473
|
|
|
451
474
|
if self.common_header.multirecord_area_offset:
|
|
452
475
|
self.multirecord_area = InventoryMultiRecordArea(
|
|
453
|
-
data[self.common_header.multirecord_area_offset:]
|
|
476
|
+
data[self.common_header.multirecord_area_offset:],
|
|
477
|
+
ignore_checksum=ignore_checksum)
|
pyipmi/helper.py
CHANGED
|
@@ -85,7 +85,7 @@ def get_sdr_data_helper(reserve_fn, get_fn, record_id, reservation_id=None):
|
|
|
85
85
|
(next_id, data) = get_fn(reservation_id, record_id, offset, length)
|
|
86
86
|
except CompletionCodeError as e:
|
|
87
87
|
if e.cc == constants.CC_CANT_RET_NUM_REQ_BYTES:
|
|
88
|
-
# reduce max
|
|
88
|
+
# reduce max length
|
|
89
89
|
max_req_len -= 4
|
|
90
90
|
if max_req_len <= 0:
|
|
91
91
|
retry = 0
|
pyipmi/hpm.py
CHANGED
|
@@ -314,7 +314,7 @@ class Hpm(object):
|
|
|
314
314
|
# tbd check version
|
|
315
315
|
|
|
316
316
|
####################################################
|
|
317
|
-
# compare current revision with upgrade image
|
|
317
|
+
# compare current revision with upgrade image earliest comp rev
|
|
318
318
|
targetCap = self.get_target_upgrade_capabilities()
|
|
319
319
|
# tbd check version
|
|
320
320
|
|
pyipmi/interfaces/aardvark.py
CHANGED
|
@@ -44,23 +44,32 @@ class Aardvark(object):
|
|
|
44
44
|
'use this interface.')
|
|
45
45
|
|
|
46
46
|
self.slave_address = slave_address
|
|
47
|
+
self.port = port
|
|
48
|
+
self.serial_number = serial_number
|
|
49
|
+
self.i2c_pullups = enable_i2c_pullups
|
|
50
|
+
self.target_power = enable_target_power
|
|
51
|
+
self.fastmode = enable_fastmode
|
|
47
52
|
self.timeout = 0.25
|
|
48
53
|
self.max_retries = 3
|
|
49
54
|
self.next_sequence_number = 0
|
|
50
55
|
|
|
51
|
-
|
|
56
|
+
def open(self):
|
|
57
|
+
self._dev = pyaardvark.open(self.port, self.serial_number)
|
|
52
58
|
self._dev.enable_i2c_slave(self.slave_address >> 1)
|
|
53
59
|
|
|
54
|
-
if
|
|
55
|
-
self.enable_pullups(
|
|
56
|
-
if
|
|
57
|
-
self.enable_target_power(
|
|
60
|
+
if self.i2c_pullups:
|
|
61
|
+
self.enable_pullups(self.i2c_pullups)
|
|
62
|
+
if self.target_power:
|
|
63
|
+
self.enable_target_power(self.target_power)
|
|
58
64
|
|
|
59
|
-
if
|
|
60
|
-
self.enable_fastmode(
|
|
65
|
+
if self.fastmode is not None:
|
|
66
|
+
self.enable_fastmode(self.fastmode)
|
|
61
67
|
else:
|
|
62
68
|
self.enable_fastmode(False)
|
|
63
69
|
|
|
70
|
+
def close(self):
|
|
71
|
+
self._dev.close()
|
|
72
|
+
|
|
64
73
|
def enable_pullups(self, enabled):
|
|
65
74
|
self._dev.i2c_pullups = enabled
|
|
66
75
|
|
|
@@ -77,11 +86,10 @@ class Aardvark(object):
|
|
|
77
86
|
self._dev.i2c_master_write(address, data)
|
|
78
87
|
|
|
79
88
|
def establish_session(self, session):
|
|
80
|
-
|
|
81
|
-
self._session = session
|
|
89
|
+
pass
|
|
82
90
|
|
|
83
91
|
def close_session(self):
|
|
84
|
-
|
|
92
|
+
pass
|
|
85
93
|
|
|
86
94
|
def is_ipmc_accessible(self, target):
|
|
87
95
|
header = IpmbHeaderReq()
|
pyipmi/interfaces/ipmb.py
CHANGED
|
@@ -45,10 +45,6 @@ class IpmbHeader(object):
|
|
|
45
45
|
*-------*--------------*----------*-------*---------------*-------*
|
|
46
46
|
"""
|
|
47
47
|
|
|
48
|
-
def __init__(self, data=None):
|
|
49
|
-
if data:
|
|
50
|
-
self.decode(data)
|
|
51
|
-
|
|
52
48
|
rs_sa = None
|
|
53
49
|
rs_lun = None
|
|
54
50
|
rq_sa = None
|
|
@@ -58,6 +54,17 @@ class IpmbHeader(object):
|
|
|
58
54
|
cmdid = None
|
|
59
55
|
checksum = None
|
|
60
56
|
|
|
57
|
+
def __init__(self, data=None):
|
|
58
|
+
if data:
|
|
59
|
+
self.decode(data)
|
|
60
|
+
|
|
61
|
+
def __str__(self):
|
|
62
|
+
return f'rs_sa=0x{self.rs_sa:02x}, rs_lun={self.rs_lun}, ' \
|
|
63
|
+
f'rq_sa=0x{self.rq_sa:02x}, rq_lun={self.rq_lun}, ' \
|
|
64
|
+
f'rq_seq={self.rq_seq}, ' \
|
|
65
|
+
f'netfn=0x{self.netfn:02x}, ' \
|
|
66
|
+
f'cmdid=0x{self.cmdid:02x}'
|
|
67
|
+
|
|
61
68
|
|
|
62
69
|
class IpmbHeaderReq(IpmbHeader):
|
|
63
70
|
"""Representation of the IPMI request message header."""
|
|
@@ -142,7 +149,7 @@ def encode_ipmb_msg(header, data):
|
|
|
142
149
|
|
|
143
150
|
|
|
144
151
|
def encode_send_message(payload, rq_sa, rs_sa, channel, seq, tracking=1):
|
|
145
|
-
"""Encode a send message command and
|
|
152
|
+
"""Encode a send message command and embed the message to be send.
|
|
146
153
|
|
|
147
154
|
payload: the message to be send as bytestring
|
|
148
155
|
rq_sa: the requester source address
|
|
@@ -171,7 +178,7 @@ def encode_send_message(payload, rq_sa, rs_sa, channel, seq, tracking=1):
|
|
|
171
178
|
|
|
172
179
|
|
|
173
180
|
def encode_bridged_message(routing, header, payload, seq):
|
|
174
|
-
"""Encode a (multi-)bridged command and
|
|
181
|
+
"""Encode a (multi-)bridged command and embed the message to be send.
|
|
175
182
|
|
|
176
183
|
routing:
|
|
177
184
|
payload: the message to be send as bytestring
|
|
@@ -214,7 +221,8 @@ def decode_bridged_message(rx_data):
|
|
|
214
221
|
return rx_data
|
|
215
222
|
|
|
216
223
|
|
|
217
|
-
def rx_filter(header, data
|
|
224
|
+
def rx_filter(header, data, rq_sa=False, rs_sa=False, rq_lun=False,
|
|
225
|
+
rs_lun=True, rq_seq=True):
|
|
218
226
|
"""Check if the message in rx_data matches to the information in header.
|
|
219
227
|
|
|
220
228
|
The following checks are done:
|
|
@@ -234,15 +242,26 @@ def rx_filter(header, data):
|
|
|
234
242
|
checks = [
|
|
235
243
|
(checksum(data[0:3]), 0, 'Header checksum failed'),
|
|
236
244
|
(checksum(data[3:]), 0, 'payload checksum failed'),
|
|
237
|
-
# rsp_header.rq_sa, header.rq_sa, 'slave address mismatch'),
|
|
238
245
|
(rsp_header.netfn, header.netfn | 1, 'NetFn mismatch'),
|
|
239
|
-
# rsp_header.rs_sa, header.rs_sa, 'target address mismatch'),
|
|
240
|
-
# rsp_header.rq_lun, header.rq_lun, 'request LUN mismatch'),
|
|
241
|
-
(rsp_header.rs_lun, header.rs_lun, 'responder LUN mismatch'),
|
|
242
|
-
(rsp_header.rq_seq, header.rq_seq, 'sequence number mismatch'),
|
|
243
246
|
(rsp_header.cmdid, header.cmdid, 'command id mismatch'),
|
|
244
247
|
]
|
|
245
248
|
|
|
249
|
+
# optional checks
|
|
250
|
+
if rq_sa:
|
|
251
|
+
checks.append((rsp_header.rq_sa, header.rq_sa, 'slave address mismatch'))
|
|
252
|
+
|
|
253
|
+
if rs_sa:
|
|
254
|
+
checks.append((rsp_header.rs_sa, header.rs_sa, 'target address mismatch'))
|
|
255
|
+
|
|
256
|
+
if rq_lun:
|
|
257
|
+
checks.append((rsp_header.rq_lun, header.rq_lun, 'request LUN mismatch'))
|
|
258
|
+
|
|
259
|
+
if rs_lun:
|
|
260
|
+
checks.append((rsp_header.rs_lun, header.rs_lun, 'responder LUN mismatch'))
|
|
261
|
+
|
|
262
|
+
if rq_seq:
|
|
263
|
+
checks.append((rsp_header.rq_seq, header.rq_seq, 'sequence number mismatch'))
|
|
264
|
+
|
|
246
265
|
match = True
|
|
247
266
|
|
|
248
267
|
for left, right, msg in checks:
|
pyipmi/interfaces/ipmbdev.py
CHANGED
|
@@ -17,18 +17,22 @@ class IpmbDev(object):
|
|
|
17
17
|
def __init__(self, slave_address=0x20, port='/dev/ipmb-0'):
|
|
18
18
|
# TODO: slave address is currently not defined here
|
|
19
19
|
self.slave_address = slave_address
|
|
20
|
+
self.port = port
|
|
20
21
|
self.timeout = 0.25
|
|
21
22
|
self.max_retries = 3
|
|
22
23
|
self.next_sequence_number = 0
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
def open(self):
|
|
26
|
+
self._dev = os.open(self.port, os.O_RDWR)
|
|
27
|
+
|
|
28
|
+
def close(self):
|
|
29
|
+
os.close(self._dev)
|
|
25
30
|
|
|
26
31
|
def establish_session(self, session):
|
|
27
|
-
|
|
28
|
-
self._session = session
|
|
32
|
+
pass
|
|
29
33
|
|
|
30
34
|
def close_session(self):
|
|
31
|
-
|
|
35
|
+
pass
|
|
32
36
|
|
|
33
37
|
def is_ipmc_accessible(self, target):
|
|
34
38
|
header = IpmbHeaderReq()
|
pyipmi/interfaces/ipmitool.py
CHANGED
|
@@ -21,7 +21,12 @@ from subprocess import Popen, PIPE
|
|
|
21
21
|
from array import array
|
|
22
22
|
|
|
23
23
|
from ..session import Session
|
|
24
|
-
from ..errors import
|
|
24
|
+
from ..errors import (
|
|
25
|
+
IpmiTimeoutError,
|
|
26
|
+
IpmiConnectionError,
|
|
27
|
+
IpmiLongPasswordError,
|
|
28
|
+
AuthenticationError,
|
|
29
|
+
)
|
|
25
30
|
from ..logger import log
|
|
26
31
|
from ..msgs import encode_message, decode_message, create_message
|
|
27
32
|
from ..msgs.constants import CC_OK
|
|
@@ -42,12 +47,17 @@ class Ipmitool(object):
|
|
|
42
47
|
IPMITOOL_PATH = 'ipmitool'
|
|
43
48
|
supported_interfaces = ['lan', 'lanplus', 'serial-terminal', 'open']
|
|
44
49
|
|
|
45
|
-
def __init__(self, interface_type='lan'):
|
|
50
|
+
def __init__(self, interface_type='lan', cipher=None):
|
|
46
51
|
if interface_type in self.supported_interfaces:
|
|
47
52
|
self._interface_type = interface_type
|
|
48
53
|
else:
|
|
49
54
|
raise RuntimeError('interface type %s not supported' %
|
|
50
55
|
interface_type)
|
|
56
|
+
if cipher is not None and int(cipher) not in range(0, 255):
|
|
57
|
+
raise RuntimeError('cipher %s not in allowed range [0-255]' %
|
|
58
|
+
cipher)
|
|
59
|
+
else:
|
|
60
|
+
self._cipher = cipher
|
|
51
61
|
|
|
52
62
|
self.re_completion_code = re.compile(
|
|
53
63
|
r"Unable to send RAW command \(.*rsp=(0x[0-9a-f]+)\)")
|
|
@@ -57,13 +67,24 @@ class Ipmitool(object):
|
|
|
57
67
|
r".*Unable to establish.*")
|
|
58
68
|
self.re_could_not_open = re.compile(
|
|
59
69
|
r".*Could not open device.*")
|
|
60
|
-
|
|
70
|
+
self.re_long_password = re.compile(
|
|
71
|
+
r".*password is longer than.*")
|
|
72
|
+
self.re_authentication_error = re.compile(
|
|
73
|
+
r".*RAKP [0-9]+ HMAC.*")
|
|
61
74
|
self._session = None
|
|
62
75
|
|
|
76
|
+
def open(self):
|
|
77
|
+
pass
|
|
78
|
+
|
|
79
|
+
def close(self):
|
|
80
|
+
pass
|
|
81
|
+
|
|
63
82
|
def establish_session(self, session):
|
|
64
|
-
# just remember session parameters here
|
|
65
83
|
self._session = session
|
|
66
84
|
|
|
85
|
+
def close_session(self):
|
|
86
|
+
pass
|
|
87
|
+
|
|
67
88
|
def rmcp_ping(self):
|
|
68
89
|
|
|
69
90
|
if self._interface_type == 'serial-terminal':
|
|
@@ -75,6 +96,7 @@ class Ipmitool(object):
|
|
|
75
96
|
cmd += (' -I %s' % self._interface_type)
|
|
76
97
|
cmd += (' -H %s' % self._session.rmcp_host)
|
|
77
98
|
cmd += (' -p %s' % self._session.rmcp_port)
|
|
99
|
+
cmd += (' -v')
|
|
78
100
|
if self._session.auth_type == Session.AUTH_TYPE_NONE:
|
|
79
101
|
cmd += (' -A NONE')
|
|
80
102
|
elif self._session.auth_type == Session.AUTH_TYPE_PASSWORD:
|
|
@@ -103,6 +125,9 @@ class Ipmitool(object):
|
|
|
103
125
|
# Don't try to parse ipmitool error messages
|
|
104
126
|
if 'failed' in line:
|
|
105
127
|
continue
|
|
128
|
+
# Don't try to parse spurious ipmitool output
|
|
129
|
+
if 'Received a response with unexpected ID' in line:
|
|
130
|
+
continue
|
|
106
131
|
|
|
107
132
|
# Check for timeout
|
|
108
133
|
if self.re_timeout.match(line):
|
|
@@ -122,13 +147,22 @@ class Ipmitool(object):
|
|
|
122
147
|
if self.re_could_not_open.match(line):
|
|
123
148
|
raise RuntimeError('ipmitool failed: {}'.format(output))
|
|
124
149
|
|
|
150
|
+
if self.re_long_password.match(line):
|
|
151
|
+
raise IpmiLongPasswordError(line)
|
|
152
|
+
|
|
153
|
+
if self.re_authentication_error.match(line):
|
|
154
|
+
raise AuthenticationError('Authentication error')
|
|
155
|
+
|
|
125
156
|
hexstr += line.replace('\r', '').strip() + ' '
|
|
126
157
|
|
|
127
158
|
hexstr = hexstr.strip()
|
|
128
159
|
if len(hexstr):
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
160
|
+
try:
|
|
161
|
+
rsp = array('B', [
|
|
162
|
+
int(value, 16) for value in hexstr.split(' ')
|
|
163
|
+
])
|
|
164
|
+
except ValueError:
|
|
165
|
+
pass
|
|
132
166
|
|
|
133
167
|
return cc, rsp
|
|
134
168
|
|
|
@@ -230,9 +264,12 @@ class Ipmitool(object):
|
|
|
230
264
|
cmd += (' -I %s' % self._interface_type)
|
|
231
265
|
cmd += (' -H %s' % self._session.rmcp_host)
|
|
232
266
|
cmd += (' -p %s' % self._session.rmcp_port)
|
|
267
|
+
cmd += (' -v')
|
|
233
268
|
|
|
234
269
|
cmd += self._build_ipmitool_priv_level(self._session.priv_level)
|
|
235
270
|
|
|
271
|
+
if self._cipher:
|
|
272
|
+
cmd += (' -C %s' % self._cipher)
|
|
236
273
|
if self._session.auth_type == Session.AUTH_TYPE_NONE:
|
|
237
274
|
cmd += ' -P ""'
|
|
238
275
|
elif self._session.auth_type == Session.AUTH_TYPE_PASSWORD:
|
pyipmi/interfaces/mock.py
CHANGED
pyipmi/interfaces/rmcp.py
CHANGED
|
@@ -248,7 +248,7 @@ class IpmiMsg(object):
|
|
|
248
248
|
return struct.unpack("<I", struct.pack(">I", seq))[0]
|
|
249
249
|
|
|
250
250
|
def _padd_password(self):
|
|
251
|
-
"""
|
|
251
|
+
"""Pad the password.
|
|
252
252
|
|
|
253
253
|
The password/key is 0 padded to 16-bytes for all specified
|
|
254
254
|
authentication types.
|
|
@@ -380,15 +380,23 @@ class Rmcp(object):
|
|
|
380
380
|
interface="rmcp",
|
|
381
381
|
quirks_cfg={'rmcp_ignore_sdu_length': True}
|
|
382
382
|
)
|
|
383
|
+
|
|
384
|
+
- `rmcp_ignore_rq_seq: bool` wheater or not to verify the req_seq field
|
|
385
|
+
for rx_filter. The default value is `False`.
|
|
386
|
+
|
|
387
|
+
Example:
|
|
388
|
+
|
|
389
|
+
interfaces.create_interface(
|
|
390
|
+
interface="rmcp",
|
|
391
|
+
quirks_cfg={'rmcp_ignore_rq_seq': True}
|
|
392
|
+
)
|
|
383
393
|
"""
|
|
384
394
|
self.host = None
|
|
385
395
|
self.port = None
|
|
386
|
-
self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
387
396
|
self.seq_number = 0xff
|
|
388
397
|
self.slave_address = slave_address
|
|
389
398
|
self.host_target = Target(host_target_address)
|
|
390
399
|
self.max_retries = max_retries
|
|
391
|
-
self.set_timeout(2.0)
|
|
392
400
|
self.next_sequence_number = 0
|
|
393
401
|
self.keep_alive_interval = keep_alive_interval
|
|
394
402
|
self._stop_keep_alive = None
|
|
@@ -396,6 +404,14 @@ class Rmcp(object):
|
|
|
396
404
|
self.transaction_lock = threading.Lock()
|
|
397
405
|
self.quirks_cfg = quirks_cfg
|
|
398
406
|
self.ignore_sdu_length = quirks_cfg.get('rmcp_ignore_sdu_length', False)
|
|
407
|
+
self.ignore_rq_seq = quirks_cfg.get('rmcp_ignore_rq_seq', False)
|
|
408
|
+
|
|
409
|
+
def open(self):
|
|
410
|
+
self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
411
|
+
self.set_timeout(2.0)
|
|
412
|
+
|
|
413
|
+
def close(self):
|
|
414
|
+
pass
|
|
399
415
|
|
|
400
416
|
def _send_rmcp_msg(self, sdu, class_of_msg):
|
|
401
417
|
rmcp = RmcpMsg(class_of_msg)
|
|
@@ -476,8 +492,7 @@ class Rmcp(object):
|
|
|
476
492
|
req = create_request_by_name('ActivateSession')
|
|
477
493
|
req.target = self.host_target
|
|
478
494
|
req.authentication.type = session.auth_type
|
|
479
|
-
req.privilege_level.maximum_requested
|
|
480
|
-
Session.PRIV_LEVEL_ADMINISTRATOR
|
|
495
|
+
req.privilege_level.maximum_requested = session.priv_level
|
|
481
496
|
req.challenge_string = challenge
|
|
482
497
|
req.session_id = self._session.sid
|
|
483
498
|
req.initial_outbound_sequence_number = random.randrange(1, 0xffffffff)
|
|
@@ -610,7 +625,8 @@ class Rmcp(object):
|
|
|
610
625
|
# it's not really a retry
|
|
611
626
|
continue
|
|
612
627
|
|
|
613
|
-
received = rx_filter(header, rx_data
|
|
628
|
+
received = rx_filter(header, rx_data,
|
|
629
|
+
rq_seq=not self.ignore_rq_seq)
|
|
614
630
|
|
|
615
631
|
if not received:
|
|
616
632
|
self._q.put(rx_data)
|
pyipmi/ipmitool.py
CHANGED
|
@@ -474,7 +474,7 @@ Options:
|
|
|
474
474
|
-I <interface> Set interface (available: rmcp, aardvark, ipmitool, ipmbdev)
|
|
475
475
|
-H <host> Set RMCP host
|
|
476
476
|
-U <user> Set RMCP user
|
|
477
|
-
-L <level> Set RMCP
|
|
477
|
+
-L <level> Set RMCP privilege level
|
|
478
478
|
-P <password> Set RMCP password
|
|
479
479
|
-o <options> Set interface specific options (name=value, separated
|
|
480
480
|
by commas, see below for available options).
|
|
@@ -488,6 +488,7 @@ Aardvark interface options:
|
|
|
488
488
|
|
|
489
489
|
Ipmitool interface options:
|
|
490
490
|
interface_type Set the interface type to be used (lan, lanplus, serial, open)
|
|
491
|
+
cipher Set the cipher to be used (0-255)
|
|
491
492
|
|
|
492
493
|
Ipmbdev interface options:
|
|
493
494
|
port=<path> Specify path to Linux IPMB device (/dev/ipmb-0 by default)
|
|
@@ -533,6 +534,8 @@ def parse_interface_options(interface_name, options):
|
|
|
533
534
|
elif interface_name == 'ipmitool':
|
|
534
535
|
if name == 'interface_type':
|
|
535
536
|
interface_options['interface_type'] = value
|
|
537
|
+
elif name == 'cipher':
|
|
538
|
+
interface_options['cipher'] = value
|
|
536
539
|
else:
|
|
537
540
|
print('Warning: unknown option %s' % name)
|
|
538
541
|
elif interface_name == 'ipmbdev':
|
|
@@ -641,9 +644,8 @@ def main():
|
|
|
641
644
|
if rmcp_priv_level is not None:
|
|
642
645
|
ipmi.session.set_priv_level(rmcp_priv_level)
|
|
643
646
|
|
|
644
|
-
ipmi.session.establish()
|
|
645
|
-
|
|
646
647
|
try:
|
|
648
|
+
ipmi.open() # this will open interface and session
|
|
647
649
|
cmd(ipmi, args)
|
|
648
650
|
except pyipmi.errors.CompletionCodeError as e:
|
|
649
651
|
print('Command returned with completion code 0x%02x' % e.cc)
|
|
@@ -661,8 +663,7 @@ def main():
|
|
|
661
663
|
sys.exit(1)
|
|
662
664
|
|
|
663
665
|
finally:
|
|
664
|
-
|
|
665
|
-
ipmi.session.close()
|
|
666
|
+
ipmi.close() # this will close interface and session
|
|
666
667
|
|
|
667
668
|
|
|
668
669
|
COMMANDS = (
|
pyipmi/messaging.py
CHANGED
pyipmi/msgs/bmc.py
CHANGED
|
@@ -14,9 +14,6 @@
|
|
|
14
14
|
# License along with this library; if not, write to the Free Software
|
|
15
15
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
16
16
|
|
|
17
|
-
from __future__ import absolute_import
|
|
18
|
-
|
|
19
|
-
|
|
20
17
|
from . import constants
|
|
21
18
|
from . import register_message_class
|
|
22
19
|
from . import Message
|
|
@@ -174,17 +171,19 @@ class GetAcpiPowerStateRsp(Message):
|
|
|
174
171
|
|
|
175
172
|
|
|
176
173
|
@register_message_class
|
|
177
|
-
class
|
|
174
|
+
class GetDeviceGuidReq(Message):
|
|
178
175
|
__cmdid__ = constants.CMDID_GET_DEVICE_GUID
|
|
179
176
|
__netfn__ = constants.NETFN_APP
|
|
180
|
-
__not_implemented__ = True
|
|
181
177
|
|
|
182
178
|
|
|
183
179
|
@register_message_class
|
|
184
|
-
class
|
|
180
|
+
class GetDeviceGuidRsp(Message):
|
|
185
181
|
__cmdid__ = constants.CMDID_GET_DEVICE_GUID
|
|
186
182
|
__netfn__ = constants.NETFN_APP | 1
|
|
187
|
-
|
|
183
|
+
__fields__ = (
|
|
184
|
+
CompletionCode(),
|
|
185
|
+
ByteArray('device_guid', 16),
|
|
186
|
+
)
|
|
188
187
|
|
|
189
188
|
|
|
190
189
|
@register_message_class
|
pyipmi/msgs/chassis.py
CHANGED
pyipmi/msgs/dcmi.py
CHANGED
|
@@ -14,8 +14,6 @@
|
|
|
14
14
|
# License along with this library; if not, write to the Free Software
|
|
15
15
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
16
16
|
|
|
17
|
-
from __future__ import absolute_import
|
|
18
|
-
|
|
19
17
|
|
|
20
18
|
from . import constants
|
|
21
19
|
from . import register_message_class
|
pyipmi/msgs/event.py
CHANGED
pyipmi/msgs/fru.py
CHANGED
pyipmi/msgs/hpm.py
CHANGED
pyipmi/msgs/lan.py
CHANGED
pyipmi/msgs/message.py
CHANGED
|
@@ -14,9 +14,6 @@
|
|
|
14
14
|
# License along with this library; if not, write to the Free Software
|
|
15
15
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
from __future__ import absolute_import
|
|
19
|
-
|
|
20
17
|
from array import array
|
|
21
18
|
|
|
22
19
|
from . import constants
|
|
@@ -57,7 +54,7 @@ class ByteArray(BaseField):
|
|
|
57
54
|
def encode(self, obj, data):
|
|
58
55
|
a = getattr(obj, self.name)
|
|
59
56
|
if len(a) != self._length(obj):
|
|
60
|
-
raise EncodingError('Array must be
|
|
57
|
+
raise EncodingError('Array must be exactly %d bytes long '
|
|
61
58
|
'(but is %d long)' %
|
|
62
59
|
(self._length(obj), len(a)))
|
|
63
60
|
for i in range(self._length(obj)):
|
|
@@ -73,7 +70,7 @@ class ByteArray(BaseField):
|
|
|
73
70
|
if self.default is not None:
|
|
74
71
|
return array('B', self.default)
|
|
75
72
|
else:
|
|
76
|
-
return array('B', self.length * '\x00')
|
|
73
|
+
return array('B', self.length * b'\x00')
|
|
77
74
|
|
|
78
75
|
|
|
79
76
|
class VariableByteArray(ByteArray):
|
|
@@ -323,7 +320,7 @@ class Message(object):
|
|
|
323
320
|
|
|
324
321
|
buf -- option message buffer to decode
|
|
325
322
|
|
|
326
|
-
Optional keyword arguments
|
|
323
|
+
Optional keyword arguments corresponds to members to set (matching
|
|
327
324
|
fields in self.__fields__, or 'data').
|
|
328
325
|
"""
|
|
329
326
|
# create message fields
|
pyipmi/msgs/picmg.py
CHANGED
|
@@ -14,8 +14,6 @@
|
|
|
14
14
|
# License along with this library; if not, write to the Free Software
|
|
15
15
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
16
16
|
|
|
17
|
-
from __future__ import absolute_import
|
|
18
|
-
|
|
19
17
|
from . import constants
|
|
20
18
|
from . import register_message_class
|
|
21
19
|
from . import Message
|
pyipmi/msgs/registry.py
CHANGED
pyipmi/msgs/sdr.py
CHANGED
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
# You should have received a copy of the GNU Lesser General Public
|
|
14
14
|
# License along with this library; if not, write to the Free Software
|
|
15
15
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
16
|
-
from __future__ import absolute_import
|
|
17
16
|
|
|
18
17
|
from . import constants
|
|
19
18
|
from . import register_message_class
|
pyipmi/msgs/sel.py
CHANGED
pyipmi/msgs/sensor.py
CHANGED
pyipmi/msgs/vita.py
CHANGED
|
@@ -14,8 +14,6 @@
|
|
|
14
14
|
# License along with this library; if not, write to the Free Software
|
|
15
15
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
16
16
|
|
|
17
|
-
from __future__ import absolute_import
|
|
18
|
-
|
|
19
17
|
from . import constants
|
|
20
18
|
from . import register_message_class
|
|
21
19
|
from . import Message
|
pyipmi/version.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# This file was autogenerated by setup.py
|
|
2
|
-
__version__ = '0.5.
|
|
2
|
+
__version__ = '0.5.8'
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: python-ipmi
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.8
|
|
4
4
|
Summary: Pure python IPMI library
|
|
5
5
|
Home-page: https://github.com/kontron/python-ipmi
|
|
6
|
-
Download-URL: https://github.com/kontron/python-ipmi/tarball/0.5.
|
|
6
|
+
Download-URL: https://github.com/kontron/python-ipmi/tarball/0.5.8
|
|
7
7
|
Author: Michael Walle, Heiko Thiery
|
|
8
8
|
Author-email: michael.walle@kontron.com, heiko.thiery@kontron.com
|
|
9
9
|
License: LGPLv2+
|
|
@@ -20,9 +20,20 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.10
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.11
|
|
22
22
|
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
24
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
25
|
License-File: COPYING
|
|
25
26
|
License-File: AUTHORS
|
|
27
|
+
Dynamic: author
|
|
28
|
+
Dynamic: author-email
|
|
29
|
+
Dynamic: classifier
|
|
30
|
+
Dynamic: description
|
|
31
|
+
Dynamic: download-url
|
|
32
|
+
Dynamic: home-page
|
|
33
|
+
Dynamic: license
|
|
34
|
+
Dynamic: license-file
|
|
35
|
+
Dynamic: platform
|
|
36
|
+
Dynamic: summary
|
|
26
37
|
|
|
27
38
|
Pure Python IPMI Library
|
|
28
39
|
========================
|
|
@@ -105,6 +116,7 @@ Example with lan interface:
|
|
|
105
116
|
|
|
106
117
|
connection.session.set_session_type_rmcp('10.0.0.1', port=623)
|
|
107
118
|
connection.session.set_auth_type_user('admin', 'admin')
|
|
119
|
+
connection.session.set_priv_level("ADMINISTRATOR")
|
|
108
120
|
connection.session.establish()
|
|
109
121
|
|
|
110
122
|
connection.get_device_id()
|
|
@@ -113,7 +125,7 @@ ipmitool command:
|
|
|
113
125
|
|
|
114
126
|
.. code:: shell
|
|
115
127
|
|
|
116
|
-
ipmitool -I lan -H 10.0.0.1 -p 623 -U "admin" -P "admin" -t 0x82 -b 0 -l 0 raw 0x06 0x01
|
|
128
|
+
ipmitool -I lan -H 10.0.0.1 -p 623 -L "ADMINISTRATOR" -U "admin" -P "admin" -t 0x82 -b 0 -l 0 raw 0x06 0x01
|
|
117
129
|
|
|
118
130
|
|
|
119
131
|
Example with serial interface:
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
pyipmi/__init__.py,sha256=3Pi4ZuxaLCa6eB0nFAMNtUjbadXw-z1OkBO2bCiK8fw,8456
|
|
2
|
+
pyipmi/bmc.py,sha256=k5ctloS-EMFybiLJIXNz0u_PpmDJwPRZnroI-1lv6LM,6715
|
|
3
|
+
pyipmi/chassis.py,sha256=pWxPm5Vtc6NlTNWyV2lqOR-73UUOf3hJ4pXypC_uV3k,9977
|
|
4
|
+
pyipmi/constants.py,sha256=3Opcz-XtjcxvYRCV5JCPkIYcNLkEutYwdk8XE2bHm9U,1421
|
|
5
|
+
pyipmi/dcmi.py,sha256=9hPYe7gfFqtX-VOkZ0cKG-LLVkwqOlYXS4UQLcny8zE,2359
|
|
6
|
+
pyipmi/emulation.py,sha256=bc4Pk1uOkqJjFdd-GrwJDCAT_u8jmezilJUbl_ibPWw,11363
|
|
7
|
+
pyipmi/errors.py,sha256=GUSGSSeFZyGomErAme3EiomBUuVQdTiYPZLLvZZtzvk,3046
|
|
8
|
+
pyipmi/event.py,sha256=BAgUSxcUwChAimHWFO3D4JAHOdEy_ZrNehl-Uq0RRvM,1537
|
|
9
|
+
pyipmi/fields.py,sha256=AVgX0TB5R0_v9ZJDffKjfgtraxAGQqHJSw8LtqHOFxo,3571
|
|
10
|
+
pyipmi/fru.py,sha256=xGbWCfYeYeL3zzeblszOl2TrEtw1w1g84QR3W5MP8Vw,18347
|
|
11
|
+
pyipmi/helper.py,sha256=n0B3jeYrrz_YB6w3-0yt-ffnqQIlY3TDE82p3nftLmM,4673
|
|
12
|
+
pyipmi/hpm.py,sha256=Wp-JBsiMxPlXQST2wVgGCBs8DsKiDry5Mr4UvsmW2hw,26070
|
|
13
|
+
pyipmi/ipmitool.py,sha256=3DCOFNe49dfl60HCRKtzXrMS656Cu9MX1bHkPD2IF0I,24491
|
|
14
|
+
pyipmi/lan.py,sha256=sC-hsKohIJ-i84Tm-VKwiElalmJSr77b8ckmNgAznpo,9592
|
|
15
|
+
pyipmi/logger.py,sha256=AKzJVgn9MWUE54jQjfDNWmUccYy7r-YsGKSU_-lr2QE,1067
|
|
16
|
+
pyipmi/messaging.py,sha256=NnIBb0hBRLqeI4oYvkNX4w18nfoQWxwXy8hzndKrF7s,7421
|
|
17
|
+
pyipmi/picmg.py,sha256=YQI4hndGW0TalBjngOvbLLwkgadEvhPm-mtwGDstuJQ,19352
|
|
18
|
+
pyipmi/sdr.py,sha256=YAA1V5Had6Scvp47ZZRa_DEQzDI6_9I7kYWepsx8n-c,24121
|
|
19
|
+
pyipmi/sel.py,sha256=CVtZIBIkHKb3LaQtkVc5wakVrKQXxzxdQz3mOJ4fjos,8154
|
|
20
|
+
pyipmi/sensor.py,sha256=J8uULOg_JUhRlRQymKQxeSAnEwI92i8qPtlCMEXft8k,8528
|
|
21
|
+
pyipmi/session.py,sha256=RGVl4BtN1QXR_Rs1RUGPzN8NZPEsm2qcm-aZSSFg2_M,4175
|
|
22
|
+
pyipmi/state.py,sha256=_gKAN1P-8wjDyn7cbn5ibKdusHNBlQqushOrAb5PCBo,615
|
|
23
|
+
pyipmi/utils.py,sha256=-CVekdRcG70Wrosx4InplKGd18U6acaLbVdInw2JE1c,4862
|
|
24
|
+
pyipmi/version.py,sha256=IJKpcQb6bs8LmpRUR1RL6EeKjO3qQEgZKlf_CM2LEGQ,64
|
|
25
|
+
pyipmi/interfaces/__init__.py,sha256=T8xUc-ymnmgkdZZ-yNIJBPSf2aEme5dhbx-jFMyXaC8,1238
|
|
26
|
+
pyipmi/interfaces/aardvark.py,sha256=BwwX8BVhmCgSakeSHtSqphC3tynlU3xtP_3Ou_mYaEU,7454
|
|
27
|
+
pyipmi/interfaces/ipmb.py,sha256=RLJQtZzKJB2RQsjvWeYcVh1fhVYszGpbu_edwitOevg,8340
|
|
28
|
+
pyipmi/interfaces/ipmbdev.py,sha256=12TJfl0GesSGpH6OxuhpqGY6cEN5jl3bHtDuYkRVV3g,5364
|
|
29
|
+
pyipmi/interfaces/ipmitool.py,sha256=krqZwurwl5sRiEof5CSro_caB4U5wFchDoiCowe-_-E,11663
|
|
30
|
+
pyipmi/interfaces/mock.py,sha256=omuyNTcg7nGdgJDZvKwhE6I96G5yWw2Qgb9o_OZ3CqE,432
|
|
31
|
+
pyipmi/interfaces/rmcp.py,sha256=7yTnHypHPNDf0tWzClBhYUPwwpmSqPMtrjItqBgx6SQ,23066
|
|
32
|
+
pyipmi/msgs/__init__.py,sha256=wGyXNh3MmElwTjgi2Mi1rhFaORz1UcSoD82BJD5-U7Q,2334
|
|
33
|
+
pyipmi/msgs/bmc.py,sha256=pVpgSpX-GrKxkXQQlLAde_avuvN1O-VD7kjRAqk3PQI,8089
|
|
34
|
+
pyipmi/msgs/chassis.py,sha256=OVZSnN3_EOmChSpTzewKj6qAkUgW70GK9d-w7RPZm-A,6299
|
|
35
|
+
pyipmi/msgs/constants.py,sha256=spdEf-tXN8E8zwrgfKzwBX_blhJmynPCqFb3FnuDi10,16342
|
|
36
|
+
pyipmi/msgs/dcmi.py,sha256=avf3JC4oD_iFm3AcBX2xIvY_q2SoVeilPI0MxAGgFzE,8245
|
|
37
|
+
pyipmi/msgs/device_messaging.py,sha256=sPzEsh6zDck_leqI-4o0-V7_jQnr62wMOVGenvgnpMM,16413
|
|
38
|
+
pyipmi/msgs/event.py,sha256=Ljo7I4UZDSGwzFQYkZZ35ER9kH0Guct1zX15NRc6xxo,2148
|
|
39
|
+
pyipmi/msgs/fru.py,sha256=88FsQ6f-mNM-abtnj0rEJbLRHTxwNC5gCKdSTDkK7J0,2725
|
|
40
|
+
pyipmi/msgs/hpm.py,sha256=fUIgu9Sr6Lu_vwkKUOepUdLp18vTqo3VSn0G9I_6IkA,10432
|
|
41
|
+
pyipmi/msgs/lan.py,sha256=uUTkDTh9zkxy4GjmmRufQrJOYrGAk5bJtn0124nE0FU,2568
|
|
42
|
+
pyipmi/msgs/message.py,sha256=rzgBy-A4sFqc4lzrKeih2HmP-yAg1RrFmO3Y4HENTA4,12212
|
|
43
|
+
pyipmi/msgs/picmg.py,sha256=_t0qye3mNUlZ-0v5hCOBW0xWOAQUnmij4S-Nq1WFL2U,25955
|
|
44
|
+
pyipmi/msgs/registry.py,sha256=oAfyJzev7nMFWELPq6kwc7kScYweh86keVjhD0O4Vsg,3639
|
|
45
|
+
pyipmi/msgs/sdr.py,sha256=NJcGN5QvieDSQ5KbOFvp_ZfsonQhrM5lwEoXzf89Qnw,6623
|
|
46
|
+
pyipmi/msgs/sel.py,sha256=1KgWUgc7W46sZJbLToxdi9mFYwDESfXoEUPJbcWg_oo,5949
|
|
47
|
+
pyipmi/msgs/sensor.py,sha256=mEa9nYkqC2Zh7t7uCGmjKHDx1hMQ9nwQ9Rq1yl25U-A,10624
|
|
48
|
+
pyipmi/msgs/session.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
49
|
+
pyipmi/msgs/vita.py,sha256=qcLdPZoERdYKxAkiWprRS-MWiINFovcTUKaJNG0L62A,19870
|
|
50
|
+
python_ipmi-0.5.8.dist-info/licenses/AUTHORS,sha256=VHH-OfOeVpe3OMDYh_z0IvLpVeVw6gqyswTIQIFFmfE,82
|
|
51
|
+
python_ipmi-0.5.8.dist-info/licenses/COPYING,sha256=AKibDRiqzUEU3s95Ei24e_Nb3a8rxQ44PJyfTCYzkLI,24486
|
|
52
|
+
python_ipmi-0.5.8.dist-info/METADATA,sha256=HNScvJdNELL0BZOe8-fk_AK0GUgJWoiGA8to7qA0Wog,7120
|
|
53
|
+
python_ipmi-0.5.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
54
|
+
python_ipmi-0.5.8.dist-info/entry_points.txt,sha256=2FOtnrLsQRRQDmQbVn_jInKHMch43rHzGZpyQ-TU3PM,53
|
|
55
|
+
python_ipmi-0.5.8.dist-info/top_level.txt,sha256=ssvC5TF8PN_MCctWAT9Z8jKsKsP2ulOTm6JN_I3EoDM,7
|
|
56
|
+
python_ipmi-0.5.8.dist-info/RECORD,,
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
pyipmi/__init__.py,sha256=fKok5-j0Yc57qmnOioSB703BhoG7qpT_9ye9uDQNgKc,7779
|
|
2
|
-
pyipmi/bmc.py,sha256=or2Dh0gDquDHYPMICWmxhgpuvz54JIGLbwyut4v-3Ds,6178
|
|
3
|
-
pyipmi/chassis.py,sha256=pWxPm5Vtc6NlTNWyV2lqOR-73UUOf3hJ4pXypC_uV3k,9977
|
|
4
|
-
pyipmi/constants.py,sha256=3Opcz-XtjcxvYRCV5JCPkIYcNLkEutYwdk8XE2bHm9U,1421
|
|
5
|
-
pyipmi/dcmi.py,sha256=9hPYe7gfFqtX-VOkZ0cKG-LLVkwqOlYXS4UQLcny8zE,2359
|
|
6
|
-
pyipmi/emulation.py,sha256=bc4Pk1uOkqJjFdd-GrwJDCAT_u8jmezilJUbl_ibPWw,11363
|
|
7
|
-
pyipmi/errors.py,sha256=kQtsjnmpEnA5TkHCNwUXfl_zFr-47eXtgQ-QUq4_iYk,2654
|
|
8
|
-
pyipmi/event.py,sha256=BAgUSxcUwChAimHWFO3D4JAHOdEy_ZrNehl-Uq0RRvM,1537
|
|
9
|
-
pyipmi/fields.py,sha256=CmbJ6OCSLgFkwVLCBr4wYXNzUzApHhfeFqAe7vGJuZ4,3570
|
|
10
|
-
pyipmi/fru.py,sha256=6FzX8UNZgptpHnO-c14v4AZcU-ToPC1C5mWWeX_xgxo,16518
|
|
11
|
-
pyipmi/helper.py,sha256=UcmwJ4ATMzxvkz7u3xXjSqkYgTi0K-vSzTAyb0JuslM,4673
|
|
12
|
-
pyipmi/hpm.py,sha256=W5tlU-zlEkIuz3-UYfTWnHApOV4HHdJ0jDaDKLCkYsc,26069
|
|
13
|
-
pyipmi/ipmitool.py,sha256=S0irUDzOUUBUol0N8AAAJboFwzL_YW4bzP1QMNlvcBM,24330
|
|
14
|
-
pyipmi/lan.py,sha256=sC-hsKohIJ-i84Tm-VKwiElalmJSr77b8ckmNgAznpo,9592
|
|
15
|
-
pyipmi/logger.py,sha256=AKzJVgn9MWUE54jQjfDNWmUccYy7r-YsGKSU_-lr2QE,1067
|
|
16
|
-
pyipmi/messaging.py,sha256=t2pcH0HDPaMu3lMgthKNrRdXMS52q0P_B2grPziyNhM,7404
|
|
17
|
-
pyipmi/picmg.py,sha256=YQI4hndGW0TalBjngOvbLLwkgadEvhPm-mtwGDstuJQ,19352
|
|
18
|
-
pyipmi/sdr.py,sha256=YAA1V5Had6Scvp47ZZRa_DEQzDI6_9I7kYWepsx8n-c,24121
|
|
19
|
-
pyipmi/sel.py,sha256=CVtZIBIkHKb3LaQtkVc5wakVrKQXxzxdQz3mOJ4fjos,8154
|
|
20
|
-
pyipmi/sensor.py,sha256=J8uULOg_JUhRlRQymKQxeSAnEwI92i8qPtlCMEXft8k,8528
|
|
21
|
-
pyipmi/session.py,sha256=RGVl4BtN1QXR_Rs1RUGPzN8NZPEsm2qcm-aZSSFg2_M,4175
|
|
22
|
-
pyipmi/state.py,sha256=_gKAN1P-8wjDyn7cbn5ibKdusHNBlQqushOrAb5PCBo,615
|
|
23
|
-
pyipmi/utils.py,sha256=-CVekdRcG70Wrosx4InplKGd18U6acaLbVdInw2JE1c,4862
|
|
24
|
-
pyipmi/version.py,sha256=YmCwXMhmfj68EZx9jcxGphvl079mMItVt-sflF5hjTY,64
|
|
25
|
-
pyipmi/interfaces/__init__.py,sha256=T8xUc-ymnmgkdZZ-yNIJBPSf2aEme5dhbx-jFMyXaC8,1238
|
|
26
|
-
pyipmi/interfaces/aardvark.py,sha256=gReGcWjhgtEhpYw61UExtNZ52b-uI2ONkT_TeGLspMI,7266
|
|
27
|
-
pyipmi/interfaces/ipmb.py,sha256=kKFbaAIy8MoSiKaIUOCwhXPD1QRfkwIpnEL8sXDHSyg,7800
|
|
28
|
-
pyipmi/interfaces/ipmbdev.py,sha256=uBVKGloOUDig6nK2V8Gi6tJJimzGFo30CtP2RLV7gQU,5346
|
|
29
|
-
pyipmi/interfaces/ipmitool.py,sha256=oN9_N1jh7ts77Kc2AqTEYmmmLSBS5h97ZaSQPmPpC8g,10539
|
|
30
|
-
pyipmi/interfaces/mock.py,sha256=5IPQd7VlWVTFvvhppCs7SPiDkJAmAjG6v0RXeXjTEFs,363
|
|
31
|
-
pyipmi/interfaces/rmcp.py,sha256=fxYeR4U03uz5Df98kzyPRmLIRp0c8CAWnpEFbwdmIHA,22587
|
|
32
|
-
pyipmi/msgs/__init__.py,sha256=wGyXNh3MmElwTjgi2Mi1rhFaORz1UcSoD82BJD5-U7Q,2334
|
|
33
|
-
pyipmi/msgs/bmc.py,sha256=6uBIScBm7gMKHHsq5qNcgf_ZkTaVlCG8dTf1sSdyyE0,8105
|
|
34
|
-
pyipmi/msgs/chassis.py,sha256=UcxGNkfiwbe_2JVNpi3pHwHcP4uev9X6vuHzvDhsDTY,6338
|
|
35
|
-
pyipmi/msgs/constants.py,sha256=spdEf-tXN8E8zwrgfKzwBX_blhJmynPCqFb3FnuDi10,16342
|
|
36
|
-
pyipmi/msgs/dcmi.py,sha256=M6OWg0NFibToibn4j4Gv08Dvuc7lwMQZ7LoxpJgNr7g,8285
|
|
37
|
-
pyipmi/msgs/device_messaging.py,sha256=sPzEsh6zDck_leqI-4o0-V7_jQnr62wMOVGenvgnpMM,16413
|
|
38
|
-
pyipmi/msgs/event.py,sha256=tGja_XhFeXhefQ5QTWFxj8VeSbMly6y_rICf7eVdpIo,2187
|
|
39
|
-
pyipmi/msgs/fru.py,sha256=0H-EztVb-tJwdWoxCTOpqlyIeAWQvdf_vYc5UGwNSpI,2764
|
|
40
|
-
pyipmi/msgs/hpm.py,sha256=BiO2LwkuWflhEuI2na6ncgxBaKXZ8PpTArLEaA5BWWc,10471
|
|
41
|
-
pyipmi/msgs/lan.py,sha256=hC-uX5h9yD2qI_Nk76NRkldK4X9nYM-TRiLOrU4ndq4,2607
|
|
42
|
-
pyipmi/msgs/message.py,sha256=xWk7073-kgwDl0n9JgFsKuJ3zE3REsvCkEkHOUcbhNk,12252
|
|
43
|
-
pyipmi/msgs/picmg.py,sha256=oZIlKDdq1r0qBl-dliAsRTiLRJOwZXNQVpsW3aWnjaE,25995
|
|
44
|
-
pyipmi/msgs/registry.py,sha256=oifolLJgg0DQwpCte2CbNM7Ua4XGABzGiWYJIFfgijQ,3640
|
|
45
|
-
pyipmi/msgs/sdr.py,sha256=JZ-p5-BbjDg4R2YpwdTz11arQcRMyAvOGg0VuSq6jn8,6662
|
|
46
|
-
pyipmi/msgs/sel.py,sha256=ON5YRoI9-WVMT09IqduK0AR28-rPcXOSzSWS3rcYBzw,5988
|
|
47
|
-
pyipmi/msgs/sensor.py,sha256=nP1JohRg5jSz23SFoOMQONojROodOSRCuaDR8tpCxjI,10663
|
|
48
|
-
pyipmi/msgs/session.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
49
|
-
pyipmi/msgs/vita.py,sha256=7NgFaB1Gy2vlerzM4pzZtpEs5Tc4T0_1EZqu2_K2fMw,19910
|
|
50
|
-
python_ipmi-0.5.5.dist-info/AUTHORS,sha256=VHH-OfOeVpe3OMDYh_z0IvLpVeVw6gqyswTIQIFFmfE,82
|
|
51
|
-
python_ipmi-0.5.5.dist-info/COPYING,sha256=AKibDRiqzUEU3s95Ei24e_Nb3a8rxQ44PJyfTCYzkLI,24486
|
|
52
|
-
python_ipmi-0.5.5.dist-info/METADATA,sha256=MrYP4DtPchuUNo-dA9R3DNMf2r2Pg9MyvcbGNdOAeW8,6801
|
|
53
|
-
python_ipmi-0.5.5.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
54
|
-
python_ipmi-0.5.5.dist-info/entry_points.txt,sha256=2FOtnrLsQRRQDmQbVn_jInKHMch43rHzGZpyQ-TU3PM,53
|
|
55
|
-
python_ipmi-0.5.5.dist-info/top_level.txt,sha256=ssvC5TF8PN_MCctWAT9Z8jKsKsP2ulOTm6JN_I3EoDM,7
|
|
56
|
-
python_ipmi-0.5.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|