From 0a51831bf0c7b99dddc4933e264cd9d45f140881 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Mon, 2 May 2016 15:53:12 -0400 Subject: [PATCH] Add disk inventory when possible from Lenovo IMM Agentless data may have information about firmware of disks. This commit adds support for reading it when available. Note that some devices may not appear, depending on the drive controller in use and timing factors. Change-Id: I24033a4fe7ed056018dab2747e71845fdcaa5cf0 --- pyghmi/ipmi/oem/lenovo/imm.py | 86 +++++++++++++++++++++++++---------- pyghmi/util/webclient.py | 7 +++ 2 files changed, 70 insertions(+), 23 deletions(-) diff --git a/pyghmi/ipmi/oem/lenovo/imm.py b/pyghmi/ipmi/oem/lenovo/imm.py index 95c4252d..cf3519c9 100644 --- a/pyghmi/ipmi/oem/lenovo/imm.py +++ b/pyghmi/ipmi/oem/lenovo/imm.py @@ -87,27 +87,35 @@ def fetch_grouped_properties(ipmicmd, groupinfo): return retdata -def fetch_adapter_firmware(ipmicmd, certverify): - adapterdata = None +def get_cached_data(ipmicmd, attribute): try: - vintage = ipmicmd.ipmi_session.lenovo_cached_adapters[1] - if vintage > _monotonic_time() - 30: - adapterdata = ipmicmd.ipmi_session.lenovo_cached_adapters[0] + kv = getattr(ipmicmd.ipmi_session, attribute) + if kv[1] > _monotonic_time() - 30: + return kv[0] except AttributeError: - pass + return None + + +def get_web_session(ipmicmd, certverify, wc): + if wc: + return wc + wc = get_imm_webclient(ipmicmd.bmc, certverify, + ipmicmd.ipmi_session.userid, + ipmicmd.ipmi_session.password) + return wc + + +def fetch_agentless_firmware(ipmicmd, certverify): + wc = None + adapterdata = get_cached_data(ipmicmd, 'lenovo_cached_adapters') if not adapterdata: - wc = get_imm_webclient(ipmicmd.bmc, certverify, - ipmicmd.ipmi_session.userid, - ipmicmd.ipmi_session.password) - if not wc: - return - wc.request('GET', '/designs/imm/dataproviders/imm_adapters.php') - rsp = wc.getresponse() - if rsp.status == 200: - adapterdata = json.loads(rsp.read()) - ipmicmd.ipmi_session.lenovo_cached_adapters = (adapterdata, - _monotonic_time()) - wc.request('GET', '/data/logout') + 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']: aname = adata['adapter.adapterName'] @@ -115,9 +123,9 @@ def fetch_adapter_firmware(ipmicmd, certverify): for fundata in adata['adapter.functions']: fdata = fundata.get('firmwares', ()) for firm in fdata: - fname = firm['firmwareName'] + fname = firm['firmwareName'].rstrip() if '.' in fname: - fname = firm['description'] + fname = firm['description'].rstrip() if fname in donenames: # ignore redundant entry continue @@ -128,9 +136,41 @@ def fetch_adapter_firmware(ipmicmd, certverify): if ('releaseDate' in firm and firm['releaseDate'] and firm['releaseDate'] != 'N/A'): - bdata['date'] = datetime.strptime(firm['releaseDate'], - '%m/%d/%Y') + try: + bdata['date'] = datetime.strptime( + firm['releaseDate'], '%m/%d/%Y') + except ValueError: + try: + bdata['date'] = datetime.strptime( + firm['releaseDate'], '%m %d %Y') + except ValueError: + pass yield ('{0} {1}'.format(aname, fname), bdata) + storagedata = get_cached_data(ipmicmd, 'lenovo_cached_storage') + if not storagedata: + wc = get_web_session(ipmicmd, certverify, wc) + if wc: + storagedata = wc.grab_json_response( + '/designs/imm/dataproviders/raid_alldevices.php') + if storagedata: + ipmicmd.ipmi_session.lenovo_cached_storage = ( + storagedata, _monotonic_time()) + if storagedata and 'items' in storagedata: + for adp in storagedata['items']: + adpname = adp['storage.vpd.productName'] + if 'children' not in adp: + adp['children'] = () + for diskent in adp['children']: + bdata = {} + diskname = '{0} Disk {1}'.format( + adpname, + diskent['storage.slotNo']) + bdata['model'] = diskent['storage.vpd.productName'].rstrip() + bdata['version'] = diskent['storage.firmwares'][0][ + 'versionStr'] + yield (diskname, bdata) + if wc: + wc.request('GET', '/data/logout') def get_firmware_inventory(ipmicmd, bmcver, certverify): @@ -169,5 +209,5 @@ def get_firmware_inventory(ipmicmd, bmcver, certverify): 'build': '/v2/bios/pending_build_id'}) if bdata: yield ('UEFI Pending Update', bdata) - for firm in fetch_adapter_firmware(ipmicmd, certverify): + for firm in fetch_agentless_firmware(ipmicmd, certverify): yield firm diff --git a/pyghmi/util/webclient.py b/pyghmi/util/webclient.py index f1a1725b..84eae8de 100644 --- a/pyghmi/util/webclient.py +++ b/pyghmi/util/webclient.py @@ -20,6 +20,7 @@ __author__ = 'jjohnson2' import Cookie import httplib +import json import pyghmi.exceptions as pygexc import socket import ssl @@ -53,6 +54,12 @@ class SecureHTTPConnection(httplib.HTTPConnection, object): self.cookies[k] = c[k].value return rsp + def grab_json_response(self, url): + self.request('GET', url) + rsp = self.getresponse() + if rsp.status == 200: + return json.loads(rsp.read()) + def request(self, method, url, body=None, headers=None): if headers is None: headers = {}