pyghmi 1.5.72__py3-none-any.whl → 1.5.76__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.
@@ -1,14 +1,129 @@
1
+ # Copyright 2025 Lenovo Corporation
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ import copy
15
+ import json
16
+ import pyghmi.constants as pygconst
1
17
  import pyghmi.redfish.oem.generic as generic
2
18
  import pyghmi.exceptions as pygexc
19
+ import pyghmi.util.webclient as webclient
20
+ import zipfile
21
+ import time
22
+ import os.path
3
23
 
4
24
 
25
+ class SensorReading(object):
26
+ def __init__(self, healthinfo, sensor=None, value=None, units=None,
27
+ unavailable=False):
28
+ if sensor:
29
+ self.name = sensor['name']
30
+ else:
31
+ self.name = healthinfo['name']
32
+ self.health = healthinfo['health']
33
+ self.states = healthinfo['states']
34
+ self.state_ids = healthinfo.get('state_ids', None)
35
+ self.value = value
36
+ self.imprecision = None
37
+ self.units = units
38
+ self.unavailable = unavailable
39
+
5
40
  class OEMHandler(generic.OEMHandler):
6
41
 
7
- def get_description(self, fishclient):
8
- bmcstgs = fishclient._do_web_request('/redfish/v1/Managers/1/Oem/Lenovo/BMCSettings')
9
- heightu = bmcstgs.get('Attributes', {}).get('ServerConfigHeightU')
10
- return {'height': heightu}
42
+ def supports_expand(self, url):
43
+ return True
44
+
45
+ def get_diagnostic_data(self, savefile, progress=None, autosuffix=False):
46
+ tsk = self._do_web_request(
47
+ '/redfish/v1/Systems/1/LogServices/DiagnosticLog/Actions/LogService.CollectDiagnosticData',
48
+ {"DiagnosticDataType": "Manager", "SelectDataTypes": []})
49
+ taskrunning = True
50
+ taskurl = tsk.get('TaskMonitor', None)
51
+ pct = 0 if taskurl else 100
52
+ durl = None
53
+ while pct < 100 and taskrunning:
54
+ status = self._do_web_request(taskurl)
55
+ durl = status.get('AdditionalDataURI', '')
56
+ pct = status.get('PercentComplete', 0)
57
+ taskrunning = status.get('TaskState', 'Complete') == 'Running'
58
+ if progress:
59
+ progress({'phase': 'initializing', 'progress': float(pct)})
60
+ if taskrunning:
61
+ time.sleep(3)
62
+ if not durl:
63
+ raise Exception("Failed getting service data url")
64
+ fname = os.path.basename(durl)
65
+ if autosuffix and not savefile.endswith('.tar.zst'):
66
+ savefile += '-{0}'.format(fname)
67
+ fd = webclient.FileDownloader(self.webclient, durl, savefile)
68
+ fd.start()
69
+ while fd.isAlive():
70
+ fd.join(1)
71
+ if progress and self.webclient.get_download_progress():
72
+ progress({'phase': 'download',
73
+ 'progress': 100 * self.webclient.get_download_progress()})
74
+ if fd.exc:
75
+ raise fd.exc
76
+ if progress:
77
+ progress({'phase': 'complete'})
78
+ return savefile
11
79
 
80
+ def get_system_power_watts(self, fishclient):
81
+ powerinfo = fishclient._do_web_request('/redfish/v1/Chassis/1/Sensors/power_Sys_Power')
82
+ return powerinfo['Reading']
83
+
84
+ def get_health(self, fishclient, verbose=True):
85
+ rsp = self._do_web_request('/api/providers/imm_active_events')
86
+ summary = {'badreadings': [], 'health': pygconst.Health.Ok}
87
+ fallbackdata = []
88
+ hmap = {
89
+ 0 : pygconst.Health.Ok,
90
+ 3: pygconst.Health.Critical,
91
+ 2: pygconst.Health.Warning,
92
+ }
93
+ infoevents = False
94
+ existingevts = set([])
95
+ for item in rsp.get('items', ()):
96
+ # while usually the ipmi interrogation shall explain things,
97
+ # just in case there is a gap, make sure at least the
98
+ # health field is accurately updated
99
+ itemseverity = hmap.get(item.get('Severity', 2),
100
+ pygconst.Health.Critical)
101
+ if itemseverity == pygconst.Health.Ok:
102
+ infoevents = True
103
+ continue
104
+ if (summary['health'] < itemseverity):
105
+ summary['health'] = itemseverity
106
+ evtsrc = item.get('Oem', {}).get('Lenovo', {}).get('Source', '')
107
+ currevt = '{}:{}'.format(evtsrc, item['Message'])
108
+ if currevt in existingevts:
109
+ continue
110
+ existingevts.add(currevt)
111
+ fallbackdata.append(SensorReading({
112
+ 'name': evtsrc,
113
+ 'states': [item['Message']],
114
+ 'health': itemseverity,
115
+ 'type': evtsrc,
116
+ }, ''))
117
+ summary['badreadings'] = fallbackdata
118
+ return summary
119
+
120
+ def _get_cpu_temps(self, fishclient):
121
+ cputemps = []
122
+ for reading in super()._get_cpu_temps(fishclient):
123
+ if 'Margin' in reading['Name']:
124
+ continue
125
+ cputemps.append(reading)
126
+ return cputemps
12
127
 
