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 <devenrao@in.ibm.com>
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 @@
{
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
'watch': {
'property': PropertyWatch,
},
+ 'pathwatch': {
+ 'path': PathWatch,
+ },
'instance': {
'element': Instance,
},
+ 'pathinstance': {
+ 'element': PathInstance,
+ },
'callback': {
'journal': Journal,
'elog': Elog,
@@ -930,6 +1104,10 @@
'method': Method,
'resolve callout': ResolveCallout,
},
+ 'pathcallback': {
+ 'eventpath': EventPath,
+ 'grouppath': GroupOfPathCallbacks,
+ },
'condition': {
'count': CountCondition,
},
@@ -1020,10 +1198,15 @@
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 @@
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<GroupOfPathCallbacks<ConfigPathCallbacks>>(
+${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<SNMPTrap<${c.eventType}>>()
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 ConfigIntfAddPaths
+{
+ using Paths = std::array<std::string, ${len(pathinstances)}>;
+
+ static auto& get()
+ {
+ static const Paths paths =
+ {
+% for p in pathinstances:
+ "${p.path}"s,
+% endfor
+ };
+ return paths;
+ }
+};
+
struct ConfigProperties
{
using Properties = std::array<std::string, ${len(propertynames)}>;
@@ -186,6 +204,22 @@
}
};
+struct ConfigPathCallbacks
+{
+ using Callbacks = std::array<std::unique_ptr<Callback>, ${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<std::unique_ptr<Watch>, ${len(watches)}>;
@@ -207,6 +241,28 @@
return propertyWatches;
}
};
+
+struct ConfigPathWatches
+{
+ using PathWatches = std::array<std::unique_ptr<Watch>, ${len(pathwatches)}>;
+
+ static auto& get()
+ {
+ static const PathWatches pathWatches =
+ {
+% for w in pathwatches:
+ std::make_unique<PathWatch<SDBusPlus>>(
+ % 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