18ffe1e44SBrad Bishop# Contributors Listed Below - COPYRIGHT 2016 28ffe1e44SBrad Bishop# [+] International Business Machines Corp. 38ffe1e44SBrad Bishop# 48ffe1e44SBrad Bishop# 58ffe1e44SBrad Bishop# Licensed under the Apache License, Version 2.0 (the "License"); 68ffe1e44SBrad Bishop# you may not use this file except in compliance with the License. 78ffe1e44SBrad Bishop# You may obtain a copy of the License at 88ffe1e44SBrad Bishop# 98ffe1e44SBrad Bishop# http://www.apache.org/licenses/LICENSE-2.0 108ffe1e44SBrad Bishop# 118ffe1e44SBrad Bishop# Unless required by applicable law or agreed to in writing, software 128ffe1e44SBrad Bishop# distributed under the License is distributed on an "AS IS" BASIS, 138ffe1e44SBrad Bishop# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148ffe1e44SBrad Bishop# implied. See the License for the specific language governing 158ffe1e44SBrad Bishop# permissions and limitations under the License. 168ffe1e44SBrad Bishop 178ffe1e44SBrad Bishopimport dbus 1884ed6e17SBrad Bishopimport dbus.service 1984ed6e17SBrad Bishopimport dbus.exceptions 208ffe1e44SBrad Bishop 21c88b0958SBrad BishopOBJ_PREFIX = '/xyz/openbmc_project' 228ffe1e44SBrad Bishop 238ffe1e44SBrad Bishop 248ffe1e44SBrad Bishopdef is_unique(connection): 258ffe1e44SBrad Bishop return connection[0] == ':' 268ffe1e44SBrad Bishop 278ffe1e44SBrad Bishop 288ffe1e44SBrad Bishopdef get_dbus(): 2993d0cf05SBrad Bishop return dbus.SystemBus() 308ffe1e44SBrad Bishop 318ffe1e44SBrad Bishop 328ffe1e44SBrad Bishopclass DbusProperties(dbus.service.Object): 33d874f0b0SBrad Bishop def __init__(self, **kw): 344fed868cSPatrick Williams self.validator = kw.pop('validator', None) 35d874f0b0SBrad Bishop super(DbusProperties, self).__init__(**kw) 368ffe1e44SBrad Bishop self.properties = {} 376835b67aSBrad Bishop self._export = False 386835b67aSBrad Bishop 396835b67aSBrad Bishop def unmask_signals(self): 406835b67aSBrad Bishop self._export = True 416835b67aSBrad Bishop inst = super(DbusProperties, self) 426835b67aSBrad Bishop if hasattr(inst, 'unmask_signals'): 436835b67aSBrad Bishop inst.unmask_signals() 446835b67aSBrad Bishop 456835b67aSBrad Bishop def mask_signals(self): 466835b67aSBrad Bishop self._export = False 476835b67aSBrad Bishop inst = super(DbusProperties, self) 486835b67aSBrad Bishop if hasattr(inst, 'mask_signals'): 496835b67aSBrad Bishop inst.mask_signals() 508ffe1e44SBrad Bishop 518ffe1e44SBrad Bishop @dbus.service.method( 528ffe1e44SBrad Bishop dbus.PROPERTIES_IFACE, 538ffe1e44SBrad Bishop in_signature='ss', out_signature='v') 548ffe1e44SBrad Bishop def Get(self, interface_name, property_name): 558ffe1e44SBrad Bishop d = self.GetAll(interface_name) 568ffe1e44SBrad Bishop try: 578ffe1e44SBrad Bishop v = d[property_name] 588ffe1e44SBrad Bishop return v 59*aea38c65SBrad Bishop except Exception: 608ffe1e44SBrad Bishop raise dbus.exceptions.DBusException( 61dc7f067dSAdriana Kobylak "Unknown property: '{}'".format(property_name), 62dc7f067dSAdriana Kobylak name="org.freedesktop.DBus.Error.UnknownProperty") 638ffe1e44SBrad Bishop 648ffe1e44SBrad Bishop @dbus.service.method( 658ffe1e44SBrad Bishop dbus.PROPERTIES_IFACE, 668ffe1e44SBrad Bishop in_signature='s', out_signature='a{sv}') 678ffe1e44SBrad Bishop def GetAll(self, interface_name): 688ffe1e44SBrad Bishop try: 698ffe1e44SBrad Bishop d = self.properties[interface_name] 708ffe1e44SBrad Bishop return d 71*aea38c65SBrad Bishop except Exception: 728ffe1e44SBrad Bishop raise dbus.exceptions.DBusException( 73dc7f067dSAdriana Kobylak "Unknown interface: '{}'".format(interface_name), 74dc7f067dSAdriana Kobylak name="org.freedesktop.DBus.Error.UnknownInterface") 758ffe1e44SBrad Bishop 768ffe1e44SBrad Bishop @dbus.service.method( 778ffe1e44SBrad Bishop dbus.PROPERTIES_IFACE, 788ffe1e44SBrad Bishop in_signature='ssv') 798ffe1e44SBrad Bishop def Set(self, interface_name, property_name, new_value): 808ffe1e44SBrad Bishop if (interface_name not in self.properties): 818ffe1e44SBrad Bishop self.properties[interface_name] = {} 820722564eSVishwanatha Subbanna 830722564eSVishwanatha Subbanna if self.validator: 840722564eSVishwanatha Subbanna self.validator(interface_name, property_name, new_value) 850722564eSVishwanatha Subbanna 868ffe1e44SBrad Bishop try: 878ffe1e44SBrad Bishop old_value = self.properties[interface_name][property_name] 888ffe1e44SBrad Bishop if (old_value != new_value): 898ffe1e44SBrad Bishop self.properties[interface_name][property_name] = new_value 906835b67aSBrad Bishop if self._export: 918ffe1e44SBrad Bishop self.PropertiesChanged( 928ffe1e44SBrad Bishop interface_name, {property_name: new_value}, []) 938ffe1e44SBrad Bishop 94*aea38c65SBrad Bishop except Exception: 958ffe1e44SBrad Bishop self.properties[interface_name][property_name] = new_value 966835b67aSBrad Bishop if self._export: 978ffe1e44SBrad Bishop self.PropertiesChanged( 988ffe1e44SBrad Bishop interface_name, {property_name: new_value}, []) 998ffe1e44SBrad Bishop 1008ffe1e44SBrad Bishop @dbus.service.method( 1018ffe1e44SBrad Bishop "org.openbmc.Object.Properties", in_signature='sa{sv}') 1028ffe1e44SBrad Bishop def SetMultiple(self, interface_name, prop_dict): 103d0827b16SBrad Bishop if (interface_name not in self.properties): 1048ffe1e44SBrad Bishop self.properties[interface_name] = {} 1058ffe1e44SBrad Bishop 1068ffe1e44SBrad Bishop value_changed = False 1078ffe1e44SBrad Bishop for property_name in prop_dict: 1088ffe1e44SBrad Bishop new_value = prop_dict[property_name] 1098ffe1e44SBrad Bishop try: 1108ffe1e44SBrad Bishop old_value = self.properties[interface_name][property_name] 1118ffe1e44SBrad Bishop if (old_value != new_value): 1128ffe1e44SBrad Bishop self.properties[interface_name][property_name] = new_value 1138ffe1e44SBrad Bishop value_changed = True 1148ffe1e44SBrad Bishop 115*aea38c65SBrad Bishop except Exception: 1168ffe1e44SBrad Bishop self.properties[interface_name][property_name] = new_value 1178ffe1e44SBrad Bishop value_changed = True 1186835b67aSBrad Bishop if (value_changed is True and self._export): 1198ffe1e44SBrad Bishop self.PropertiesChanged(interface_name, prop_dict, []) 1208ffe1e44SBrad Bishop 1218ffe1e44SBrad Bishop @dbus.service.signal( 1228ffe1e44SBrad Bishop dbus.PROPERTIES_IFACE, signature='sa{sv}as') 1238ffe1e44SBrad Bishop def PropertiesChanged( 1248ffe1e44SBrad Bishop self, interface_name, changed_properties, invalidated_properties): 1258ffe1e44SBrad Bishop pass 1268ffe1e44SBrad Bishop 1278ffe1e44SBrad Bishop 1282b054348SBrad Bishopdef add_interfaces_to_class(cls, ifaces): 1292b054348SBrad Bishop """ 1302b054348SBrad Bishop The built-in Introspect method in dbus-python doesn't find 1312b054348SBrad Bishop interfaces if the @method or @signal decorators aren't used 1322b054348SBrad Bishop (property-only interfaces). Use this method on a class 1332b054348SBrad Bishop derived from dbus.service.Object to help the dbus-python provided 1342b054348SBrad Bishop Introspect method find these interfaces. 1352b054348SBrad Bishop 1362b054348SBrad Bishop Arguments: 1372b054348SBrad Bishop cls -- The dbus.service.Object superclass to add interfaces to. 1382b054348SBrad Bishop ifaces -- The property-only interfaces to add to the class. 1392b054348SBrad Bishop """ 1402b054348SBrad Bishop 1412b054348SBrad Bishop for iface in ifaces: 1422b054348SBrad Bishop class_table_key = '{}.{}'.format(cls.__module__, cls.__name__) 1432b054348SBrad Bishop cls._dbus_class_table[class_table_key].setdefault(iface, {}) 1442b054348SBrad Bishop 1452b054348SBrad Bishop 1462b054348SBrad Bishopdef add_interfaces(ifaces): 1472b054348SBrad Bishop """ 1482b054348SBrad Bishop A class decorator for add_interfaces_to_class. 1492b054348SBrad Bishop """ 1502b054348SBrad Bishop 1512b054348SBrad Bishop def decorator(cls): 1522b054348SBrad Bishop undecorated = cls.__init__ 1532b054348SBrad Bishop 1542b054348SBrad Bishop def ctor(obj, *a, **kw): 1552b054348SBrad Bishop undecorated(obj, *a, **kw) 1562b054348SBrad Bishop add_interfaces_to_class(cls, ifaces) 1572b054348SBrad Bishop 1582b054348SBrad Bishop cls.__init__ = ctor 1592b054348SBrad Bishop return cls 1602b054348SBrad Bishop return decorator 1612b054348SBrad Bishop 1622b054348SBrad Bishop 1638ffe1e44SBrad Bishopclass DbusObjectManager(dbus.service.Object): 164d874f0b0SBrad Bishop def __init__(self, **kw): 165d874f0b0SBrad Bishop super(DbusObjectManager, self).__init__(**kw) 1668ffe1e44SBrad Bishop self.objects = {} 1676835b67aSBrad Bishop self._export = False 1686835b67aSBrad Bishop 1696835b67aSBrad Bishop def unmask_signals(self): 1706835b67aSBrad Bishop self._export = True 1716835b67aSBrad Bishop inst = super(DbusObjectManager, self) 1726835b67aSBrad Bishop if hasattr(inst, 'unmask_signals'): 1736835b67aSBrad Bishop inst.unmask_signals() 1746835b67aSBrad Bishop 1756835b67aSBrad Bishop def mask_signals(self): 1766835b67aSBrad Bishop self._export = False 1776835b67aSBrad Bishop inst = super(DbusObjectManager, self) 1786835b67aSBrad Bishop if hasattr(inst, 'mask_signals'): 1796835b67aSBrad Bishop inst.mask_signals() 1808ffe1e44SBrad Bishop 1818ffe1e44SBrad Bishop def add(self, object_path, obj): 1828ffe1e44SBrad Bishop self.objects[object_path] = obj 1836835b67aSBrad Bishop if self._export: 1848ffe1e44SBrad Bishop self.InterfacesAdded(object_path, obj.properties) 1858ffe1e44SBrad Bishop 1868ffe1e44SBrad Bishop def remove(self, object_path): 1878ffe1e44SBrad Bishop obj = self.objects.pop(object_path, None) 1888ffe1e44SBrad Bishop obj.remove_from_connection() 1896835b67aSBrad Bishop if self._export: 1909172f3e7SCamVan Nguyen self.InterfacesRemoved(object_path, list(obj.properties.keys())) 1918ffe1e44SBrad Bishop 1928ffe1e44SBrad Bishop def get(self, object_path, default=None): 1938ffe1e44SBrad Bishop return self.objects.get(object_path, default) 1948ffe1e44SBrad Bishop 1958ffe1e44SBrad Bishop @dbus.service.method( 1968ffe1e44SBrad Bishop "org.freedesktop.DBus.ObjectManager", 1978ffe1e44SBrad Bishop in_signature='', out_signature='a{oa{sa{sv}}}') 1988ffe1e44SBrad Bishop def GetManagedObjects(self): 1998ffe1e44SBrad Bishop data = {} 2009172f3e7SCamVan Nguyen for objpath in list(self.objects.keys()): 2018ffe1e44SBrad Bishop data[objpath] = self.objects[objpath].properties 2028ffe1e44SBrad Bishop return data 2038ffe1e44SBrad Bishop 2048ffe1e44SBrad Bishop @dbus.service.signal( 2058ffe1e44SBrad Bishop "org.freedesktop.DBus.ObjectManager", signature='oa{sa{sv}}') 2068ffe1e44SBrad Bishop def InterfacesAdded(self, object_path, properties): 2070b30e97dSBrad Bishop pass 2088ffe1e44SBrad Bishop 2098ffe1e44SBrad Bishop @dbus.service.signal( 2108ffe1e44SBrad Bishop "org.freedesktop.DBus.ObjectManager", signature='oas') 2118ffe1e44SBrad Bishop def InterfacesRemoved(self, object_path, interfaces): 2128ffe1e44SBrad Bishop pass 213