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