pyghmi 1.5.77__py3-none-any.whl → 1.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.
- pyghmi/ipmi/command.py +16 -0
- pyghmi/ipmi/oem/generic.py +16 -2
- pyghmi/ipmi/oem/lenovo/config.py +10 -1
- pyghmi/ipmi/oem/lenovo/handler.py +21 -0
- pyghmi/ipmi/oem/lenovo/imm.py +52 -8
- pyghmi/ipmi/oem/lenovo/nextscale.py +7 -1
- pyghmi/ipmi/private/serversession.py +3 -3
- pyghmi/redfish/command.py +21 -4
- pyghmi/redfish/oem/generic.py +37 -7
- pyghmi/redfish/oem/lenovo/smm3.py +77 -3
- pyghmi/redfish/oem/lenovo/tsma.py +1 -1
- pyghmi/redfish/oem/lenovo/xcc.py +41 -7
- pyghmi/redfish/oem/lenovo/xcc3.py +40 -4
- {pyghmi-1.5.77.dist-info → pyghmi-1.6.1.dist-info}/METADATA +1 -1
- {pyghmi-1.5.77.dist-info → pyghmi-1.6.1.dist-info}/RECORD +21 -21
- {pyghmi-1.5.77.dist-info → pyghmi-1.6.1.dist-info}/WHEEL +1 -1
- pyghmi-1.6.1.dist-info/pbr.json +1 -0
- pyghmi-1.5.77.dist-info/pbr.json +0 -1
- {pyghmi-1.5.77.dist-info → pyghmi-1.6.1.dist-info}/AUTHORS +0 -0
- {pyghmi-1.5.77.dist-info → pyghmi-1.6.1.dist-info}/LICENSE +0 -0
- {pyghmi-1.5.77.dist-info → pyghmi-1.6.1.dist-info}/entry_points.txt +0 -0
- {pyghmi-1.5.77.dist-info → pyghmi-1.6.1.dist-info}/top_level.txt +0 -0
pyghmi/ipmi/command.py
CHANGED
@@ -654,6 +654,14 @@ class Command(object):
|
|
654
654
|
return sel.EventHandler(self.init_sdr(), self).decode_pet(specifictrap,
|
655
655
|
petdata)
|
656
656
|
|
657
|
+
def get_ikvm_methods(self):
|
658
|
+
self.oem_init()
|
659
|
+
return self._oem.get_ikvm_methods()
|
660
|
+
|
661
|
+
def get_ikvm_launchdata(self):
|
662
|
+
self.oem_init()
|
663
|
+
return self._oem.get_ikvm_launchdata()
|
664
|
+
|
657
665
|
def get_inventory_descriptions(self):
|
658
666
|
"""Retrieve list of things that could be inventoried
|
659
667
|
|
@@ -1652,6 +1660,10 @@ class Command(object):
|
|
1652
1660
|
r['privilege_level'] = privilege_levels[data[1] & 0b00001111]
|
1653
1661
|
return r
|
1654
1662
|
|
1663
|
+
def get_screenshot(self, outfile):
|
1664
|
+
self.oem_init()
|
1665
|
+
return self._oem.get_screenshot(outfile)
|
1666
|
+
|
1655
1667
|
def get_channel_info(self, channel=None):
|
1656
1668
|
"""Get channel info
|
1657
1669
|
|
@@ -2212,6 +2224,10 @@ class Command(object):
|
|
2212
2224
|
self.oem_init()
|
2213
2225
|
return self._oem.get_graphical_console()
|
2214
2226
|
|
2227
|
+
def get_update_status(self):
|
2228
|
+
self.oem_init()
|
2229
|
+
return self._oem.get_update_status()
|
2230
|
+
|
2215
2231
|
def update_firmware(self, filename, data=None, progress=None, bank=None):
|
2216
2232
|
"""Send file to BMC to perform firmware update
|
2217
2233
|
|
pyghmi/ipmi/oem/generic.py
CHANGED
@@ -42,12 +42,22 @@ class OEMHandler(object):
|
|
42
42
|
"""
|
43
43
|
return {}
|
44
44
|
|
45
|
+
def get_screenshot(self, outfile):
|
46
|
+
return {}
|
47
|
+
|
45
48
|
def get_system_power_watts(self, ipmicmd):
|
46
49
|
# Use DCMI getpower reading command
|
47
50
|
rsp = ipmicmd.xraw_command(netfn=0x2c, command=2, data=(0xdc, 1, 0, 0))
|
48
51
|
wattage = struct.unpack('<H', rsp['data'][1:3])[0]
|
49
52
|
return wattage
|
50
|
-
|
53
|
+
|
54
|
+
def get_ikvm_methods(self):
|
55
|
+
return []
|
56
|
+
|
57
|
+
def get_ikvm_launchdata(self):
|
58
|
+
# no standard ikvm behavior, must be oem defined
|
59
|
+
return {}
|
60
|
+
|
51
61
|
def get_average_processor_temperature(self, ipmicmd):
|
52
62
|
# DCMI suggests preferrence for 0x37 ('Air inlet')
|
53
63
|
# If not that, then 0x40 ('Air inlet')
|
@@ -332,13 +342,17 @@ class OEMHandler(object):
|
|
332
342
|
raise exc.UnsupportedFunctionality(
|
333
343
|
'Remote storage configuration not supported on this platform')
|
334
344
|
|
345
|
+
def get_update_status(self):
|
346
|
+
raise exc.UnsupportedFunctionality(
|
347
|
+
'Firmwore update not supported on this platform')
|
348
|
+
|
335
349
|
def update_firmware(self, filename, data=None, progress=None, bank=None):
|
336
350
|
raise exc.UnsupportedFunctionality(
|
337
351
|
'Firmware update not supported on this platform')
|
338
352
|
|
339
353
|
def reseat_bay(self, bay):
|
340
354
|
raise exc.UnsupportedFunctionality(
|
341
|
-
'
|
355
|
+
'Reseat not supported on this platform')
|
342
356
|
|
343
357
|
def get_graphical_console(self):
|
344
358
|
"""Get graphical console launcher"""
|
pyghmi/ipmi/oem/lenovo/config.py
CHANGED
@@ -51,7 +51,16 @@ class Unsupported(Exception):
|
|
51
51
|
def fromstring(inputdata):
|
52
52
|
if b'!entity' in inputdata.lower():
|
53
53
|
raise Exception('Unsupported XML')
|
54
|
-
|
54
|
+
try:
|
55
|
+
return etree.fromstring(inputdata)
|
56
|
+
except etree.XMLSyntaxError:
|
57
|
+
inputdata = bytearray(inputdata.decode('utf8', errors='backslashreplace').encode())
|
58
|
+
for i in range(len(inputdata)):
|
59
|
+
if inputdata[i] < 0x20 and inputdata[i] not in (9, 0xa, 0xd):
|
60
|
+
inputdata[i] = 63
|
61
|
+
inputdata = bytes(inputdata)
|
62
|
+
return etree.fromstring(inputdata)
|
63
|
+
|
55
64
|
|
56
65
|
|
57
66
|
def run_command_with_retry(connection, data):
|
@@ -211,11 +211,25 @@ class OEMHandler(generic.OEMHandler):
|
|
211
211
|
self._mrethidx = rsp['data'][0]
|
212
212
|
return self._mrethidx
|
213
213
|
|
214
|
+
def get_screenshot(self, outfile):
|
215
|
+
if self.has_xcc:
|
216
|
+
return self.immhandler.get_screenshot(outfile)
|
217
|
+
return {}
|
218
|
+
|
214
219
|
def remove_storage_configuration(self, cfgspec):
|
215
220
|
if self.has_xcc:
|
216
221
|
return self.immhandler.remove_storage_configuration(cfgspec)
|
217
222
|
return super(OEMHandler, self).remove_storage_configuration()
|
218
223
|
|
224
|
+
def get_ikvm_methods(self):
|
225
|
+
if self.has_xcc:
|
226
|
+
return ['url']
|
227
|
+
|
228
|
+
def get_ikvm_launchdata(self):
|
229
|
+
if self.has_xcc:
|
230
|
+
return self.immhandler.get_ikvm_launchdata()
|
231
|
+
return {}
|
232
|
+
|
219
233
|
def clear_storage_arrays(self):
|
220
234
|
if self.has_xcc:
|
221
235
|
return self.immhandler.clear_storage_arrays()
|
@@ -1175,6 +1189,13 @@ class OEMHandler(generic.OEMHandler):
|
|
1175
1189
|
else:
|
1176
1190
|
raise
|
1177
1191
|
|
1192
|
+
def get_update_status(self):
|
1193
|
+
if self.is_fpc or self.has_tsma:
|
1194
|
+
return "ready"
|
1195
|
+
if self.has_xcc:
|
1196
|
+
return self.immhandler.get_update_status()
|
1197
|
+
return super(OEMHandler, self).get_update_status()
|
1198
|
+
|
1178
1199
|
def update_firmware(self, filename, data=None, progress=None, bank=None):
|
1179
1200
|
if self.has_xcc:
|
1180
1201
|
return self.immhandler.update_firmware(
|
pyghmi/ipmi/oem/lenovo/imm.py
CHANGED
@@ -617,7 +617,9 @@ class IMMClient(object):
|
|
617
617
|
skipkeys.add(fwi['key'])
|
618
618
|
if fwi.get('fw_status', 0) == 2:
|
619
619
|
bdata = {}
|
620
|
-
if '
|
620
|
+
if 'fw_pkg_version' in fwi and fwi['fw_pkg_version']:
|
621
|
+
bdata['version'] = fwi['fw_pkg_version']
|
622
|
+
elif 'fw_version_pend' in fwi:
|
621
623
|
bdata['version'] = fwi['fw_version_pend']
|
622
624
|
yield '{0} Pending Update'.format(aname), bdata
|
623
625
|
for fwi in fwu.get('items', []):
|
@@ -914,6 +916,14 @@ class XCCClient(IMMClient):
|
|
914
916
|
self.ipmicmd.ipmi_session.register_keepalive(self.keepalive, None)
|
915
917
|
self.adp_referer = None
|
916
918
|
|
919
|
+
def get_screenshot(self, outfile):
|
920
|
+
self.wc.grab_json_response('/api/providers/rp_screenshot')
|
921
|
+
url = '/download/HostScreenShot.png'
|
922
|
+
fd = webclient.FileDownloader(self.wc, url, outfile)
|
923
|
+
fd.start()
|
924
|
+
fd.join()
|
925
|
+
|
926
|
+
|
917
927
|
def get_user_privilege_level(self, uid):
|
918
928
|
uid = uid - 1
|
919
929
|
accurl = '/redfish/v1/AccountService/Accounts/{0}'.format(uid)
|
@@ -922,6 +932,18 @@ class XCCClient(IMMClient):
|
|
922
932
|
return accinfo.get('RoleId', None)
|
923
933
|
return None
|
924
934
|
|
935
|
+
def get_ikvm_methods(self):
|
936
|
+
return ['url']
|
937
|
+
|
938
|
+
def get_ikvm_launchdata(self):
|
939
|
+
access = self.grab_redfish_response_with_status('/redfish/v1/Managers/1/Oem/Lenovo/RemoteControl/Actions/LenovoRemoteControlService.GetRemoteConsoleToken', {})
|
940
|
+
if access[0].get('Token', None):
|
941
|
+
accessinfo = {
|
942
|
+
'url': '/#/login?{}&context=remote&mode=multi'.format(access[0]['Token'])
|
943
|
+
}
|
944
|
+
return accessinfo
|
945
|
+
return {}
|
946
|
+
|
925
947
|
def set_user_access(self, uid, privilege_level):
|
926
948
|
uid = uid - 1
|
927
949
|
role = None
|
@@ -940,8 +962,11 @@ class XCCClient(IMMClient):
|
|
940
962
|
|
941
963
|
def reseat(self):
|
942
964
|
wc = self.wc.dupe(timeout=5)
|
943
|
-
|
944
|
-
|
965
|
+
try:
|
966
|
+
rsp = wc.grab_json_response_with_status(
|
967
|
+
'/api/providers/virt_reseat', '{}')
|
968
|
+
except socket.timeout:
|
969
|
+
return # probably reseated itself and unable to reply
|
945
970
|
if rsp[1] == 500 and rsp[0] == 'Target Unavailable':
|
946
971
|
return
|
947
972
|
if rsp[1] != 200 or rsp[0].get('return', 1) != 0:
|
@@ -1283,8 +1308,14 @@ class XCCClient(IMMClient):
|
|
1283
1308
|
return True
|
1284
1309
|
|
1285
1310
|
def get_diagnostic_data(self, savefile, progress=None, autosuffix=False):
|
1286
|
-
self.wc.grab_json_response('/api/providers/ffdc',
|
1287
|
-
|
1311
|
+
result = self.wc.grab_json_response('/api/providers/ffdc',
|
1312
|
+
{'Generate_FFDC_status': 1})
|
1313
|
+
rsp = self.wc.grab_json_response('/api/providers/ffdc',
|
1314
|
+
{'Generate_FFDC': 1})
|
1315
|
+
if rsp.get('return', 0) == 4:
|
1316
|
+
rsp = self.wc.grab_json_response('/api/providers/ffdc',
|
1317
|
+
{'Generate_FFDC': 1,
|
1318
|
+
'thermal_log': 0})
|
1288
1319
|
percent = 0
|
1289
1320
|
while percent != 100:
|
1290
1321
|
ipmisession.Session.pause(3)
|
@@ -2075,14 +2106,18 @@ class XCCClient(IMMClient):
|
|
2075
2106
|
# the validating phase; add a retry here so we don't exit the loop in this case
|
2076
2107
|
retry = 3
|
2077
2108
|
while not complete and retry > 0:
|
2078
|
-
|
2079
|
-
|
2109
|
+
try:
|
2110
|
+
pgress, status = self.grab_redfish_response_with_status(
|
2111
|
+
monitorurl)
|
2112
|
+
except socket.timeout:
|
2113
|
+
pgress = None
|
2080
2114
|
if status < 200 or status >= 300:
|
2081
2115
|
raise Exception(pgress)
|
2082
2116
|
if not pgress:
|
2083
2117
|
retry -= 1
|
2084
2118
|
ipmisession.Session.pause(3)
|
2085
2119
|
continue
|
2120
|
+
retry = 3 # reset retry counter
|
2086
2121
|
for msg in pgress.get('Messages', []):
|
2087
2122
|
if 'Verify failed' in msg.get('Message', ''):
|
2088
2123
|
raise Exception(msg['Message'])
|
@@ -2103,6 +2138,8 @@ class XCCClient(IMMClient):
|
|
2103
2138
|
ipmisession.Session.pause(3)
|
2104
2139
|
else:
|
2105
2140
|
ipmisession.Session.pause(3)
|
2141
|
+
if not retry:
|
2142
|
+
raise Exception('Falied to monitor update progress due to excessive timeouts')
|
2106
2143
|
if bank == 'backup':
|
2107
2144
|
return 'complete'
|
2108
2145
|
return 'pending'
|
@@ -2116,7 +2153,14 @@ class XCCClient(IMMClient):
|
|
2116
2153
|
|
2117
2154
|
def set_custom_user_privilege(self, uid, privilege):
|
2118
2155
|
return self.set_user_access(self, uid, privilege)
|
2119
|
-
|
2156
|
+
|
2157
|
+
def get_update_status(self):
|
2158
|
+
upd = self.grab_redfish_response_emptyonerror('/redfish/v1/UpdateService')
|
2159
|
+
health = upd.get('Status', {}).get('Health', 'bod')
|
2160
|
+
if health == 'OK':
|
2161
|
+
return 'ready'
|
2162
|
+
return 'unavailable'
|
2163
|
+
|
2120
2164
|
def update_firmware(self, filename, data=None, progress=None, bank=None):
|
2121
2165
|
usd = self.grab_redfish_response_emptyonerror(
|
2122
2166
|
'/redfish/v1/UpdateService')
|
@@ -762,7 +762,13 @@ class SMMClient(object):
|
|
762
762
|
rsp = {'data': [1]}
|
763
763
|
rsp['data'] = bytearray(rsp['data'])
|
764
764
|
if rsp['data'][0] == 2: # shared io
|
765
|
-
|
765
|
+
try:
|
766
|
+
rsp = self.ipmicmd.xraw_command(0x32, 0xa7, data=[bay - 1])
|
767
|
+
except Exception:
|
768
|
+
raise Exception('Shared IO detected trying to reseat {}, '
|
769
|
+
'but unable to determine status of '
|
770
|
+
'partner bay {}'.format(
|
771
|
+
bay, bay - 1))
|
766
772
|
rsp['data'] = bytearray(rsp['data'])
|
767
773
|
if rsp['data'][1] == 0x80:
|
768
774
|
raise Exception('Unable to reseat bay {0} due to bay {1} '
|
@@ -108,7 +108,8 @@ class ServerSession(ipmisession.Session):
|
|
108
108
|
# ignore null username for now
|
109
109
|
return
|
110
110
|
self.username = bytes(data[28:])
|
111
|
-
|
111
|
+
password = self.authdata.get(self.username.decode('utf-8'))
|
112
|
+
if password is None:
|
112
113
|
# don't think about invalid usernames for now
|
113
114
|
return
|
114
115
|
uuidbytes = self.uuid.bytes
|
@@ -118,8 +119,7 @@ class ServerSession(ipmisession.Session):
|
|
118
119
|
+ self.Rm + self.Rc + uuidbytes
|
119
120
|
+ bytearray([self.rolem, len(self.username)]))
|
120
121
|
hmacdata += self.username
|
121
|
-
self.kuid =
|
122
|
-
'utf-8')
|
122
|
+
self.kuid = password.encode('utf-8')
|
123
123
|
if self.kg is None:
|
124
124
|
self.kg = self.kuid
|
125
125
|
authcode = hmac.new(
|
pyghmi/redfish/command.py
CHANGED
@@ -432,6 +432,15 @@ class Command(object):
|
|
432
432
|
self._do_web_request(accinfo[0], userinfo, method='PATCH', etag=etag)
|
433
433
|
return True
|
434
434
|
|
435
|
+
def get_screenshot(self, outfile):
|
436
|
+
return self.oem.get_screenshot(outfile)
|
437
|
+
|
438
|
+
def get_ikvm_methods(self):
|
439
|
+
return self.oem.get_ikvm_methods()
|
440
|
+
|
441
|
+
def get_ikvm_launchdata(self):
|
442
|
+
return self.oem.get_ikvm_launchdata()
|
443
|
+
|
435
444
|
def user_delete(self, uid):
|
436
445
|
self.oem.user_delete(uid)
|
437
446
|
|
@@ -513,10 +522,8 @@ class Command(object):
|
|
513
522
|
raise exc.InvalidParameterValue(
|
514
523
|
"Unknown power state %s requested" % powerstate)
|
515
524
|
powerstate = powerstates[powerstate]
|
516
|
-
|
525
|
+
self._do_web_request(
|
517
526
|
self.powerurl, {'ResetType': powerstate})
|
518
|
-
if result[1] < 200 or result[1] >= 300:
|
519
|
-
raise exc.PyghmiException(result[0])
|
520
527
|
if wait and reqpowerstate in ('on', 'off', 'softoff', 'shutdown'):
|
521
528
|
if reqpowerstate in ('softoff', 'shutdown'):
|
522
529
|
reqpowerstate = 'off'
|
@@ -837,6 +844,8 @@ class Command(object):
|
|
837
844
|
self._do_web_request(url, {'ResetType': action})
|
838
845
|
|
839
846
|
def set_identify(self, on=True, blink=None):
|
847
|
+
if hasattr(self.oem, 'set_identify'):
|
848
|
+
return self.oem.set_identify(on, blink)
|
840
849
|
targurl = self.sysurl
|
841
850
|
if not targurl:
|
842
851
|
root = self._do_web_request('/redfish/v1')
|
@@ -1115,7 +1124,7 @@ class Command(object):
|
|
1115
1124
|
yield res
|
1116
1125
|
|
1117
1126
|
def _extract_fwinfo(self, inf):
|
1118
|
-
currinf =
|
1127
|
+
currinf = self._oem._extract_fwinfo(inf)
|
1119
1128
|
fwi, url = inf
|
1120
1129
|
fwname = fwi.get('Name', 'Unknown')
|
1121
1130
|
if fwname in self._fwnamemap:
|
@@ -1129,6 +1138,7 @@ class Command(object):
|
|
1129
1138
|
currinf['id'] = fwi.get('Id', None)
|
1130
1139
|
currinf['version'] = fwi.get('Version', 'Unknown')
|
1131
1140
|
currinf['date'] = parse_time(fwi.get('ReleaseDate', ''))
|
1141
|
+
currinf['software_id'] = fwi.get('SoftwareId', '')
|
1132
1142
|
if not (currinf['version'] or currinf['date']):
|
1133
1143
|
return None, None
|
1134
1144
|
# TODO(Jarrod Johnson): OEM extended data with buildid
|
@@ -1419,6 +1429,8 @@ class Command(object):
|
|
1419
1429
|
self.wc.stdheaders['X-Auth-Token'] = self.xauthtoken
|
1420
1430
|
if 'Authorization' in self.wc.stdheaders:
|
1421
1431
|
del self.wc.stdheaders['Authorization']
|
1432
|
+
for res in self.oem.list_media(self, cache=False):
|
1433
|
+
pass
|
1422
1434
|
|
1423
1435
|
def detach_remote_media(self):
|
1424
1436
|
try:
|
@@ -1452,6 +1464,8 @@ class Command(object):
|
|
1452
1464
|
method='PATCH')
|
1453
1465
|
else:
|
1454
1466
|
raise
|
1467
|
+
for res in self.oem.list_media(self, cache=False):
|
1468
|
+
pass
|
1455
1469
|
|
1456
1470
|
def upload_media(self, filename, progress=None, data=None):
|
1457
1471
|
"""Upload a file to be hosted on the target BMC
|
@@ -1466,6 +1480,9 @@ class Command(object):
|
|
1466
1480
|
"""
|
1467
1481
|
return self.oem.upload_media(filename, progress, data)
|
1468
1482
|
|
1483
|
+
def get_update_status(self):
|
1484
|
+
return self.oem.get_update_status()
|
1485
|
+
|
1469
1486
|
def update_firmware(self, file, data=None, progress=None, bank=None):
|
1470
1487
|
"""Send file to BMC to perform firmware update
|
1471
1488
|
|
pyghmi/redfish/oem/generic.py
CHANGED
@@ -13,6 +13,7 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
15
|
import base64
|
16
|
+
import copy
|
16
17
|
from fnmatch import fnmatch
|
17
18
|
import json
|
18
19
|
import os
|
@@ -193,6 +194,10 @@ class OEMHandler(object):
|
|
193
194
|
self._urlcache = cache
|
194
195
|
self.webclient = webclient
|
195
196
|
|
197
|
+
def get_screenshot(self, outfile):
|
198
|
+
raise exc.UnsupportedFunctionality(
|
199
|
+
'Retrieving screenshot is not implemented for this platform')
|
200
|
+
|
196
201
|
def supports_expand(self, url):
|
197
202
|
# Unfortunately, the state of expand in redfish is pretty dicey,
|
198
203
|
# so an OEM handler must opt into this behavior
|
@@ -569,13 +574,14 @@ class OEMHandler(object):
|
|
569
574
|
pendingsettings, self.attrdeps, reginfo,
|
570
575
|
fishclient._setbiosurl)
|
571
576
|
|
572
|
-
def _set_redfish_settings(self,
|
577
|
+
def _set_redfish_settings(self, inchangeset, fishclient, currsettings,
|
573
578
|
rawsettings, pendingsettings, attrdeps, reginfo,
|
574
579
|
seturl):
|
575
580
|
etag = pendingsettings.get('@odata.etag', None)
|
576
581
|
pendingsettings = pendingsettings.get('Attributes', {})
|
577
582
|
dephandler = AttrDependencyHandler(attrdeps, rawsettings,
|
578
583
|
pendingsettings)
|
584
|
+
changeset = copy.deepcopy(inchangeset)
|
579
585
|
for change in list(changeset):
|
580
586
|
if change not in currsettings:
|
581
587
|
found = False
|
@@ -650,6 +656,9 @@ class OEMHandler(object):
|
|
650
656
|
return {}
|
651
657
|
|
652
658
|
|
659
|
+
def _extract_fwinfo(self, inf):
|
660
|
+
return {}
|
661
|
+
|
653
662
|
def get_firmware_inventory(self, components, fishclient):
|
654
663
|
return []
|
655
664
|
|
@@ -663,13 +672,13 @@ class OEMHandler(object):
|
|
663
672
|
except AttributeError:
|
664
673
|
self.password = password
|
665
674
|
|
666
|
-
def list_media(self, fishclient):
|
667
|
-
bmcinfo = fishclient._do_web_request(fishclient._bmcurl)
|
675
|
+
def list_media(self, fishclient, cache=True):
|
676
|
+
bmcinfo = fishclient._do_web_request(fishclient._bmcurl, cache=cache)
|
668
677
|
vmcoll = bmcinfo.get('VirtualMedia', {}).get('@odata.id', None)
|
669
678
|
if vmcoll:
|
670
|
-
vmlist = fishclient._do_web_request(vmcoll)
|
679
|
+
vmlist = fishclient._do_web_request(vmcoll, cache=cache)
|
671
680
|
vmurls = [x['@odata.id'] for x in vmlist.get('Members', [])]
|
672
|
-
for vminfo in fishclient._do_bulk_requests(vmurls):
|
681
|
+
for vminfo in fishclient._do_bulk_requests(vmurls, cache=cache):
|
673
682
|
vminfo = vminfo[0]
|
674
683
|
if vminfo.get('Image', None):
|
675
684
|
imageurl = vminfo['Image'].replace(
|
@@ -1018,6 +1027,12 @@ class OEMHandler(object):
|
|
1018
1027
|
return topdata
|
1019
1028
|
return topdata
|
1020
1029
|
|
1030
|
+
def get_ikvm_methods(self):
|
1031
|
+
return []
|
1032
|
+
|
1033
|
+
def get_ikvm_launchdata(self):
|
1034
|
+
return {}
|
1035
|
+
|
1021
1036
|
def get_storage_configuration(self):
|
1022
1037
|
raise exc.UnsupportedFunctionality(
|
1023
1038
|
'Remote storage configuration not supported on this platform')
|
@@ -1038,6 +1053,15 @@ class OEMHandler(object):
|
|
1038
1053
|
raise exc.UnsupportedFunctionality(
|
1039
1054
|
'Remote media upload not supported on this platform')
|
1040
1055
|
|
1056
|
+
def get_update_status(self):
|
1057
|
+
upd = self._do_web_request('/redfish/v1/UpdateService')
|
1058
|
+
health = upd.get('Status', {}).get('Health', 'Unknown')
|
1059
|
+
if health == 'OK':
|
1060
|
+
return 'ready'
|
1061
|
+
if health == 'Unknown' and upd.get('ServiceEnabled'):
|
1062
|
+
return 'ready'
|
1063
|
+
return 'unavailable'
|
1064
|
+
|
1041
1065
|
def update_firmware(self, filename, data=None, progress=None, bank=None, otherfields=()):
|
1042
1066
|
# disable cache to make sure we trigger the token renewal logic if needed
|
1043
1067
|
usd = self._do_web_request('/redfish/v1/UpdateService', cache=False)
|
@@ -1090,11 +1114,15 @@ class OEMHandler(object):
|
|
1090
1114
|
retry = 3
|
1091
1115
|
pct = 0.0
|
1092
1116
|
while not complete and retry > 0:
|
1093
|
-
|
1117
|
+
try:
|
1118
|
+
pgress = self._do_web_request(monitorurl, cache=False)
|
1119
|
+
except socket.timeout:
|
1120
|
+
pgress = None
|
1094
1121
|
if not pgress:
|
1095
1122
|
retry -= 1
|
1096
1123
|
time.sleep(3)
|
1097
1124
|
continue
|
1125
|
+
retry = 3 # reset retry counter
|
1098
1126
|
for msg in pgress.get('Messages', []):
|
1099
1127
|
if 'Verify failed' in msg.get('Message', ''):
|
1100
1128
|
raise Exception(msg['Message'])
|
@@ -1119,6 +1147,8 @@ class OEMHandler(object):
|
|
1119
1147
|
time.sleep(3)
|
1120
1148
|
else:
|
1121
1149
|
time.sleep(3)
|
1150
|
+
if not retry:
|
1151
|
+
raise Exception('Falied to monitor update progress due to excessive timeouts')
|
1122
1152
|
return 'pending'
|
1123
1153
|
finally:
|
1124
1154
|
if 'HttpPushUriTargetsBusy' in usd:
|
@@ -1266,4 +1296,4 @@ class OEMHandler(object):
|
|
1266
1296
|
|
1267
1297
|
def reseat_bay(self, bay):
|
1268
1298
|
raise exc.UnsupportedFunctionality(
|
1269
|
-
'
|
1299
|
+
'Reseat not supported on this platform')
|
@@ -12,8 +12,13 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
+
import copy
|
16
|
+
import os
|
15
17
|
import pyghmi.redfish.oem.generic as generic
|
16
18
|
import pyghmi.constants as pygconst
|
19
|
+
import pyghmi.util.webclient as webclient
|
20
|
+
import pyghmi.exceptions as exc
|
21
|
+
import time
|
17
22
|
|
18
23
|
healthlookup = {
|
19
24
|
'ok': pygconst.Health.Ok,
|
@@ -38,6 +43,9 @@ def _baytonumber(bay):
|
|
38
43
|
def _baytolabel(bay):
|
39
44
|
try:
|
40
45
|
baynum = int(bay)
|
46
|
+
if baynum < 1:
|
47
|
+
raise exc.UnsupportedFunctionality(
|
48
|
+
'Reseat not supported for whole chassis')
|
41
49
|
# need to convert to 1a, 1b, etc...
|
42
50
|
vertidx = ((baynum - 1) // 2 + 1) << 4
|
43
51
|
horizidx = (baynum - 1) % 2 + 10
|
@@ -54,9 +62,74 @@ class OEMHandler(generic.OEMHandler):
|
|
54
62
|
health = healthlookup.get(health, pygconst.Health.Critical)
|
55
63
|
return {'health': health}
|
56
64
|
|
65
|
+
def set_identify(self, on=True, blink=False):
|
66
|
+
if on:
|
67
|
+
state = 'On'
|
68
|
+
elif blink:
|
69
|
+
state = 'Blinking'
|
70
|
+
else:
|
71
|
+
state = 'Off'
|
72
|
+
self._do_web_request('/redfish/v1/Chassis/chassis1', {
|
73
|
+
'Oem': {'Lenovo': {'LED': {'IdentifyLED': {
|
74
|
+
'State': state
|
75
|
+
}}}
|
76
|
+
}}, method='PATCH')
|
77
|
+
|
57
78
|
def get_system_configuration(self, hideadvanced=True, fishclient=None):
|
58
79
|
return {}
|
59
80
|
|
81
|
+
def get_diagnostic_data(self, savefile, progress=None, autosuffix=False):
|
82
|
+
tsk = self._do_web_request(
|
83
|
+
'/redfish/v1/Managers/bmc/LogServices/Dump/Actions/LogService.CollectDiagnosticData',
|
84
|
+
{"DiagnosticDataType": "Manager"})
|
85
|
+
taskrunning = True
|
86
|
+
taskurl = tsk.get('@odata.id', None)
|
87
|
+
pct = 0 if taskurl else 100
|
88
|
+
durl = None
|
89
|
+
while pct < 100 and taskrunning:
|
90
|
+
status = self._do_web_request(taskurl)
|
91
|
+
durl = status.get('AdditionalDataURI', '')
|
92
|
+
pct = status.get('PercentComplete', 0)
|
93
|
+
taskrunning = status.get('TaskState', 'Complete') == 'Running'
|
94
|
+
if progress:
|
95
|
+
progress({'phase': 'initializing', 'progress': float(pct)})
|
96
|
+
if taskrunning:
|
97
|
+
time.sleep(3)
|
98
|
+
if not durl:
|
99
|
+
for hdr in status.get('Payload', {}).get('HttpHeaders', []):
|
100
|
+
if hdr.startswith('Location: '):
|
101
|
+
|
102
|
+
enturl = hdr.replace('Location: ', '')
|
103
|
+
entryinfo = self._do_web_request(enturl)
|
104
|
+
durl = entryinfo.get('AdditionalDataURI', None)
|
105
|
+
break
|
106
|
+
if not durl:
|
107
|
+
raise Exception("Failed getting service data url")
|
108
|
+
fname = os.path.basename(durl)
|
109
|
+
if autosuffix and not savefile.endswith('.tar.xz'):
|
110
|
+
savefile += time.strftime('-SMM3_%Y%m%d_%H%M%S.tar.xz')
|
111
|
+
fd = webclient.FileDownloader(self.webclient, durl, savefile)
|
112
|
+
fd.start()
|
113
|
+
while fd.isAlive():
|
114
|
+
fd.join(1)
|
115
|
+
if progress and self.webclient.get_download_progress():
|
116
|
+
progress({'phase': 'download',
|
117
|
+
'progress': 100 * self.webclient.get_download_progress()})
|
118
|
+
if fd.exc:
|
119
|
+
raise fd.exc
|
120
|
+
if progress:
|
121
|
+
progress({'phase': 'complete'})
|
122
|
+
return savefile
|
123
|
+
|
124
|
+
def _extract_fwinfo(self, inf):
|
125
|
+
fwi, url = inf
|
126
|
+
currinf = {}
|
127
|
+
buildid = fwi.get('Oem', {}).get('Lenovo', {}).get('ExtendedVersion', None)
|
128
|
+
if buildid:
|
129
|
+
currinf['build'] = buildid
|
130
|
+
return currinf
|
131
|
+
|
132
|
+
|
60
133
|
def _get_node_info(self):
|
61
134
|
nodeinfo = self._varsysinfo
|
62
135
|
if not nodeinfo:
|
@@ -69,9 +142,10 @@ class OEMHandler(generic.OEMHandler):
|
|
69
142
|
if len(chassismembs) == 1:
|
70
143
|
chassisurl = chassismembs[0]['@odata.id']
|
71
144
|
nodeinfo = self._do_web_request(chassisurl)
|
72
|
-
|
73
|
-
|
74
|
-
|
145
|
+
newnodeinfo = copy.deepcopy(nodeinfo)
|
146
|
+
newnodeinfo['SKU'] = nodeinfo['Model']
|
147
|
+
newnodeinfo['Model'] = 'N1380 Enclosure'
|
148
|
+
return newnodeinfo
|
75
149
|
|
76
150
|
def reseat_bay(self, bay):
|
77
151
|
bayid = _baytolabel(bay)
|
@@ -799,7 +799,7 @@ class TsmHandler(generic.OEMHandler):
|
|
799
799
|
raise exc.UnsupportedFunctionality(
|
800
800
|
'Remote media upload not supported on this system')
|
801
801
|
|
802
|
-
def list_media(self, fishclient=None):
|
802
|
+
def list_media(self, fishclient=None, cache=True):
|
803
803
|
wc = self.wc
|
804
804
|
rsp = wc.grab_json_response('/api/settings/media/general')
|
805
805
|
cds = rsp['cd_remote_server_address']
|
pyghmi/redfish/oem/lenovo/xcc.py
CHANGED
@@ -150,6 +150,13 @@ class OEMHandler(generic.OEMHandler):
|
|
150
150
|
self.fwc = None
|
151
151
|
self.fwo = None
|
152
152
|
|
153
|
+
def get_screenshot(self, outfile):
|
154
|
+
self.wc.grab_json_response('/api/providers/rp_screenshot')
|
155
|
+
url = '/download/HostScreenShot.png'
|
156
|
+
fd = webclient.FileDownloader(self.wc, url, outfile)
|
157
|
+
fd.start()
|
158
|
+
fd.join()
|
159
|
+
|
153
160
|
def get_extended_bmc_configuration(self, fishclient, hideadvanced=True):
|
154
161
|
immsettings = self.get_system_configuration(fetchimm=True, hideadvanced=hideadvanced)
|
155
162
|
for setting in list(immsettings):
|
@@ -157,6 +164,17 @@ class OEMHandler(generic.OEMHandler):
|
|
157
164
|
del immsettings[setting]
|
158
165
|
return immsettings
|
159
166
|
|
167
|
+
def get_ikvm_methods(self):
|
168
|
+
return ['url']
|
169
|
+
|
170
|
+
def get_ikvm_launchdata(self):
|
171
|
+
access = self._do_web_request('/redfish/v1/Managers/1/Oem/Lenovo/RemoteControl/Actions/LenovoRemoteControlService.GetRemoteConsoleToken', {})
|
172
|
+
if access.get('Token', None):
|
173
|
+
accessinfo = {
|
174
|
+
'url': '/#/login?{}&context=remote&mode=multi'.format(access['Token'])
|
175
|
+
}
|
176
|
+
return accessinfo
|
177
|
+
|
160
178
|
def get_system_configuration(self, hideadvanced=True, fishclient=None,
|
161
179
|
fetchimm=False):
|
162
180
|
if not self.fwc:
|
@@ -293,8 +311,12 @@ class OEMHandler(generic.OEMHandler):
|
|
293
311
|
raise pygexc.UnsupportedFunctionality(
|
294
312
|
'This is not an enclosure manager')
|
295
313
|
wc = self.wc.dupe(timeout=5)
|
296
|
-
|
297
|
-
|
314
|
+
try:
|
315
|
+
rsp = wc.grab_json_response_with_status(
|
316
|
+
'/api/providers/virt_reseat', '{}')
|
317
|
+
except socket.timeout:
|
318
|
+
# Can't be certain, but most likely a timeout'
|
319
|
+
return
|
298
320
|
if rsp[1] == 500 and rsp[0] == 'Target Unavailable':
|
299
321
|
return
|
300
322
|
if rsp[1] != 200 or rsp[0].get('return', 1) != 0:
|
@@ -638,7 +660,9 @@ class OEMHandler(generic.OEMHandler):
|
|
638
660
|
skipkeys.add(fwi['key'])
|
639
661
|
if fwi.get('fw_status', 0) == 2:
|
640
662
|
bdata = {}
|
641
|
-
if '
|
663
|
+
if 'fw_pkg_version' in fwi and fwi['fw_pkg_version']:
|
664
|
+
bdata['version'] = fwi['fw_pkg_version']
|
665
|
+
elif 'fw_version_pend' in fwi:
|
642
666
|
bdata['version'] = fwi['fw_version_pend']
|
643
667
|
yield '{0} Pending Update'.format(aname), bdata
|
644
668
|
for fwi in fdata.get('items', []):
|
@@ -1127,7 +1151,7 @@ class OEMHandler(generic.OEMHandler):
|
|
1127
1151
|
res = wc.grab_json_response_with_status(url, body, method=method)
|
1128
1152
|
return res
|
1129
1153
|
|
1130
|
-
def list_media(self, fishclient):
|
1154
|
+
def list_media(self, fishclient, cache=True):
|
1131
1155
|
rt = self.wc.grab_json_response('/api/providers/rp_vm_remote_getdisk')
|
1132
1156
|
if 'items' in rt:
|
1133
1157
|
for mt in rt['items']:
|
@@ -1290,11 +1314,15 @@ class OEMHandler(generic.OEMHandler):
|
|
1290
1314
|
# the validating phase; add a retry here so we don't exit the loop in this case
|
1291
1315
|
retry = 3
|
1292
1316
|
while not complete and retry > 0:
|
1293
|
-
|
1317
|
+
try:
|
1318
|
+
pgress = self._do_web_request(monitorurl, cache=False)
|
1319
|
+
except socket.timeout:
|
1320
|
+
pgress = None
|
1294
1321
|
if not pgress:
|
1295
1322
|
retry -= 1
|
1296
1323
|
time.sleep(3)
|
1297
1324
|
continue
|
1325
|
+
retry = 3 # reset retry counter
|
1298
1326
|
for msg in pgress.get('Messages', []):
|
1299
1327
|
if 'Verify failed' in msg.get('Message', ''):
|
1300
1328
|
raise Exception(msg['Message'])
|
@@ -1316,6 +1344,8 @@ class OEMHandler(generic.OEMHandler):
|
|
1316
1344
|
time.sleep(3)
|
1317
1345
|
else:
|
1318
1346
|
time.sleep(3)
|
1347
|
+
if not retry:
|
1348
|
+
raise Exception('Falied to monitor update progress due to excessive timeouts')
|
1319
1349
|
if bank == 'backup':
|
1320
1350
|
return 'complete'
|
1321
1351
|
return 'pending'
|
@@ -1530,8 +1560,12 @@ class OEMHandler(generic.OEMHandler):
|
|
1530
1560
|
return 'pending'
|
1531
1561
|
|
1532
1562
|
def get_diagnostic_data(self, savefile, progress=None, autosuffix=False):
|
1533
|
-
self.wc.grab_json_response('/api/providers/ffdc',
|
1534
|
-
|
1563
|
+
rsp = self.wc.grab_json_response('/api/providers/ffdc',
|
1564
|
+
{'Generate_FFDC': 1})
|
1565
|
+
if rsp.get('return', 0) == 4:
|
1566
|
+
rsp = self.wc.grab_json_response('/api/providers/ffdc',
|
1567
|
+
{'Generate_FFDC': 1,
|
1568
|
+
'thermal_log': 0})
|
1535
1569
|
percent = 0
|
1536
1570
|
while percent != 100:
|
1537
1571
|
time.sleep(3)
|
@@ -42,6 +42,14 @@ class OEMHandler(generic.OEMHandler):
|
|
42
42
|
def supports_expand(self, url):
|
43
43
|
return True
|
44
44
|
|
45
|
+
def get_screenshot(self, outfile):
|
46
|
+
wc = self.webclient.dupe()
|
47
|
+
self._get_session_token(wc)
|
48
|
+
url = '/web_download/Mini_ScreenShot.jpg'
|
49
|
+
fd = webclient.FileDownloader(wc, url, outfile)
|
50
|
+
fd.start()
|
51
|
+
fd.join()
|
52
|
+
|
45
53
|
def get_diagnostic_data(self, savefile, progress=None, autosuffix=False):
|
46
54
|
tsk = self._do_web_request(
|
47
55
|
'/redfish/v1/Systems/1/LogServices/DiagnosticLog/Actions/LogService.CollectDiagnosticData',
|
@@ -77,6 +85,17 @@ class OEMHandler(generic.OEMHandler):
|
|
77
85
|
progress({'phase': 'complete'})
|
78
86
|
return savefile
|
79
87
|
|
88
|
+
def get_ikvm_methods(self):
|
89
|
+
return ['openbmc', 'url']
|
90
|
+
|
91
|
+
def get_ikvm_launchdata(self):
|
92
|
+
access = self._do_web_request('/redfish/v1/Managers/1/Oem/Lenovo/RemoteControl/Actions/LenovoRemoteControlService.GetRemoteConsoleToken', {})
|
93
|
+
if access.get('Token', None):
|
94
|
+
accessinfo = {
|
95
|
+
'url': '/#/login?{}&context=remote&mode=multi'.format(access['Token'])
|
96
|
+
}
|
97
|
+
return accessinfo
|
98
|
+
|
80
99
|
def get_system_power_watts(self, fishclient):
|
81
100
|
powerinfo = fishclient._do_web_request('/redfish/v1/Chassis/1/Sensors/power_Sys_Power')
|
82
101
|
return powerinfo['Reading']
|
@@ -270,7 +289,7 @@ class OEMHandler(generic.OEMHandler):
|
|
270
289
|
acctattribs['Oem']['Lenovo'][
|
271
290
|
self.oemacctmap[key.lower()]] = currval
|
272
291
|
if key.lower() == 'password_expiration':
|
273
|
-
warntime =
|
292
|
+
warntime = int(int(currval) * 0.08)
|
274
293
|
acctattribs['Oem']['Lenovo'][
|
275
294
|
'PasswordExpirationWarningPeriod'] = warntime
|
276
295
|
elif key.lower() in self.acctmap:
|
@@ -413,6 +432,13 @@ class OEMHandler(generic.OEMHandler):
|
|
413
432
|
progress({'phase': 'complete'})
|
414
433
|
|
415
434
|
def get_firmware_inventory(self, components, fishclient):
|
435
|
+
sfs = fishclient._do_web_request('/api/providers/system_firmware_status')
|
436
|
+
pendingscm = sfs.get('fpga_scm_pending_build', None)
|
437
|
+
pendinghpm = sfs.get('fpga_hpm_pending_build', None)
|
438
|
+
if pendingscm == '*':
|
439
|
+
pendingscm = None
|
440
|
+
if pendinghpm == '*':
|
441
|
+
pendinghpm = None
|
416
442
|
fwlist = fishclient._do_web_request(fishclient._fwinventory + '?$expand=.')
|
417
443
|
fwlist = copy.deepcopy(fwlist.get('Members', []))
|
418
444
|
self._fwnamemap = {}
|
@@ -432,9 +458,11 @@ class OEMHandler(generic.OEMHandler):
|
|
432
458
|
swid = redres.get('SoftwareId', '')
|
433
459
|
buildid = ''
|
434
460
|
version = redres.get('Version', None)
|
435
|
-
|
436
|
-
|
437
|
-
|
461
|
+
for prefix in ['FPGA-', 'UEFI-', 'BMC-', 'LXPM-', 'DRVWN-', 'DRVLN-', 'LXUM']:
|
462
|
+
if swid.startswith(prefix):
|
463
|
+
buildid = swid.split('-')[1] + version.split('-')[0]
|
464
|
+
version = '-'.join(version.split('-')[1:])
|
465
|
+
break
|
438
466
|
if version:
|
439
467
|
redres['Version'] = version
|
440
468
|
cres = fishclient._extract_fwinfo(res)
|
@@ -443,6 +471,14 @@ class OEMHandler(generic.OEMHandler):
|
|
443
471
|
if buildid:
|
444
472
|
cres[1]['build'] = buildid
|
445
473
|
yield cres
|
474
|
+
if cres[0] == 'SCM-FPGA' and pendingscm:
|
475
|
+
yield 'SCM-FPGA Pending', {
|
476
|
+
'Name': 'SCM-FPGA Pending',
|
477
|
+
'build': pendingscm}
|
478
|
+
elif cres[0] == 'HPM-FPGA' and pendinghpm:
|
479
|
+
yield 'HPM-FPGA Pending', {
|
480
|
+
'Name': 'HPM-FPGA Pending',
|
481
|
+
'build': pendinghpm}
|
446
482
|
raise pygexc.BypassGenericBehavior()
|
447
483
|
|
448
484
|
|
@@ -11,25 +11,25 @@ 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=
|
14
|
+
pyghmi/ipmi/command.py,sha256=hSxL67zvlROMVyUtERc7UDRlJ7Bbk28seGG_RCtuWa0,90945
|
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
|
20
|
+
pyghmi/ipmi/oem/generic.py,sha256=Ih8BoVebCCmgmHgbO1gJuprecRXG8vi2n4bZ-Oy6r7c,18966
|
21
21
|
pyghmi/ipmi/oem/lookup.py,sha256=Ex00OEEolsdWCVhyP0QDGzOxHGEA7sKI8a8fW4kJPD8,3653
|
22
22
|
pyghmi/ipmi/oem/lenovo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
23
|
-
pyghmi/ipmi/oem/lenovo/config.py,sha256=
|
23
|
+
pyghmi/ipmi/oem/lenovo/config.py,sha256=aNN5dvbGlNpWlrrvlWthyAO0PGn6A9Pf75wjhVleu_k,26692
|
24
24
|
pyghmi/ipmi/oem/lenovo/cpu.py,sha256=POZMP9n2S1v6r8iNStkCOVEiQYs3ut3RqL_9x-kgOFw,1651
|
25
25
|
pyghmi/ipmi/oem/lenovo/dimm.py,sha256=L8k1aBgtvxqyubDBNKdDkz80pDE8Sck1eMLcMz1GhFI,1875
|
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=
|
30
|
-
pyghmi/ipmi/oem/lenovo/imm.py,sha256=
|
29
|
+
pyghmi/ipmi/oem/lenovo/handler.py,sha256=ubLUJS9c3yuZiCH1m2I5-NFI9CbpRh3_okijQxARoxM,57236
|
30
|
+
pyghmi/ipmi/oem/lenovo/imm.py,sha256=MFd26rim8d3yVrKWxXVchaXNch93ACelgDqmjxVZu9s,113461
|
31
31
|
pyghmi/ipmi/oem/lenovo/inventory.py,sha256=FLJJinw-ibdHtf3KmrTzhWXbQrpxq3TSycVf96Hg7cw,5911
|
32
|
-
pyghmi/ipmi/oem/lenovo/nextscale.py,sha256=
|
32
|
+
pyghmi/ipmi/oem/lenovo/nextscale.py,sha256=bvY7MLOGMioXT7F6HBt5BBftGAEYNo2GkBNjwysPAWs,43734
|
33
33
|
pyghmi/ipmi/oem/lenovo/pci.py,sha256=S7p-5Q2qu2YhlffN-LEmIvjfXim6OlfYL7Q6r6VZqJ4,2020
|
34
34
|
pyghmi/ipmi/oem/lenovo/psu.py,sha256=ISgGe7MdLd1Z7MiRcgJ0gyC92m-4CDNmhMs-H0T3GVY,3098
|
35
35
|
pyghmi/ipmi/oem/lenovo/raid_controller.py,sha256=hr9W17FwgpG9B544eebkEH88gOlU6M4gIapZq7WOPsw,2335
|
@@ -37,25 +37,25 @@ pyghmi/ipmi/oem/lenovo/raid_drive.py,sha256=NZoQrgipBXrxYhSXShpHkaylv9aTxwGNmv7P
|
|
37
37
|
pyghmi/ipmi/private/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
38
38
|
pyghmi/ipmi/private/constants.py,sha256=ViuB_nXsMM5LjkT9FGf2it2KQKvEehd5cZJgewjmVds,66936
|
39
39
|
pyghmi/ipmi/private/localsession.py,sha256=DThuwgvsAJT2AQ8byg4TA8AZG4hBBHnT-pxIJRsISCE,4879
|
40
|
-
pyghmi/ipmi/private/serversession.py,sha256=
|
40
|
+
pyghmi/ipmi/private/serversession.py,sha256=H5toINVu7sEuc13MWJHVG3zqNCyMY1tYXjQ4ZOOjQfE,16411
|
41
41
|
pyghmi/ipmi/private/session.py,sha256=276g11vswSuXxEkXaCqfBE68eStZ4KymKS5uDGHzjJQ,81797
|
42
42
|
pyghmi/ipmi/private/simplesession.py,sha256=cNGaoT0uWIKDut6gUG9kAOX_b_qTzdB26R6I6Qk7cns,58834
|
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=
|
46
|
+
pyghmi/redfish/command.py,sha256=0mLgsynfiyfi_i4wtL3ZqPR6CeeHajj-azqTW7EUE3I,61278
|
47
47
|
pyghmi/redfish/oem/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
48
|
-
pyghmi/redfish/oem/generic.py,sha256=
|
48
|
+
pyghmi/redfish/oem/generic.py,sha256=5RalOmcBlnvVx05sgo9xCYkTVZ8CrhKMb7pDTtuLAls,56718
|
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
54
|
pyghmi/redfish/oem/lenovo/main.py,sha256=bnx8LuC_C4_OluNR8JSHIxtSlM4_jdBb4cUzJM6mazE,2597
|
55
|
-
pyghmi/redfish/oem/lenovo/smm3.py,sha256=
|
56
|
-
pyghmi/redfish/oem/lenovo/tsma.py,sha256=
|
57
|
-
pyghmi/redfish/oem/lenovo/xcc.py,sha256=
|
58
|
-
pyghmi/redfish/oem/lenovo/xcc3.py,sha256=
|
55
|
+
pyghmi/redfish/oem/lenovo/smm3.py,sha256=W3PKHpFNj5Ujql-neWTH3UgYGDZXQlBvC1aRX97GV8A,5982
|
56
|
+
pyghmi/redfish/oem/lenovo/tsma.py,sha256=6GELCuriumARj_kv7fgqtUpo9ekiWHpQcM9v_mnGILI,34645
|
57
|
+
pyghmi/redfish/oem/lenovo/xcc.py,sha256=78ksNj2-0jquj61lmAZldy3DdcR5KndqbLQ2Y4ZSFOM,84234
|
58
|
+
pyghmi/redfish/oem/lenovo/xcc3.py,sha256=KBJQLAIpaU32bfFzKxZ9jH7oHnGgJIBz0bMZT-TMKy8,20989
|
59
59
|
pyghmi/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
60
60
|
pyghmi/tests/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
61
61
|
pyghmi/tests/unit/base.py,sha256=xWImA7zPRgfrEe2xAdRZ6w_dLwExGRBJ5CBybssUQGg,744
|
@@ -64,11 +64,11 @@ pyghmi/tests/unit/ipmi/test_sdr.py,sha256=vb3iLY0cnHJ2K_m4xgYUjEcbPd_ZYhYx-uBowB
|
|
64
64
|
pyghmi/util/__init__.py,sha256=GZLBWJiun2Plb_VE9dDSh4_PQMCha3gA7QLUqx3oSYI,25
|
65
65
|
pyghmi/util/parse.py,sha256=6VlyBCEcE8gy8PJWmEDdtCyWATaKwPaTswCdioPCWOE,2120
|
66
66
|
pyghmi/util/webclient.py,sha256=782_yMuy_LuN9E2vh2EJ-R64X_EyvLLRuurE__jfn20,15371
|
67
|
-
pyghmi-1.
|
68
|
-
pyghmi-1.
|
69
|
-
pyghmi-1.
|
70
|
-
pyghmi-1.
|
71
|
-
pyghmi-1.
|
72
|
-
pyghmi-1.
|
73
|
-
pyghmi-1.
|
74
|
-
pyghmi-1.
|
67
|
+
pyghmi-1.6.1.dist-info/AUTHORS,sha256=-0iHKtdQwAJfAGKcruCnvcQXrXuE_LgBZ3P15DJI1xY,2044
|
68
|
+
pyghmi-1.6.1.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
69
|
+
pyghmi-1.6.1.dist-info/METADATA,sha256=t5NiZ7qQvKHYxH4qSU85HdVzQygxx10AKpqsUT6qk8c,1136
|
70
|
+
pyghmi-1.6.1.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
|
71
|
+
pyghmi-1.6.1.dist-info/entry_points.txt,sha256=-OpJliDzATxmuPXK0VR3Ma-Yk_i4ZhfIIB-12A26dSI,168
|
72
|
+
pyghmi-1.6.1.dist-info/pbr.json,sha256=WluQ4jTELF6lRCdfFuR9bmRh8RujczTU1WXGdV0F-sM,46
|
73
|
+
pyghmi-1.6.1.dist-info/top_level.txt,sha256=aDtt6S9eVu6-tNdaUs4Pz9PbdUd69bziZZMhNvk9Ulc,7
|
74
|
+
pyghmi-1.6.1.dist-info/RECORD,,
|
@@ -0,0 +1 @@
|
|
1
|
+
{"git_version": "33cff21", "is_release": true}
|
pyghmi-1.5.77.dist-info/pbr.json
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
{"git_version": "4bbf63c", "is_release": true}
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|