From 6d56f2177211315ccf1af6bed36029d99a52e1b8 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Thu, 12 Aug 2021 11:25:14 -0400 Subject: [PATCH] Fix expired weakref reference exception there is a global cache in sdr.py. Sensors and FRUs are cached here. So if ipmicmd is reinitialized, Sensors in cache still ref to old ipmicmd, then it will throw expired weakref reference exception when call these cached Sensors. Current changes will still cache Sensors and FRUs, but when call cached sensors every time, we pass in current using ipmicmd. Change-Id: I976760d8cb0a7f78a4f6468c52212649790dbbc2 --- pyghmi/ipmi/command.py | 5 +++-- pyghmi/ipmi/oem/lenovo/config.py | 12 ++++++++---- pyghmi/ipmi/sdr.py | 21 ++++++++++----------- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/pyghmi/ipmi/command.py b/pyghmi/ipmi/command.py index acea5358..e4113a96 100644 --- a/pyghmi/ipmi/command.py +++ b/pyghmi/ipmi/command.py @@ -759,7 +759,7 @@ class Command(object): if 'error' in rsp: raise exc.IpmiException(rsp['error'], rsp['code']) return self._sdr.sensors[sensor].decode_sensor_reading( - rsp['data']) + self, rsp['data']) self.oem_init() return self._oem.get_sensor_reading(sensorname) @@ -980,7 +980,8 @@ class Command(object): if rsp['code'] == 203: # Sensor does not exist, optional dev continue raise exc.IpmiException(rsp['error'], code=rsp['code']) - yield self._sdr.sensors[sensor].decode_sensor_reading(rsp['data']) + yield self._sdr.sensors[sensor].\ + decode_sensor_reading(self, rsp['data']) self.oem_init() for reading in self._oem.get_sensor_data(): yield reading diff --git a/pyghmi/ipmi/oem/lenovo/config.py b/pyghmi/ipmi/oem/lenovo/config.py index f51eae45..1badb6d5 100644 --- a/pyghmi/ipmi/oem/lenovo/config.py +++ b/pyghmi/ipmi/oem/lenovo/config.py @@ -305,6 +305,10 @@ class LenovoFirmwareConfig(object): readonly = setting.get('gray-if') if readonly: readonly = _convert_syntax(readonly) + else: + access = setting.get('access') + if access == 'readonly': + readonly = 'true' possible = [] current = None default = None @@ -485,10 +489,6 @@ class LenovoFirmwareConfig(object): for option in options.keys(): if options[option]['new_value'] is None: continue - if options[option]['current'] == options[option]['new_value']: - continue - if options[option]['pending'] == options[option]['new_value']: - continue if options[option]['readonly']: errstr = '{0} is read only'.format(option) if options[option]['readonly_why']: @@ -496,6 +496,10 @@ class LenovoFirmwareConfig(object): ','.join(sorted(options[option]['readonly_why']))) errstr += ea raise pygexc.InvalidParameterValue(errstr) + if options[option]['current'] == options[option]['new_value']: + continue + if options[option]['pending'] == options[option]['new_value']: + continue if isinstance(options[option]['new_value'], six.string_types): # Coerce a simple string parameter to the expected list format options[option]['new_value'] = [options[option]['new_value']] diff --git a/pyghmi/ipmi/sdr.py b/pyghmi/ipmi/sdr.py index 92b78184..d54a1d7b 100644 --- a/pyghmi/ipmi/sdr.py +++ b/pyghmi/ipmi/sdr.py @@ -288,7 +288,7 @@ class SDREntry(object): external code to pay attention to this class. """ - def __init__(self, entrybytes, ipmicmd, reportunsupported=False, + def __init__(self, entrybytes, reportunsupported=False, mfg_id=0, prod_id=0): self.mfg_id = mfg_id self.prod_id = prod_id @@ -296,7 +296,6 @@ class SDREntry(object): # moment self.readable = True self.reportunsupported = reportunsupported - self.ipmicmd = ipmicmd if entrybytes[2] != 0x51: # only recognize '1.5', the only version defined at time of writing raise NotImplementedError @@ -478,7 +477,7 @@ class SDREntry(object): health = const.Health.Warning return desc, health - def decode_sensor_reading(self, reading): + def decode_sensor_reading(self, ipmicmd, reading): numeric = None output = { 'name': self.sensor_name, @@ -498,8 +497,8 @@ class SDREntry(object): if numeric is not None: lowerbound = numeric - (0.5 + (self.tolerance / 2.0)) upperbound = numeric + (0.5 + (self.tolerance / 2.0)) - lowerbound = self.decode_value(lowerbound) - upperbound = self.decode_value(upperbound) + lowerbound = self.decode_value(ipmicmd, lowerbound) + upperbound = self.decode_value(ipmicmd, upperbound) output['value'] = (lowerbound + upperbound) / 2.0 output['imprecision'] = output['value'] - lowerbound discrete = False @@ -555,13 +554,13 @@ class SDREntry(object): output['state_ids'].append(self.assert_trap_value(6)) return SensorReading(output, self.unit_suffix) - def _set_tmp_formula(self, value): - rsp = self.ipmicmd.raw_command(netfn=4, command=0x23, - data=(self.sensor_number, value)) + def _set_tmp_formula(self, ipmicmd, value): + rsp = ipmicmd.raw_command(netfn=4, command=0x23, + data=(self.sensor_number, value)) # skip next reading field, not used in on-demand situation self.decode_formula(rsp['data'][1:]) - def decode_value(self, value): + def decode_value(self, ipmicmd, value): # Take the input value and return meaningful value linearization = self.linearization if linearization > 11: # direct calling code to get factors @@ -571,7 +570,7 @@ class SDREntry(object): # fashion. However for now opt for retrieving rows as needed # rather than tracking all that information for a relatively # rare behavior - self._set_tmp_formula(value) + self._set_tmp_formula(ipmicmd, value) linearization = 0 # time to compute the pre-linearization value. decoded = float((value * self.m + self.b) @@ -834,7 +833,7 @@ class SDR(object): yield number def add_sdr(self, sdrbytes): - newent = SDREntry(sdrbytes, self.ipmicmd, False, self.mfg_id, + newent = SDREntry(sdrbytes, False, self.mfg_id, self.prod_id) if newent.sdrtype == TYPE_SENSOR: id = '{0}.{1}.{2}'.format(