Promote obmc.mapper to python package
Enable additional modules in the mapper package namespace.
Change-Id: If2b38eef13b194a6087bb80947884f94bb2a5881
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
diff --git a/obmc/mapper/bindings.py b/obmc/mapper/bindings.py
new file mode 100644
index 0000000..f193a50
--- /dev/null
+++ b/obmc/mapper/bindings.py
@@ -0,0 +1,163 @@
+# Contributors Listed Below - COPYRIGHT 2016
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+
+import dbus
+import obmc.dbuslib.enums
+import obmc.utils.misc
+import obmc.utils.pathtree
+
+
+MAPPER_NAME = 'org.openbmc.ObjectMapper'
+MAPPER_IFACE = MAPPER_NAME
+MAPPER_PATH = '/org/openbmc/ObjectMapper'
+MAPPER_NOT_FOUND = MAPPER_NAME + '.Error.NotFound'
+
+
+class Mapper:
+ def __init__(self, bus):
+ self.bus = bus
+ obj = bus.get_object(MAPPER_NAME, MAPPER_PATH, introspect=False)
+ self.iface = dbus.Interface(
+ obj, dbus_interface=MAPPER_IFACE)
+
+ def get_object(self, path):
+ return self.iface.GetObject(path)
+
+ def get_subtree_paths(self, path='/', depth=0):
+ return self.iface.GetSubTreePaths(path, depth)
+
+ def get_subtree(self, path='/', depth=0):
+ return self.iface.GetSubTree(path, depth)
+
+ def get_ancestors(self, path):
+ return self.iface.GetAncestors(path)
+
+ @staticmethod
+ def __try_properties_interface(f, *a):
+ try:
+ return f(*a)
+ except dbus.exceptions.DBusException, e:
+ if obmc.dbuslib.enums.DBUS_UNKNOWN_INTERFACE in \
+ e.get_dbus_message():
+ # interface doesn't have any properties
+ return None
+ if obmc.dbuslib.enums.DBUS_UNKNOWN_METHOD == e.get_dbus_name():
+ # properties interface not implemented at all
+ return None
+ raise
+
+ @staticmethod
+ def __get_properties_on_iface(properties_iface, iface):
+ properties = Mapper.__try_properties_interface(
+ properties_iface.GetAll, iface)
+ if properties is None:
+ return {}
+ return properties
+
+ def __get_properties_on_bus(self, path, bus, interfaces, match):
+ properties = {}
+ obj = self.bus.get_object(bus, path, introspect=False)
+ properties_iface = dbus.Interface(
+ obj, dbus_interface=dbus.PROPERTIES_IFACE)
+ for i in interfaces:
+ if not match(i):
+ continue
+ properties.update(self.__get_properties_on_iface(
+ properties_iface, i))
+
+ return properties
+
+ def enumerate_object(
+ self, path,
+ match=obmc.utils.misc.org_dot_openbmc_match,
+ mapper_data=None):
+ if mapper_data is None:
+ mapper_data = {path: self.get_object(path)}
+
+ obj = {}
+
+ for owner, interfaces in mapper_data[path].iteritems():
+ obj.update(
+ self.__get_properties_on_bus(
+ path, owner, interfaces, match))
+
+ return obj
+
+ def enumerate_subtree(
+ self, path='/',
+ match=obmc.utils.misc.org_dot_openbmc_match,
+ mapper_data=None):
+ if mapper_data is None:
+ mapper_data = self.get_subtree(path)
+ managers = {}
+ owners = []
+
+ # look for objectmanager implementations as they result
+ # in fewer dbus calls
+ for path, bus_data in mapper_data.iteritems():
+ for owner, interfaces in bus_data.iteritems():
+ owners.append(owner)
+ if dbus.BUS_DAEMON_IFACE + '.ObjectManager' in interfaces:
+ managers[owner] = path
+
+ # also look in the parent objects
+ ancestors = self.get_ancestors(path)
+
+ # finally check the root for one too
+ try:
+ ancestors.update({path: self.get_object(path)})
+ except dbus.exceptions.DBusException, e:
+ if e.get_dbus_name() != MAPPER_NOT_FOUND:
+ raise
+
+ for path, bus_data in ancestors.iteritems():
+ for owner, interfaces in bus_data.iteritems():
+ if dbus.BUS_DAEMON_IFACE + '.ObjectManager' in interfaces:
+ managers[owner] = path
+
+ # make all the manager gmo (get managed objects) calls
+ results = {}
+ for owner, path in managers.iteritems():
+ if owner not in owners:
+ continue
+ obj = self.bus.get_object(owner, path, introspect=False)
+ iface = dbus.Interface(
+ obj, dbus.BUS_DAEMON_IFACE + '.ObjectManager')
+
+ # flatten (remove interface names) gmo results
+ for path, interfaces in iface.GetManagedObjects().iteritems():
+ if path not in mapper_data.iterkeys():
+ continue
+ properties = {}
+ for iface, props in interfaces.iteritems():
+ properties.update(props)
+ results.setdefault(path, {}).setdefault(owner, properties)
+
+ # make dbus calls for any remaining objects
+ for path, bus_data in mapper_data.iteritems():
+ for owner, interfaces in bus_data.iteritems():
+ if results.setdefault(path, {}).setdefault(owner, {}):
+ continue
+ results[path][owner].update(
+ self.__get_properties_on_bus(
+ path, owner, interfaces, match))
+
+ objs = obmc.utils.pathtree.PathTree()
+ for path, owners in results.iteritems():
+ for owner, properties in owners.iteritems():
+ objs.setdefault(path, {}).update(properties)
+
+ return objs