2
0
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:
Allan Vidal
2015-10-14 16:55:00 -03:00
parent c2238a8587
commit d560e17389
4 changed files with 66 additions and 25 deletions

View File

@@ -47,6 +47,7 @@ def get_categories():
"netfn": 0x06,
"command": 0x59,
"data": (0x00, 0xc1, 0x02, 0x00)
}
},
"workaround_bmc_bug": True
}
}

View File

@@ -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:

View File

@@ -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

View File

@@ -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"),