Skip to content

Commit

Permalink
Redfish for mainline commit
Browse files Browse the repository at this point in the history
Closes: #776
Change-Id: I7f7b1bc5d4a16494fc5f9ec18a89348448019b33
Co-Authored-by: Moritz Kiemer <[email protected]>
  • Loading branch information
Yogibaer75 and mo-ki committed Dec 13, 2024
1 parent 984e057 commit 00c8b51
Show file tree
Hide file tree
Showing 40 changed files with 4,402 additions and 0 deletions.
14 changes: 14 additions & 0 deletions cmk/gui/views/inventory/_builtin_display_hints.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,20 @@ def register(inventory_displayhints: InventoryHintRegistry) -> None:
".hardware.cpu.nodes:*.node_name": {"title": _l("Node name")},
".hardware.cpu.nodes:*.cores": {"title": _l("#Cores"), "paint": "count"},
".hardware.cpu.nodes:*.model": {"title": _l("CPU model")},
".hardware.firmware.": {"title": _l("Firmware")},
".hardware.firmware.redfish:": {
"title": _l("Redfish"),
"keyorder": ["component", "version", "location", "description"],
"view": "invfirmwareredfish",
},
".hardware.firmware.redfish:*.component": {"title": _l("Component")},
".hardware.firmware.redfish:*.version": {"title": _l("Version")},
".hardware.firmware.redfish:*.location": {"title": _l("Location")},
".hardware.firmware.redfish:*.description": {"title": _l("Description")},
".hardware.firmware.redfish:*.updateable": {
"title": _l("Update possible"),
"paint": "bool",
},
".hardware.memory.": {
"title": _l("Memory (RAM)"),
"keyorder": ["total_ram_usable", "total_swap", "total_vmalloc"],
Expand Down
156 changes: 156 additions & 0 deletions cmk/plugins/redfish/agent_based/inv_redfish_firmware.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
#!/usr/bin/env python3
# Copyright (C) 2024 Checkmk GmbH - License: GNU General Public License v2
# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
# conditions defined in the file COPYING, which is part of this source code package.
'''Redfish firmware inventory for HPE devices'''

from cmk.agent_based.v2 import (
AgentSection,
CheckPlugin,
CheckResult,
DiscoveryResult,
InventoryPlugin,
InventoryResult,
Result,
Service,
State,
TableRow,
)
from cmk_addons.plugins.redfish.lib import (
RedfishAPIData,
parse_redfish_multiple,
redfish_health_state,
)

agent_section_redfish_firmware = AgentSection(
name="redfish_firmwareinventory",
parse_function=parse_redfish_multiple,
parsed_section_name="redfish_firmware",
)


def _item_name(item_data, padding):
"""build item name for inventory entry"""
if not item_data.get('Id'):
if item_data.get('Name'):
item_name = item_data.get('Name')
else:
return None
elif item_data.get('Id').isdigit():
item_name = f"{item_data.get('Id').zfill(padding)}-{item_data.get('Name')}"
elif item_data.get('Id') == item_data.get('Name'):
item_name = item_data.get('Name')
elif item_data.get('Description') == "Represents Firmware Inventory":
prefix = item_data.get('Id').split("-")[0]
item_name = f"{prefix}-{item_data.get('Name')}"
else:
item_name = f"{item_data.get('Id')}-{item_data.get('Name')}"
return item_name


def inventory_redfish_firmware(section: RedfishAPIData) -> InventoryResult:
"""create inventory table for firmware"""
path = ["hardware", "firmware", "redfish"]
if section.get("FirmwareInventory", {}).get("Current"):
data = section.get("FirmwareInventory", {}).get("Current")
padding = len(str(len(data)))
for index, entry_id in enumerate(data):
entry = data.get(entry_id)
component_name = f"{str(index).zfill(padding)}-{entry[0].get('Name')}"
yield TableRow(
path=path,
key_columns={
"component": component_name,
},
inventory_columns={
"version": entry[0].get("VersionString"),
"location": entry[0].get("Location"),
},
)
else:
padding = len(str(len(section)))
for _key, entry in section.items():
item_name = _item_name(entry, padding)
if not item_name:
continue
if entry.get('Description') == "Represents Firmware Inventory":
description = entry.get('Id')
else:
description = entry.get('Description')
yield TableRow(
path=path,
key_columns={
"component": item_name,
},
inventory_columns={
"version": entry.get("Version"),
"description": description,
"updateable": entry.get("Updateable"),
},
)


inventory_plugin_redfish_firmware = InventoryPlugin(
name="redfish_firmware",
inventory_function=inventory_redfish_firmware,
)


def discovery_redfish_firmware(section: RedfishAPIData) -> DiscoveryResult:
"""discover service if data exists"""
if section:
yield Service()


def check_redfish_firmware(section: RedfishAPIData) -> CheckResult:
"""check the health state of the firmware"""

padding = len(str(len(section)))
overall_state = 0
msg_text = ""
info_text = ""
info_list = []
for _key, entry in section.items():
if not entry.get("Status"):
continue
component_name = _item_name(entry, padding)
comp_state, comp_msg = redfish_health_state(entry.get("Status", {}))
if entry.get("Status", {}).get("State", "UNKNOWN") == "StandbyOffline":
comp_state = 0
overall_state = max(overall_state, comp_state)
if comp_state != 0:
msg_text += f"{component_name} - {comp_msg} - "
info_list.append(
[component_name, comp_msg, entry.get("Version"), entry.get("Updateable")]
)

if not msg_text:
msg_text = "All firmware in optimal state"

line_bracket = "<tr>%s</tr>"
cell_bracket = "<td>%s</td>"
cell_seperator = ""
headers = ("Component", "Status", "Version", "Updateable")
info_text = f'<table style="border-collapse: separate; border-spacing: 10px 0;">{(
"<tr><th>"
+ "</th><th>".join(headers)
+ "</th></tr>"
+ "".join(
[
line_bracket
% cell_seperator.join([cell_bracket % value for value in info_entry])
for info_entry in info_list
]
)
)}</table>'

