From 80c70610a0ea96cf609387638f9f3f9bee0c581d Mon Sep 17 00:00:00 2001 From: Marri Devender Rao Date: Thu, 12 Apr 2018 09:22:55 -0500 Subject: Modify parser and add mako scripts for watch on object path Added support for watch and callback on 'interface added' signal for the specified object paths. Added mako scripts for events to auto create callback and watch objects for the specified object path groups. Clients specify object paths to watch and callbacks to invoke in the config.yaml file Change-Id: I3fa2ea1520649120b927c0cb83a16e5cace2f24e Signed-off-by: Marri Devender Rao --- src/example/example.yaml | 25 ++++ src/main.cpp | 9 ++ src/pdmgen.py | 190 ++++++++++++++++++++++++++++++- src/templates/callbackpathgroup.mako.cpp | 2 + src/templates/eventpath.mako.cpp | 1 + src/templates/generated.mako.hpp | 56 +++++++++ 6 files changed, 282 insertions(+), 1 deletion(-) create mode 100644 src/templates/callbackpathgroup.mako.cpp create mode 100644 src/templates/eventpath.mako.cpp (limited to 'src') diff --git a/src/example/example.yaml b/src/example/example.yaml index ec0a611..b011a26 100644 --- a/src/example/example.yaml +++ b/src/example/example.yaml @@ -244,3 +244,28 @@ countbound: 3 op: '>=' bound: 115 + +- name: errorlog path group + class: group + group: path + members: + - meta: PATH + path: /xyz/openbmc_project/logging + +- name: pathwatch errorlog + description: > + 'A pathwatch watches on the specified object path goup. + pathcallback are actions PDM should take when instructed to do so.' + + class: pathwatch + pathwatch: path + paths: errorlog path group + pathcallback: create errorlog event + +- name: create errorlog event + description: > + 'eventType specifies the type of the SNMP notification.' + class: pathcallback + pathcallback: eventpath + paths: errorlog path group + eventType: ErrorTrap diff --git a/src/main.cpp b/src/main.cpp index 68cef3e..3b75e3b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,6 +54,15 @@ int main(void) { watch->callback(Context::START); } + for (auto& watch : ConfigPathWatches::get()) + { + watch->start(); + } + + for (auto& watch : ConfigPathWatches::get()) + { + watch->callback(Context::START); + } Loop::run(); diff --git a/src/pdmgen.py b/src/pdmgen.py index 48d4589..c4184fc 100755 --- a/src/pdmgen.py +++ b/src/pdmgen.py @@ -354,6 +354,17 @@ class Instance(ConfigEntry): super(Instance, self).setup(objs) +class PathInstance(ConfigEntry): + '''Path association.''' + + def __init__(self, *a, **kw): + super(PathInstance, self).__init__(**kw) + + def setup(self, objs): + '''Resolve elements to indices.''' + self.path = self.name['path']['path'] + self.pathmeta = self.name['path']['meta'] + super(PathInstance, self).setup(objs) class Group(ConfigEntry): '''Pop the members keyword for groups.''' @@ -468,6 +479,27 @@ class GroupOfInstances(ImplicitGroup): super(GroupOfInstances, self).setup(objs) +class GroupOfPathInstances(ImplicitGroup): + '''A group of path instances.''' + + def __init__(self, *a, **kw): + super(GroupOfPathInstances, self).__init__(**kw) + + def setup(self, objs): + '''Resolve group members.''' + + def map_member(x): + path = get_index(objs, 'pathname', x['path']['path']) + pathmeta = get_index(objs, 'meta', x['path']['meta']) + pathinstance = get_index(objs, 'pathinstance', x) + return (path, pathmeta, pathinstance) + + self.members = map( + map_member, + self.members) + + super(GroupOfPathInstances, self).setup(objs) + class HasPropertyIndex(ConfigEntry): '''Handle config file directives that require an index to be @@ -531,6 +563,54 @@ class HasPropertyIndex(ConfigEntry): super(HasPropertyIndex, self).setup(objs) +class HasPathIndex(ConfigEntry): + '''Handle config file directives that require an index to be + constructed.''' + + def __init__(self, *a, **kw): + self.paths = kw.pop('paths') + super(HasPathIndex, self).__init__(**kw) + + def factory(self, objs): + '''Create a group of instances for this index.''' + + members = [] + path_group = get_index( + objs, 'pathgroup', self.paths, config=self.configfile) + + for path in objs['pathgroup'][path_group].members: + member = { + 'path': path, + } + members.append(member) + + args = { + 'members': members, + 'class': 'pathinstancegroup', + 'pathinstancegroup': 'pathinstance', + 'name': '{0}'.format(self.paths) + } + + group = GroupOfPathInstances(configfile=self.configfile, **args) + add_unique(group, objs, config=self.configfile) + group.factory(objs) + + super(HasPathIndex, self).factory(objs) + + def setup(self, objs): + '''Resolve path and instance groups.''' + + self.pathinstances = get_index( + objs, + 'pathinstancegroup', + '{0}'.format(self.paths), + config=self.configfile) + self.paths = get_index( + objs, + 'pathgroup', + self.paths, + config=self.configfile) + super(HasPathIndex, self).setup(objs) class PropertyWatch(HasPropertyIndex): '''Handle the property watch config file directive.''' @@ -551,6 +631,23 @@ class PropertyWatch(HasPropertyIndex): super(PropertyWatch, self).setup(objs) +class PathWatch(HasPathIndex): + '''Handle the path watch config file directive.''' + + def __init__(self, *a, **kw): + self.pathcallback = kw.pop('pathcallback', None) + super(PathWatch, self).__init__(**kw) + + def setup(self, objs): + '''Resolve optional callback.''' + if self.pathcallback: + self.pathcallback = get_index( + objs, + 'pathcallback', + self.pathcallback, + config=self.configfile) + super(PathWatch, self).setup(objs) + class Callback(HasPropertyIndex): '''Interface and common logic for callbacks.''' @@ -558,6 +655,11 @@ class Callback(HasPropertyIndex): def __init__(self, *a, **kw): super(Callback, self).__init__(**kw) +class PathCallback(HasPathIndex): + '''Interface and common logic for callbacks.''' + + def __init__(self, *a, **kw): + super(PathCallback, self).__init__(**kw) class ConditionCallback(ConfigEntry, Renderer): '''Handle the journal callback config file directive.''' @@ -718,6 +820,19 @@ class Event(Callback, Renderer): c=self, indent=indent) +class EventPath(PathCallback, Renderer): + '''Handle the event path callback config file directive.''' + + def __init__(self, *a, **kw): + self.eventType = kw.pop('eventType') + super(EventPath, self).__init__(**kw) + + def construct(self, loader, indent): + return self.render( + loader, + 'eventpath.mako.cpp', + c=self, + indent=indent) class ElogWithMetadata(Callback, Renderer): '''Handle the elog_with_metadata callback config file directive.''' @@ -854,6 +969,24 @@ class CallbackGraphEntry(Group): super(CallbackGraphEntry, self).setup(objs) +class PathCallbackGraphEntry(Group): + '''An entry in a traversal list for groups of callbacks.''' + + def __init__(self, *a, **kw): + super(PathCallbackGraphEntry, self).__init__(**kw) + + def setup(self, objs): + '''Resolve group members.''' + + def map_member(x): + return get_index( + objs, 'pathcallback', x, config=self.configfile) + + self.members = map( + map_member, + self.members) + + super(PathCallbackGraphEntry, self).setup(objs) class GroupOfCallbacks(ConfigEntry, Renderer): '''Handle the callback group config file directive.''' @@ -893,6 +1026,42 @@ class GroupOfCallbacks(ConfigEntry, Renderer): c=self, indent=indent) +class GroupOfPathCallbacks(ConfigEntry, Renderer): + '''Handle the callback group config file directive.''' + + def __init__(self, *a, **kw): + self.members = kw.pop('members') + super(GroupOfPathCallbacks, self).__init__(**kw) + + def factory(self, objs): + '''Create a graph instance for this group of callbacks.''' + + args = { + 'configfile': self.configfile, + 'members': self.members, + 'class': 'pathcallbackgroup', + 'pathcallbackgroup': 'pathcallback', + 'name': self.members + } + + entry = PathCallbackGraphEntry(**args) + add_unique(entry, objs, config=self.configfile) + super(GroupOfPathCallbacks, self).factory(objs) + + def setup(self, objs): + '''Resolve graph entry.''' + + self.graph = get_index( + objs, 'callbackpathgroup', self.members, config=self.configfile) + + super(GroupOfPathCallbacks, self).setup(objs) + + def construct(self, loader, indent): + return self.render( + loader, + 'callbackpathgroup.mako.cpp', + c=self, + indent=indent) class Everything(Renderer): '''Parse/render entry point.''' @@ -901,7 +1070,6 @@ class Everything(Renderer): def classmap(cls, sub=None): '''Map render item class and subclass entries to the appropriate handler methods.''' - class_map = { 'path': { 'element': Path, @@ -918,9 +1086,15 @@ class Everything(Renderer): 'watch': { 'property': PropertyWatch, }, + 'pathwatch': { + 'path': PathWatch, + }, 'instance': { 'element': Instance, }, + 'pathinstance': { + 'element': PathInstance, + }, 'callback': { 'journal': Journal, 'elog': Elog, @@ -930,6 +1104,10 @@ class Everything(Renderer): 'method': Method, 'resolve callout': ResolveCallout, }, + 'pathcallback': { + 'eventpath': EventPath, + 'grouppath': GroupOfPathCallbacks, + }, 'condition': { 'count': CountCondition, }, @@ -1020,10 +1198,15 @@ class Everything(Renderer): self.propertynames = kw.pop('propertyname', []) self.propertygroups = kw.pop('propertygroup', []) self.instances = kw.pop('instance', []) + self.pathinstances = kw.pop('pathinstance', []) self.instancegroups = kw.pop('instancegroup', []) + self.pathinstancegroups = kw.pop('pathinstancegroup', []) self.watches = kw.pop('watch', []) + self.pathwatches = kw.pop('pathwatch', []) self.callbacks = kw.pop('callback', []) + self.pathcallbacks = kw.pop('pathcallback', []) self.callbackgroups = kw.pop('callbackgroup', []) + self.pathcallbackgroups = kw.pop('pathcallbackgroup', []) self.conditions = kw.pop('condition', []) super(Everything, self).__init__(**kw) @@ -1047,10 +1230,15 @@ class Everything(Renderer): pathgroups=self.pathgroups, propertygroups=self.propertygroups, instances=self.instances, + pathinstances=self.pathinstances, watches=self.watches, + pathwatches=self.pathwatches, instancegroups=self.instancegroups, + pathinstancegroups=self.pathinstancegroups, callbacks=self.callbacks, + pathcallbacks=self.pathcallbacks, callbackgroups=self.callbackgroups, + pathcallbackgroups=self.pathcallbackgroups, conditions=self.conditions, indent=Indent())) diff --git a/src/templates/callbackpathgroup.mako.cpp b/src/templates/callbackpathgroup.mako.cpp new file mode 100644 index 0000000..33418d5 --- /dev/null +++ b/src/templates/callbackpathgroup.mako.cpp @@ -0,0 +1,2 @@ +std::make_unique>( +${indent(1)}ConfigPathCallbackGroups::get()[${c.graph}])\ \ No newline at end of file diff --git a/src/templates/eventpath.mako.cpp b/src/templates/eventpath.mako.cpp new file mode 100644 index 0000000..3fa9fb9 --- /dev/null +++ b/src/templates/eventpath.mako.cpp @@ -0,0 +1 @@ +std::make_unique>() diff --git a/src/templates/generated.mako.hpp b/src/templates/generated.mako.hpp index 1b73198..8dbaa20 100644 --- a/src/templates/generated.mako.hpp +++ b/src/templates/generated.mako.hpp @@ -12,9 +12,11 @@ #include "errors.hpp" #include "method.hpp" #include "propertywatchimpl.hpp" +#include "pathwatchimpl.hpp" #include "resolve_errors.hpp" #include "sdbusplus.hpp" #include "event.hpp" +#include "snmp_trap.hpp" #include "sdevent.hpp" using namespace std::string_literals; @@ -75,6 +77,22 @@ struct ConfigInterfaces } }; +struct ConfigIntfAddPaths +{ + using Paths = std::array; + + static auto& get() + { + static const Paths paths = + { +% for p in pathinstances: + "${p.path}"s, +% endfor + }; + return paths; + } +}; + struct ConfigProperties { using Properties = std::array; @@ -186,6 +204,22 @@ struct ConfigPropertyCallbacks } }; +struct ConfigPathCallbacks +{ + using Callbacks = std::array, ${len(pathcallbacks)}>; + + static auto& get() + { + static const Callbacks pathCallbacks = + { +% for c in pathcallbacks: + ${c.construct(loader, indent=indent +3)}, +% endfor + }; + return pathCallbacks; + } +}; + struct ConfigPropertyWatches { using PropertyWatches = std::array, ${len(watches)}>; @@ -207,6 +241,28 @@ struct ConfigPropertyWatches return propertyWatches; } }; + +struct ConfigPathWatches +{ + using PathWatches = std::array, ${len(pathwatches)}>; + + static auto& get() + { + static const PathWatches pathWatches = + { +% for w in pathwatches: + std::make_unique>( + % if w.pathcallback is None: + ConfigIntfAddPaths::get()[${w.pathinstances}]), + % else: + ConfigIntfAddPaths::get()[${w.pathinstances}], + *ConfigPathCallbacks::get()[${w.pathcallback}]), + % endif +% endfor + }; + return pathWatches; + } +}; } // namespace monitoring } // namespace dbus } // namespace phosphor -- cgit v1.2.1