13
128
  def get_system_configuration(self, hideadvanced=True, fishclient=None):
14
129
  stgs = self._getsyscfg(fishclient)[0]
@@ -25,7 +140,7 @@ class OEMHandler(generic.OEMHandler):
25
140
  bmchangeset[stg.replace('BMC.', '')] = changeset[stg]
26
141
  del changeset[stg]
27
142
  if stg.startswith('UEFI.'):
28
- changeset[stg.replace('UEFI.' '')] = changeset[stg]
143
+ changeset[stg.replace('UEFI.', '')] = changeset[stg]
29
144
  del changeset[stg]
30
145
  if stg.startswith('VPD.'):
31
146
  vpdchangeset[stg.replace('VPD.', '')] = changeset[stg]
@@ -57,6 +172,159 @@ class OEMHandler(generic.OEMHandler):
57
172
  fishclient._do_web_request('/redfish/v1/Managers/1/Oem/Lenovo/BMCSettings', cache=False)
58
173
  return ret
59
174
 
175
+ oemacctmap = {
176
+ 'password_reuse_count': 'MinimumPasswordReuseCycle',
177
+ 'password_change_interval': 'MinimumPasswordChangeIntervalHours',
178
+ 'password_expiration': 'PasswordExpirationPeriodDays',
179
+ 'password_complexity': 'ComplexPassword',
180
+ }
181
+
182
+ acctmap = {
183
+ 'password_login_failures': 'AccountLockoutThreshold',
184
+ 'password_min_length': 'MinPasswordLength',
185
+ 'password_lockout_period': 'AccountLockoutDuration',
186
+ }
187
+
188
+ def update_firmware(self, filename, data=None, progress=None, bank=None, otherfields=()):
189
+ if not otherfields and bank == 'backup':
190
+ uxzcount = 0
191
+ otherfields = {'UpdateParameters': {"Targets": ["/redfish/v1/UpdateService/FirmwareInventory/BMC-Backup"]}}
192
+ needseek = False
193
+ if data and hasattr(data, 'read'):
194
+ if zipfile.is_zipfile(data):
195
+ needseek = True
196
+ z = zipfile.ZipFile(data)
197
+ else:
198
+ data.seek(0)
199
+ elif data is None and zipfile.is_zipfile(filename):
200
+ z = zipfile.ZipFile(filename)
201
+ if z:
202
+ for tmpname in z.namelist():
203
+ if tmpname.startswith('payloads/'):
204
+ uxzcount += 1
205
+ if tmpname.endswith('.uxz'):
206
+ wrappedfilename = tmpname
207
+ if uxzcount == 1 and wrappedfilename:
208
+ filename = os.path.basename(wrappedfilename)
209
+ data = z.open(wrappedfilename)
210
+ elif needseek:
211
+ data.seek(0)
212
+ super().update_firmware(filename, data=data, progress=progress, bank=bank, otherfields=otherfields)
213
+
214
+ def get_bmc_configuration(self):
215
+ settings = {}
216
+ acctsrv = self._do_web_request('/redfish/v1/AccountService')
217
+ for oemstg in self.oemacctmap:
218
+ settings[oemstg] = {
219
+ 'value': acctsrv['Oem']['Lenovo'][self.oemacctmap[oemstg]]}
220
+ for stg in self.acctmap:
221
+ settings[stg] = {
222
+ 'value': acctsrv[self.acctmap[stg]]}
223
+ bmcstgs = self._do_web_request('/redfish/v1/Managers/1/Oem/Lenovo/BMCSettings')
224
+ bmcattrs = bmcstgs['Attributes']
225
+ self.ethoverusb = True if 'EthOverUSBEnabled' in bmcattrs else False
226
+ usbcfg = bmcattrs.get('NetMgrUsb0Enabled', bmcattrs.get('EthOverUSBEnabled', 'False'))
227
+ usbeth = 'Enable' if usbcfg == 'True' else 'Disable'
228
+ settings['usb_ethernet'] = {
229
+ 'value': usbeth
230
+ }
231
+ usbcfg = bmcattrs.get('NetMgrUsb0PortForwardingEnabled', bmcattrs.get('EthOverUSBPortForwardingEnabled', 'False'))
232
+ fwd = 'Enable' if usbcfg == 'True' else 'Disable'
233
+ settings['usb_ethernet_port_forwarding'] = fwd
234
+ mappings = []
235
+ for idx in range(1, 11):
236
+ keyname = 'NetMgrUsb0PortForwardingPortMapping.{}'.format(idx)
237
+ keyaltname = 'EthOverUSBPortForwardingPortMapping_{}'.format(idx)
238
+ currval = bmcattrs.get(keyname, bmcattrs.get(keyaltname, '0,0'))
239
+ if currval == '0,0':
240
+ continue
241
+ src, dst = currval.split(',')
242
+ mappings.append('{}:{}'.format(src,dst))
243
+ settings['usb_forwarded_ports'] = {'value': ','.join(mappings)}
244
+ return settings
245
+
246
+ def set_bmc_configuration(self, changeset):
247
+ acctattribs = {}
248
+ usbsettings = {}
249
+ for key in changeset:
250
+ if isinstance(changeset[key], str):
251
+ changeset[key] = {'value': changeset[key]}
252
+ currval = changeset[key].get('value', None)
253
+ if key == 'password_complexity':
254
+ if currval.lower() in ("false", 0):
255
+ currval = False
256
+ elif currval.lower() in ('true', 1):
257
+ currval = True
258
+ elif key.lower().startswith('usb_'):
259
+ if 'forwarded_ports' not in key.lower():
260
+ currval = currval.lower()
261
+ if currval and 'disabled'.startswith(currval):
262
+ currval = 'False'
263
+ elif currval and 'enabled'.startswith(currval):
264
+ currval = 'True'
265
+ else:
266
+ currval = int(currval)
267
+ if key.lower() in self.oemacctmap:
268
+ if 'Oem' not in acctattribs:
269
+ acctattribs['Oem'] = {'Lenovo': {}}
270
+ acctattribs['Oem']['Lenovo'][
271
+ self.oemacctmap[key.lower()]] = currval
272
+ if key.lower() == 'password_expiration':
273
+ warntime = str(int(int(currval) * 0.08))
274
+ acctattribs['Oem']['Lenovo'][
275
+ 'PasswordExpirationWarningPeriod'] = warntime
276
+ elif key.lower() in self.acctmap:
277
+ acctattribs[self.acctmap[key.lower()]] = currval
278
+ elif key.lower() in (
279
+ 'usb_ethernet', 'usb_ethernet_port_forwarding',
280
+ 'usb_forwarded_ports'):
281
+ usbsettings[key] = currval
282
+ else:
283
+ raise pygexc.InvalidParameterValue(
284
+ '{0} not a known setting'.format(key))
285
+ if acctattribs:
286
+ self._do_web_request(
287
+ '/redfish/v1/AccountService', acctattribs, method='PATCH')
288
+ self._do_web_request('/redfish/v1/AccountService', cache=False)
289
+ if usbsettings:
290
+ self.apply_usb_configuration(usbsettings)
291
+
292
+ def apply_usb_configuration(self, usbsettings):
293
+ bmcattribs = {}
294
+ if not hasattr(self, 'ethoverusb'):
295
+ self.get_bmc_configuration()
296
+
297
+ if 'usb_forwarded_ports' in usbsettings:
298
+ pairs = usbsettings['usb_forwarded_ports'].split(',')
299
+ idx = 1
300
+ for pair in pairs:
301
+ if self.ethoverusb:
302
+ keyname = 'EthOverUSBPortForwardingPortMapping_{}'.format(idx)
303
+ else:
304
+ keyname = 'NetMgrUsb0PortForwardingPortMapping.{}'.format(idx)
305
+ pair = pair.replace(':', ',')
306
+ bmcattribs[keyname] = pair
307
+ idx += 1
308
+ while idx < 11:
309
+ if self.ethoverusb:
310
+ keyname = 'EthOverUSBPortForwardingPortMapping_{}'.format(idx)
311
+ else:
312
+ keyname = 'NetMgrUsb0PortForwardingPortMapping.{}'.format(idx)
313
+ bmcattribs[keyname] = '0,0'
314
+ idx += 1
315
+ if 'usb_ethernet' in usbsettings:
316
+ keyname = 'EthOverUSBEnabled' if self.ethoverusb else 'NetMgrUsb0Enabled'
317
+ bmcattribs[keyname] = usbsettings['usb_ethernet']
318
+ if 'usb_ethernet_port_forwarding' in usbsettings:
319
+ keyname = 'EthOverUSBPortForwardingEnabled' if self.ethoverusb else 'NetMgrUsb0PortForwardingEnabled'
320
+ bmcattribs[keyname] = usbsettings[
321
+ 'usb_ethernet_port_forwarding']
322
+ self._do_web_request(
323
+ '/redfish/v1/Managers/1/Oem/Lenovo/BMCSettings',
324
+ {'Attributes': bmcattribs}, method='PATCH')
325
+ self._do_web_request(
326
+ '/redfish/v1/Managers/1/Oem/Lenovo/BMCSettings', cache=False)
327
+
60
328
  def get_extended_bmc_configuration(self, fishclient, hideadvanced=True):