yield Result(state=State(overall_state), summary=msg_text, details=info_text)


check_plugin_redfish_firmware = CheckPlugin(
name="redfish_firmware",
service_name="Firmware health",
sections=["redfish_firmware"],
discovery_function=discovery_redfish_firmware,
check_function=check_redfish_firmware,
)
48 changes: 48 additions & 0 deletions cmk/plugins/redfish/agent_based/inv_redfish_firmware_hpe_ilo4.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/env python3
# Copyright (C) 2024 Checkmk GmbH - License: GNU General Public License v2
# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
# conditions defined in the file COPYING, which is part of this source code package.
"""Redfish firmware inventory for HPE devices"""

from cmk.agent_based.v2 import (
AgentSection,
InventoryPlugin,
InventoryResult,
TableRow,
)
from cmk_addons.plugins.redfish.lib import (
RedfishAPIData,
parse_redfish,
)


agent_section_redfish_firmware_hpe_ilo4 = AgentSection(
name="redfish_firmware_hpe_ilo4",
parse_function=parse_redfish,
parsed_section_name="redfish_firmware_hpe_ilo4",
)


def inventory_redfish_firmware_hpe_ilo4(section: RedfishAPIData) -> InventoryResult:
"""create inventory table for firmware"""
path = ["hardware", "firmware", "redfish"]
padding = len(str(len(section)))
for index, entry_id in enumerate(section):
entry = section.get(entry_id)
component_name = f"{str(index).zfill(padding)}-{entry[0].get('Name')}"
yield TableRow(
path=path,
key_columns={
"component": component_name,
},
inventory_columns={
"version": entry[0].get("VersionString"),
"location": entry[0].get("Location"),
},
)


inventory_plugin_redfish_firmware_hpe_ilo4 = InventoryPlugin(
name="redfish_firmware_hpe_ilo4",
inventory_function=inventory_redfish_firmware_hpe_ilo4,
)
13 changes: 13 additions & 0 deletions cmk/plugins/redfish/agent_based/redfish_arraycontrollers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env python3
# Copyright (C) 2024 Checkmk GmbH - License: GNU General Public License v2
# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
# conditions defined in the file COPYING, which is part of this source code package.

