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