From 407c180d709d0d1b53180c2d00b682ee4cc397c4 Mon Sep 17 00:00:00 2001 From: Lucio Seki Date: Mon, 24 Aug 2015 16:03:39 -0300 Subject: [PATCH] Add RAID drive and controller to ThinkServer inventory Change-Id: Icfda252540cf4e2a7da720530889c9d60fbfeeff --- pyghmi/ipmi/oem/lenovo/handler.py | 9 ++- pyghmi/ipmi/oem/lenovo/inventory.py | 14 ++++- pyghmi/ipmi/oem/lenovo/raid_controller.py | 65 ++++++++++++++++++++ pyghmi/ipmi/oem/lenovo/raid_drive.py | 74 +++++++++++++++++++++++ 4 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 pyghmi/ipmi/oem/lenovo/raid_controller.py create mode 100644 pyghmi/ipmi/oem/lenovo/raid_drive.py diff --git a/pyghmi/ipmi/oem/lenovo/handler.py b/pyghmi/ipmi/oem/lenovo/handler.py index 708f3c2d..d48b3c1b 100755 --- a/pyghmi/ipmi/oem/lenovo/handler.py +++ b/pyghmi/ipmi/oem/lenovo/handler.py @@ -29,12 +29,16 @@ from pyghmi.ipmi.oem.lenovo import firmware from pyghmi.ipmi.oem.lenovo import inventory from pyghmi.ipmi.oem.lenovo import pci from pyghmi.ipmi.oem.lenovo import psu +from pyghmi.ipmi.oem.lenovo import raid_controller +from pyghmi.ipmi.oem.lenovo import raid_drive inventory.register_inventory_category(cpu) inventory.register_inventory_category(dimm) inventory.register_inventory_category(pci) inventory.register_inventory_category(drive) inventory.register_inventory_category(psu) +inventory.register_inventory_category(raid_drive) +inventory.register_inventory_category(raid_controller) firmware_types = { @@ -220,7 +224,10 @@ class OEMHandler(generic.OEMHandler): continue else: try: - items = inventory.parse_inventory_category(catid, rsp) + items = inventory.parse_inventory_category( + catid, rsp, + countable=catspec.get("countable", True) + ) except Exception: # If we can't parse an inventory category, ignore it print traceback.print_exc() diff --git a/pyghmi/ipmi/oem/lenovo/inventory.py b/pyghmi/ipmi/oem/lenovo/inventory.py index 7014c40a..39c2b528 100755 --- a/pyghmi/ipmi/oem/lenovo/inventory.py +++ b/pyghmi/ipmi/oem/lenovo/inventory.py @@ -50,7 +50,7 @@ class EntryField(object): # General parameter parsing functions -def parse_inventory_category(name, info): +def parse_inventory_category(name, info, countable=True): """Parses every entry in an inventory category (CPU, memory, PCI, drives, etc). @@ -59,19 +59,27 @@ def parse_inventory_category(name, info): :param name: the name of the parameter (e.g.: "cpu") :param info: a list of integers with raw data read from an IPMI requests + :param countable: whether the data have an entries count field :returns: dict -- a list of entries in the category. """ raw = info["data"][1:] cur = 0 - count = struct.unpack("B", raw[cur])[0] - cur += 1 + if countable: + count = struct.unpack("B", raw[cur])[0] + cur += 1 + else: + count = 0 entries = [] while cur < len(raw): read, cpu = categories[name]["parser"](raw[cur:]) cur = cur + read + if not countable: + # count by myself + count += 1 + cpu["index"] = count entries.append(cpu) # TODO(avidal): raise specific exception to point that there's data left in diff --git a/pyghmi/ipmi/oem/lenovo/raid_controller.py b/pyghmi/ipmi/oem/lenovo/raid_controller.py new file mode 100644 index 00000000..eb5df944 --- /dev/null +++ b/pyghmi/ipmi/oem/lenovo/raid_controller.py @@ -0,0 +1,65 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2015 Lenovo +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from pyghmi.ipmi.oem.lenovo.inventory import EntryField, \ + parse_inventory_category_entry + +raid_controller_fields = ( + EntryField("ControllerID", "I"), + EntryField("AdapterType", "B", mapper={ + 0x00: "Unknown", + 0x01: "RAIDController" + }), + EntryField("SupercapPresence", "B", mapper={ + 0x00: "Absent", + 0x01: "Present" + }), + EntryField("FlashComponent1Name", "16s"), + EntryField("FlashComponent1Version", "64s"), + EntryField("FlashComponent2Name", "16s"), + EntryField("FlashComponent2Version", "64s"), + EntryField("FlashComponent3Name", "16s"), + EntryField("FlashComponent3Version", "64s"), + EntryField("FlashComponent4Name", "16s"), + EntryField("FlashComponent4Version", "64s"), + EntryField("FlashComponent5Name", "16s"), + EntryField("FlashComponent5Version", "64s"), + EntryField("FlashComponent6Name", "16s"), + EntryField("FlashComponent6Version", "64s"), + EntryField("FlashComponent7Name", "16s"), + EntryField("FlashComponent7Version", "64s"), + EntryField("FlashComponent8Name", "16s"), + EntryField("FlashComponent8Version", "64s") +) + + +def parse_raid_controller_info(raw): + return parse_inventory_category_entry(raw, raid_controller_fields) + + +def get_categories(): + return { + "raid_controller": { + "idstr": "RAID Controller {0}", + "parser": parse_raid_controller_info, + "countable": False, + "command": { + "netfn": 0x06, + "command": 0x59, + "data": (0x00, 0xc4, 0x00, 0x00) + } + } + } diff --git a/pyghmi/ipmi/oem/lenovo/raid_drive.py b/pyghmi/ipmi/oem/lenovo/raid_drive.py new file mode 100644 index 00000000..b9180fd6 --- /dev/null +++ b/pyghmi/ipmi/oem/lenovo/raid_drive.py @@ -0,0 +1,74 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2015 Lenovo +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from pyghmi.ipmi.oem.lenovo.inventory import EntryField, \ + parse_inventory_category_entry + +raid_drive_fields = ( + EntryField("index", "B"), + EntryField("VendorID", "64s"), + EntryField("Size", "I", + valuefunc=lambda v: str(v) + " MB"), + EntryField("MediaType", "B", mapper={ + 0x00: "HDD", + 0x01: "SSD", + 0x02: "SSM_FLASH" + }), + EntryField("InterfaceType", "B", mapper={ + 0x00: "Unknown", + 0x01: "ParallelSCSI", + 0x02: "SAS", + 0x03: "SATA", + 0x04: "FC" + }), + EntryField("FormFactor", "B", mapper={ + 0x00: "Unknown", + 0x01: "2.5in", + 0x02: "3.5in" + }), + EntryField("LinkSpeed", "B", mapper={ + 0x00: "Unknown", + 0x01: "1.5 Gb/s", + 0x02: "3.0 Gb/s", + 0x03: "6.0 Gb/s", + 0x04: "12.0 Gb/s" + }), + EntryField("SlotNumber", "B"), + EntryField("DeviceState", "B", mapper={ + 0x00: "active", + 0x01: "stopped", + 0xff: "transitioning" + }), + # There seems to be an undocumented byte at the end + EntryField("Reserved", "B", include=False)) + + +def parse_raid_drive_info(raw): + return parse_inventory_category_entry(raw, raid_drive_fields) + + +def get_categories(): + return { + "raid_raid_drive": { + "idstr": "RAID Drive {0}", + "parser": parse_raid_drive_info, + "command": { + "netfn": 0x06, + "command": 0x59, + "data": (0x00, 0xc5, 0x00, 0x00) + } + } + }