diff --git a/pyghmi/ipmi/command.py b/pyghmi/ipmi/command.py index 43355978..5388391d 100644 --- a/pyghmi/ipmi/command.py +++ b/pyghmi/ipmi/command.py @@ -620,7 +620,8 @@ class Command(object): for fruid in self._sdr.fru: if self._sdr.fru[fruid].fru_name == component: return self._oem.process_fru(fru.FRU( - ipmicmd=self, fruid=fruid, sdr=self._sdr.fru[fruid]).info) + ipmicmd=self, fruid=fruid, sdr=self._sdr.fru[fruid]).info, + component) return self._oem.get_inventory_of_component(component) def _get_zero_fru(self): @@ -664,7 +665,8 @@ class Command(object): fruinf = fru.FRU( ipmicmd=self, fruid=fruid, sdr=self._sdr.fru[fruid]).info if fruinf is not None: - fruinf = self._oem.process_fru(fruinf) + fruinf = self._oem.process_fru(fruinf, + self._sdr.fru[fruid].fru_name) yield (self._sdr.fru[fruid].fru_name, fruinf) for componentpair in self._oem.get_oem_inventory(): yield componentpair diff --git a/pyghmi/ipmi/oem/generic.py b/pyghmi/ipmi/oem/generic.py index a0dc3dce..4451e1c3 100644 --- a/pyghmi/ipmi/oem/generic.py +++ b/pyghmi/ipmi/oem/generic.py @@ -167,7 +167,7 @@ class OEMHandler(object): """ return None - def process_fru(self, fru): + def process_fru(self, fru, name=None): """Modify a fru entry with OEM understanding. Given a fru, clarify 'extra' fields according to OEM rules and diff --git a/pyghmi/ipmi/oem/lenovo/handler.py b/pyghmi/ipmi/oem/lenovo/handler.py index cf3c02e4..160916df 100755 --- a/pyghmi/ipmi/oem/lenovo/handler.py +++ b/pyghmi/ipmi/oem/lenovo/handler.py @@ -487,7 +487,7 @@ class OEMHandler(generic.OEMHandler): else: raise pygexc.UnsupportedFunctionality() - def process_fru(self, fru): + def process_fru(self, fru, name=None): if fru is None: return fru if self.has_tsm: @@ -551,6 +551,8 @@ class OEMHandler(generic.OEMHandler): idx = idx + 6 except (AttributeError, KeyError, IndexError): pass + if self.has_xcc and name and name.startswith('PSU '): + self.immhandler.augment_psu_info(fru, name) return fru elif self.is_fpc == 2: # SMM variant fru['oem_parser'] = 'lenovo' diff --git a/pyghmi/ipmi/oem/lenovo/imm.py b/pyghmi/ipmi/oem/lenovo/imm.py index 641804d5..23d62684 100644 --- a/pyghmi/ipmi/oem/lenovo/imm.py +++ b/pyghmi/ipmi/oem/lenovo/imm.py @@ -422,6 +422,9 @@ class IMMClient(object): raise Exception(result['reason']) self.weblogout() + def fetch_psu_firmware(self): + return [] + def fetch_agentless_firmware(self): adapterdata = self.get_cached_data('lenovo_cached_adapters') if not adapterdata: @@ -1176,6 +1179,24 @@ class XCCClient(IMMClient): def keepalive(self): self._refresh_token_wc(self._keepalivesession) + def fetch_psu_firmware(self): + psudata = self.get_cached_data('lenovo_cached_psu') + if not psudata: + if self.wc: + psudata = self.wc.grab_json_response( + '/api/function/psu_update?params=GetPsuListAndFW') + if psudata: + self.datacache['lenovo_cached_psu'] = ( + psudata, util._monotonic_time()) + if not psudata: + return + for psu in psudata['items']: + yield ('PSU {0}'.format(psu['slot']), + { + 'model': psu['model'], + 'version': psu['version'], + }) + def get_firmware_inventory(self, bmcver, components): # First we fetch the system firmware found in imm properties # then check for agentless, if agentless, get adapter info using @@ -1265,6 +1286,8 @@ class XCCClient(IMMClient): 'lxpm'))): for firm in self.fetch_agentless_firmware(): yield firm + for firm in self.fetch_psu_firmware(): + yield firm def detach_remote_media(self): if self.webkeepalive: @@ -1534,6 +1557,30 @@ class XCCClient(IMMClient): return 'complete' return 'pending' + def add_psu_hwinfo(self, hwmap): + psud = self.wc.grab_json_response('/api/dataset/imm_power_supplies') + if not psud: + return + for psus in psud['items'][0]['power']: + hwmap['PSU {0}'.format(psus['name'])] = { + 'Wattage': psus['rated_power'], + 'FRU Number': psus['fru_number'], + } + + def augment_psu_info(self, info, psuname): + psud = self.get_cached_data('lenovo_cached_psuhwinfo') + if not psud: + psud = self.wc.grab_json_response('/api/dataset/imm_power_supplies') + if not psud: + return + self.datacache['lenovo_cached_psuhwinfo'] = ( + psud, util._monotonic_time()) + matchname = int(psuname.split(' ')[1]) + for psus in psud['items'][0]['power']: + if psus['name'] == matchname: + info['Wattage'] = psus['rated_power'] + break + def get_health(self, summary): wc = self.get_webclient(False) rsp = wc.grab_json_response('/api/providers/imm_active_events')