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