pyghmi 1.6.5__py3-none-any.whl → 1.6.6__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 +17 -4
- pyghmi/ipmi/oem/generic.py +1 -1
- pyghmi/ipmi/oem/lenovo/handler.py +2 -2
- pyghmi/ipmi/oem/lenovo/imm.py +99 -89
- pyghmi/redfish/command.py +32 -40
- pyghmi/redfish/oem/dell/main.py +1 -1
- pyghmi/redfish/oem/generic.py +159 -5
- pyghmi/redfish/oem/lenovo/main.py +12 -4
- pyghmi/redfish/oem/lenovo/xcc.py +54 -29
- pyghmi/redfish/oem/lenovo/xcc3.py +10 -2
- pyghmi/redfish/oem/lookup.py +10 -5
- {pyghmi-1.6.5.dist-info → pyghmi-1.6.6.dist-info}/METADATA +1 -1
- {pyghmi-1.6.5.dist-info → pyghmi-1.6.6.dist-info}/RECORD +19 -19
- pyghmi-1.6.6.dist-info/pbr.json +1 -0
- pyghmi-1.6.5.dist-info/pbr.json +0 -1
- {pyghmi-1.6.5.dist-info → pyghmi-1.6.6.dist-info}/AUTHORS +0 -0
- {pyghmi-1.6.5.dist-info → pyghmi-1.6.6.dist-info}/LICENSE +0 -0
- {pyghmi-1.6.5.dist-info → pyghmi-1.6.6.dist-info}/WHEEL +0 -0
- {pyghmi-1.6.5.dist-info → pyghmi-1.6.6.dist-info}/entry_points.txt +0 -0
- {pyghmi-1.6.5.dist-info → pyghmi-1.6.6.dist-info}/top_level.txt +0 -0
pyghmi/ipmi/command.py
CHANGED
@@ -842,6 +842,12 @@ class Command(object):
|
|
842
842
|
fetchdata = fetched['data']
|
843
843
|
if bytearray(fetchdata)[0] != 17:
|
844
844
|
return None
|
845
|
+
if param == 0x14:
|
846
|
+
vlaninfo = struct.unpack('<H', fetchdata[1:])[0]
|
847
|
+
if vlaninfo & 0x8000 == 0x8000:
|
848
|
+
return vlaninfo & 0xfff
|
849
|
+
else:
|
850
|
+
return 'off'
|
845
851
|
if len(fetchdata) == 5: # IPv4 address
|
846
852
|
if prefixlen:
|
847
853
|
return _mask_to_cidr(fetchdata[1:])
|
@@ -936,7 +942,7 @@ class Command(object):
|
|
936
942
|
return retdata
|
937
943
|
|
938
944
|
def set_net_configuration(self, ipv4_address=None, ipv4_configuration=None,
|
939
|
-
ipv4_gateway=None, channel=None):
|
945
|
+
ipv4_gateway=None, vlan_id=None, channel=None):
|
940
946
|
"""Set network configuration data.
|
941
947
|
|
942
948
|
Apply desired network configuration data, leaving unspecified
|
@@ -950,7 +956,7 @@ class Command(object):
|
|
950
956
|
:param channel: LAN channel to configure, defaults to autodetect
|
951
957
|
"""
|
952
958
|
if (ipv4_address is None and ipv4_configuration is None
|
953
|
-
and ipv4_gateway is None):
|
959
|
+
and ipv4_gateway is None and vlan_id is None):
|
954
960
|
return
|
955
961
|
if channel is None:
|
956
962
|
channel = self.get_network_channel()
|
@@ -977,6 +983,12 @@ class Command(object):
|
|
977
983
|
if ipv4_gateway is not None:
|
978
984
|
cmddata = bytearray((channel, 12)) + socket.inet_aton(ipv4_gateway)
|
979
985
|
self.xraw_command(netfn=0xc, command=1, data=cmddata)
|
986
|
+
if vlan_id in ('off', 0, '0'):
|
987
|
+
cmddata = bytearray((channel, 0x14, 0, 0))
|
988
|
+
self.xraw_command(netfn=0xc, command=1, data=cmddata)
|
989
|
+
elif vlan_id is not None:
|
990
|
+
cmddata = bytearray((channel, 0x14)) + struct.pack('<H', int(vlan_id) | 0x8000)
|
991
|
+
self.xraw_command(netfn=0xc, command=1, data=cmddata)
|
980
992
|
|
981
993
|
def get_storage_configuration(self):
|
982
994
|
""""Get storage configuration data
|
@@ -1071,6 +1083,7 @@ class Command(object):
|
|
1071
1083
|
retdata['ipv4_gateway_mac'] = self._fetch_lancfg_param(channel, 13)
|
1072
1084
|
retdata['ipv4_backup_gateway_mac'] = self._fetch_lancfg_param(
|
1073
1085
|
channel, 15)
|
1086
|
+
retdata['vlan_id'] = self._fetch_lancfg_param(channel, 0x14)
|
1074
1087
|
self.oem_init()
|
1075
1088
|
self._oem.add_extra_net_configuration(retdata, channel)
|
1076
1089
|
return retdata
|
@@ -2166,14 +2179,14 @@ class Command(object):
|
|
2166
2179
|
|
2167
2180
|
return True
|
2168
2181
|
|
2169
|
-
def get_firmware(self, components=()):
|
2182
|
+
def get_firmware(self, components=(), category=None):
|
2170
2183
|
"""Retrieve OEM Firmware information"""
|
2171
2184
|
|
2172
2185
|
self.oem_init()
|
2173
2186
|
mcinfo = self.xraw_command(netfn=6, command=1)
|
2174
2187
|
major, minor = struct.unpack('BB', mcinfo['data'][2:4])
|
2175
2188
|
bmcver = '{0}.{1}'.format(major, hex(minor)[2:])
|
2176
|
-
return self._oem.get_oem_firmware(bmcver, components)
|
2189
|
+
return self._oem.get_oem_firmware(bmcver, components, category)
|
2177
2190
|
|
2178
2191
|
def get_capping_enabled(self):
|
2179
2192
|
"""Get PSU based power capping status
|
pyghmi/ipmi/oem/generic.py
CHANGED
@@ -279,7 +279,7 @@ class OEMHandler(object):
|
|
279
279
|
fru['oem_parser'] = None
|
280
280
|
return fru
|
281
281
|
|
282
|
-
def get_oem_firmware(self, bmcver, components):
|
282
|
+
def get_oem_firmware(self, bmcver, components, category):
|
283
283
|
"""Get Firmware information."""
|
284
284
|
|
285
285
|
# Here the bmc version is passed into the OEM handler, to allow
|
@@ -842,7 +842,7 @@ class OEMHandler(generic.OEMHandler):
|
|
842
842
|
return False
|
843
843
|
return False
|
844
844
|
|
845
|
-
def get_oem_firmware(self, bmcver, components):
|
845
|
+
def get_oem_firmware(self, bmcver, components, category):
|
846
846
|
if self.has_tsm or self.has_ami or self.has_asrock:
|
847
847
|
command = firmware.get_categories()["firmware"]
|
848
848
|
fw_cmd = self.get_cmd_type("firmware", command)
|
@@ -865,7 +865,7 @@ class OEMHandler(generic.OEMHandler):
|
|
865
865
|
bios_versions,
|
866
866
|
self.has_asrock)
|
867
867
|
elif self.has_imm:
|
868
|
-
return self.immhandler.get_firmware_inventory(bmcver, components)
|
868
|
+
return self.immhandler.get_firmware_inventory(bmcver, components, category)
|
869
869
|
elif self.is_fpc:
|
870
870
|
return nextscale.get_fpc_firmware(bmcver, self.ipmicmd,
|
871
871
|
self._fpc_variant)
|
pyghmi/ipmi/oem/lenovo/imm.py
CHANGED
@@ -556,84 +556,86 @@ class IMMClient(object):
|
|
556
556
|
def fetch_psu_firmware(self):
|
557
557
|
return []
|
558
558
|
|
559
|
-
def fetch_agentless_firmware(self):
|
559
|
+
def fetch_agentless_firmware(self, needdisk=True, needadp=True):
|
560
560
|
skipkeys = set([])
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
if
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
if 'versionStr' in firm and firm['versionStr']:
|
605
|
-
bdata['version'] = firm['versionStr']
|
606
|
-
if ('releaseDate' in firm
|
607
|
-
and firm['releaseDate']
|
608
|
-
and firm['releaseDate'] != 'N/A'):
|
609
|
-
try:
|
610
|
-
bdata['date'] = self._parse_builddate(
|
611
|
-
firm['releaseDate'])
|
612
|
-
except ValueError:
|
613
|
-
pass
|
614
|
-
yield '{0} {1}'.format(aname, fname), bdata
|
615
|
-
for fwi in fwu.get('items', []):
|
616
|
-
if fwi.get('key', -1) == adata.get('key', -2):
|
617
|
-
skipkeys.add(fwi['key'])
|
618
|
-
if fwi.get('fw_status', 0) == 2:
|
561
|
+
if needadp:
|
562
|
+
cd = self.get_cached_data('lenovo_cached_adapters_fu')
|
563
|
+
if cd:
|
564
|
+
adapterdata, fwu = cd
|
565
|
+
else:
|
566
|
+
adapterdata = None
|
567
|
+
if not adapterdata:
|
568
|
+
if self.updating:
|
569
|
+
raise pygexc.TemporaryError(
|
570
|
+
'Cannot read extended inventory during firmware update')
|
571
|
+
if self.wc:
|
572
|
+
adapterdata = self.wc.grab_json_response(
|
573
|
+
self.ADP_URL, referer=self.adp_referer)
|
574
|
+
if self.ADP_FU_URL:
|
575
|
+
fwu = self.wc.grab_json_response(
|
576
|
+
self.ADP_FU_URL, referer=self.adp_referer)
|
577
|
+
else:
|
578
|
+
fwu = {}
|
579
|
+
if adapterdata:
|
580
|
+
self.datacache['lenovo_cached_adapters_fu'] = (
|
581
|
+
(adapterdata, fwu), util._monotonic_time())
|
582
|
+
if adapterdata and 'items' in adapterdata:
|
583
|
+
anames = {}
|
584
|
+
for adata in adapterdata['items']:
|
585
|
+
aname = adata[self.ADP_NAME]
|
586
|
+
if aname in anames:
|
587
|
+
anames[aname] += 1
|
588
|
+
aname = '{0} {1}'.format(aname, anames[aname])
|
589
|
+
else:
|
590
|
+
anames[aname] = 1
|
591
|
+
donenames = set([])
|
592
|
+
for fundata in adata[self.ADP_FUN]:
|
593
|
+
fdata = fundata.get('firmwares', ())
|
594
|
+
for firm in fdata:
|
595
|
+
fname = firm['firmwareName'].rstrip()
|
596
|
+
if '.' in fname:
|
597
|
+
fname = firm['description'].rstrip()
|
598
|
+
if fname in donenames:
|
599
|
+
# ignore redundant entry
|
600
|
+
continue
|
601
|
+
if not fname:
|
602
|
+
continue
|
603
|
+
donenames.add(fname)
|
619
604
|
bdata = {}
|
620
|
-
if '
|
621
|
-
bdata['version'] =
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
605
|
+
if 'versionStr' in firm and firm['versionStr']:
|
606
|
+
bdata['version'] = firm['versionStr']
|
607
|
+
if ('releaseDate' in firm
|
608
|
+
and firm['releaseDate']
|
609
|
+
and firm['releaseDate'] != 'N/A'):
|
610
|
+
try:
|
611
|
+
bdata['date'] = self._parse_builddate(
|
612
|
+
firm['releaseDate'])
|
613
|
+
except ValueError:
|
614
|
+
pass
|
615
|
+
yield '{0} {1}'.format(aname, fname), bdata
|
616
|
+
for fwi in fwu.get('items', []):
|
617
|
+
if fwi.get('key', -1) == adata.get('key', -2):
|
618
|
+
skipkeys.add(fwi['key'])
|
619
|
+
if fwi.get('fw_status', 0) == 2:
|
620
|
+
bdata = {}
|
621
|
+
if 'fw_pkg_version' in fwi and fwi['fw_pkg_version']:
|
622
|
+
bdata['version'] = fwi['fw_pkg_version']
|
623
|
+
elif 'fw_version_pend' in fwi:
|
624
|
+
bdata['version'] = fwi['fw_version_pend']
|
625
|
+
yield '{0} Pending Update'.format(aname), bdata
|
626
|
+
for fwi in fwu.get('items', []):
|
627
|
+
if fwi.get('key', -1) > 0 and fwi['key'] not in skipkeys:
|
631
628
|
bdata = {}
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
629
|
+
bdata['version'] = fwi['fw_version']
|
630
|
+
yield fwi['adapterName'], bdata
|
631
|
+
if fwi.get('fw_status', 0) == 2:
|
632
|
+
bdata = {}
|
633
|
+
if 'fw_version_pend' in fwi:
|
634
|
+
bdata['version'] = fwi['fw_version_pend']
|
635
|
+
yield '{0} Pending Update'.format(fwi['adapterName']), bdata
|
636
|
+
if needdisk:
|
637
|
+
for disk in self.disk_inventory():
|
638
|
+
yield disk
|
637
639
|
self.weblogout()
|
638
640
|
|
639
641
|
def disk_inventory(self, mode=0):
|
@@ -829,11 +831,13 @@ class IMMClient(object):
|
|
829
831
|
self.weblogout()
|
830
832
|
return hwmap
|
831
833
|
|
832
|
-
def get_firmware_inventory(self, bmcver, components):
|
834
|
+
def get_firmware_inventory(self, bmcver, components, category):
|
833
835
|
# First we fetch the system firmware found in imm properties
|
834
836
|
# then check for agentless, if agentless, get adapter info using
|
835
837
|
# https, using the caller TLS verification scheme
|
836
838
|
components = set(components)
|
839
|
+
if 'core' in components:
|
840
|
+
category = 'core'
|
837
841
|
if not components or set(('imm', 'xcc', 'bmc', 'core')) & components:
|
838
842
|
rsp = self.ipmicmd.xraw_command(netfn=0x3a, command=0x50)
|
839
843
|
immverdata = self.parse_imm_buildinfo(rsp['data'])
|
@@ -1811,12 +1815,16 @@ class XCCClient(IMMClient):
|
|
1811
1815
|
{'model': psu['model'],
|
1812
1816
|
'version': psu['version']})
|
1813
1817
|
|
1814
|
-
def get_firmware_inventory(self, bmcver, components):
|
1818
|
+
def get_firmware_inventory(self, bmcver, components, category):
|
1815
1819
|
# First we fetch the system firmware found in imm properties
|
1816
1820
|
# then check for agentless, if agentless, get adapter info using
|
1817
1821
|
# https, using the caller TLS verification scheme
|
1822
|
+
if 'core' in components:
|
1823
|
+
category = 'core'
|
1824
|
+
if not category:
|
1825
|
+
category = 'all'
|
1818
1826
|
components = set(components)
|
1819
|
-
if (not components
|
1827
|
+
if category in ('all', 'core') and (not components
|
1820
1828
|
or set(('core', 'imm', 'bmc', 'xcc')) & components):
|
1821
1829
|
rsp = self.ipmicmd.xraw_command(netfn=0x3a, command=0x50)
|
1822
1830
|
immverdata = self.parse_imm_buildinfo(rsp['data'])
|
@@ -1854,7 +1862,7 @@ class XCCClient(IMMClient):
|
|
1854
1862
|
'date': '/v2/ibmc/dm/fw/imm3/primary_pending_build_date'})
|
1855
1863
|
if bdata:
|
1856
1864
|
yield '{0} Pending Update'.format(self.bmcname), bdata
|
1857
|
-
if not components or set(('core', 'uefi', 'bios')) & components:
|
1865
|
+
if category in ('all', 'core') and not components or set(('core', 'uefi', 'bios')) & components:
|
1858
1866
|
bdata = self.fetch_grouped_properties({
|
1859
1867
|
'build': '/v2/bios/build_id',
|
1860
1868
|
'version': '/v2/bios/build_version',
|
@@ -1867,7 +1875,7 @@ class XCCClient(IMMClient):
|
|
1867
1875
|
'build': '/v2/bios/pending_build_id'})
|
1868
1876
|
if bdata:
|
1869
1877
|
yield 'UEFI Pending Update', bdata
|
1870
|
-
if not components or set(('lxpm', 'core')) & components:
|
1878
|
+
if category in ('all', 'core') and not components or set(('lxpm', 'core')) & components:
|
1871
1879
|
bdata = self.fetch_grouped_properties({
|
1872
1880
|
'build': '/v2/tdm/build_id',
|
1873
1881
|
'version': '/v2/tdm/build_version',
|
@@ -1888,7 +1896,7 @@ class XCCClient(IMMClient):
|
|
1888
1896
|
})
|
1889
1897
|
if bdata:
|
1890
1898
|
yield 'LXPM Linux Driver Bundle', bdata
|
1891
|
-
if not components or set(('lxum', 'core')):
|
1899
|
+
if category in ('all', 'core') and (not components or set(('lxum', 'core'))):
|
1892
1900
|
sysinf = self.wc.grab_json_response('/api/dataset/sys_info')
|
1893
1901
|
for item in sysinf.get('items', {}):
|
1894
1902
|
for firm in item.get('firmware', []):
|
@@ -1899,7 +1907,7 @@ class XCCClient(IMMClient):
|
|
1899
1907
|
}
|
1900
1908
|
if firm['type'] == 10:
|
1901
1909
|
yield ('LXUM', firminfo)
|
1902
|
-
if not components or set(('core', 'fpga')) in components:
|
1910
|
+
if category in ('all', 'core') and (not components or set(('core', 'fpga')) in components):
|
1903
1911
|
try:
|
1904
1912
|
fpga = self.ipmicmd.xraw_command(netfn=0x3a, command=0x6b,
|
1905
1913
|
data=(0,))
|
@@ -1909,11 +1917,12 @@ class XCCClient(IMMClient):
|
|
1909
1917
|
except pygexc.IpmiException as ie:
|
1910
1918
|
if ie.ipmicode != 193:
|
1911
1919
|
raise
|
1912
|
-
|
1913
|
-
|
1914
|
-
|
1915
|
-
|
1916
|
-
|
1920
|
+
needdiskfirmware = category in ('all', 'disks')
|
1921
|
+
needadapterfirmware = category in ('all', 'adapters')
|
1922
|
+
needpsufirmware = category in ('all', 'misc')
|
1923
|
+
for firm in self.fetch_agentless_firmware(needdisk=needdiskfirmware, needadp=needadapterfirmware):
|
1924
|
+
yield firm
|
1925
|
+
if needpsufirmware:
|
1917
1926
|
for firm in self.fetch_psu_firmware():
|
1918
1927
|
yield firm
|
1919
1928
|
|
@@ -2089,13 +2098,14 @@ class XCCClient(IMMClient):
|
|
2089
2098
|
'progress': 100 * wc.get_upload_progress()})
|
2090
2099
|
if uploadthread.rspstatus >= 300 or uploadthread.rspstatus < 200:
|
2091
2100
|
rsp = uploadthread.rsp
|
2092
|
-
errmsg = ''
|
2101
|
+
errmsg = f'Upload failed with HTTP status {uploadthread.rspstatus}'
|
2093
2102
|
try:
|
2094
2103
|
rsp = json.loads(rsp)
|
2095
2104
|
errmsg = (
|
2096
2105
|
rsp['error']['@Message.ExtendedInfo'][0]['Message'])
|
2097
2106
|
except Exception:
|
2098
|
-
|
2107
|
+
errmsg = errmsg + ': ' + str(rsp)
|
2108
|
+
raise Exception(errmsg)
|
2099
2109
|
raise Exception(errmsg)
|
2100
2110
|
rsp = json.loads(uploadthread.rsp)
|
2101
2111
|
monitorurl = rsp['@odata.id']
|
pyghmi/redfish/command.py
CHANGED
@@ -188,43 +188,11 @@ class Command(object):
|
|
188
188
|
self._varsensormap = {}
|
189
189
|
self.powerurl = None
|
190
190
|
self.sysurl = None
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
if res[1] == 401:
|
195
|
-
raise exc.PyghmiException('Access Denied')
|
196
|
-
elif res[1] < 200 or res[1] >= 300:
|
197
|
-
raise exc.PyghmiException(repr(res[0]))
|
198
|
-
bmcs = res[0]['Members']
|
199
|
-
if len(bmcs) == 1:
|
200
|
-
self._varbmcurl = bmcs[0]['@odata.id']
|
191
|
+
tmpoem = oem.get_oem_handler({}, sysurl, self.wc, self._urlcache, self,
|
192
|
+
rootinfo=overview)
|
193
|
+
self._varbmcurl = tmpoem.get_default_mgrurl()
|
201
194
|
if 'Systems' in overview:
|
202
|
-
|
203
|
-
res = self.wc.grab_json_response_with_status(systems)
|
204
|
-
if res[1] == 401:
|
205
|
-
raise exc.PyghmiException('Access Denied')
|
206
|
-
elif res[1] < 200 or res[1] >= 300:
|
207
|
-
raise exc.PyghmiException(repr(res[0]))
|
208
|
-
members = res[0]
|
209
|
-
systems = members['Members']
|
210
|
-
if sysurl:
|
211
|
-
for system in systems:
|
212
|
-
if system['@odata.id'] == sysurl or system['@odata.id'].split('/')[-1] == sysurl:
|
213
|
-
self.sysurl = system['@odata.id']
|
214
|
-
break
|
215
|
-
else:
|
216
|
-
raise exc.PyghmiException(
|
217
|
-
'Specified sysurl not found: {0}'.format(sysurl))
|
218
|
-
else:
|
219
|
-
if len(systems) > 1:
|
220
|
-
systems = [x for x in systems if 'DPU' not in x['@odata.id']]
|
221
|
-
if len(systems) > 1:
|
222
|
-
raise exc.PyghmiException(
|
223
|
-
'Multi system manager, sysurl is required parameter')
|
224
|
-
if len(systems):
|
225
|
-
self.sysurl = systems[0]['@odata.id']
|
226
|
-
else:
|
227
|
-
self.sysurl = None
|
195
|
+
self.sysurl = tmpoem.get_default_sysurl()
|
228
196
|
self.powerurl = self.sysinfo.get('Actions', {}).get(
|
229
197
|
'#ComputerSystem.Reset', {}).get('target', None)
|
230
198
|
|
@@ -271,6 +239,16 @@ class Command(object):
|
|
271
239
|
okroles.add('ReadOnly')
|
272
240
|
return okroles
|
273
241
|
|
242
|
+
def get_trusted_cas(self):
|
243
|
+
for ca in self.oem.get_trusted_cas():
|
244
|
+
yield ca
|
245
|
+
|
246
|
+
def add_trusted_ca(self, pemdata):
|
247
|
+
return self.oem.add_trusted_ca(pemdata)
|
248
|
+
|
249
|
+
def del_trusted_ca(self, certid):
|
250
|
+
return self.oem.del_trusted_ca(certid)
|
251
|
+
|
274
252
|
def get_users(self):
|
275
253
|
"""get list of users and channel access information (helper)
|
276
254
|
|
@@ -1026,13 +1004,13 @@ class Command(object):
|
|
1026
1004
|
self._do_web_request(nicurl, patch, 'PATCH')
|
1027
1005
|
|
1028
1006
|
def set_net_configuration(self, ipv4_address=None, ipv4_configuration=None,
|
1029
|
-
ipv4_gateway=None, name=None):
|
1007
|
+
ipv4_gateway=None, vlan_id=None, name=None):
|
1030
1008
|
patch = {}
|
1031
1009
|
ipinfo = {}
|
1032
1010
|
dodhcp = None
|
1033
1011
|
netmask = None
|
1034
1012
|
if (ipv4_address is None and ipv4_configuration is None
|
1035
|
-
and ipv4_gateway is None):
|
1013
|
+
and ipv4_gateway is None and vlan_id is None):
|
1036
1014
|
return
|
1037
1015
|
if ipv4_address:
|
1038
1016
|
if '/' in ipv4_address:
|
@@ -1054,6 +1032,10 @@ class Command(object):
|
|
1054
1032
|
or 'IPv4StaticAddresses' in patch):
|
1055
1033
|
dodhcp = False
|
1056
1034
|
patch['DHCPv4'] = {'DHCPEnabled': False}
|
1035
|
+
if vlan_id in ('off', 0, '0'):
|
1036
|
+
patch['VLAN'] = {'VLANEnable': False}
|
1037
|
+
elif vlan_id:
|
1038
|
+
patch['VLAN'] = {'VLANEnable': True, 'VLANId': int(vlan_id)}
|
1057
1039
|
if patch:
|
1058
1040
|
nicurl = self._get_bmc_nic_url(name)
|
1059
1041
|
try:
|
@@ -1079,6 +1061,11 @@ class Command(object):
|
|
1079
1061
|
if gws:
|
1080
1062
|
for gw in gws:
|
1081
1063
|
retdata['static_gateway'] = gw['Address']
|
1064
|
+
tagged = netcfg.get('VLAN', {}).get('VLANEnabled', False)
|
1065
|
+
if tagged:
|
1066
|
+
retdata['vlan_id'] = netcfg.get('VLAN', {}).get('VLANId', None)
|
1067
|
+
else:
|
1068
|
+
retdata['vlan_id'] = 'off'
|
1082
1069
|
return retdata
|
1083
1070
|
|
1084
1071
|
def get_net_configuration(self, name=None):
|
@@ -1101,6 +1088,11 @@ class Command(object):
|
|
1101
1088
|
hasgateway = _mask_to_cidr(currip['Gateway'])
|
1102
1089
|
retval['ipv4_gateway'] = currip['Gateway'] if hasgateway else None
|
1103
1090
|
retval['ipv4_configuration'] = currip['AddressOrigin']
|
1091
|
+
tagged = netcfg.get('VLAN', {}).get('VLANEnable', False)
|
1092
|
+
if tagged:
|
1093
|
+
retval['vlan_id'] = netcfg.get('VLAN', {}).get('VLANId', None)
|
1094
|
+
else:
|
1095
|
+
retval['vlan_id'] = 'off'
|
1104
1096
|
return retval
|
1105
1097
|
|
1106
1098
|
def get_hostname(self):
|
@@ -1111,10 +1103,10 @@ class Command(object):
|
|
1111
1103
|
self._do_web_request(self._bmcnicurl,
|
1112
1104
|
{'HostName': hostname}, 'PATCH')
|
1113
1105
|
|
1114
|
-
def get_firmware(self, components=()):
|
1106
|
+
def get_firmware(self, components=(), category=None):
|
1115
1107
|
self._fwnamemap = {}
|
1116
1108
|
try:
|
1117
|
-
for firminfo in self.oem.get_firmware_inventory(components, self):
|
1109
|
+
for firminfo in self.oem.get_firmware_inventory(components, self, category):
|
1118
1110
|
yield firminfo
|
1119
1111
|
except exc.BypassGenericBehavior:
|
1120
1112
|
return
|
pyghmi/redfish/oem/dell/main.py
CHANGED
@@ -15,6 +15,6 @@
|
|
15
15
|
from pyghmi.redfish.oem.dell import idrac
|
16
16
|
|
17
17
|
|
18
|
-
def get_handler(sysinfo, sysurl, webclient, cache, cmd):
|
18
|
+
def get_handler(sysinfo, sysurl, webclient, cache, cmd, rootinfo={}):
|
19
19
|
return idrac.OEMHandler(sysinfo, sysurl, webclient, cache,
|
20
20
|
gpool=cmd._gpool)
|
pyghmi/redfish/oem/generic.py
CHANGED
@@ -23,6 +23,7 @@ from datetime import timedelta
|
|
23
23
|
from dateutil import tz
|
24
24
|
import socket
|
25
25
|
import time
|
26
|
+
import uuid
|
26
27
|
|
27
28
|
import pyghmi.constants as const
|
28
29
|
import pyghmi.exceptions as exc
|
@@ -31,6 +32,27 @@ import pyghmi.util.webclient as webclient
|
|
31
32
|
from pyghmi.util.parse import parse_time
|
32
33
|
|
33
34
|
|
35
|
+
def _pem_to_dict(pemdata, uefi=False):
|
36
|
+
"""Pull PEM into a dict
|
37
|
+
|
38
|
+
Accepts a file-like or a string or bytes.
|
39
|
+
|
40
|
+
A dict with the PEM as a value for CertificateString is created.
|
41
|
+
If uefi, then "UefiSignatureOwner" is also created with a random GUID.
|
42
|
+
This is how redfish expects certificate information for CAs to be provided for
|
43
|
+
UEFI and for itself.
|
44
|
+
"""
|
45
|
+
if hasattr(pemdata, 'read'):
|
46
|
+
pemdata = pemdata.read()
|
47
|
+
if isinstance(pemdata, bytes):
|
48
|
+
pemdata = pemdata.decode('utf-8')
|
49
|
+
cert_dict = {
|
50
|
+
'CertificateString': pemdata,
|
51
|
+
'CertificateType': 'PEM',
|
52
|
+
}
|
53
|
+
if uefi:
|
54
|
+
cert_dict['UefiSignatureOwner'] = str(uuid.uuid4())
|
55
|
+
return cert_dict
|
34
56
|
|
35
57
|
class SensorReading(object):
|
36
58
|
def __init__(self, healthinfo, sensor=None, value=None, units=None,
|
@@ -188,17 +210,75 @@ class OEMHandler(object):
|
|
188
210
|
hostnic = None
|
189
211
|
usegenericsensors = True
|
190
212
|
|
191
|
-
def
|
213
|
+
def _invalidate_url_cache(self, url):
|
214
|
+
if url is None:
|
215
|
+
return
|
216
|
+
if url in self._urlcache:
|
217
|
+
del self._urlcache[url]
|
218
|
+
if url + '?$expand=.' in self._urlcache:
|
219
|
+
del self._urlcache[url + '?$expand=.']
|
220
|
+
|
221
|
+
def __init__(self, sysinfo, sysurl, webclient, cache, gpool=None, rootinfo={}):
|
192
222
|
self._gpool = gpool
|
193
223
|
self._varsysinfo = sysinfo
|
194
224
|
self._varsysurl = sysurl
|
225
|
+
self._varbmcurl = None
|
195
226
|
self._urlcache = cache
|
196
227
|
self.webclient = webclient
|
197
228
|
self._hwnamemap = {}
|
229
|
+
self._rootinfo = rootinfo
|
230
|
+
if not self._rootinfo:
|
231
|
+
self._rootinfo = self.webclient.grab_json_response(
|
232
|
+
'/redfish/v1/')
|
233
|
+
self._varbmcurl = None
|
234
|
+
self._varsysurl = sysurl
|
198
235
|
|
199
236
|
def get_screenshot(self, outfile):
|
200
237
|
raise exc.UnsupportedFunctionality(
|
201
238
|
'Retrieving screenshot is not implemented for this platform')
|
239
|
+
|
240
|
+
def get_default_mgrurl(self):
|
241
|
+
if not self._varbmcurl and 'Managers' in self._rootinfo:
|
242
|
+
bmcoll = self._rootinfo['Managers']['@odata.id']
|
243
|
+
res = self.webclient.grab_json_response_with_status(bmcoll)
|
244
|
+
if res[1] == 401:
|
245
|
+
raise exc.PyghmiException('Access Denied')
|
246
|
+
elif res[1] < 200 or res[1] >= 300:
|
247
|
+
raise exc.PyghmiException(repr(res[0]))
|
248
|
+
bmcs = res[0]['Members']
|
249
|
+
if len(bmcs) == 1:
|
250
|
+
self._varbmcurl = bmcs[0]['@odata.id']
|
251
|
+
return self._varbmcurl
|
252
|
+
|
253
|
+
def get_default_sysurl(self):
|
254
|
+
if not self._varsysurl and 'Systems' in self._rootinfo:
|
255
|
+
systems = self._rootinfo['Systems']['@odata.id']
|
256
|
+
res = self.webclient.grab_json_response_with_status(systems)
|
257
|
+
if res[1] == 401:
|
258
|
+
raise exc.PyghmiException('Access Denied')
|
259
|
+
elif res[1] < 200 or res[1] >= 300:
|
260
|
+
raise exc.PyghmiException(repr(res[0]))
|
261
|
+
members = res[0]
|
262
|
+
systems = members['Members']
|
263
|
+
if self._varsysurl:
|
264
|
+
for system in systems:
|
265
|
+
if system['@odata.id'] == self._varsysurl or system['@odata.id'].split('/')[-1] == self._varsysurl:
|
266
|
+
self._varsysurl = system['@odata.id']
|
267
|
+
break
|
268
|
+
else:
|
269
|
+
raise exc.PyghmiException(
|
270
|
+
'Specified sysurl not found: {0}'.format(self._varsysurl))
|
271
|
+
else:
|
272
|
+
if len(systems) > 1:
|
273
|
+
systems = [x for x in systems if 'DPU' not in x['@odata.id']]
|
274
|
+
if len(systems) > 1:
|
275
|
+
raise exc.PyghmiException(
|
276
|
+
'Multi system manager, sysurl is required parameter')
|
277
|
+
if len(systems):
|
278
|
+
self._varsysurl = systems[0]['@odata.id']
|
279
|
+
else:
|
280
|
+
self._varsysurl = None
|
281
|
+
return self._varsysurl
|
202
282
|
|
203
283
|
def supports_expand(self, url):
|
204
284
|
# Unfortunately, the state of expand in redfish is pretty dicey,
|
@@ -236,6 +316,68 @@ class OEMHandler(object):
|
|
236
316
|
cputemps.append(temp)
|
237
317
|
return cputemps
|
238
318
|
|
319
|
+
@property
|
320
|
+
def _bmcurl(self):
|
321
|
+
if not self._varbmcurl:
|
322
|
+
self._varbmcurl = self.sysinfo.get('Links', {}).get(
|
323
|
+
'ManagedBy', [{}])[0].get('@odata.id', None)
|
324
|
+
return self._varbmcurl
|
325
|
+
|
326
|
+
@property
|
327
|
+
def sysinfo(self):
|
328
|
+
return self._do_web_request(self._varsysurl)
|
329
|
+
|
330
|
+
def add_trusted_ca(self, pemdata):
|
331
|
+
mgrinfo = self._do_web_request(self._bmcurl)
|
332
|
+
secpolicy = mgrinfo.get('SecurityPolicy', {}).get('@odata.id', None)
|
333
|
+
if secpolicy:
|
334
|
+
secinfo = self._do_web_request(secpolicy)
|
335
|
+
certcoll = secinfo.get('TLS', {}).get('Client', {}).get('TrustedCertificates', {}).get('@odata.id', None)
|
336
|
+
self._invalidate_url_cache(certcoll)
|
337
|
+
if certcoll:
|
338
|
+
certpayload = _pem_to_dict(pemdata)
|
339
|
+
self._do_web_request(certcoll, certpayload)
|
340
|
+
return True
|
341
|
+
raise exc.PyghmiException('Platform does not support adding trusted CAs')
|
342
|
+
|
343
|
+
def del_trusted_ca(self, certid):
|
344
|
+
mgrinfo = self._do_web_request(self._bmcurl)
|
345
|
+
secpolicy = mgrinfo.get('SecurityPolicy', {}).get('@odata.id', None)
|
346
|
+
if secpolicy:
|
347
|
+
secinfo = self._do_web_request(secpolicy)
|
348
|
+
certcoll = secinfo.get('TLS', {}).get('Client', {}).get('TrustedCertificates', {}).get('@odata.id', None)
|
349
|
+
if certcoll:
|
350
|
+
certs = self._get_expanded_data(certcoll)
|
351
|
+
certs = certs.get('Members', [])
|
352
|
+
for cert in certs:
|
353
|
+
if cert.get('Id', '') == certid:
|
354
|
+
self._do_web_request(cert['@odata.id'], method='DELETE')
|
355
|
+
self._invalidate_url_cache(certcoll)
|
356
|
+
return True
|
357
|
+
raise exc.PyghmiException(f'No such certificate found: {certid}')
|
358
|
+
|
359
|
+
def get_trusted_cas(self):
|
360
|
+
mgrinfo = self._do_web_request(self._bmcurl)
|
361
|
+
secpolicy = mgrinfo.get('SecurityPolicy', {}).get('@odata.id', None)
|
362
|
+
if secpolicy:
|
363
|
+
secinfo = self._do_web_request(secpolicy)
|
364
|
+
certcoll = secinfo.get('TLS', {}).get('Client', {}).get('TrustedCertificates', {}).get('@odata.id', None)
|
365
|
+
if certcoll:
|
366
|
+
certs = self._get_expanded_data(certcoll)
|
367
|
+
certs = certs.get('Members', [])
|
368
|
+
for cert in certs:
|
369
|
+
certdesc = {
|
370
|
+
'id': cert.get('Id', ''),
|
371
|
+
'name': cert.get('Name', ''),
|
372
|
+
'pem': cert.get('CertificateString', None),
|
373
|
+
'subject': cert.get('Subject', {}).get('CommonName', ''),
|
374
|
+
'sans': cert.get('Subject', {}).get('AlternativeNames', []),
|
375
|
+
'issuer': cert.get('Issuer', {}).get('CommonName', ''),
|
376
|
+
'validfrom': cert.get('ValidNotBefore', ''),
|
377
|
+
'validto': cert.get('ValidNotAfter', ''),
|
378
|
+
}
|
379
|
+
yield certdesc
|
380
|
+
|
239
381
|
def get_event_log(self, clear=False, fishclient=None, extraurls=[]):
|
240
382
|
bmcinfo = self._do_web_request(fishclient._bmcurl)
|
241
383
|
lsurl = bmcinfo.get('LogServices', {}).get('@odata.id', None)
|
@@ -257,7 +399,16 @@ class OEMHandler(object):
|
|
257
399
|
lurls.extend(extraurls)
|
258
400
|
for lurl in lurls:
|
259
401
|
lurl = lurl['@odata.id']
|
260
|
-
|
402
|
+
try:
|
403
|
+
loginfo = self._do_web_request(lurl, cache=(not clear))
|
404
|
+
except Exception:
|
405
|
+
record = {}
|
406
|
+
record['log_id'] = os.path.basename(lurl)
|
407
|
+
record['message'] = 'Could not retrieve log at {0}'.format(lurl)
|
408
|
+
record['severity'] = const.Health.Ok
|
409
|
+
record['timestamp'] = datetime.now().strftime('%Y-%m-%dT%H:%M:%S')
|
410
|
+
yield record
|
411
|
+
continue
|
261
412
|
entriesurl = loginfo.get('Entries', {}).get('@odata.id', None)
|
262
413
|
if not entriesurl:
|
263
414
|
continue
|
@@ -667,7 +818,7 @@ class OEMHandler(object):
|
|
667
818
|
def _extract_fwinfo(self, inf):
|
668
819
|
return {}
|
669
820
|
|
670
|
-
def get_firmware_inventory(self, components, fishclient):
|
821
|
+
def get_firmware_inventory(self, components, fishclient, category=None):
|
671
822
|
return []
|
672
823
|
|
673
824
|
def set_credentials(self, username, password):
|
@@ -1088,14 +1239,15 @@ class OEMHandler(object):
|
|
1088
1239
|
if (uploadthread.rspstatus >= 300
|
1089
1240
|
or uploadthread.rspstatus < 200):
|
1090
1241
|
rsp = uploadthread.rsp
|
1091
|
-
errmsg = ''
|
1242
|
+
errmsg = f'Update attempt resulted in response status {uploadthread.rspstatus}'
|
1092
1243
|
try:
|
1093
1244
|
rsp = json.loads(rsp)
|
1094
1245
|
errmsg = (
|
1095
1246
|
rsp['error'][
|
1096
1247
|
'@Message.ExtendedInfo'][0]['Message'])
|
1097
1248
|
except Exception:
|
1098
|
-
|
1249
|
+
errmsg = errmsg + ': ' + repr(rsp)
|
1250
|
+
raise Exception(errmsg)
|
1099
1251
|
raise Exception(errmsg)
|
1100
1252
|
return self.continue_update(uploadthread, progress)
|
1101
1253
|
finally:
|
@@ -1215,6 +1367,8 @@ class OEMHandler(object):
|
|
1215
1367
|
res = self._get_cache(url)
|
1216
1368
|
if res:
|
1217
1369
|
return res
|
1370
|
+
# If doing a method that may change remote url state, invalidate cache
|
1371
|
+
self._invalidate_url_cache(url)
|
1218
1372
|
wc = self.webclient.dupe()
|
1219
1373
|
if etag:
|
1220
1374
|
wc.stdheaders['If-Match'] = etag
|
@@ -18,19 +18,27 @@ from pyghmi.redfish.oem.lenovo import xcc
|
|
18
18
|
from pyghmi.redfish.oem.lenovo import xcc3
|
19
19
|
from pyghmi.redfish.oem.lenovo import smm3
|
20
20
|
|
21
|
-
def get_handler(sysinfo, sysurl, webclient, cache, cmd):
|
21
|
+
def get_handler(sysinfo, sysurl, webclient, cache, cmd, rootinfo={}):
|
22
|
+
if not sysinfo: # we are before establishing there is one system, and one manager...
|
23
|
+
systems, status = webclient.grab_json_response_with_status('/redfish/v1/Systems')
|
24
|
+
if status == 200:
|
25
|
+
for system in systems.get('Members', []):
|
26
|
+
if system.get('@odata.id', '').endswith('/1'):
|
27
|
+
sysurl = system['@odata.id']
|
28
|
+
sysinfo, status = webclient.grab_json_response_with_status(sysurl)
|
29
|
+
break
|
22
30
|
leninf = sysinfo.get('Oem', {}).get('Lenovo', {})
|
23
31
|
mgrinfo = {}
|
24
32
|
if leninf:
|
25
|
-
|
33
|
+
mgrinfo, status = webclient.grab_json_response_with_status('/redfish/v1/Managers/1')
|
26
34
|
if status != 200:
|
27
35
|
mgrinfo = {}
|
28
36
|
if not leninf:
|
29
37
|
bmcinfo = cmd.bmcinfo
|
30
38
|
if 'Ami' in bmcinfo.get('Oem', {}):
|
31
39
|
return tsma.TsmHandler(sysinfo, sysurl, webclient, cache)
|
32
|
-
elif 'xclarity controller' in
|
33
|
-
if
|
40
|
+
elif 'xclarity controller' in mgrinfo.get('Model', '').lower():
|
41
|
+
if mgrinfo['Model'].endswith('3'):
|
34
42
|
return xcc3.OEMHandler(sysinfo, sysurl, webclient, cache,
|
35
43
|
gpool=cmd._gpool)
|
36
44
|
else:
|
pyghmi/redfish/oem/lenovo/xcc.py
CHANGED
@@ -699,33 +699,57 @@ class OEMHandler(generic.OEMHandler):
|
|
699
699
|
for diskent in adp.get('aimDisks', ()):
|
700
700
|
yield self._get_disk_firmware_single(diskent)
|
701
701
|
|
702
|
-
def get_firmware_inventory(self, components, fishclient):
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
702
|
+
def get_firmware_inventory(self, components, fishclient, category=None):
|
703
|
+
|
704
|
+
if components and 'core' in components:
|
705
|
+
category = 'core'
|
706
|
+
components = components - set(['core'])
|
707
|
+
if not category:
|
708
|
+
category = 'all'
|
709
|
+
if category in ('all', 'core'):
|
710
|
+
sysinf = self.wc.grab_json_response('/api/dataset/sys_info')
|
711
|
+
for item in sysinf.get('items', {}):
|
712
|
+
for firm in item.get('firmware', []):
|
713
|
+
firminfo = {
|
714
|
+
'version': firm['version'],
|
715
|
+
'build': firm['build'],
|
716
|
+
'date': parse_time(firm['release_date']),
|
717
|
+
}
|
718
|
+
if firm['type'] == 5:
|
719
|
+
yield ('XCC', firminfo)
|
720
|
+
elif firm['type'] == 6:
|
721
|
+
yield ('XCC Backup', firminfo)
|
722
|
+
elif firm['type'] == 0:
|
723
|
+
yield ('UEFI', firminfo)
|
724
|
+
elif firm['type'] == 7:
|
725
|
+
yield ('LXPM', firminfo)
|
726
|
+
elif firm['type'] == 8:
|
727
|
+
yield ('LXPM Windows Driver Bundle', firminfo)
|
728
|
+
elif firm['type'] == 9:
|
729
|
+
yield ('LXPM Linux Driver Bundle', firminfo)
|
730
|
+
elif firm['type'] == 10:
|
731
|
+
yield ('LXUM', firminfo)
|
732
|
+
if components:
|
733
|
+
components = set([x.lower() for x in components])
|
734
|
+
components = components - set((
|
735
|
+
'core', 'uefi', 'bios', 'xcc', 'bmc', 'imm', 'fpga',
|
736
|
+
'lxpm'))
|
737
|
+
if not components:
|
738
|
+
return
|
739
|
+
if not components:
|
740
|
+
components = set(('all',))
|
741
|
+
needadapterfirmware = False
|
742
|
+
needdiskfirmware = False
|
743
|
+
if category in ('all', 'adapters'):
|
744
|
+
needadapterfirmware = True
|
745
|
+
if category in ('all', 'disks'):
|
746
|
+
needdiskfirmware = True
|
747
|
+
if needadapterfirmware:
|
748
|
+
for adpinfo in self._get_agentless_firmware(components):
|
749
|
+
yield adpinfo
|
750
|
+
if needdiskfirmware:
|
751
|
+
for adpinfo in self._get_disk_firmware(components):
|
752
|
+
yield adpinfo
|
729
753
|
raise pygexc.BypassGenericBehavior()
|
730
754
|
|
731
755
|
def get_storage_configuration(self, logout=True):
|
@@ -1296,14 +1320,15 @@ class OEMHandler(generic.OEMHandler):
|
|
1296
1320
|
if (uploadthread.rspstatus >= 300
|
1297
1321
|
or uploadthread.rspstatus < 200):
|
1298
1322
|
rsp = uploadthread.rsp
|
1299
|
-
errmsg = ''
|
1323
|
+
errmsg = f'Update attempt resulted in response status {uploadthread.rspstatus}'
|
1300
1324
|
try:
|
1301
1325
|
rsp = json.loads(rsp)
|
1302
1326
|
errmsg = (
|
1303
1327
|
rsp['error'][
|
1304
1328
|
'@Message.ExtendedInfo'][0]['Message'])
|
1305
1329
|
except Exception:
|
1306
|
-
|
1330
|
+
errmsg = f'Update attempt resulted in response status {uploadthread.rspstatus}: "{repr(rsp)}"'
|
1331
|
+
raise Exception(errmsg)
|
1307
1332
|
raise Exception(errmsg)
|
1308
1333
|
rsp = json.loads(uploadthread.rsp)
|
1309
1334
|
monitorurl = rsp['@odata.id']
|
@@ -128,7 +128,9 @@ class OEMHandler(generic.OEMHandler):
|
|
128
128
|
anames = {}
|
129
129
|
for adata, _ in adapterdata:
|
130
130
|
skipadapter = False
|
131
|
-
clabel = adata['Slot']['Location']['PartLocation']
|
131
|
+
clabel = adata['Slot']['Location']['PartLocation'].get('LocationType','')
|
132
|
+
if not clabel:
|
133
|
+
clabel = adata['Slot']['Location']['PartLocation'].get('ServiceLabel', '').split("=")[0]
|
132
134
|
if clabel != 'Embedded':
|
133
135
|
aslot = adata['Slot']['Location']['PartLocation']['LocationOrdinalValue']
|
134
136
|
clabel = 'Slot {0}'.format(aslot)
|
@@ -240,10 +242,16 @@ class OEMHandler(generic.OEMHandler):
|
|
240
242
|
standalonedisks = []
|
241
243
|
pools = []
|
242
244
|
for item in rsp.get('Members',[]):
|
245
|
+
# Drives shown at 'Direct attached drives' in XCC
|
246
|
+
# cannot be used for RAID creation
|
247
|
+
if item['Id'].lower() == 'direct_attached_nvme':
|
248
|
+
continue
|
243
249
|
cdisks = [item['Drives'][i]['@odata.id'] for i in range(len(item['Drives']))]
|
244
250
|
cid = '{0},{1}'.format(
|
245
251
|
item['Id'],
|
246
252
|
item['StorageControllers'][0]['Location']['PartLocation'].get('LocationOrdinalValue', -1))
|
253
|
+
if item['Id'].lower() == 'vroc':
|
254
|
+
cid = 'vroc,0'
|
247
255
|
storage_pools = self._get_expanded_data(item['StoragePools']['@odata.id'])
|
248
256
|
for p in storage_pools['Members']:
|
249
257
|
vols = self._get_expanded_data(p['AllocatedVolumes']['@odata.id'])
|
@@ -1122,7 +1130,7 @@ class OEMHandler(generic.OEMHandler):
|
|
1122
1130
|
if progress:
|
1123
1131
|
progress({'phase': 'complete'})
|
1124
1132
|
|
1125
|
-
def get_firmware_inventory(self, components, fishclient):
|
1133
|
+
def get_firmware_inventory(self, components, fishclient, category):
|
1126
1134
|
sfs = fishclient._do_web_request('/api/providers/system_firmware_status')
|
1127
1135
|
pendingscm = sfs.get('fpga_scm_pending_build', None)
|
1128
1136
|
pendinghpm = sfs.get('fpga_hpm_pending_build', None)
|
pyghmi/redfish/oem/lookup.py
CHANGED
@@ -22,18 +22,23 @@ OEMMAP = {
|
|
22
22
|
}
|
23
23
|
|
24
24
|
|
25
|
-
def get_oem_handler(sysinfo, sysurl, webclient, cache, cmd):
|
25
|
+
def get_oem_handler(sysinfo, sysurl, webclient, cache, cmd, rootinfo={}):
|
26
|
+
if rootinfo.get('Vendor', None) in OEMMAP:
|
27
|
+
return OEMMAP[rootinfo['Vendor']].get_handler(sysinfo, sysurl,
|
28
|
+
webclient, cache, cmd, rootinfo)
|
26
29
|
for oem in sysinfo.get('Oem', {}):
|
27
30
|
if oem in OEMMAP:
|
28
31
|
return OEMMAP[oem].get_handler(sysinfo, sysurl, webclient, cache,
|
29
|
-
cmd)
|
32
|
+
cmd, rootinfo)
|
30
33
|
for oem in sysinfo.get('Links', {}).get('OEM', []):
|
31
34
|
if oem in OEMMAP:
|
32
35
|
return OEMMAP[oem].get_handler(sysinfo, sysurl, webclient, cache,
|
33
|
-
cmd)
|
36
|
+
cmd, rootinfo)
|
37
|
+
if rootinfo: # rootinfo indicates early invocation, bmcinfo not ready yet
|
38
|
+
return generic.OEMHandler(sysinfo, sysurl, webclient, cache, cmd._gpool, rootinfo)
|
34
39
|
bmcinfo = cmd.bmcinfo
|
35
40
|
for oem in bmcinfo.get('Oem', {}):
|
36
41
|
if oem in OEMMAP:
|
37
42
|
return OEMMAP[oem].get_handler(sysinfo, sysurl, webclient, cache,
|
38
|
-
cmd)
|
39
|
-
return generic.OEMHandler(sysinfo, sysurl, webclient, cache, cmd._gpool)
|
43
|
+
cmd, rootinfo)
|
44
|
+
return generic.OEMHandler(sysinfo, sysurl, webclient, cache, cmd._gpool, rootinfo)
|
@@ -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=
|
14
|
+
pyghmi/ipmi/command.py,sha256=hG5ekt_dExSLrTV6fkr4nFh1U5LylArYdCZolR26DtU,91643
|
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=ssNf1IH2_6yPkg38bRePVEwLzue4UUa7l7nsqsyQEP4,18976
|
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=aNN5dvbGlNpWlrrvlWthyAO0PGn6A9Pf75wjhVleu_k,26692
|
@@ -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=
|
30
|
-
pyghmi/ipmi/oem/lenovo/imm.py,sha256=
|
29
|
+
pyghmi/ipmi/oem/lenovo/handler.py,sha256=MGfQd08Fd013tH9CwkmfwT7Tkh8BvbdVgeZ4T68GOW8,57256
|
30
|
+
pyghmi/ipmi/oem/lenovo/imm.py,sha256=h33_6yNbTgFhhyiBwdWaUOjcpjpQ1gbXK1YPv0DuOC0,114400
|
31
31
|
pyghmi/ipmi/oem/lenovo/inventory.py,sha256=FLJJinw-ibdHtf3KmrTzhWXbQrpxq3TSycVf96Hg7cw,5911
|
32
32
|
pyghmi/ipmi/oem/lenovo/nextscale.py,sha256=bvY7MLOGMioXT7F6HBt5BBftGAEYNo2GkBNjwysPAWs,43734
|
33
33
|
pyghmi/ipmi/oem/lenovo/pci.py,sha256=S7p-5Q2qu2YhlffN-LEmIvjfXim6OlfYL7Q6r6VZqJ4,2020
|
@@ -43,19 +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=
|
46
|
+
pyghmi/redfish/command.py,sha256=WyxyJDqYTdnMJiZ4gnYsj9kBSXhXbBIZcLY0Ok72NKY,60849
|
47
47
|
pyghmi/redfish/oem/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
48
|
-
pyghmi/redfish/oem/generic.py,sha256=
|
49
|
-
pyghmi/redfish/oem/lookup.py,sha256=
|
48
|
+
pyghmi/redfish/oem/generic.py,sha256=T6DYrH5Tp3v4fzK9tFd3X5UjXp4ljofCGbwm6T88Rpk,64549
|
49
|
+
pyghmi/redfish/oem/lookup.py,sha256=9zVqiNMzUS_zwlIp8luZHbN1VTOlyIVQAKnPh1KDf48,1957
|
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
|
-
pyghmi/redfish/oem/dell/main.py,sha256=
|
52
|
+
pyghmi/redfish/oem/dell/main.py,sha256=LnX4p_IOsJNJYbv7p344izj1diLoJZvRLFwCv1aHlAY,806
|
53
53
|
pyghmi/redfish/oem/lenovo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
54
|
-
pyghmi/redfish/oem/lenovo/main.py,sha256=
|
54
|
+
pyghmi/redfish/oem/lenovo/main.py,sha256=SLiEHa28NxItqt89SDeM05Em9bJE5dkxNhJ8oCWFtXY,3098
|
55
55
|
pyghmi/redfish/oem/lenovo/smm3.py,sha256=QHasf5QofFuYqtHPeqcwCEJUbd0PV5_C6u-Y8FVdqCk,7598
|
56
56
|
pyghmi/redfish/oem/lenovo/tsma.py,sha256=6GELCuriumARj_kv7fgqtUpo9ekiWHpQcM9v_mnGILI,34645
|
57
|
-
pyghmi/redfish/oem/lenovo/xcc.py,sha256
|
58
|
-
pyghmi/redfish/oem/lenovo/xcc3.py,sha256=
|
57
|
+
pyghmi/redfish/oem/lenovo/xcc.py,sha256=-tLtHv9lPvVSdzNvRhZaG0zFWFJYKv4n0-80gBH_h3E,85401
|
58
|
+
pyghmi/redfish/oem/lenovo/xcc3.py,sha256=VV2-apjbjKG806_6Zh05AapdlrLAe-GRs6-3ahVAFHI,56271
|
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=i1rJ7NBlPQFTRv7kgzbTaOHsWuPeXcMAjRXm_i8CI0A,15652
|
67
|
-
pyghmi-1.6.
|
68
|
-
pyghmi-1.6.
|
69
|
-
pyghmi-1.6.
|
70
|
-
pyghmi-1.6.
|
71
|
-
pyghmi-1.6.
|
72
|
-
pyghmi-1.6.
|
73
|
-
pyghmi-1.6.
|
74
|
-
pyghmi-1.6.
|
67
|
+
pyghmi-1.6.6.dist-info/AUTHORS,sha256=yv4aQom_PII-SNqbeeKrfH-spcG85PRPsZ71Iqjl_fU,2083
|
68
|
+
pyghmi-1.6.6.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
69
|
+
pyghmi-1.6.6.dist-info/METADATA,sha256=iloesXFPEZB8FN0TeZqEecJ7N8cu32uZZJ0YNQLlZRo,1136
|
70
|
+
pyghmi-1.6.6.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
|
71
|
+
pyghmi-1.6.6.dist-info/entry_points.txt,sha256=-OpJliDzATxmuPXK0VR3Ma-Yk_i4ZhfIIB-12A26dSI,168
|
72
|
+
pyghmi-1.6.6.dist-info/pbr.json,sha256=x80AgrPN_697hTcIaJgg-7AmGBFEMVnPZC9dLcdPS_g,46
|
73
|
+
pyghmi-1.6.6.dist-info/top_level.txt,sha256=aDtt6S9eVu6-tNdaUs4Pz9PbdUd69bziZZMhNvk9Ulc,7
|
74
|
+
pyghmi-1.6.6.dist-info/RECORD,,
|
@@ -0,0 +1 @@
|
|
1
|
+
{"git_version": "bbebfd9", "is_release": true}
|
pyghmi-1.6.5.dist-info/pbr.json
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
{"git_version": "f56e000", "is_release": true}
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|