From 5756a1e37797d629de1b83937280c8039084e3c6 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Mon, 26 Aug 2024 16:22:08 -0400 Subject: [PATCH] Extend MAC collection in redfish There is yet another flavor of MAC address organization. So make sure we provide chances to hit it at least three of the various ways redfish may choose to manifest mac addresses. There are other paths to the data as well, but hopefully an implementation at least implements one of the three. Change-Id: Iaba947e2e16f14b6e7a94018beac046efd73bc25 --- pyghmi/redfish/oem/generic.py | 94 +++++++++++++++++++++++++++-------- 1 file changed, 73 insertions(+), 21 deletions(-) diff --git a/pyghmi/redfish/oem/generic.py b/pyghmi/redfish/oem/generic.py index ad11f1e2..8b251e1a 100644 --- a/pyghmi/redfish/oem/generic.py +++ b/pyghmi/redfish/oem/generic.py @@ -43,6 +43,11 @@ class SensorReading(object): self.units = units self.unavailable = unavailable +def _normalize_mac(mac): + if ':' not in mac: + mac = ':'.join((mac[:2], mac[2:4], mac[4:6], mac[6:8], mac[8:10], mac[10:12])) + return mac.lower() + _healthmap = { 'Critical': const.Health.Critical, 'Unknown': const.Health.Warning, @@ -611,22 +616,39 @@ class OEMHandler(object): yield (dname, ddata) def _get_adp_inventory(self, onlyname=False, withids=False, urls=None): + foundmacs = False + macinfobyadpname = {} + if 'NetworkInterfaces' in self._varsysinfo: + nifurls = self._do_web_request(self._varsysinfo['NetworkInterfaces']['@odata.id']) + nifurls = nifurls.get('Members', []) + nifurls = [x['@odata.id'] for x in nifurls] + for nifurl in nifurls: + nifinfo = self._do_web_request(nifurl) + + nadurl = nifinfo.get('Links', {}).get('NetworkAdapter', {}).get("@odata.id") + if nadurl: + nadinfo = self._do_web_request(nadurl) + if 'Name' not in nadinfo: + continue + nicname = nadinfo['Name'] + yieldinf = {} + macidx = 1 + for ctrlr in nadinfo.get('Controllers', []): + porturls = [x['@odata.id'] for x in ctrlr.get( + 'Links', {}).get('Ports', [])] + for porturl in porturls: + portinfo = self._do_web_request(porturl) + macs = [x for x in portinfo.get( + 'Ethernet', {}).get( + 'AssociatedMACAddresses', [])] + for mac in macs: + label = 'MAC Address {}'.format(macidx) + yieldinf[label] = _normalize_mac(mac) + macidx += 1 + foundmacs = True + macinfobyadpname[nicname] = yieldinf if not urls: urls = self._get_adp_urls() - if not urls: - # No PCIe device inventory, but *maybe* ethernet inventory... - aidx = 1 - for nicinfo in self._get_eth_urls(): - nicinfo = self._do_web_request(nicinfo) - nicname = nicinfo.get('Name', None) - nicinfo = nicinfo.get('MACAddress', None) - if not nicname: - nicname = 'NIC' - if nicinfo: - yield (nicname, - {'MAC Address {0}'.format(aidx): nicinfo}) - aidx += 1 - return for inf in self._do_bulk_requests(urls): adpinfo, url = inf aname = adpinfo.get('Name', 'Unknown') @@ -648,6 +670,8 @@ class OEMHandler(object): yieldinf = {'Id': adpinfo.get('Id', aname)} else: yieldinf = {} + if aname in macinfobyadpname: + yieldinf.update(macinfobyadpname[aname]) funurls = [x['@odata.id'] for x in functions] for fun in self._do_bulk_requests(funurls): funinfo, url = fun @@ -660,14 +684,42 @@ class OEMHandler(object): yieldinf['PCI Subsystem Vendor ID'] = funinfo[ 'SubsystemVendorId'].replace('0x', '') yieldinf['Type'] = funinfo['DeviceClass'] - for nicinfo in funinfo.get('Links', {}).get( - 'EthernetInterfaces', []): - nicinfo = self._do_web_request(nicinfo['@odata.id']) - macaddr = nicinfo.get('MACAddress', None) - if macaddr: - yieldinf['MAC Address {0}'.format(nicidx)] = macaddr - nicidx += 1 + if aname not in macinfobyadpname: + for nicinfo in funinfo.get('Links', {}).get( + 'EthernetInterfaces', []): + nicinfo = self._do_web_request(nicinfo['@odata.id']) + macaddr = nicinfo.get('MACAddress', None) + if macaddr: + macaddr = _normalize_mac(macaddr) + foundmacs = True + yieldinf['MAC Address {0}'.format(nicidx)] = macaddr + nicidx += 1 + if aname in macinfobyadpname: + del macinfobyadpname[aname] yield aname, yieldinf + if macinfobyadpname: + for adp in macinfobyadpname: + yield adp, macinfobyadpname[adp] + if not foundmacs: + # No PCIe device inventory, but *maybe* ethernet inventory... + idxsbyname = {} + for nicinfo in self._get_eth_urls(): + nicinfo = self._do_web_request(nicinfo) + nicname = nicinfo.get('Name', None) + nicinfo = nicinfo.get('MACAddress', nicinfo.get('PermanentAddress', None)) + if nicinfo and ':' not in nicinfo: + nicinfo = ':'.join(( + nicinfo[:2], nicinfo[2:4], nicinfo[4:6], nicinfo[6:8], + nicinfo[8:10], nicinfo[10:12])) + if not nicname: + nicname = 'NIC' + if nicinfo: + if nicname not in idxsbyname: + idxsbyname[nicname] = 0 + idxsbyname[nicname] += 1 + nicinfo = nicinfo.lower() + yield (nicname, + {'MAC Address {}'.format(idxsbyname[nicname]): nicinfo}) def _get_eth_urls(self): ethurls = self._varsysinfo.get('EthernetInterfaces', {})