diff options
| author | Patrick Williams <patrick@stwcx.xyz> | 2015-10-29 14:22:29 -0500 |
|---|---|---|
| committer | Patrick Williams <patrick@stwcx.xyz> | 2015-10-29 14:22:29 -0500 |
| commit | e290f5cdccf14e50e838366367c91e0464f792f6 (patch) | |
| tree | e59c12f991407609552ee4ab1313cc11209d961a | |
| parent | 64d9b0ce3697c4fc3e000815667b0ced47af5ed6 (diff) | |
| parent | 3f43cdbebb681926ae17bff4b44b36ff90361204 (diff) | |
| download | phosphor-objmgr-e290f5cdccf14e50e838366367c91e0464f792f6.tar.gz phosphor-objmgr-e290f5cdccf14e50e838366367c91e0464f792f6.zip | |
Merge pull request #2 from bradbishop/master
introspection parser
| -rw-r--r-- | OpenBMCMapper.py | 107 | ||||
| -rw-r--r-- | phosphor-mapper | 81 |
2 files changed, 122 insertions, 66 deletions
diff --git a/OpenBMCMapper.py b/OpenBMCMapper.py index 1862a46..30a93fb 100644 --- a/OpenBMCMapper.py +++ b/OpenBMCMapper.py @@ -16,6 +16,9 @@ # implied. See the License for the specific language governing # permissions and limitations under the License. +from xml.etree import ElementTree +import dbus + MAPPER_NAME = 'org.openbmc.objectmapper' MAPPER_IFACE = MAPPER_NAME + '.ObjectMapper' MAPPER_PATH = '/org/openbmc/objectmapper/objectmapper' @@ -41,3 +44,107 @@ class Path: if not last: last = self.depth() return prefix + '/'.join(self.parts[first:last]) + +class IntrospectionNodeParser: + def __init__(self, data): + self.data = data + self.cache = {} + + def parse_args(self): + return [ x.attrib for x in self.data.findall('arg') ] + + def parse_children(self): + return [ x.attrib['name'] for x in self.data.findall('node') ] + + def parse_method_or_signal(self): + name = self.data.attrib['name'] + return name, self.parse_args() + + def parse_interface(self): + iface = {} + iface['method'] = {} + iface['signal'] = {} + name = self.data.attrib['name'] + + for node in self.data: + p = IntrospectionNodeParser(node) + if node.tag not in ['method', 'signal']: + continue + n, element = p.parse_method_or_signal() + iface[node.tag][n] = element + + return name, iface + + def parse_node(self): + if self.cache: + return self.cache + + self.cache['interfaces'] = {} + self.cache['children'] = [] + + for node in self.data: + p = IntrospectionNodeParser(node) + if node.tag == 'interface': + name, ifaces = p.parse_interface() + self.cache['interfaces'][name] = ifaces + elif node.tag == 'node': + self.cache['children'] = self.parse_children() + + return self.cache + + def get_interfaces(self): + return self.parse_node()['interfaces'] + + def get_children(self): + return self.parse_node()['children'] + + def recursive_binding(self): + return any('/' in s for s in self.get_children()) + +class IntrospectionParser: + def __init__(self, name, bus): + self.name = name + self.bus = bus + + def _introspect(self, path): + try: + obj = self.bus.get_object(self.name, path) + iface = dbus.Interface(obj, dbus.BUS_DAEMON_IFACE + '.Introspectable') + data = iface.Introspect() + except dbus.DBusException: + return None + + return IntrospectionNodeParser(ElementTree.fromstring(data)) + + def _discover_flat(self, path, parser): + items = {} + interfaces = parser.get_interfaces().keys() + if interfaces: + items[path] = {} + items[path]['interfaces'] = interfaces + + return items + + def introspect(self, path = '/', parser = None): + items = {} + if not parser: + parser = self._introspect(path) + if not parser: + return {} + items.update(self._discover_flat(path, parser)) + + if path != '/': + path += '/' + + if parser.recursive_binding(): + callback = self._discover_flat + else: + callback = self.introspect + + for k in parser.get_children(): + parser = self._introspect(path + k) + if not parser: + continue + items.update(callback(path + k, parser)) + + return items diff --git a/phosphor-mapper b/phosphor-mapper index 28d2600..313baa2 100644 --- a/phosphor-mapper +++ b/phosphor-mapper @@ -21,8 +21,7 @@ import dbus import dbus.service import dbus.mainloop.glib import gobject -from xml.etree import ElementTree -from OpenBMCMapper import Path +from OpenBMCMapper import Path, IntrospectionParser import OpenBMCMapper class DictionaryCache: @@ -201,7 +200,7 @@ class ObjectMapper(dbus.service.Object): def process_new_owner(self, name): # unique name - return self.discover([ Owner(name, self.bus) ]) + return self.discover([ IntrospectionParser(name, self.bus.dbus) ]) def process_old_owner(self, name): # unique name @@ -217,6 +216,17 @@ class ObjectMapper(dbus.service.Object): if old: self.process_old_owner(old) + def add_match_interfaces(self, owner, path, interfaces): + for x in interfaces: + if self.intf_match not in x: + continue + + self.cache.add_item((path, owner, x)) + + def add_match_items(self, owner, bus_items): + for x,y in bus_items.iteritems(): + self.add_match_interfaces(owner, x, y['interfaces']) + def discover(self, owners = None): discovery = not self.discovery_done if not owners: @@ -229,7 +239,7 @@ class ObjectMapper(dbus.service.Object): if self.cache.has_bus(o.name): continue - self.cache.add_items(o.discover(self.intf_match)) + self.add_match_items(o.name, o.introspect()) if discovery: print "ObjectMapper discovery complete..." @@ -249,67 +259,6 @@ class ObjectMapper(dbus.service.Object): values.update(self.GetTree(x, depth, match_type)) return values -class IntrospectionParser: - def __init__(self, data): - self.data = data - self.cache = {} - - def get_interfaces(self, match): - if 'interfaces' not in self.cache.keys(): - self.cache['interfaces'] = [ x.attrib['name' ] \ - for x in self.data.findall('interface') \ - if match in x.attrib['name'] ] - return self.cache['interfaces'] - - def get_kids(self): - if 'kids' not in self.cache.keys(): - self.cache['kids'] = [ x.attrib['name' ] \ - for x in self.data.findall('node') ] - return self.cache['kids'] - - def recursive_binding(self): - return any('/' in s for s in self.get_kids()) - -class Owner: - def __init__(self, name, bus): - self.name = name - self.bus = bus - - def introspect(self, path): - try: - obj = self.bus.dbus.get_object(self.name, path) - iface = dbus.Interface(obj, 'org.freedesktop.DBus.Introspectable') - data = iface.Introspect() - except dbus.DBusException: - return None - - return IntrospectionParser(ElementTree.fromstring(data)) - - def discover(self, match, path = '/'): - parser = self.introspect(path) - if not parser: - return [] - - items = [] - for x in parser.get_interfaces(match): - items.append((path, self.name, x)) - - if path != '/': - path += '/' - - recursive = parser.recursive_binding() - for k in parser.get_kids(): - if recursive: - parser = self.introspect(path + k) - if not parser: - return [] - for x in parser.get_interfaces(match): - items.append((path + k, self.name, x)) - else: - items.extend(self.discover(match, path + k)) - - return items - class BusWrapper: def __init__(self, bus): self.dbus = bus @@ -325,7 +274,7 @@ class BusWrapper: for x in self.get_service_names(match) ] ) ) def get_owners(self, match): - return [ Owner(x, self) \ + return [ IntrospectionParser(x, self.dbus) \ for x in self.get_owner_names(match) ] if __name__ == '__main__': |