61
329
  cfgin = self._get_lnv_bmcstgs(fishclient)[0]
62
330
  cfgout = {}
@@ -99,17 +367,60 @@ class OEMHandler(generic.OEMHandler):
99
367
  currsettings[setting] = val
100
368
  return currsettings, reginfo
101
369
 
370
+ def get_description(self, fishclient):
371
+ rsp = self._get_expanded_data('/redfish/v1/Chassis')
372
+ for chassis in rsp['Members']:
373
+ if (chassis['@odata.id'] == '/redfish/v1/Chassis/1'
374
+ and chassis['ChassisType'] != 'Blade'):
375
+ hmm = chassis.get('HeightMm', None)
376
+ if hmm:
377
+ return {'height': hmm/44.45}
378
+ if (chassis['@odata.id'] == '/redfish/v1/Chassis/Enclosure'
379
+ and chassis.get('ChassisType', None) == 'Enclosure'):
380
+ try:
381
+ slot = chassis['Location']['PartLocation']['LocationOrdinalValue']
382
+ slotnum = (2 * (slot >> 4) - 1) + ((slot & 15) % 10)
383
+ slotcoord = [slot >> 4, (slot & 15) - 9]
384
+ return {'slot': slotnum, 'slotlabel': '{:02x}'.format(slot), 'slotcoord': slotcoord}
385
+ except KeyError:
386
+ continue
387
+ return {}
388
+
389
+ def upload_media(self, filename, progress=None, data=None):
390
+ wc = self.webclient
391
+ uploadthread = webclient.FileUploader(
392
+ wc, '/rdoc_upload', filename, data,
393
+ formname='file',
394
+ formwrap=True)
395
+ uploadthread.start()
396
+ while uploadthread.isAlive():
397
+ uploadthread.join(3)
398
+ if progress:
399
+ progress({'phase': 'upload',
400
+ 'progress': 100 * wc.get_upload_progress()})
401
+ rsp = json.loads(uploadthread.rsp)
402
+ if rsp['return'] != 0:
403
+ raise Exception('Issue uploading file')
404
+ remfilename = rsp['upload_filename']
405
+ if progress:
406
+ progress({'phase': 'upload',
407
+ 'progress': 100.0})
408
+ self._do_web_request(
409
+ '/redfish/v1/Systems/1/VirtualMedia/RDOC1',
410
+ {'Image':'file:///gpx/rdocupload/' + remfilename,
411
+ 'WriteProtected': False}, method='PATCH')
412
+ if progress:
413
+ progress({'phase': 'complete'})
414
+
102
415
  def get_firmware_inventory(self, components, fishclient):
