From c6344502303bc355fd990a31d40428a326551526 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Wed, 4 May 2016 10:25:23 -0400 Subject: [PATCH] Add Hardware inventory from Lenovo Agentless Lenovo System X systems offer up more inventory over agentless. Provide this data when the possibility presents itself. Change-Id: Ic377e951b5a6308157891f98dfdad6311337af48 --- pyghmi/ipmi/oem/lenovo/handler.py | 38 ++++++++++++++- pyghmi/ipmi/oem/lenovo/imm.py | 79 +++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+), 1 deletion(-) diff --git a/pyghmi/ipmi/oem/lenovo/handler.py b/pyghmi/ipmi/oem/lenovo/handler.py index 771fcd73..960f2ea9 100755 --- a/pyghmi/ipmi/oem/lenovo/handler.py +++ b/pyghmi/ipmi/oem/lenovo/handler.py @@ -116,6 +116,7 @@ led_status = { 0xFF: "On" } led_status_default = "Blink" +mac_format = '{0:02x}:{1:02x}:{2:02x}:{3:02x}:{4:02x}:{5:02x}' def _megarac_abbrev_image(name): @@ -292,6 +293,8 @@ class OEMHandler(generic.OEMHandler): if not self.oem_inventory_info: self._collect_tsm_inventory() return iter(self.oem_inventory_info) + elif self.has_imm: + return imm.get_hw_descriptions(self.ipmicmd, self._certverify) return () def get_oem_inventory(self): @@ -299,6 +302,9 @@ class OEMHandler(generic.OEMHandler): self._collect_tsm_inventory() for compname in self.oem_inventory_info: yield (compname, self.oem_inventory_info[compname]) + elif self.has_imm: + for inv in imm.get_hw_inventory(self.ipmicmd, self._certverify): + yield inv def get_sensor_data(self): if self.is_fpc: @@ -319,6 +325,9 @@ class OEMHandler(generic.OEMHandler): if self.has_tsm: self._collect_tsm_inventory() return self.oem_inventory_info.get(component, None) + if self.has_imm: + return imm.get_component_inventory(self.ipmicmd, self._certverify, + component) def _collect_tsm_inventory(self): self.oem_inventory_info = {} @@ -415,7 +424,34 @@ class OEMHandler(generic.OEMHandler): byteguid.extend('\x00' * (16 - len(byteguid))) if byteguid not in ('\x20' * 16, '\x00' * 16, '\xff' * 16): fru['UUID'] = util.decode_wireformat_uuid(byteguid) - except (AttributeError, KeyError): + except (AttributeError, KeyError, IndexError): + pass + return fru + elif self.has_imm: + fru['oem_parser'] = 'lenovo' + try: + bextra = fru['board_extra'] + fru['FRU Number'] = bextra[0] + fru['Revision'] = bextra[4] + macs = bextra[6] + macprefix = None + idx = 0 + endidx = len(macs) - 5 + macprefix = None + while idx < endidx: + currmac = macs[idx:idx+6] + if currmac == b'\x00\x00\x00\x00\x00\x00': + break + # VPD may veer off, detect and break off + if macprefix is None: + macprefix = currmac[:3] + elif currmac[:3] != macprefix: + break + ms = mac_format.format(*currmac) + ifidx = idx / 6 + 1 + fru['MAC Address {0}'.format(ifidx)] = ms + idx = idx + 6 + except (AttributeError, KeyError, IndexError): pass return fru else: diff --git a/pyghmi/ipmi/oem/lenovo/imm.py b/pyghmi/ipmi/oem/lenovo/imm.py index cf3519c9..84bd8a46 100644 --- a/pyghmi/ipmi/oem/lenovo/imm.py +++ b/pyghmi/ipmi/oem/lenovo/imm.py @@ -173,6 +173,85 @@ def fetch_agentless_firmware(ipmicmd, certverify): wc.request('GET', '/data/logout') +def get_hw_inventory(ipmicmd, certverify): + hwmap = hardware_inventory_map(ipmicmd, certverify) + for key in hwmap: + yield (key, hwmap[key]) + + +def get_hw_descriptions(ipmicmd, certverify): + hwmap = hardware_inventory_map(ipmicmd, certverify) + for key in hwmap: + yield key + + +def get_component_inventory(ipmicmd, certverify, compname): + hwmap = hardware_inventory_map(ipmicmd, certverify) + try: + return hwmap[compname] + except KeyError: + return None + + +def hardware_inventory_map(ipmicmd, certverify): + hwmap = get_cached_data(ipmicmd, 'lenovo_cached_hwmap') + if hwmap: + return hwmap + hwmap = {} + wc = None + adapterdata = get_cached_data(ipmicmd, 'lenovo_cached_adapters') + if not adapterdata: + wc = get_web_session(ipmicmd, certverify, wc) + if wc: + adapterdata = wc.grab_json_response( + '/designs/imm/dataproviders/imm_adapters.php') + if adapterdata: + ipmicmd.ipmi_session.lenovo_cached_adapters = ( + adapterdata, _monotonic_time()) + if adapterdata: + for adata in adapterdata['items']: + skipadapter = False + if not adata['adapter.oobSupported']: + continue + aslot = None + aname = adata['adapter.adapterName'] + clabel = adata['adapter.connectorLabel'] + if clabel == 'Unknown': + continue + if clabel != 'Onboard': + aslot = adata['adapter.slotNo'] + if clabel == 'ML2': + clabel = 'ML2 (Slot {0})'.format(aslot) + else: + clabel = 'Slot {0}'.format(aslot) + bdata = {'location': clabel} + for fundata in adata['adapter.functions']: + bdata['pcislot'] = '{0:02x}:{1:02x}'.format( + fundata['generic.busNo'], fundata['generic.devNo']) + serialdata = fundata.get('vpd.serialNo', None) + if (serialdata and serialdata != 'N/A' and + '---' not in serialdata): + bdata['serial'] = serialdata + partnum = fundata.get('vpd.partNo', None) + if partnum and partnum != 'N/A': + bdata['partnumber'] = partnum + if 'network.pPorts' in fundata: + for portinfo in fundata['network.pPorts']: + for lp in portinfo['logicalPorts']: + ma = lp['networkAddr'] + ma = ':'.join( + [ma[i:i+2] for i in xrange( + 0, len(ma), 2)]).lower() + bdata['MAC Address {0}'.format( + portinfo['portIndex'])] = ma + elif clabel == 'Onboard': # skip the various onboard non-nic + skipadapter = True + if not skipadapter: + hwmap[aname] = bdata + ipmicmd.ipmi_session.lenovo_cached_hwmap = (hwmap, _monotonic_time()) + return hwmap + + def get_firmware_inventory(ipmicmd, bmcver, certverify): # First we fetch the system firmware found in imm properties # then check for agentless, if agentless, get adapter info using