xref: /openbmc/sdbusplus/tools/sdbusplus/event.py (revision d925c0bc)
1import os
2
3import jsonschema
4import yaml
5
6from .namedelement import NamedElement
7from .property import Property
8from .renderer import Renderer
9
10
11class EventMetadata(Property):
12    def __init__(self, **kwargs):
13        self.primary = kwargs.pop("primary", False)
14        super(EventMetadata, self).__init__(**kwargs)
15
16
17class EventLanguage(object):
18    def __init__(self, **kwargs):
19        super(EventLanguage, self).__init__()
20        self.description = kwargs.pop("description", False)
21        self.message = kwargs.pop("message")
22        self.resolution = kwargs.pop("resolution", False)
23
24
25class EventElement(NamedElement):
26    def __init__(self, **kwargs):
27        self.is_error = kwargs.pop("is_error", False)
28        self.deprecated = kwargs.pop("deprecated", None)
29        self.errno = kwargs.pop("errno", "EIO")
30        self.redfish_map = kwargs.pop("redfish-mapping", None)
31        if not self.redfish_map:
32            self.languages = {
33                key: EventLanguage(**kwargs.pop(key, {})) for key in ["en"]
34            }
35        else:
36            self.languages = {
37                "en": EventLanguage(
38                    **{"message": f"Redfish({self.redfish_map})"}
39                )
40            }
41        self.metadata = [
42            EventMetadata(**n) for n in kwargs.pop("metadata", [])
43        ]
44        self.severity = EventElement.syslog_severity(
45            kwargs.pop("severity", "informational")
46        )
47
48        super(EventElement, self).__init__(**kwargs)
49
50    def cpp_includes(self, interface):
51        includes = []
52        for m in self.metadata:
53            includes.extend(m.enum_headers(interface))
54        return sorted(set(includes))
55
56    def __getattribute__(self, name):
57        lam = {"description": lambda: self.__description()}.get(name)
58
59        if lam:
60            return lam()
61        try:
62            return super(EventElement, self).__getattribute__(name)
63        except Exception:
64            raise AttributeError(
65                "Attribute '%s' not found in %s.EventElement"
66                % (name, self.__module__)
67            )
68
69    def __description(self):
70        en = self.languages["en"]
71        if en.description:
72            return en.description
73        return en.message
74
75    @staticmethod
76    def syslog_severity(severity: str) -> str:
77        return {
78            "emergency": "LOG_EMERG",
79            "alert": "LOG_ALERT",
80            "critical": "LOG_CRIT",
81            "error": "LOG_ERR",
82            "warning": "LOG_WARNING",
83            "notice": "LOG_NOTICE",
84            "informational": "LOG_INFO",
85            "debug": "LOG_DEBUG",
86        }[severity]
87
88
89class Event(NamedElement, Renderer):
90    @staticmethod
91    def load(name, rootdir, schemadir):
92        schemafile = os.path.join(schemadir, "events.schema.yaml")
93        with open(schemafile) as f:
94            data = f.read()
95            schema = yaml.safe_load(data)
96
97            spec = jsonschema.Draft202012Validator
98            spec.check_schema(schema)
99
100            validator = spec(schema)
101
102        filename = os.path.join(
103            rootdir, name.replace(".", "/") + ".events.yaml"
104        )
105
106        with open(filename) as f:
107            data = f.read()
108            y = yaml.safe_load(data)
109
110            validator.validate(y)
111
112            y["name"] = name
113            return Event(**y)
114
115    def __init__(self, **kwargs):
116        self.version = kwargs.pop("version")
117        self.errors = [
118            EventElement(**n, is_error=True) for n in kwargs.pop("errors", [])
119        ]
120        self.events = [EventElement(**n) for n in kwargs.pop("events", [])]
121
122        super(Event, self).__init__(**kwargs)
123
124    def cpp_includes(self):
125        includes = []
126        for e in self.errors:
127            includes.extend(e.cpp_includes(self.name))
128        for e in self.events:
129            includes.extend(e.cpp_includes(self.name))
130        return sorted(set(includes))
131
132    def markdown(self, loader):
133        return self.render(loader, "events.md.mako", events=self)
134
135    def exception_header(self, loader):
136        return self.render(loader, "events.hpp.mako", events=self)
137
138    def exception_cpp(self, loader):
139        return self.render(loader, "events.cpp.mako", events=self)
140