103
- fwlist = fishclient._do_web_request(fishclient._fwinventory)
104
- rawfwurls = [x['@odata.id'] for x in fwlist.get('Members', [])]
105
- fwurls = []
106
- for fwurl in rawfwurls:
416
+ fwlist = fishclient._do_web_request(fishclient._fwinventory + '?$expand=.')
417
+ fwlist = copy.deepcopy(fwlist.get('Members', []))
418
+ self._fwnamemap = {}
419
+ for redres in fwlist:
420
+ fwurl = redres['@odata.id']
421
+ res = (redres, fwurl)
107
422
  if fwurl.startswith('/redfish/v1/UpdateService/FirmwareInventory/Bundle.'):
108
423
  continue # skip Bundle information for now
109
- fwurls.append(fwurl)
110
- self._fwnamemap = {}
111
- for res in fishclient._do_bulk_requests(fwurls):
112
- redres = res[0]
113
424
  if redres.get('Name', '').startswith('Firmware:'):
114
425
  redres['Name'] = redres['Name'].replace('Firmware:', '')
115
426
  if redres['Name'].startswith('Firmware-PSoC') and 'Drive_Backplane' in redres["@odata.id"]:
pyghmi/util/webclient.py CHANGED
@@ -97,8 +97,9 @@ class FileDownloader(threading.Thread):
97
97
 
