mirror of
https://opendev.org/x/pyghmi
synced 2025-08-26 13:00:31 +00:00
Fix TS inventory parsing bugs (DIMM, PSU)
Change-Id: I4c1eb83db7950aba542a5931e172232b1395239f
This commit is contained in:
@@ -47,6 +47,7 @@ def get_categories():
|
||||
"netfn": 0x06,
|
||||
"command": 0x59,
|
||||
"data": (0x00, 0xc1, 0x02, 0x00)
|
||||
}
|
||||
},
|
||||
"workaround_bmc_bug": True
|
||||
}
|
||||
}
|
||||
|
@@ -25,6 +25,7 @@ import pyghmi.ipmi.private.util as util
|
||||
from pyghmi.ipmi.oem.lenovo import cpu
|
||||
from pyghmi.ipmi.oem.lenovo import dimm
|
||||
from pyghmi.ipmi.oem.lenovo import drive
|
||||
|
||||
from pyghmi.ipmi.oem.lenovo import firmware
|
||||
from pyghmi.ipmi.oem.lenovo import inventory
|
||||
from pyghmi.ipmi.oem.lenovo import pci
|
||||
@@ -254,31 +255,55 @@ class OEMHandler(generic.OEMHandler):
|
||||
def _collect_tsm_inventory(self):
|
||||
self.oem_inventory_info = {}
|
||||
for catid, catspec in inventory.categories.items():
|
||||
try:
|
||||
rsp = self.ipmicmd.xraw_command(**catspec["command"])
|
||||
except pygexc.IpmiException:
|
||||
continue
|
||||
if (catspec.get("workaround_bmc_bug", False)):
|
||||
rsp = None
|
||||
tmp_command = dict(catspec["command"])
|
||||
tmp_command["data"] = list(tmp_command["data"])
|
||||
count = 0
|
||||
for i in xrange(0x01, 0xff):
|
||||
tmp_command["data"][-1] = i
|
||||
try:
|
||||
partrsp = self.ipmicmd.xraw_command(**tmp_command)
|
||||
if rsp is None:
|
||||
rsp = partrsp
|
||||
rsp["data"] = list(rsp["data"])
|
||||
else:
|
||||
rsp["data"].extend(partrsp["data"][1:])
|
||||
count += 1
|
||||
except Exception:
|
||||
break
|
||||
# If we didn't get any response, assume we don't have
|
||||
# this category and go on to the next one
|
||||
if rsp is None:
|
||||
continue
|
||||
rsp["data"].insert(1, count)
|
||||
rsp["data"] = buffer(bytearray(rsp["data"]))
|
||||
else:
|
||||
try:
|
||||
items = inventory.parse_inventory_category(
|
||||
catid, rsp,
|
||||
countable=catspec.get("countable", True)
|
||||
)
|
||||
rsp = self.ipmicmd.xraw_command(**catspec["command"])
|
||||
except pygexc.IpmiException:
|
||||
continue
|
||||
# Parse the response we got
|
||||
try:
|
||||
items = inventory.parse_inventory_category(
|
||||
catid, rsp,
|
||||
countable=catspec.get("countable", True)
|
||||
)
|
||||
except Exception:
|
||||
# If we can't parse an inventory category, ignore it
|
||||
print traceback.print_exc()
|
||||
continue
|
||||
|
||||
for item in items:
|
||||
try:
|
||||
key = catspec["idstr"].format(item["index"])
|
||||
del item["index"]
|
||||
self.oem_inventory_info[key] = item
|
||||
except Exception:
|
||||
# If we can't parse an inventory category, ignore it
|
||||
# If we can't parse an inventory item, ignore it
|
||||
print traceback.print_exc()
|
||||
continue
|
||||
|
||||
for item in items:
|
||||
try:
|
||||
key = catspec["idstr"].format(item["index"])
|
||||
del item["index"]
|
||||
self.oem_inventory_info[key] = item
|
||||
except Exception:
|
||||
# If we can't parse an inventory item, ignore it
|
||||
print traceback.print_exc()
|
||||
continue
|
||||
|
||||
def get_leds(self):
|
||||
if self.has_tsm:
|
||||
for (name, id_) in leds.items():
|
||||
@@ -348,10 +373,10 @@ class OEMHandler(generic.OEMHandler):
|
||||
|
||||
:param enable: True for enable and False for disable
|
||||
"""
|
||||
# 1 – Enable power capping(default)
|
||||
# 1 - Enable power capping(default)
|
||||
if enable:
|
||||
statecode = 1
|
||||
# 0 – Disable power capping
|
||||
# 0 - Disable power capping
|
||||
else:
|
||||
statecode = 0
|
||||
if self.has_tsm:
|
||||
|
@@ -38,15 +38,19 @@ class EntryField(object):
|
||||
output
|
||||
:param valuefunc: a function to be called to change the value in the last
|
||||
step of the build process.
|
||||
:param presence: whether the field indicates presence. In this case, the
|
||||
field will not be included. If the value is false, the
|
||||
item will be discarded.
|
||||
"""
|
||||
def __init__(self, name, fmt, include=True, mapper=None, valuefunc=None,
|
||||
multivaluefunc=False):
|
||||
multivaluefunc=False, presence=False):
|
||||
self.name = name
|
||||
self.fmt = fmt
|
||||
self.include = include
|
||||
self.mapper = mapper
|
||||
self.valuefunc = valuefunc
|
||||
self.multivaluefunc = multivaluefunc
|
||||
self.presence = presence
|
||||
|
||||
|
||||
# General parameter parsing functions
|
||||
@@ -71,11 +75,16 @@ def parse_inventory_category(name, info, countable=True):
|
||||
cur += 1
|
||||
else:
|
||||
count = 0
|
||||
discarded = 0
|
||||
|
||||
entries = []
|
||||
while cur < len(raw):
|
||||
read, cpu = categories[name]["parser"](raw[cur:])
|
||||
cur = cur + read
|
||||
# Account for discarded entries (because they are not present)
|
||||
if cpu is None:
|
||||
discarded += 1
|
||||
continue
|
||||
if not countable:
|
||||
# count by myself
|
||||
count += 1
|
||||
@@ -88,7 +97,7 @@ def parse_inventory_category(name, info, countable=True):
|
||||
raise Exception
|
||||
# TODO(avidal): raise specific exception to point that the number of
|
||||
# entries is different than the expected
|
||||
if count != len(entries):
|
||||
if count - discarded != len(entries):
|
||||
raise Exception
|
||||
return entries
|
||||
|
||||
@@ -108,11 +117,15 @@ def parse_inventory_category_entry(raw, fields):
|
||||
|
||||
obj = {}
|
||||
bytes_read = 0
|
||||
discard = False
|
||||
for field in fields:
|
||||
value = struct.unpack_from(field.fmt, r)[0]
|
||||
read = struct.calcsize(field.fmt)
|
||||
bytes_read += read
|
||||
r = r[read:]
|
||||
# If this entry is not actually present, just parse and then discard it
|
||||
if field.presence and not bool(value):
|
||||
discard = True
|
||||
if not field.include:
|
||||
continue
|
||||
|
||||
@@ -129,4 +142,6 @@ def parse_inventory_category_entry(raw, fields):
|
||||
for key in value:
|
||||
obj[key] = value[key]
|
||||
|
||||
if discard:
|
||||
obj = None
|
||||
return bytes_read, obj
|
||||
|
@@ -83,7 +83,7 @@ def psu_status_word_parser(word):
|
||||
|
||||
psu_fields = (
|
||||
EntryField("index", "B"),
|
||||
EntryField("Presence State", "B", include=False),
|
||||
EntryField("Presence State", "B", presence=True),
|
||||
EntryField("Capacity W", "<H"),
|
||||
EntryField("Board manufacturer", "18s"),
|
||||
EntryField("Board model", "18s"),
|
||||
|
Reference in New Issue
Block a user