diff --git a/pyghmi/exceptions.py b/pyghmi/exceptions.py index 2818b6a9..5997b96e 100644 --- a/pyghmi/exceptions.py +++ b/pyghmi/exceptions.py @@ -60,3 +60,11 @@ class BypassGenericBehavior(PyghmiException): # Indicates that an OEM handler wants to abort any standards based # follow up pass + +class FallbackData(PyghmiException): + # Indicates the OEM handler has data to be used if the generic + # check comes up empty + def __init__(self, fallbackdata): + self.fallbackdata = fallbackdata + + pass diff --git a/pyghmi/ipmi/command.py b/pyghmi/ipmi/command.py index 235a06b8..464dd936 100644 --- a/pyghmi/ipmi/command.py +++ b/pyghmi/ipmi/command.py @@ -703,6 +703,7 @@ class Command(object): warning, critical, or failed assessments. """ summary = {'badreadings': [], 'health': const.Health.Ok} + fallbackreadings = [] try: self.oem_init() self._oem.get_health(summary) @@ -712,6 +713,9 @@ class Command(object): summary['badreadings'].append(reading) except exc.BypassGenericBehavior: pass + except exc.FallbackData as fd: + if not summary['badreadings']: + summary['badreadings'] = fd.fallbackdata return summary def get_sensor_reading(self, sensorname): diff --git a/pyghmi/ipmi/oem/lenovo/imm.py b/pyghmi/ipmi/oem/lenovo/imm.py index 762be2c2..600e635f 100644 --- a/pyghmi/ipmi/oem/lenovo/imm.py +++ b/pyghmi/ipmi/oem/lenovo/imm.py @@ -1678,16 +1678,18 @@ class XCCClient(IMMClient): else: # The XCC reports healthy, no need to interrogate raise pygexc.BypassGenericBehavior() + fallbackdata = [] + hmap = { + 'E': pygconst.Health.Critical, + 'W': pygconst.Health.Warning, + } for item in rsp.get('items', ()): # while usually the ipmi interrogation shall explain things, # just in case there is a gap, make sure at least the # health field is accurately updated - if (item['severity'] == 'W' and - summary['health'] < pygconst.Health.Warning): - summary['health'] = pygconst.Health.Warning - if (item['severity'] == 'E' and - summary['health'] < pygconst.Health.Critical): - summary['health'] = pygconst.Health.Critical + itemseverity = hmap.get(item.get('severity', 'E'), 'E') + if (summary['health'] < itemseverity): + summary['health'] = itemseverity if item['cmnid'] == 'FQXSPPW0104J': # This event does not get modeled by the sensors # add a made up sensor to explain @@ -1697,10 +1699,27 @@ class XCCClient(IMMClient): 'state_ids': [3], 'health': pygconst.Health.Warning, 'type': 'Power'}, '')) + elif item['cmnid'] == 'FQXSFMA0041K': + summary['badreadings'].append( + sdr.SensorReading({ + 'name': 'Optane DCPDIMM', + 'health': pygconst.Health.Warning, + 'type': 'Memory', + 'states': ['Near/Far Memory Ratio not recommended']}, + '') + ) + else: + fallbackdata.append(sdr.SensorReading({ + 'name': item['source'], + 'states': [item['message']], + 'health': itemseverity, + 'type': item['source'], + }, '')) if summary.get('health', pygconst.Health.Ok) == pygconst.Health.Ok: # Fault LED is lit without explanation, mark critical # to encourage examination summary['health'] = pygconst.Health.Critical + raise pygexc.FallbackData(fallbackdata) # Will use the generic handling for unhealthy systems def get_licenses(self):