98
98
 
99
99
  def get_upload_form(filename, data, formname, otherfields):
100
+ ffilename = filename.split('/')[-1]
100
101
  if not formname:
101
- formname = filename
102
+ formname = ffilename
102
103
  try:
103
104
  return uploadforms[filename]
104
105
  except KeyError:
@@ -106,16 +107,22 @@ def get_upload_form(filename, data, formname, otherfields):
106
107
  data = data.read()
107
108
  except AttributeError:
108
109
  pass
109
- form = (b'--' + BND
110
+ form = b''
111
+ for ofield in otherfields:
112
+ tfield = otherfields[ofield]
113
+ xtra=''
114
+ if isinstance(tfield, dict):
115
+ tfield = json.dumps(tfield)
116
+ xtra = '\r\nContent-Type: application/json'
117
+ form += (b'--' + BND
118
+ + '\r\nContent-Disposition: form-data; '
119
+ 'name="{0}"{1}\r\n\r\n{2}\r\n'.format(
120
+ ofield, xtra, tfield).encode('utf-8'))
121
+ form += (b'--' + BND
110
122
  + '\r\nContent-Disposition: form-data; '
111
123
  'name="{0}"; filename="{1}"\r\n'.format(
112
- formname, filename).encode('utf-8'))
124
+ formname, ffilename).encode('utf-8'))
113
125
  form += b'Content-Type: application/octet-stream\r\n\r\n' + data
114
- for ofield in otherfields:
115
- form += (b'\r\n--' + BND
116
- + '\r\nContent-Disposition: form-data; '
117
- 'name="{0}"\r\n\r\n{1}'.format(
118
- ofield, otherfields[ofield]).encode('utf-8'))
119
126
  form += b'\r\n--' + BND + b'--\r\n'
120
127
  uploadforms[filename] = form
121
128
  return form
@@ -272,6 +279,22 @@ class SecureHTTPConnection(httplib.HTTPConnection, object):
272
279
  return json.loads(body) if body else {}, rsp.status
273
280
  return body, rsp.status
274
281
 
282
+ def grab_rsp(self, url, data=None, referer=None, headers=None, method=None):
283
+ webclient = self.dupe()
284
+ if isinstance(data, dict):
285
+ data = json.dumps(data)
286
+ if data:
287
+ if not method:
288
+ method = 'POST'
289
+ webclient.request(method, url, data, referer=referer,
290
+ headers=headers)
291
+ else:
292
+ if not method:
293
+ method = 'GET'
294
+ webclient.request(method, url, referer=referer, headers=headers)
295
+ rsp = webclient.getresponse()
296
+ return rsp
297
+
275
298
  def download(self, url, file):
