1#!/usr/bin/env python 2 3# TODO: openbmc/openbmc#2994 remove python 2 support 4try: # python 2 5 import gobject 6except ImportError: # python 3 7 from gi.repository import GObject as gobject 8import dbus 9import dbus.service 10import dbus.mainloop.glib 11from obmc.dbuslib.bindings import get_dbus, DbusProperties, DbusObjectManager 12 13DBUS_NAME = 'org.openbmc.control.Chassis' 14OBJ_NAME = '/org/openbmc/control/chassis0' 15CONTROL_INTF = 'org.openbmc.Control' 16 17MACHINE_ID = '/etc/machine-id' 18 19POWER_OFF = 0 20POWER_ON = 1 21 22BOOTED = 100 23 24 25class ChassisControlObject(DbusProperties, DbusObjectManager): 26 def getUuid(self): 27 uuid = "" 28 try: 29 with open(MACHINE_ID) as f: 30 data = f.readline().rstrip('\n') 31 if (len(data) == 32): 32 uuid = data 33 else: 34 print("ERROR: UUID is not formatted correctly: " + data) 35 except Exception: 36 print("ERROR: Unable to open uuid file: " + MACHINE_ID) 37 38 return uuid 39 40 def __init__(self, bus, name): 41 super(ChassisControlObject, self).__init__( 42 conn=bus, 43 object_path=name) 44 # load utilized objects 45 self.dbus_objects = { 46 'power_control': { 47 'bus_name': 'org.openbmc.control.Power', 48 'object_name': '/org/openbmc/control/power0', 49 'interface_name': 'org.openbmc.control.Power' 50 }, 51 'host_services': { 52 'bus_name': 'org.openbmc.HostServices', 53 'object_name': '/org/openbmc/HostServices', 54 'interface_name': 'org.openbmc.HostServices' 55 }, 56 'systemd': { 57 'bus_name': 'org.freedesktop.systemd1', 58 'object_name': '/org/freedesktop/systemd1', 59 'interface_name': 'org.freedesktop.systemd1.Manager' 60 }, 61 } 62 63 # uuid 64 self.Set(DBUS_NAME, "uuid", self.getUuid()) 65 self.Set(DBUS_NAME, "reboot", 0) 66 67 bus.add_signal_receiver(self.power_button_signal_handler, 68 dbus_interface="org.openbmc.Button", 69 signal_name="Released", 70 path="/org/openbmc/buttons/power0") 71 bus.add_signal_receiver(self.long_power_button_signal_handler, 72 dbus_interface="org.openbmc.Button", 73 signal_name="PressedLong", 74 path="/org/openbmc/buttons/power0") 75 bus.add_signal_receiver(self.softreset_button_signal_handler, 76 dbus_interface="org.openbmc.Button", 77 signal_name="Released", 78 path="/org/openbmc/buttons/reset0") 79 80 bus.add_signal_receiver(self.host_watchdog_signal_handler, 81 dbus_interface="org.openbmc.Watchdog", 82 signal_name="WatchdogError") 83 84 85 def getInterface(self, name): 86 o = self.dbus_objects[name] 87 obj = bus.get_object(o['bus_name'], o['object_name'], introspect=False) 88 return dbus.Interface(obj, o['interface_name']) 89 90 @dbus.service.method(DBUS_NAME, 91 in_signature='', out_signature='') 92 def powerOn(self): 93 print("Turn on power and boot") 94 self.Set(DBUS_NAME, "reboot", 0) 95 intf = self.getInterface('systemd') 96 f = getattr(intf, 'StartUnit') 97 f.call_async('obmc-host-start@0.target', 'replace') 98 return None 99 100 @dbus.service.method(DBUS_NAME, 101 in_signature='', out_signature='') 102 def powerOff(self): 103 print("Turn off power") 104 intf = self.getInterface('systemd') 105 f = getattr(intf, 'StartUnit') 106 f.call_async('obmc-chassis-hard-poweroff@0.target', 'replace') 107 return None 108 109 @dbus.service.method(DBUS_NAME, 110 in_signature='', out_signature='') 111 def softPowerOff(self): 112 print("Soft off power") 113 intf = self.getInterface('systemd') 114 f = getattr(intf, 'StartUnit') 115 f.call_async('obmc-host-shutdown@0.target', 'replace') 116 return None 117 118 @dbus.service.method(DBUS_NAME, 119 in_signature='', out_signature='') 120 def reboot(self): 121 print("Rebooting") 122 if self.getPowerState() == POWER_OFF: 123 self.powerOn() 124 else: 125 self.Set(DBUS_NAME, "reboot", 1) 126 self.powerOff() 127 return None 128 129 @dbus.service.method(DBUS_NAME, 130 in_signature='', out_signature='') 131 def softReboot(self): 132 print("Soft Rebooting") 133 if self.getPowerState() == POWER_OFF: 134 self.powerOn() 135 else: 136 self.Set(DBUS_NAME, "reboot", 1) 137 self.softPowerOff() 138 return None 139 140 @dbus.service.method(DBUS_NAME, 141 in_signature='', out_signature='') 142 def quiesce(self): 143 intf = self.getInterface('systemd') 144 f = getattr(intf, 'StartUnit') 145 f.call_async('obmc-host-quiesce@0.target', 'replace') 146 return None 147 148 @dbus.service.method(DBUS_NAME, 149 in_signature='', out_signature='i') 150 def getPowerState(self): 151 intf = self.getInterface('power_control') 152 return intf.getPowerState() 153 154 # Signal handler 155 156 def power_button_signal_handler(self): 157 # toggle power, power-on / soft-power-off 158 state = self.getPowerState() 159 if state == POWER_OFF: 160 self.powerOn() 161 elif state == POWER_ON: 162 self.softPowerOff() 163 164 def long_power_button_signal_handler(self): 165 print("Long-press button, hard power off") 166 self.powerOff() 167 168 def softreset_button_signal_handler(self): 169 self.softReboot() 170 171 def host_watchdog_signal_handler(self): 172 print("Watchdog Error, Going to quiesce") 173 self.quiesce() 174 175 176if __name__ == '__main__': 177 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) 178 179 bus = get_dbus() 180 obj = ChassisControlObject(bus, OBJ_NAME) 181 mainloop = gobject.MainLoop() 182 183 obj.unmask_signals() 184 name = dbus.service.BusName(DBUS_NAME, bus) 185 186 print("Running ChassisControlService") 187 mainloop.run() 188 189# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 190