1#!/usr/bin/env python 2 3import gobject 4import dbus 5import dbus.service 6import dbus.mainloop.glib 7from obmc.dbuslib.bindings import get_dbus, DbusProperties, DbusObjectManager 8 9DBUS_NAME = 'org.openbmc.control.Chassis' 10OBJ_NAME = '/org/openbmc/control/chassis0' 11CONTROL_INTF = 'org.openbmc.Control' 12 13MACHINE_ID = '/etc/machine-id' 14 15POWER_OFF = 0 16POWER_ON = 1 17 18BOOTED = 100 19 20 21class ChassisControlObject(DbusProperties, DbusObjectManager): 22 def getUuid(self): 23 uuid = "" 24 try: 25 with open(MACHINE_ID) as f: 26 data = f.readline().rstrip('\n') 27 if (len(data) == 32): 28 uuid = data 29 else: 30 print "ERROR: UUID is not formatted correctly: " + data 31 except: 32 print "ERROR: Unable to open uuid file: " + MACHINE_ID 33 34 return uuid 35 36 def __init__(self, bus, name): 37 self.dbus_objects = {} 38 DbusProperties.__init__(self) 39 DbusObjectManager.__init__(self) 40 dbus.service.Object.__init__(self, bus, name) 41 ## load utilized objects 42 self.dbus_objects = { 43 'power_control': { 44 'bus_name': 'org.openbmc.control.Power', 45 'object_name': '/org/openbmc/control/power0', 46 'interface_name': 'org.openbmc.control.Power' 47 }, 48 'identify_led': { 49 'bus_name': 'org.openbmc.control.led', 50 'object_name': '/org/openbmc/control/led/identify', 51 'interface_name': 'org.openbmc.Led' 52 }, 53 'host_services': { 54 'bus_name': 'org.openbmc.HostServices', 55 'object_name': '/org/openbmc/HostServices', 56 'interface_name': 'org.openbmc.HostServices' 57 }, 58 'settings': { 59 'bus_name': 'org.openbmc.settings.Host', 60 'object_name': '/org/openbmc/settings/host0', 61 'interface_name': 'org.freedesktop.DBus.Properties' 62 }, 63 'systemd': { 64 'bus_name': 'org.freedesktop.systemd1', 65 'object_name': '/org/freedesktop/systemd1', 66 'interface_name': 'org.freedesktop.systemd1.Manager' 67 }, 68 } 69 70 # uuid 71 self.Set(DBUS_NAME, "uuid", self.getUuid()) 72 self.Set(DBUS_NAME, "reboot", 0) 73 74 bus.add_signal_receiver(self.power_button_signal_handler, 75 dbus_interface="org.openbmc.Button", 76 signal_name="Released", 77 path="/org/openbmc/buttons/power0") 78 bus.add_signal_receiver(self.long_power_button_signal_handler, 79 dbus_interface="org.openbmc.Button", 80 signal_name="PressedLong", 81 path="/org/openbmc/buttons/power0") 82 bus.add_signal_receiver(self.softreset_button_signal_handler, 83 dbus_interface="org.openbmc.Button", 84 signal_name="Released", 85 path="/org/openbmc/buttons/reset0") 86 87 bus.add_signal_receiver(self.host_watchdog_signal_handler, 88 dbus_interface="org.openbmc.Watchdog", 89 signal_name="WatchdogError") 90 91 bus.add_signal_receiver(self.emergency_shutdown_signal_handler, 92 dbus_interface="org.openbmc.SensorThresholds", 93 signal_name="Emergency") 94 95 bus.add_signal_receiver(self.SystemStateHandler, 96 signal_name="GotoSystemState") 97 98 def getInterface(self, name): 99 o = self.dbus_objects[name] 100 obj = bus.get_object(o['bus_name'], o['object_name'], introspect=False) 101 return dbus.Interface(obj, o['interface_name']) 102 103 @dbus.service.method(DBUS_NAME, 104 in_signature='', out_signature='') 105 def setIdentify(self): 106 print "Turn on identify" 107 intf = self.getInterface('identify_led') 108 intf.setOn() 109 return None 110 111 @dbus.service.method(DBUS_NAME, 112 in_signature='', out_signature='') 113 def clearIdentify(self): 114 print "Turn on identify" 115 intf = self.getInterface('identify_led') 116 intf.setOff() 117 return None 118 119 @dbus.service.method(DBUS_NAME, 120 in_signature='', out_signature='') 121 def powerOn(self): 122 print "Turn on power and boot" 123 self.Set(DBUS_NAME, "reboot", 0) 124 intf = self.getInterface('systemd') 125 f = getattr(intf, 'StartUnit') 126 f.call_async('obmc-chassis-start@0.target', 'replace') 127 return None 128 129 @dbus.service.method(DBUS_NAME, 130 in_signature='', out_signature='') 131 def powerOff(self): 132 print "Turn off power" 133 134 intf = self.getInterface('systemd') 135 f = getattr(intf, 'StartUnit') 136 f.call_async('obmc-chassis-stop@0.target', 'replace') 137 return None 138 139 @dbus.service.method(DBUS_NAME, 140 in_signature='', out_signature='') 141 def softPowerOff(self): 142 print "Soft off power" 143 intf = self.getInterface('host_services') 144 ## host services will call power off when ready 145 intf.SoftPowerOff() 146 return None 147 148 @dbus.service.method(DBUS_NAME, 149 in_signature='', out_signature='') 150 def reboot(self): 151 print "Rebooting" 152 if self.getPowerState() == POWER_OFF: 153 self.powerOn() 154 else: 155 self.Set(DBUS_NAME, "reboot", 1) 156 self.powerOff() 157 return None 158 159 @dbus.service.method(DBUS_NAME, 160 in_signature='', out_signature='') 161 def softReboot(self): 162 print "Soft Rebooting" 163 if self.getPowerState() == POWER_OFF: 164 self.powerOn() 165 else: 166 self.Set(DBUS_NAME, "reboot", 1) 167 self.softPowerOff() 168 return None 169 170 @dbus.service.method(DBUS_NAME, 171 in_signature='', out_signature='i') 172 def getPowerState(self): 173 intf = self.getInterface('power_control') 174 return intf.getPowerState() 175 176 ## Signal handler 177 178 def SystemStateHandler(self, state_name): 179 if state_name in ["HOST_POWERED_OFF", "HOST_POWERED_ON"]: 180 intf = self.getInterface('settings') 181 intf.Set("org.openbmc.settings.Host", "system_state", state_name) 182 183 if (state_name == "HOST_POWERED_OFF" and self.Get(DBUS_NAME, 184 "reboot") == 1): 185 self.powerOn() 186 187 def power_button_signal_handler(self): 188 # toggle power, power-on / soft-power-off 189 state = self.getPowerState() 190 if state == POWER_OFF: 191 self.powerOn() 192 elif state == POWER_ON: 193 self.softPowerOff() 194 195 def long_power_button_signal_handler(self): 196 print "Long-press button, hard power off" 197 self.powerOff() 198 199 def softreset_button_signal_handler(self): 200 self.softReboot() 201 202 def host_watchdog_signal_handler(self): 203 print "Watchdog Error, Hard Rebooting" 204 self.Set(DBUS_NAME, "reboot", 1) 205 self.powerOff() 206 207 def emergency_shutdown_signal_handler(self, message): 208 print "Emergency Shutdown!" 209 # Log an event. 210 try: 211 # Exception happens or not, we need to power off. 212 obj = bus.get_object("org.openbmc.records.events", 213 "/org/openbmc/records/events", 214 introspect=False) 215 intf = dbus.Interface(obj, "org.openbmc.recordlog") 216 desc = message 217 sev = "critical error" 218 details = "Get emergency shutdown signal. Shutdown the host." 219 debug = dbus.ByteArray("") 220 intf.acceptBMCMessage(desc, sev, details, debug) 221 except Exception as e: 222 print "Emergency shutdown signal handler: log event error." 223 print e 224 self.powerOff() 225 226 227if __name__ == '__main__': 228 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) 229 230 bus = get_dbus() 231 obj = ChassisControlObject(bus, OBJ_NAME) 232 mainloop = gobject.MainLoop() 233 234 obj.unmask_signals() 235 name = dbus.service.BusName(DBUS_NAME, bus) 236 237 print "Running ChassisControlService" 238 mainloop.run() 239