276
299
  """Download a file to filename or file object
277
300
 
@@ -390,3 +413,4 @@ class SecureHTTPConnection(httplib.HTTPConnection, object):
390
413
  except httplib.CannotSendRequest:
391
414
  self.broken = True
392
415
  raise
416
+
@@ -1,12 +1,11 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyghmi
3
- Version: 1.5.72
3
+ Version: 1.5.76
4
4
  Summary: Python General Hardware Management Initiative (IPMI and others)
5
5
  Home-page: http://github.com/openstack/pyghmi/
6
6
  Author: Jarrod Johnson
7
7
  Author-email: jjohnson2@lenovo.com
8
8
  License: Apache License, Version 2.0
9
- Platform: UNKNOWN
10
9
  Classifier: Intended Audience :: Information Technology
11
10
  Classifier: Intended Audience :: System Administrators
12
11
  Classifier: License :: OSI Approved :: Apache Software License
@@ -18,14 +17,14 @@ Classifier: Programming Language :: Python :: 3
18
17
  Classifier: Programming Language :: Python :: 3.6
19
18
  Classifier: Programming Language :: Python :: 3.7
20
19
  Classifier: Programming Language :: Python :: 3.8
21
- Requires-Dist: cryptography (>=2.1)
22
- Requires-Dist: python-dateutil (>=2.8.1)
23
- Requires-Dist: six (>=1.10.0)
20
+ License-File: LICENSE
21
+ License-File: AUTHORS
22
+ Requires-Dist: cryptography >=2.1
23
+ Requires-Dist: python-dateutil >=2.8.1
24
+ Requires-Dist: six >=1.10.0
24
25
 
25
26
  This is a pure python implementation of IPMI protocol.
26
27
 
27
28
  pyghmicons and pyghmiutil are example scripts to show how one may incorporate
28
29
  this library into python code
29
30
 
30
-
31
-
@@ -11,13 +11,13 @@ pyghmi/cmd/pyghmiutil.py,sha256=hir7FFvwKDNxYGpOPCgIVSgHP4UsVKFIbVBgBWqkBxA,2917
11
11
  pyghmi/cmd/virshbmc.py,sha256=rNbRJrVnx5BmQQLVRV8JK3lW9YWUcP7Z8hCWfpfVLCM,5149
12
12
  pyghmi/ipmi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  pyghmi/ipmi/bmc.py,sha256=LJBF90msq8xFcZSUe3s3jVcW02Ib-0Fc5zWvQNtGmcQ,7283
14
- pyghmi/ipmi/command.py,sha256=DkqKeuicNL02JY2pQzZJwJLRvgH3Uakr5DKm0ElPFkY,90345
14
+ pyghmi/ipmi/command.py,sha256=qfoo_s2zosV7prL7IpuAaFwlBRM6ormXnPWqFj1LFoA,90521
15
15
  pyghmi/ipmi/console.py,sha256=Jle7uJI3ZQS6cMwbEisFEvXjmu5MVqMs17BcAlygR_4,23369
16
16
  pyghmi/ipmi/events.py,sha256=zgUidJIARHomwxasgeYAzDO1AEMfEOzb6XVxzry22Us,22569
17
17
  pyghmi/ipmi/fru.py,sha256=sw5ZBMrEVSBDgOUPVU_ksehQMJvrl2v-r7rVyA9xoiE,14430
18
18
  pyghmi/ipmi/sdr.py,sha256=U4NH-ca1zwEmU_dKT2wvXY2vEvXh33dV9rIUlmf_5Xw,32999
19
19
  pyghmi/ipmi/oem/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
- pyghmi/ipmi/oem/generic.py,sha256=HQ-9qTYIBpZqB1K75jTOTSUsirrKAQcI8BhLx0eAJ1g,18518
20
+ pyghmi/ipmi/oem/generic.py,sha256=-5mIxczwkvOdRy2NSPbSgPerQ5AMez-KhC8AkOrwkL0,18614
21
21
  pyghmi/ipmi/oem/lookup.py,sha256=Ex00OEEolsdWCVhyP0QDGzOxHGEA7sKI8a8fW4kJPD8,3653
22
22
  pyghmi/ipmi/oem/lenovo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  pyghmi/ipmi/oem/lenovo/config.py,sha256=jSA8_NACwzouLpAhsu591QQFaBYPEU7NHvhpEddLQpg,26105
@@ -26,8 +26,8 @@ pyghmi/ipmi/oem/lenovo/dimm.py,sha256=L8k1aBgtvxqyubDBNKdDkz80pDE8Sck1eMLcMz1GhF
26
26
  pyghmi/ipmi/oem/lenovo/drive.py,sha256=MmVgaosEwJXcwi1kKYGnY-dbrx4Zp55941qWMvprUMA,2055
27
27
  pyghmi/ipmi/oem/lenovo/energy.py,sha256=THttIqlwpnj7ljbBWTHjelDLmDaQiCuMvNqJy9Ec7j8,6355
28
28
  pyghmi/ipmi/oem/lenovo/firmware.py,sha256=KS9uUBjFUzvdMw_e-kpr5sYIvFUaeg0yqyo69T94IVc,3747
29
- pyghmi/ipmi/oem/lenovo/handler.py,sha256=8OBkpxpPiwRFnBBCbs7RI4HtrdPT9k-cpZTEbAuuiG4,56536
30
- pyghmi/ipmi/oem/lenovo/imm.py,sha256=2LFdzkTvgn4VaaXTHVazv6TTAosEAyIs77FMB6_fIBI,111202
29
+ pyghmi/ipmi/oem/lenovo/handler.py,sha256=Y2c_IZph1VE5rP8d2fZASQulDtxL_yGv7bvJNtDxwL8,56632
30
+ pyghmi/ipmi/oem/lenovo/imm.py,sha256=Yfrafthw1HU7Blw4JWnkryc2AEeUAoVok06A53hKvZc,111538
31
31
  pyghmi/ipmi/oem/lenovo/inventory.py,sha256=FLJJinw-ibdHtf3KmrTzhWXbQrpxq3TSycVf96Hg7cw,5911
32
32
  pyghmi/ipmi/oem/lenovo/nextscale.py,sha256=ojLh17M87GnKUl-3yCTJcIJca1mpcrhlc7rQmhpby3A,43407
33
33
  pyghmi/ipmi/oem/lenovo/pci.py,sha256=S7p-5Q2qu2YhlffN-LEmIvjfXim6OlfYL7Q6r6VZqJ4,2020
@@ -43,18 +43,19 @@ pyghmi/ipmi/private/simplesession.py,sha256=cNGaoT0uWIKDut6gUG9kAOX_b_qTzdB26R6I
43
43
  pyghmi/ipmi/private/spd.py,sha256=oEPSXm19X2eNXDiyW_6fVjBFqhuuMAtBI9quRJgclH4,27094
44
44
  pyghmi/ipmi/private/util.py,sha256=ayYodiSydlrrt0_pQppoRB1T6n-KNOiHZSfAlCMcpG0,3847
45
45
  pyghmi/redfish/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
46
- pyghmi/redfish/command.py,sha256=SEiaw74uQQTzGrRkWFRKRcGnVpHXd2Kvgch4Ty_7oks,57340
46
+ pyghmi/redfish/command.py,sha256=Rn2oooBAvnsGM46pS9TM7WVjDXGwrwlZY9mZqzC-97I,60741
47
47
  pyghmi/redfish/oem/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
- pyghmi/redfish/oem/generic.py,sha256=lOj8FgJOMC5rLj4IHM0Bfls4NkRNVFHrGw__FHjFjEc,46367
48
+ pyghmi/redfish/oem/generic.py,sha256=dwad7SwV4zYka0oKrSIBfjXu3KyFbOidVGXAW08tfAE,55691
49
49
  pyghmi/redfish/oem/lookup.py,sha256=pfJW5xSkUY61OirMeYy0b1SbjBFz6IDfN5ZOYog_Yq4,1530
50
50
  pyghmi/redfish/oem/dell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
51
  pyghmi/redfish/oem/dell/idrac.py,sha256=pNnmqdV1sOP3ABw0xq0wF1QEO2L8onT7Osc_-sDO8EU,2146
52
52
  pyghmi/redfish/oem/dell/main.py,sha256=g8773SShUpbYxXB9zVx2pD5z1xP04wB_sXAxcAs6_xY,793
53
53
  pyghmi/redfish/oem/lenovo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
- pyghmi/redfish/oem/lenovo/main.py,sha256=-50u7hTT8urunKTOult2MNMAqLU09sOv_cJZsViwGcU,2249
54
+ pyghmi/redfish/oem/lenovo/main.py,sha256=bnx8LuC_C4_OluNR8JSHIxtSlM4_jdBb4cUzJM6mazE,2597
55
+ pyghmi/redfish/oem/lenovo/smm3.py,sha256=FWNCR6eSK6a9ZgZ5G-HyAllYkUD5hZeO7oOVKNNslEE,3152
55
56
  pyghmi/redfish/oem/lenovo/tsma.py,sha256=puSj0fO5Dt5VpDoEMVTRY95CP9q18eXcAqq7TDK350E,34633
56
- pyghmi/redfish/oem/lenovo/xcc.py,sha256=wsAo-69qSV1eamFLBDx-dS3dn67V05xUrWfK7r8f0_g,82705
57
- pyghmi/redfish/oem/lenovo/xcc3.py,sha256=p0tDMXVm4Z7oheindI0RInth8xvCLBt8CqwS42T1cMQ,5843
57
+ pyghmi/redfish/oem/lenovo/xcc.py,sha256=DG0GVEl_n-k77p_CFzUISLQ3AlTgppc9_yPwPy20Q4o,82735
58
+ pyghmi/redfish/oem/lenovo/xcc3.py,sha256=NYL_6akVaS5sYL6f3beHSZjWeRGlDTbAkzYojDK_G6I,19516
58
59
  pyghmi/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
60
  pyghmi/tests/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
61
  pyghmi/tests/unit/base.py,sha256=xWImA7zPRgfrEe2xAdRZ6w_dLwExGRBJ5CBybssUQGg,744
@@ -62,12 +63,12 @@ pyghmi/tests/unit/ipmi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
62
63
  pyghmi/tests/unit/ipmi/test_sdr.py,sha256=vb3iLY0cnHJ2K_m4xgYUjEcbPd_ZYhYx-uBowByplXw,824
63
64
  pyghmi/util/__init__.py,sha256=GZLBWJiun2Plb_VE9dDSh4_PQMCha3gA7QLUqx3oSYI,25
64
65
  pyghmi/util/parse.py,sha256=6VlyBCEcE8gy8PJWmEDdtCyWATaKwPaTswCdioPCWOE,2120
65
- pyghmi/util/webclient.py,sha256=jV091_s-HWNDVMKfMxB5XljqiwinQkfXJgHt1u6Umms,14526
66
- pyghmi-1.5.72.dist-info/AUTHORS,sha256=-0iHKtdQwAJfAGKcruCnvcQXrXuE_LgBZ3P15DJI1xY,2044
67
- pyghmi-1.5.72.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
68
- pyghmi-1.5.72.dist-info/METADATA,sha256=RHABrdEfRdrxJAbFBYVzLnYMfik-0KQmilz1mbfOq_I,1119
69
- pyghmi-1.5.72.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92
70
- pyghmi-1.5.72.dist-info/entry_points.txt,sha256=WkbeJkEZzG9MOILxkaEPSEQ109YP9euntH9kcxbysuk,169
71
- pyghmi-1.5.72.dist-info/pbr.json,sha256=xzV_2z-mjUTo-ASlE1utsOowAV3Aa33TPNq7HGCInsg,46
72
- pyghmi-1.5.72.dist-info/top_level.txt,sha256=aDtt6S9eVu6-tNdaUs4Pz9PbdUd69bziZZMhNvk9Ulc,7
73
- pyghmi-1.5.72.dist-info/RECORD,,
66
+ pyghmi/util/webclient.py,sha256=782_yMuy_LuN9E2vh2EJ-R64X_EyvLLRuurE__jfn20,15371
67
+ pyghmi-1.5.76.dist-info/AUTHORS,sha256=-0iHKtdQwAJfAGKcruCnvcQXrXuE_LgBZ3P15DJI1xY,2044
68
+ pyghmi-1.5.76.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
69
+ pyghmi-1.5.76.dist-info/METADATA,sha256=1__ebGoQR_mgCzeiVv6VwBIcV9zh-ealhXSjKe_VseE,1137
70
+ pyghmi-1.5.76.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
71
+ pyghmi-1.5.76.dist-info/entry_points.txt,sha256=-OpJliDzATxmuPXK0VR3Ma-Yk_i4ZhfIIB-12A26dSI,168
72
+ pyghmi-1.5.76.dist-info/pbr.json,sha256=7P9y3sOyYyYsFR7KO_P8o4k1UQpTfZtkxoIp2PRUYv8,46
73
+ pyghmi-1.5.76.dist-info/top_level.txt,sha256=aDtt6S9eVu6-tNdaUs4Pz9PbdUd69bziZZMhNvk9Ulc,7
74
+ pyghmi-1.5.76.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.34.2)
2
+ Generator: setuptools (75.3.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -3,4 +3,3 @@ fakebmc = pyghmi.cmd.fakebmc:main
3
3
  pyghmicons = pyghmi.cmd.pyghmicons:main
4
4
  pyghmiutil = pyghmi.cmd.pyghmiutil:main
5
5
  virshbmc = pyghmi.cmd.virshbmc:main
6
-
@@ -0,0 +1 @@
1
+ {"git_version": "345fd8b", "is_release": true}
@@ -1 +0,0 @@
1
- {"git_version": "b6776ce", "is_release": true}