blob: ab235244504df3f708148ff42fba4d42f6322b11 [file] [log] [blame]
Brad Bishop8ffe1e42016-02-11 16:15:40 -05001# Contributors Listed Below - COPYRIGHT 2016
2# [+] International Business Machines Corp.
3#
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14# implied. See the License for the specific language governing
15# permissions and limitations under the License.
16
17import dbus
Brad Bishopf6c2a942016-04-01 14:44:12 -040018import obmc.dbuslib.enums
19import obmc.utils.misc
20import obmc.utils.pathtree
Brad Bishop8ffe1e42016-02-11 16:15:40 -050021
Brad Bishop51c55392016-05-18 08:23:29 -040022MAPPER_NAME = 'org.openbmc.ObjectMapper'
23MAPPER_IFACE = MAPPER_NAME
24MAPPER_PATH = '/org/openbmc/ObjectMapper'
25MAPPER_NOT_FOUND = MAPPER_NAME + '.Error.NotFound'
Brad Bishop8ffe1e42016-02-11 16:15:40 -050026
27
28class Mapper:
29 def __init__(self, bus):
30 self.bus = bus
31 obj = bus.get_object(MAPPER_NAME, MAPPER_PATH, introspect=False)
32 self.iface = dbus.Interface(
33 obj, dbus_interface=MAPPER_IFACE)
34
35 def get_object(self, path):
36 return self.iface.GetObject(path)
37
38 def get_subtree_paths(self, path='/', depth=0):
39 return self.iface.GetSubTreePaths(path, depth)
40
41 def get_subtree(self, path='/', depth=0):
42 return self.iface.GetSubTree(path, depth)
43
44 def get_ancestors(self, path):
45 return self.iface.GetAncestors(path)
Brad Bishopf6c2a942016-04-01 14:44:12 -040046
47 @staticmethod
48 def __try_properties_interface(f, *a):
49 try:
50 return f(*a)
51 except dbus.exceptions.DBusException, e:
52 if obmc.dbuslib.enums.DBUS_UNKNOWN_INTERFACE in \
53 e.get_dbus_message():
54 # interface doesn't have any properties
55 return None
56 if obmc.dbuslib.enums.DBUS_UNKNOWN_METHOD == e.get_dbus_name():
57 # properties interface not implemented at all
58 return None
59 raise
60
61 @staticmethod
62 def __get_properties_on_iface(properties_iface, iface):
63 properties = Mapper.__try_properties_interface(
64 properties_iface.GetAll, iface)
65 if properties is None:
66 return {}
67 return properties
68
69 def __get_properties_on_bus(self, path, bus, interfaces, match):
70 properties = {}
71 obj = self.bus.get_object(bus, path, introspect=False)
72 properties_iface = dbus.Interface(
73 obj, dbus_interface=dbus.PROPERTIES_IFACE)
74 for i in interfaces:
75 if not match(i):
76 continue
77 properties.update(self.__get_properties_on_iface(
78 properties_iface, i))
79
80 return properties
81
82 def enumerate_object(
83 self, path,
84 match=obmc.utils.misc.org_dot_openbmc_match,
85 mapper_data=None):
86 if mapper_data is None:
87 mapper_data = {path: self.get_object(path)}
88
89 obj = {}
90
91 for owner, interfaces in mapper_data[path].iteritems():
92 obj.update(
93 self.__get_properties_on_bus(
94 path, owner, interfaces, match))
95
96 return obj
97
98 def enumerate_subtree(
99 self, path='/',
100 match=obmc.utils.misc.org_dot_openbmc_match,
101 mapper_data=None):
102 if mapper_data is None:
103 mapper_data = self.get_subtree(path)
104 managers = {}
105 owners = []
106
107 # look for objectmanager implementations as they result
108 # in fewer dbus calls
109 for path, bus_data in mapper_data.iteritems():
110 for owner, interfaces in bus_data.iteritems():
111 owners.append(owner)
112 if dbus.BUS_DAEMON_IFACE + '.ObjectManager' in interfaces:
113 managers[owner] = path
114
115 # also look in the parent objects
116 ancestors = self.get_ancestors(path)
117
118 # finally check the root for one too
119 try:
120 ancestors.update({path: self.get_object(path)})
121 except dbus.exceptions.DBusException, e:
122 if e.get_dbus_name() != obmc.mapper.MAPPER_NOT_FOUND:
123 raise
124
125 for path, bus_data in ancestors.iteritems():
126 for owner, interfaces in bus_data.iteritems():
127 if dbus.BUS_DAEMON_IFACE + '.ObjectManager' in interfaces:
128 managers[owner] = path
129
130 # make all the manager gmo (get managed objects) calls
131 results = {}
132 for owner, path in managers.iteritems():
133 if owner not in owners:
134 continue
135 obj = self.bus.get_object(owner, path, introspect=False)
136 iface = dbus.Interface(
137 obj, dbus.BUS_DAEMON_IFACE + '.ObjectManager')
138
139 # flatten (remove interface names) gmo results
140 for path, interfaces in iface.GetManagedObjects().iteritems():
141 if path not in mapper_data.iterkeys():
142 continue
143 properties = {}
144 for iface, props in interfaces.iteritems():
145 properties.update(props)
146 results.setdefault(path, {}).setdefault(owner, properties)
147
148 # make dbus calls for any remaining objects
149 for path, bus_data in mapper_data.iteritems():
150 for owner, interfaces in bus_data.iteritems():
151 if results.setdefault(path, {}).setdefault(owner, {}):
152 continue
153 results[path][owner].update(
154 self.__get_properties_on_bus(
155 path, owner, interfaces, match))
156
157 objs = obmc.utils.pathtree.PathTree()
158 for path, owners in results.iteritems():
159 for owner, properties in owners.iteritems():
160 objs.setdefault(path, {}).update(properties)
161
162 return objs