from cmk.agent_based.v2 import AgentSection
from cmk_addons.plugins.redfish.lib import parse_redfish_multiple

agent_section_redfish_arraycontrollers = AgentSection(
name="redfish_arraycontrollers",
parse_function=parse_redfish_multiple,
parsed_section_name="redfish_arraycontrollers",
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env python3
# Copyright (C) 2024 Checkmk GmbH - License: GNU General Public License v2
# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
# conditions defined in the file COPYING, which is part of this source code package.

from cmk.agent_based.v2 import (
CheckPlugin,
CheckResult,
DiscoveryResult,
Result,
Service,
State,
)
from cmk_addons.plugins.redfish.lib import (
RedfishAPIData,
redfish_health_state,
)


def discovery_redfish_arraycontrollers_generic(
section: RedfishAPIData,
) -> DiscoveryResult:
for key in section.keys():
if section[key].get("Oem"):
if section[key]["Oem"].get("Dell"):
yield Service(item=section[key]["Id"])


def check_redfish_arraycontrollers_generic(
item: str, section: RedfishAPIData
) -> CheckResult:
data = section.get(item, None)
if data is None:
return

if data.get("[email protected]") == 1:
ctrl_data = data.get("StorageControllers")[0]

storage_msg = (
f"Type: {ctrl_data.get('Model')}, "
f"RaidLevels: {','.join(ctrl_data.get('SupportedRAIDTypes', []))}, "
f"DeviceProtocols: {','.join(ctrl_data.get('SupportedDeviceProtocols', []))}"
)
yield Result(state=State(0), summary=storage_msg)

dev_state, dev_msg = redfish_health_state(data.get("Status", {}))
status = dev_state
message = dev_msg

yield Result(state=State(status), notice=message)


check_plugin_redfish_arraycontrollers_generic = CheckPlugin(
name="redfish_arraycontrollers_generic",
service_name="Storage Controller %s",
sections=["redfish_arraycontrollers"],
discovery_function=discovery_redfish_arraycontrollers_generic,
check_function=check_redfish_arraycontrollers_generic,
)
52 changes: 52 additions & 0 deletions cmk/plugins/redfish/agent_based/redfish_arraycontrollers_hpe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env python3
# Copyright (C) 2024 Checkmk GmbH - License: GNU General Public License v2
# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
# conditions defined in the file COPYING, which is part of this source code package.

from cmk.agent_based.v2 import (
CheckPlugin,
CheckResult,
DiscoveryResult,
Result,
Service,
State,
)
from cmk_addons.plugins.redfish.lib import (
RedfishAPIData,
redfish_health_state,
)


def discovery_redfish_arraycontrollers_hpe(section: RedfishAPIData) -> DiscoveryResult:
for key in section.keys():
if "SmartStorageArrayController" in section[key]["@odata.type"]:
yield Service(item=section[key]["Id"])


def check_redfish_arraycontrollers_hpe(
item: str, section: RedfishAPIData
) -> CheckResult:
data = section.get(item, None)
if data is None:
return

dev_type = data.get("Model")
dev_ser = data.get("SerialNumber")

storage_msg = f"Type: {dev_type}, Serial: {dev_ser}"
yield Result(state=State(0), summary=storage_msg)

dev_state, dev_msg = redfish_health_state(data.get("Status", {}))
status = dev_state
message = dev_msg

yield Result(state=State(status), notice=message)


check_plugin_redfish_arraycontrollers_hpe = CheckPlugin(
name="redfish_arraycontrollers_hpe",
service_name="Storage Controller %s",
sections=["redfish_arraycontrollers"],
discovery_function=discovery_redfish_arraycontrollers_hpe,
check_function=check_redfish_arraycontrollers_hpe,
)
Loading

0 comments on commit 00c8b51

Please sign in to comment.