sdbus++: events: generate Redfish registry
Create an initial Redfish Message Registry from an events.yaml
file. This includes a few OEM properties under "OpenBMC_Mapping"
in order to give hints to bmcweb on how to do:
- Map OpenBMC Events to Redfish Events.
- Map AdditionalData fields to MessageArgs.
Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
Change-Id: I7260c2344a8509bbcad7a6653ccf2b3578427e45
diff --git a/tools/sdbusplus/event.py b/tools/sdbusplus/event.py
index 03137c5..2c8d935 100644
--- a/tools/sdbusplus/event.py
+++ b/tools/sdbusplus/event.py
@@ -1,3 +1,6 @@
+import datetime
+import itertools
+import json
import os
import jsonschema
@@ -41,9 +44,10 @@
self.metadata = [
EventMetadata(**n) for n in kwargs.pop("metadata", [])
]
- self.severity = EventElement.syslog_severity(
- kwargs.pop("severity", "informational")
- )
+
+ self.severity = kwargs.pop("severity", "informational")
+ self.syslog_sev = EventElement.syslog_severity(self.severity)
+ self.registry_sev = EventElement.registry_severity(self.severity)
super(EventElement, self).__init__(**kwargs)
@@ -53,6 +57,55 @@
includes.extend(m.enum_headers(interface))
return sorted(set(includes))
+ def registry_event(self, interface, language):
+ if language not in self.languages:
+ language = "en"
+ language_data = self.languages[language]
+
+ args = [x for x in self.metadata if x.primary]
+
+ for i, arg in enumerate(args):
+ language_data.message = language_data.message.replace(
+ f"{{{arg.name}}}", f"%{i+1}"
+ )
+
+ result = {}
+ if language_data.description:
+ result["Description"] = language_data.description
+ result["Message"] = language_data.message
+ if language_data.resolution:
+ result["Resolution"] = language_data.resolution
+
+ result["MessageSeverity"] = self.registry_sev
+
+ result["NumberOfArgs"] = len(args)
+ result["ParamTypes"] = [x.registry_type() for x in args]
+
+ result["OEM"] = {
+ "OpenBMC_Mapping": {
+ "Event": interface + "." + self.name,
+ "Args": self.registry_args_mapping(interface),
+ }
+ }
+
+ return result
+
+ def registry_mapping(self, interface):
+ return {
+ "RedfishEvent": self.redfish_map,
+ "Args": self.registry_args_mapping(interface),
+ }
+
+ def registry_args_mapping(self, interface):
+ args = [x for x in self.metadata if x.primary]
+ return [
+ {
+ "Name": x.SNAKE_CASE,
+ "Type": x.cppTypeParam(interface, full=True),
+ }
+ for x in args
+ ]
+
def __getattribute__(self, name):
lam = {"description": lambda: self.__description()}.get(name)
@@ -85,6 +138,19 @@
"debug": "LOG_DEBUG",
}[severity]
+ @staticmethod
+ def registry_severity(severity: str) -> str:
+ return {
+ "emergency": "Critical",
+ "alert": "Critical",
+ "critical": "Critical",
+ "error": "Warning",
+ "warning": "Warning",
+ "notice": "Warning",
+ "informational": "OK",
+ "debug": "OK",
+ }[severity]
+
class Event(NamedElement, Renderer):
@staticmethod
@@ -137,3 +203,35 @@
def exception_cpp(self, loader):
return self.render(loader, "events.cpp.mako", events=self)
+
+ def exception_registry(self, loader):
+ language = "en"
+ registryName = self.registryPrefix("OpenBMC")
+
+ messages = {}
+ mappings = {}
+
+ for e in itertools.chain(self.errors, self.events):
+ if e.redfish_map:
+ mappings[self.name + "." + e.name] = e.registry_mapping(
+ self.name
+ )
+ else:
+ messages[e.name] = e.registry_event(self.name, language)
+
+ result = {
+ "@Redfish.Copyright": f"Copyright 2024-{datetime.date.today().year} OpenBMC.",
+ "@odata.type": "#MessageRegistry.v1_6_3.MessageRegistry",
+ "Id": f"{registryName}.{self.version}",
+ "Language": f"{language}",
+ "Message": messages,
+ "Name": f"OpenBMC Message Registry for {self.name}",
+ "OwningEntity": "OpenBMC",
+ "RegistryPrefix": f"{registryName}",
+ "RegistryVersion": f"{self.version}",
+ }
+
+ if len(mappings) != 0:
+ result["OEM"] = ({"OpenBMC_Mapping": mappings},)
+
+ return json.dumps(result, indent=4)
diff --git a/tools/sdbusplus/main.py b/tools/sdbusplus/main.py
index ac66f99..15a94ce 100644
--- a/tools/sdbusplus/main.py
+++ b/tools/sdbusplus/main.py
@@ -20,6 +20,7 @@
"common-header": "common_header",
"exception-cpp": "exception_cpp",
"exception-header": "exception_header",
+ "exception-registry": "exception_registry",
"markdown": "markdown",
"server-cpp": "server_cpp",
"server-header": "server_header",
diff --git a/tools/sdbusplus/namedelement.py b/tools/sdbusplus/namedelement.py
index 87cb86d..c8afb31 100644
--- a/tools/sdbusplus/namedelement.py
+++ b/tools/sdbusplus/namedelement.py
@@ -55,6 +55,15 @@
def cppNamespacedClass(self):
return self.cppNamespace() + "::" + self.classname
+ def registryPrefix(self, root_prefix):
+ name = inflection.camelize(
+ self.name.replace("xyz.openbmc_project.", "")
+ .replace("com.", "")
+ .replace(".", "_"),
+ uppercase_first_letter=True,
+ )
+ return root_prefix + "_" + name
+
""" Some names are reserved in some languages. Fixup names to avoid using
reserved words.
"""
diff --git a/tools/sdbusplus/property.py b/tools/sdbusplus/property.py
index 898aa28..4d79cb6 100644
--- a/tools/sdbusplus/property.py
+++ b/tools/sdbusplus/property.py
@@ -202,47 +202,77 @@
return result
+ propertyMap = {
+ "byte": {"cppName": "uint8_t", "params": 0},
+ "boolean": {"cppName": "bool", "params": 0},
+ "int16": {"cppName": "int16_t", "params": 0},
+ "uint16": {"cppName": "uint16_t", "params": 0},
+ "int32": {"cppName": "int32_t", "params": 0},
+ "uint32": {"cppName": "uint32_t", "params": 0},
+ "int64": {
+ "cppName": "int64_t",
+ "params": 0,
+ "registryName": "number",
+ },
+ "uint64": {
+ "cppName": "uint64_t",
+ "params": 0,
+ "registryName": "number",
+ },
+ "size": {
+ "cppName": "size_t",
+ "params": 0,
+ "registryName": "number",
+ },
+ "ssize": {"cppName": "ssize_t", "params": 0},
+ "double": {
+ "cppName": "double",
+ "params": 0,
+ "registryName": "number",
+ },
+ "unixfd": {"cppName": "sdbusplus::message::unix_fd", "params": 0},
+ "string": {
+ "cppName": "std::string",
+ "params": 0,
+ "registryName": "string",
+ },
+ "object_path": {
+ "cppName": "sdbusplus::message::object_path",
+ "params": 0,
+ "registryName": "string",
+ },
+ "signature": {
+ "cppName": "sdbusplus::message::signature",
+ "params": 0,
+ },
+ "array": {"cppName": "std::vector", "params": 1},
+ "set": {"cppName": "std::set", "params": 1},
+ "struct": {"cppName": "std::tuple", "params": -1},
+ "variant": {"cppName": "std::variant", "params": -1},
+ "dict": {"cppName": "std::map", "params": 2},
+ "enum": {
+ "cppName": "enum",
+ "params": 1,
+ "registryName": "number",
+ },
+ }
+
+ """ Get the registry type of the property. """
+
+ def registry_type(self):
+ return Property.propertyMap[self.typeName]["registryName"]
+
""" Take a list of dbus types and perform validity checking, such as:
[ variant [ dict [ int32, int32 ], double ] ]
This function then converts the type-list into a C++ type string.
"""
def __parse_cpp_type__(self, typeTuple):
- propertyMap = {
- "byte": {"cppName": "uint8_t", "params": 0},
- "boolean": {"cppName": "bool", "params": 0},
- "int16": {"cppName": "int16_t", "params": 0},
- "uint16": {"cppName": "uint16_t", "params": 0},
- "int32": {"cppName": "int32_t", "params": 0},
- "uint32": {"cppName": "uint32_t", "params": 0},
- "int64": {"cppName": "int64_t", "params": 0},
- "uint64": {"cppName": "uint64_t", "params": 0},
- "size": {"cppName": "size_t", "params": 0},
- "ssize": {"cppName": "ssize_t", "params": 0},
- "double": {"cppName": "double", "params": 0},
- "unixfd": {"cppName": "sdbusplus::message::unix_fd", "params": 0},
- "string": {"cppName": "std::string", "params": 0},
- "object_path": {
- "cppName": "sdbusplus::message::object_path",
- "params": 0,
- },
- "signature": {
- "cppName": "sdbusplus::message::signature",
- "params": 0,
- },
- "array": {"cppName": "std::vector", "params": 1},
- "set": {"cppName": "std::set", "params": 1},
- "struct": {"cppName": "std::tuple", "params": -1},
- "variant": {"cppName": "std::variant", "params": -1},
- "dict": {"cppName": "std::map", "params": 2},
- "enum": {"cppName": "enum", "params": 1},
- }
-
if len(typeTuple) != 2:
raise RuntimeError("Invalid typeTuple %s" % typeTuple)
first = typeTuple[0]
- entry = propertyMap[first]
+ entry = Property.propertyMap[first]
result = entry["cppName"]
diff --git a/tools/sdbusplus/templates/event.hpp.mako b/tools/sdbusplus/templates/event.hpp.mako
index 8cf6e31..21171ea 100644
--- a/tools/sdbusplus/templates/event.hpp.mako
+++ b/tools/sdbusplus/templates/event.hpp.mako
@@ -43,7 +43,7 @@
"${event.description}";
static constexpr auto errWhat =
"${events.name}.${event.name}: ${event.description}";
- static constexpr int errSeverity = ${event.severity};
+ static constexpr int errSeverity = ${event.syslog_sev};
static constexpr auto errErrno = ${event.errno};
};