blob: 43d1af2cd8372cd6bca3533740dac05e9ce51753 [file] [log] [blame]
Brad Bishopea2bc0c2016-07-25 09:05:39 -04001# 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
18import obmc.dbuslib.enums
19import obmc.utils.misc
20import obmc.utils.pathtree
21
Brad Bishop5fd9c472016-07-25 09:09:00 -040022
Brad Bishopb301f2f2016-10-05 20:02:57 -040023MAPPER_NAME = 'xyz.openbmc_project.ObjectMapper'
Brad Bishopea2bc0c2016-07-25 09:05:39 -040024MAPPER_IFACE = MAPPER_NAME
Brad Bishopb301f2f2016-10-05 20:02:57 -040025MAPPER_PATH = '/xyz/openbmc_project/ObjectMapper'
Brad Bishopfba8ea32016-09-20 15:45:18 -040026MAPPER_NOT_FOUND = 'org.freedesktop.DBus.Error.FileNotFound'
Brad Bishopea2bc0c2016-07-25 09:05:39 -040027
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
Brad Bishop1eba37d2016-09-20 08:12:25 -040036 @staticmethod
37 def retry(func, retries):
38 e = None
39 count = 0
40 while count < retries:
41 try:
42 return func()
43 except dbus.exceptions.DBusException, e:
44 if e.get_dbus_name() is not \
45 'org.freedesktop.DBus.Error.ObjectPathInUse':
46 raise
Brad Bishopea2bc0c2016-07-25 09:05:39 -040047
Brad Bishop1eba37d2016-09-20 08:12:25 -040048 count += 1
49 if e:
50 raise e
Brad Bishopea2bc0c2016-07-25 09:05:39 -040051
Brad Bishopbf464f42016-11-02 00:37:06 -040052 def get_object(self, path, retries=5, interfaces=[]):
Brad Bishop1eba37d2016-09-20 08:12:25 -040053 return self.retry(
Brad Bishopbf464f42016-11-02 00:37:06 -040054 lambda: self.iface.GetObject(
55 path, interfaces, signature='sas'),
Brad Bishop1eba37d2016-09-20 08:12:25 -040056 retries)
Brad Bishopea2bc0c2016-07-25 09:05:39 -040057
Brad Bishopbf464f42016-11-02 00:37:06 -040058 def get_subtree_paths(self, path='/', depth=0, retries=5, interfaces=[]):
Brad Bishop1eba37d2016-09-20 08:12:25 -040059 return self.retry(
Brad Bishopbf464f42016-11-02 00:37:06 -040060 lambda: self.iface.GetSubTreePaths(
61 path, depth, interfaces, signature='sias'),
Brad Bishop1eba37d2016-09-20 08:12:25 -040062 retries)
63
Brad Bishopbf464f42016-11-02 00:37:06 -040064 def get_subtree(self, path='/', depth=0, retries=5, interfaces=[]):
Brad Bishop1eba37d2016-09-20 08:12:25 -040065 return self.retry(
Brad Bishopbf464f42016-11-02 00:37:06 -040066 lambda: self.iface.GetSubTree(
67 path, depth, interfaces, signature='sias'),
Brad Bishop1eba37d2016-09-20 08:12:25 -040068 retries)
69
Brad Bishopbf464f42016-11-02 00:37:06 -040070 def get_ancestors(self, path, retries=5, interfaces=[]):
Brad Bishop1eba37d2016-09-20 08:12:25 -040071 return self.retry(
Brad Bishopbf464f42016-11-02 00:37:06 -040072 lambda: self.iface.GetAncestors(
73 path, interfaces, signature='sas'),
Brad Bishop1eba37d2016-09-20 08:12:25 -040074 retries)
Brad Bishopea2bc0c2016-07-25 09:05:39 -040075
76 @staticmethod
77 def __try_properties_interface(f, *a):
78 try:
79 return f(*a)
80 except dbus.exceptions.DBusException, e:
81 if obmc.dbuslib.enums.DBUS_UNKNOWN_INTERFACE in \
82 e.get_dbus_message():
83 # interface doesn't have any properties
84 return None
85 if obmc.dbuslib.enums.DBUS_UNKNOWN_METHOD == e.get_dbus_name():
86 # properties interface not implemented at all
87 return None
88 raise
89
90 @staticmethod
91 def __get_properties_on_iface(properties_iface, iface):
92 properties = Mapper.__try_properties_interface(
93 properties_iface.GetAll, iface)
94 if properties is None:
95 return {}
96 return properties
97
98 def __get_properties_on_bus(self, path, bus, interfaces, match):
99 properties = {}
100 obj = self.bus.get_object(bus, path, introspect=False)
101 properties_iface = dbus.Interface(
102 obj, dbus_interface=dbus.PROPERTIES_IFACE)
103 for i in interfaces:
104 if not match(i):
105 continue
106 properties.update(self.__get_properties_on_iface(
107 properties_iface, i))
108
109 return properties
110
111 def enumerate_object(
112 self, path,
113 match=obmc.utils.misc.org_dot_openbmc_match,
114 mapper_data=None):
115 if mapper_data is None:
116 mapper_data = {path: self.get_object(path)}
117
118 obj = {}
119
120 for owner, interfaces in mapper_data[path].iteritems():
121 obj.update(
122 self.__get_properties_on_bus(
123 path, owner, interfaces, match))
124
125 return obj
126
127 def enumerate_subtree(
128 self, path='/',
129 match=obmc.utils.misc.org_dot_openbmc_match,
130 mapper_data=None):
131 if mapper_data is None:
132 mapper_data = self.get_subtree(path)
133 managers = {}
134 owners = []
135
136 # look for objectmanager implementations as they result
137 # in fewer dbus calls
138 for path, bus_data in mapper_data.iteritems():
139 for owner, interfaces in bus_data.iteritems():
140 owners.append(owner)
141 if dbus.BUS_DAEMON_IFACE + '.ObjectManager' in interfaces:
142 managers[owner] = path
143
144 # also look in the parent objects
145 ancestors = self.get_ancestors(path)
146
147 # finally check the root for one too
148 try:
149 ancestors.update({path: self.get_object(path)})
150 except dbus.exceptions.DBusException, e:
Brad Bishop5fd9c472016-07-25 09:09:00 -0400151 if e.get_dbus_name() != MAPPER_NOT_FOUND:
Brad Bishopea2bc0c2016-07-25 09:05:39 -0400152 raise
153
154 for path, bus_data in ancestors.iteritems():
155 for owner, interfaces in bus_data.iteritems():
156 if dbus.BUS_DAEMON_IFACE + '.ObjectManager' in interfaces:
157 managers[owner] = path
158
159 # make all the manager gmo (get managed objects) calls
160 results = {}
161 for owner, path in managers.iteritems():
162 if owner not in owners:
163 continue
164 obj = self.bus.get_object(owner, path, introspect=False)
165 iface = dbus.Interface(
166 obj, dbus.BUS_DAEMON_IFACE + '.ObjectManager')
167
168 # flatten (remove interface names) gmo results
169 for path, interfaces in iface.GetManagedObjects().iteritems():
170 if path not in mapper_data.iterkeys():
171 continue
172 properties = {}
173 for iface, props in interfaces.iteritems():
174 properties.update(props)
175 results.setdefault(path, {}).setdefault(owner, properties)
176
177 # make dbus calls for any remaining objects
178 for path, bus_data in mapper_data.iteritems():
179 for owner, interfaces in bus_data.iteritems():
180 if results.setdefault(path, {}).setdefault(owner, {}):
181 continue
182 results[path][owner].update(
183 self.__get_properties_on_bus(
184 path, owner, interfaces, match))
185
186 objs = obmc.utils.pathtree.PathTree()
187 for path, owners in results.iteritems():
188 for owner, properties in owners.iteritems():
189 objs.setdefault(path, {}).update(properties)
190
191 return objs