blob: 68ffb63326f3b407790a71eb528e42bf0e5ca7b8 [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
22MAPPER_NAME = 'org.openbmc.objectmapper'
23MAPPER_IFACE = MAPPER_NAME + '.ObjectMapper'
24MAPPER_PATH = '/org/openbmc/objectmapper/objectmapper'
25ENUMERATE_IFACE = 'org.openbmc.Object.Enumerate'
26MAPPER_NOT_FOUND = 'org.openbmc.objectmapper.Error.NotFound'
27
28
29class Mapper:
30 def __init__(self, bus):
31 self.bus = bus
32 obj = bus.get_object(MAPPER_NAME, MAPPER_PATH, introspect=False)
33 self.iface = dbus.Interface(
34 obj, dbus_interface=MAPPER_IFACE)
35
36 def get_object(self, path):
37 return self.iface.GetObject(path)
38
39 def get_subtree_paths(self, path='/', depth=0):
40 return self.iface.GetSubTreePaths(path, depth)
41
42 def get_subtree(self, path='/', depth=0):
43 return self.iface.GetSubTree(path, depth)
44
45 def get_ancestors(self, path):
46 return self.iface.GetAncestors(path)
Brad Bishopf6c2a942016-04-01 14:44:12 -040047
48 @staticmethod
49 def __try_properties_interface(f, *a):
50 try:
51 return f(*a)
52 except dbus.exceptions.DBusException, e:
53 if obmc.dbuslib.enums.DBUS_UNKNOWN_INTERFACE in \
54 e.get_dbus_message():
55 # interface doesn't have any properties
56 return None
57 if obmc.dbuslib.enums.DBUS_UNKNOWN_METHOD == e.get_dbus_name():
58 # properties interface not implemented at all
59 return None
60 raise
61
62 @staticmethod
63 def __get_properties_on_iface(properties_iface, iface):
64 properties = Mapper.__try_properties_interface(
65 properties_iface.GetAll, iface)
66 if properties is None:
67 return {}
68 return properties
69
70 def __get_properties_on_bus(self, path, bus, interfaces, match):
71 properties = {}
72 obj = self.bus.get_object(bus, path, introspect=False)
73 properties_iface = dbus.Interface(
74 obj, dbus_interface=dbus.PROPERTIES_IFACE)
75 for i in interfaces:
76 if not match(i):
77 continue
78 properties.update(self.__get_properties_on_iface(
79 properties_iface, i))
80
81 return properties
82
83 def enumerate_object(
84 self, path,
85 match=obmc.utils.misc.org_dot_openbmc_match,
86 mapper_data=None):
87 if mapper_data is None:
88 mapper_data = {path: self.get_object(path)}
89
90 obj = {}
91
92 for owner, interfaces in mapper_data[path].iteritems():
93 obj.update(
94 self.__get_properties_on_bus(
95 path, owner, interfaces, match))
96
97 return obj
98
99 def enumerate_subtree(
100 self, path='/',
101 match=obmc.utils.misc.org_dot_openbmc_match,
102 mapper_data=None):
103 if mapper_data is None:
104 mapper_data = self.get_subtree(path)
105 managers = {}
106 owners = []
107
108 # look for objectmanager implementations as they result
109 # in fewer dbus calls
110 for path, bus_data in mapper_data.iteritems():
111 for owner, interfaces in bus_data.iteritems():
112 owners.append(owner)
113 if dbus.BUS_DAEMON_IFACE + '.ObjectManager' in interfaces:
114 managers[owner] = path
115
116 # also look in the parent objects
117 ancestors = self.get_ancestors(path)
118
119 # finally check the root for one too
120 try:
121 ancestors.update({path: self.get_object(path)})
122 except dbus.exceptions.DBusException, e:
123 if e.get_dbus_name() != obmc.mapper.MAPPER_NOT_FOUND:
124 raise
125
126 for path, bus_data in ancestors.iteritems():
127 for owner, interfaces in bus_data.iteritems():
128 if dbus.BUS_DAEMON_IFACE + '.ObjectManager' in interfaces:
129 managers[owner] = path
130
131 # make all the manager gmo (get managed objects) calls
132 results = {}
133 for owner, path in managers.iteritems():
134 if owner not in owners:
135 continue
136 obj = self.bus.get_object(owner, path, introspect=False)
137 iface = dbus.Interface(
138 obj, dbus.BUS_DAEMON_IFACE + '.ObjectManager')
139
140 # flatten (remove interface names) gmo results
141 for path, interfaces in iface.GetManagedObjects().iteritems():
142 if path not in mapper_data.iterkeys():
143 continue
144 properties = {}
145 for iface, props in interfaces.iteritems():
146 properties.update(props)
147 results.setdefault(path, {}).setdefault(owner, properties)
148
149 # make dbus calls for any remaining objects
150 for path, bus_data in mapper_data.iteritems():
151 for owner, interfaces in bus_data.iteritems():
152 if results.setdefault(path, {}).setdefault(owner, {}):
153 continue
154 results[path][owner].update(
155 self.__get_properties_on_bus(
156 path, owner, interfaces, match))
157
158 objs = obmc.utils.pathtree.PathTree()
159 for path, owners in results.iteritems():
160 for owner, properties in owners.iteritems():
161 objs.setdefault(path, {}).update(properties)
162
163 return objs