2
0
mirror of https://github.com/xcat2/confluent.git synced 2026-08-27 00:56:45 +00:00

Merge pull request #277 from Obihoernchen/fix/ipmi-completion-code-checks

Act on the ipmi completion codes again
This commit is contained in:
Jarrod Johnson
2026-08-15 10:28:20 -04:00
committed by GitHub
3 changed files with 60 additions and 38 deletions
+23 -11
View File
@@ -453,9 +453,11 @@ class Command(object):
retry=True, timeout=None, rslun=0):
"""Send raw ipmi command to BMC, raising exception on error
This is identical to raw_command, except it raises exceptions
This is identical to oldraw_command, except it raises exceptions
on IPMI errors and returns data as a buffer. This is the recommend
function to use. The response['data'] being a buffer allows
function to use, and a caller that has to act on a particular
completion code reads it from the exception's ipmicode. The
response['data'] being a buffer allows
traditional indexed access as well as works nicely with
struct.unpack_from when certain data is coming back.
@@ -1089,13 +1091,14 @@ class Command(object):
await self.init_sdr()
for sensor in self._sdr.get_sensor_numbers():
currsensor = self._sdr.sensors[sensor]
rsp = await self.raw_command(command=0x2d, netfn=4,
rslun=currsensor.sensor_lun,
data=(currsensor.sensor_number,))
if 'error' in rsp:
if rsp['code'] == 203: # Sensor does not exist, optional dev
try:
rsp = await self.raw_command(command=0x2d, netfn=4,
rslun=currsensor.sensor_lun,
data=(currsensor.sensor_number,))
except exc.IpmiException as ie:
if ie.ipmicode == 203: # Sensor does not exist, optional dev
continue
raise exc.IpmiException(rsp['error'], code=rsp['code'])
raise
yield await self._sdr.sensors[sensor].\
decode_sensor_reading(self, rsp['data'])
await self.oem_init()
@@ -1304,9 +1307,18 @@ class Command(object):
# handler of commands
lanchan = await self.get_network_channel()
if self._ipv6support is None:
rsp = await self.raw_command(netfn=0xc, command=0x2, data=(2, lanchan,
0x32, 0, 0))
self._ipv6support = rsp['code'] == 0
try:
await self.raw_command(netfn=0xc, command=0x2,
data=(2, lanchan, 0x32, 0, 0))
self._ipv6support = True
except exc.IpmiException as ie:
# A platform without the standard parameter says so in the
# completion code, which is the answer. Anything else, a
# timeout or a lost session, is not, and must not be remembered
# as the platform's answer for the rest of the session.
if not 0 < ie.ipmicode <= 0xff:
raise
self._ipv6support = False
return self._ipv6support
async def set_alert_destination(self, ip=None, acknowledge_required=None,
+11 -12
View File
@@ -150,8 +150,6 @@ class FRU(object):
async def fetch_fru(self, fruid):
response = await self.ipmicmd.raw_command(
netfn=0xa, command=0x10, data=[fruid])
if 'error' in response:
raise iexc.IpmiException(response['error'], code=response['code'])
frusize = response['data'][0] | (response['data'][1] << 8)
# In our case, we don't need to think too hard about whether
# the FRU is word or byte, we just process what we get back in the
@@ -165,20 +163,21 @@ class FRU(object):
offset = 0
self.rawfru = bytearray([])
while chunksize:
response = await self.ipmicmd.raw_command(
netfn=0xa, command=0x11, data=[fruid, offset & 0xff,
offset >> 8, chunksize])
if response['code'] in (201, 202):
try:
response = await self.ipmicmd.raw_command(
netfn=0xa, command=0x11, data=[fruid, offset & 0xff,
offset >> 8, chunksize])
except iexc.IpmiException as ie:
# if it was too big, back off and try smaller
# Try just over half to mitigate the chance of
# one request becoming three rather than just two
if chunksize == 3:
raise iexc.IpmiException(response['error'])
chunksize //= 2
chunksize += 2
smaller = chunksize // 2 + 2
if ie.ipmicode not in (201, 202) or smaller >= chunksize:
# Nothing left to give up, and asking again unchanged would
# never end
raise
chunksize = smaller
continue
elif 'error' in response:
raise iexc.IpmiException(response['error'], response['code'])
offset += response['data'][0]
if response['data'][0] == 0:
break
+26 -15
View File
@@ -769,24 +769,35 @@ class SDR(object):
rqdata = [rsvid & 0xff, rsvid >> 8,
recid & 0xff, recid >> 8,
offset, size]
sdrrec = await self.ipmicmd.raw_command(netfn=0x0a, command=0x23,
data=rqdata)
if sdrrec['code'] == 0xca:
if size == 0xff: # get just 5 to get header to know length
size = 5
elif size > 5:
size //= 2
try:
sdrrec = await self.ipmicmd.raw_command(
netfn=0x0a, command=0x23, data=rqdata)
except exc.IpmiException as ie:
# The two codes this loop negotiates with, rather than
# failures: more asked for than the bmc will return at once,
# and a reservation that has gone stale
if ie.ipmicode == 0xca:
if size == 0xff: # get just 5 to get header to know length
size = 5
continue
# push things over such that it's less
# likely to be just 1 short of a read
# and incur a whole new request
size += 2
chunksize = size
continue
if sdrrec['code'] == 0xc5: # need a new reservation id
rsvid = 0
continue
if sdrrec['code'] != 0:
raise exc.IpmiException(sdrrec['error'])
smaller = size // 2 + 2
if smaller >= size or (currlen == 0 and smaller < 5):
# Nothing left to give up, and asking again
# unchanged would never end. A header read has to
# be 5 bytes to carry the record length, so a
# smaller one could not be parsed either
raise
size = chunksize = smaller
continue
if ie.ipmicode == 0xc5: # need a new reservation id
# Take one here rather than leaving it to the top of
# the loop, which only reserves for a partial read
rsvid = await self.get_sdr_reservation()
continue
raise
if newrecid == 0:
newrecid = (sdrrec['data'][1] << 8) + sdrrec['data'][0]
if currlen == 0: