blob: ea0da5c515c83e38f5969df7bf75cfecbcd06968 [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 Bishop84ed6e12016-09-08 21:39:34 -040018import dbus.service
19import dbus.exceptions
Brad Bishop8ffe1e42016-02-11 16:15:40 -050020
Brad Bishopc88b0952017-07-29 23:03:30 -040021OBJ_PREFIX = '/xyz/openbmc_project'
Brad Bishop8ffe1e42016-02-11 16:15:40 -050022
23
24def is_unique(connection):
25 return connection[0] == ':'
26
27
Brad Bishop8ffe1e42016-02-11 16:15:40 -050028def get_dbus():
Brad Bishop93d0cf02016-09-08 21:37:27 -040029 return dbus.SystemBus()
Brad Bishop8ffe1e42016-02-11 16:15:40 -050030
31
32class DbusProperties(dbus.service.Object):
Brad Bishopd874f0b2016-09-08 22:16:58 -040033 def __init__(self, **kw):
Patrick Williams4fed8682016-09-28 13:19:14 -050034 self.validator = kw.pop('validator', None)
Brad Bishopd874f0b2016-09-08 22:16:58 -040035 super(DbusProperties, self).__init__(**kw)
Brad Bishop8ffe1e42016-02-11 16:15:40 -050036 self.properties = {}
Brad Bishop6835b672016-06-27 21:55:29 -040037 self._export = False
38
39 def unmask_signals(self):
40 self._export = True
41 inst = super(DbusProperties, self)
42 if hasattr(inst, 'unmask_signals'):
43 inst.unmask_signals()
44
45 def mask_signals(self):
46 self._export = False
47 inst = super(DbusProperties, self)
48 if hasattr(inst, 'mask_signals'):
49 inst.mask_signals()
Brad Bishop8ffe1e42016-02-11 16:15:40 -050050
51 @dbus.service.method(
52 dbus.PROPERTIES_IFACE,
53 in_signature='ss', out_signature='v')
54 def Get(self, interface_name, property_name):
55 d = self.GetAll(interface_name)
56 try:
57 v = d[property_name]
58 return v
59 except:
60 raise dbus.exceptions.DBusException(
61 "org.freedesktop.UnknownProperty: "+property_name)
62
63 @dbus.service.method(
64 dbus.PROPERTIES_IFACE,
65 in_signature='s', out_signature='a{sv}')
66 def GetAll(self, interface_name):
67 try:
68 d = self.properties[interface_name]
69 return d
70 except:
71 raise dbus.exceptions.DBusException(
72 "org.freedesktop.UnknownInterface: "+interface_name)
73
74 @dbus.service.method(
75 dbus.PROPERTIES_IFACE,
76 in_signature='ssv')
77 def Set(self, interface_name, property_name, new_value):
78 if (interface_name not in self.properties):
79 self.properties[interface_name] = {}
Vishwanatha Subbanna07225642016-09-20 20:41:15 +053080
81 if self.validator:
82 self.validator(interface_name, property_name, new_value)
83
Brad Bishop8ffe1e42016-02-11 16:15:40 -050084 try:
85 old_value = self.properties[interface_name][property_name]
86 if (old_value != new_value):
87 self.properties[interface_name][property_name] = new_value
Brad Bishop6835b672016-06-27 21:55:29 -040088 if self._export:
89 self.PropertiesChanged(
90 interface_name, {property_name: new_value}, [])
Brad Bishop8ffe1e42016-02-11 16:15:40 -050091
92 except:
93 self.properties[interface_name][property_name] = new_value
Brad Bishop6835b672016-06-27 21:55:29 -040094 if self._export:
95 self.PropertiesChanged(
96 interface_name, {property_name: new_value}, [])
Brad Bishop8ffe1e42016-02-11 16:15:40 -050097
98 @dbus.service.method(
99 "org.openbmc.Object.Properties", in_signature='sa{sv}')
100 def SetMultiple(self, interface_name, prop_dict):
Brad Bishopd0827b12016-05-12 16:48:57 -0400101 if (interface_name not in self.properties):
Brad Bishop8ffe1e42016-02-11 16:15:40 -0500102 self.properties[interface_name] = {}
103
104 value_changed = False
105 for property_name in prop_dict:
106 new_value = prop_dict[property_name]
107 try:
108 old_value = self.properties[interface_name][property_name]
109 if (old_value != new_value):
110 self.properties[interface_name][property_name] = new_value
111 value_changed = True
112
113 except:
114 self.properties[interface_name][property_name] = new_value
115 value_changed = True
Brad Bishop6835b672016-06-27 21:55:29 -0400116 if (value_changed is True and self._export):
Brad Bishop8ffe1e42016-02-11 16:15:40 -0500117 self.PropertiesChanged(interface_name, prop_dict, [])
118
119 @dbus.service.signal(
120 dbus.PROPERTIES_IFACE, signature='sa{sv}as')
121 def PropertiesChanged(
122 self, interface_name, changed_properties, invalidated_properties):
123 pass
124
125
Brad Bishop2b054342017-10-27 15:33:02 -0400126def add_interfaces_to_class(cls, ifaces):
127 """
128 The built-in Introspect method in dbus-python doesn't find
129 interfaces if the @method or @signal decorators aren't used
130 (property-only interfaces). Use this method on a class
131 derived from dbus.service.Object to help the dbus-python provided
132 Introspect method find these interfaces.
133
134 Arguments:
135 cls -- The dbus.service.Object superclass to add interfaces to.
136 ifaces -- The property-only interfaces to add to the class.
137 """
138
139 for iface in ifaces:
140 class_table_key = '{}.{}'.format(cls.__module__, cls.__name__)
141 cls._dbus_class_table[class_table_key].setdefault(iface, {})
142
143
144def add_interfaces(ifaces):
145 """
146 A class decorator for add_interfaces_to_class.
147 """
148
149 def decorator(cls):
150 undecorated = cls.__init__
151
152 def ctor(obj, *a, **kw):
153 undecorated(obj, *a, **kw)
154 add_interfaces_to_class(cls, ifaces)
155
156 cls.__init__ = ctor
157 return cls
158 return decorator
159
160
Brad Bishop8ffe1e42016-02-11 16:15:40 -0500161class DbusObjectManager(dbus.service.Object):
Brad Bishopd874f0b2016-09-08 22:16:58 -0400162 def __init__(self, **kw):
163 super(DbusObjectManager, self).__init__(**kw)
Brad Bishop8ffe1e42016-02-11 16:15:40 -0500164 self.objects = {}
Brad Bishop6835b672016-06-27 21:55:29 -0400165 self._export = False
166
167 def unmask_signals(self):
168 self._export = True
169 inst = super(DbusObjectManager, self)
170 if hasattr(inst, 'unmask_signals'):
171 inst.unmask_signals()
172
173 def mask_signals(self):
174 self._export = False
175 inst = super(DbusObjectManager, self)
176 if hasattr(inst, 'mask_signals'):
177 inst.mask_signals()
Brad Bishop8ffe1e42016-02-11 16:15:40 -0500178
179 def add(self, object_path, obj):
180 self.objects[object_path] = obj
Brad Bishop6835b672016-06-27 21:55:29 -0400181 if self._export:
182 self.InterfacesAdded(object_path, obj.properties)
Brad Bishop8ffe1e42016-02-11 16:15:40 -0500183
184 def remove(self, object_path):
185 obj = self.objects.pop(object_path, None)
186 obj.remove_from_connection()
Brad Bishop6835b672016-06-27 21:55:29 -0400187 if self._export:
188 self.InterfacesRemoved(object_path, obj.properties.keys())
Brad Bishop8ffe1e42016-02-11 16:15:40 -0500189
190 def get(self, object_path, default=None):
191 return self.objects.get(object_path, default)
192
193 @dbus.service.method(
194 "org.freedesktop.DBus.ObjectManager",
195 in_signature='', out_signature='a{oa{sa{sv}}}')
196 def GetManagedObjects(self):
197 data = {}
198 for objpath in self.objects.keys():
199 data[objpath] = self.objects[objpath].properties
200 return data
201
202 @dbus.service.signal(
203 "org.freedesktop.DBus.ObjectManager", signature='oa{sa{sv}}')
204 def InterfacesAdded(self, object_path, properties):
Brad Bishop0b30e972016-06-21 14:58:14 -0400205 pass
Brad Bishop8ffe1e42016-02-11 16:15:40 -0500206
207 @dbus.service.signal(
208 "org.freedesktop.DBus.ObjectManager", signature='oas')
209 def InterfacesRemoved(self, object_path, interfaces):
210 pass