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__(conn=bus, object_path=name) 42 # load utilized objects 43 self.dbus_objects = { 44 "power_control": { 45 "bus_name": "org.openbmc.control.Power", 46 "object_name": "/org/openbmc/control/power0", 47 "interface_name": "org.openbmc.control.Power", 48 }, 49 "host_services": { 50 "bus_name": "org.openbmc.HostServices", 51 "object_name": "/org/openbmc/HostServices", 52 "interface_name": "org.openbmc.HostServices", 53 }, 54 "systemd": { 55 "bus_name": "org.freedesktop.systemd1", 56 "object_name": "/org/freedesktop/systemd1", 57 "interface_name": "org.freedesktop.systemd1.Manager", 58 }, 59 } 60 61 # uuid 62 self.Set(DBUS_NAME, "uuid", self.getUuid()) 63 self.Set(DBUS_NAME, "reboot", 0) 64 65 bus.add_signal_receiver( 66 self.power_button_signal_handler, 67 dbus_interface="org.openbmc.Button", 68 signal_name="Released", 69 path="/org/openbmc/buttons/power0", 70 ) 71 bus.add_signal_receiver( 72 self.long_power_button_signal_handler, 73 dbus_interface="org.openbmc.Button", 74 signal_name="PressedLong", 75 path="/org/openbmc/buttons/power0", 76 ) 77 bus.add_signal_receiver( 78 self.softreset_button_signal_handler, 79 dbus_interface="org.openbmc.Button", 80 signal_name="Released", 81 path="/org/openbmc/buttons/reset0", 82 ) 83 84 bus.add_signal_receiver( 85 self.host_watchdog_signal_handler, 86 dbus_interface="org.openbmc.Watchdog", 87 signal_name="WatchdogError", 88 ) 89 90 def getInterface(self, name): 91 o = self.dbus_objects[name] 92 obj = bus.get_object(o["bus_name"], o["object_name"], introspect=False) 93 return dbus.Interface(obj, o["interface_name"]) 94 95 @dbus.service.method(DBUS_NAME, in_signature="", out_signature="") 96 def powerOn(self): 97 print("Turn on power and boot") 98 self.Set(DBUS_NAME, "reboot", 0) 99 intf = self.getInterface("systemd") 100 f = getattr(intf, "StartUnit") 101 f.call_async("obmc-host-start@0.target", "replace") 102 return None 103 104 @dbus.service.method(DBUS_NAME, in_signature="", out_signature="") 105 def powerOff(self): 106 print("Turn off power") 107 intf = self.getInterface("systemd") 108 f = getattr(intf, "StartUnit") 109 f.call_async("obmc-chassis-hard-poweroff@0.target", "replace") 110 return None 111 112 @dbus.service.method(DBUS_NAME, in_signature="", out_signature="") 113 def softPowerOff(self): 114 print("Soft off power") 115 intf = self.getInterface("systemd") 116 f = getattr(intf, "StartUnit") 117 f.call_async("obmc-host-shutdown@0.target", "replace") 118 return None 119 120 @dbus.service.method(DBUS_NAME, in_signature="", out_signature="") 121 def reboot(self): 122 print("Rebooting") 123 if self.getPowerState() != POWER_OFF: 124 self.Set(DBUS_NAME, "reboot", 1) 125 self.powerOff() 126 return None 127 128 @dbus.service.method(DBUS_NAME, in_signature="", out_signature="") 129 def softReboot(self): 130 print("Soft Rebooting") 131 if self.getPowerState() != POWER_OFF: 132 self.Set(DBUS_NAME, "reboot", 1) 133 self.softPowerOff() 134 return None 135 136 @dbus.service.method(DBUS_NAME, in_signature="", out_signature="") 137 def quiesce(self): 138 intf = self.getInterface("systemd") 139 f = getattr(intf, "StartUnit") 140 f.call_async("obmc-host-quiesce@0.target", "replace") 141 return None 142 143 @dbus.service.method(DBUS_NAME, in_signature="", out_signature="i") 144 def getPowerState(self): 145 intf = self.getInterface("power_control") 146 return intf.getPowerState() 147 148 # Signal handler 149 150 def power_button_signal_handler(self): 151 # toggle power, power-on / soft-power-off 152 state = self.getPowerState() 153 if state == POWER_OFF: 154 self.powerOn() 155 elif state == POWER_ON: 156 self.softPowerOff() 157 158 def long_power_button_signal_handler(self): 159 print("Long-press button, hard power off") 160 self.powerOff() 161 162 def softreset_button_signal_handler(self): 163 self.softReboot() 164 165 def host_watchdog_signal_handler(self): 166 print("Watchdog Error, Going to quiesce") 167 self.quiesce() 168 169 170if __name__ == "__main__": 171 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) 172 173 bus = get_dbus() 174 obj = ChassisControlObject(bus, OBJ_NAME) 175 mainloop = gobject.MainLoop() 176 177 obj.unmask_signals() 178 name = dbus.service.BusName(DBUS_NAME, bus) 179 180 print("Running ChassisControlService") 181 mainloop.run() 182 183# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 184