blob: 373d8763b842f64351e84f21c7b703875bb256bd [file] [log] [blame]
Brad Bishop87c6b732016-08-30 19:17:57 -04001#!/usr/bin/env python
Norman Jamese2765102015-08-19 22:00:55 -05002
Norman James6f8d0422015-09-14 18:48:00 -05003import gobject
Norman Jamese2765102015-08-19 22:00:55 -05004import dbus
5import dbus.service
6import dbus.mainloop.glib
Brad Bishop84e73b52016-05-12 15:57:52 -04007from obmc.dbuslib.bindings import get_dbus, DbusProperties, DbusObjectManager
Norman Jamese2765102015-08-19 22:00:55 -05008
Norman James3f97c5d2015-08-26 17:44:14 -05009DBUS_NAME = 'org.openbmc.control.Chassis'
Norman James8fee6f22015-10-28 12:48:43 -050010OBJ_NAME = '/org/openbmc/control/chassis0'
Norman Jamesa3e47c42015-10-18 14:43:10 -050011CONTROL_INTF = 'org.openbmc.Control'
Norman James3f97c5d2015-08-26 17:44:14 -050012
Norman Jamesad8c3d32016-02-11 15:19:01 -060013MACHINE_ID = '/etc/machine-id'
14
Norman James2a3d20b2015-08-20 07:09:33 -050015POWER_OFF = 0
16POWER_ON = 1
17
Norman James9e6acf92015-09-08 07:00:04 -050018BOOTED = 100
19
Norman James90baede2015-09-02 20:32:49 -050020
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050021class 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
Adriana Kobylak08d3bdb2015-10-20 16:59:14 -050033
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050034 return uuid
Norman Jamescfc2b442015-10-31 17:31:46 -050035
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050036 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 },
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050053 '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 },
Brad Bishopabe0f682016-08-22 19:27:18 -040063 'systemd': {
64 'bus_name': 'org.freedesktop.systemd1',
65 'object_name': '/org/freedesktop/systemd1',
66 'interface_name': 'org.freedesktop.systemd1.Manager'
Andrew Geissler6b63e9a2016-06-30 10:45:01 -050067 },
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050068 }
Norman James72567ba2016-01-13 16:57:48 -060069
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050070 # uuid
71 self.Set(DBUS_NAME, "uuid", self.getUuid())
72 self.Set(DBUS_NAME, "reboot", 0)
Norman James72567ba2016-01-13 16:57:48 -060073
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050074 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")
Adriana Kobylakeeb9b442016-08-15 11:12:53 -050078 bus.add_signal_receiver(self.long_power_button_signal_handler,
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050079 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")
Norman James471ab592015-08-30 22:29:40 -050097
Norman James9e6acf92015-09-08 07:00:04 -050098
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050099 def getInterface(self, name):
100 o = self.dbus_objects[name]
101 obj = bus.get_object(o['bus_name'], o['object_name'], introspect=False)
102 return dbus.Interface(obj, o['interface_name'])
Norman Jamese2765102015-08-19 22:00:55 -0500103
Norman Jamese2765102015-08-19 22:00:55 -0500104
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500105 @dbus.service.method(DBUS_NAME,
106 in_signature='', out_signature='')
107 def setIdentify(self):
108 print "Turn on identify"
109 intf = self.getInterface('identify_led')
110 intf.setOn()
111 return None
Norman Jamese2765102015-08-19 22:00:55 -0500112
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500113 @dbus.service.method(DBUS_NAME,
114 in_signature='', out_signature='')
115 def clearIdentify(self):
116 print "Turn on identify"
117 intf = self.getInterface('identify_led')
118 intf.setOff()
119 return None
Norman Jamese2765102015-08-19 22:00:55 -0500120
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500121 @dbus.service.method(DBUS_NAME,
122 in_signature='', out_signature='')
123 def powerOn(self):
124 print "Turn on power and boot"
125 self.Set(DBUS_NAME, "reboot", 0)
Brad Bishopabe0f682016-08-22 19:27:18 -0400126 intf = self.getInterface('systemd')
127 f = getattr(intf, 'StartUnit')
128 f.call_async('obmc-chassis-start@0.target', 'replace')
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500129 return None
Norman Jamese2765102015-08-19 22:00:55 -0500130
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500131 @dbus.service.method(DBUS_NAME,
132 in_signature='', out_signature='')
133 def powerOff(self):
134 print "Turn off power"
Brad Bishopabe0f682016-08-22 19:27:18 -0400135
136 intf = self.getInterface('systemd')
137 f = getattr(intf, 'StartUnit')
138 f.call_async('obmc-chassis-stop@0.target', 'replace')
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500139 return None
Norman James362a80f2015-09-14 14:04:39 -0500140
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500141 @dbus.service.method(DBUS_NAME,
142 in_signature='', out_signature='')
143 def softPowerOff(self):
144 print "Soft off power"
145 intf = self.getInterface('host_services')
146 ## host services will call power off when ready
147 intf.SoftPowerOff()
148 return None
Norman James362a80f2015-09-14 14:04:39 -0500149
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500150 @dbus.service.method(DBUS_NAME,
151 in_signature='', out_signature='')
152 def reboot(self):
153 print "Rebooting"
154 if self.getPowerState() == POWER_OFF:
155 self.powerOn();
156 else:
157 self.Set(DBUS_NAME, "reboot", 1)
158 self.powerOff()
159 return None
Norman Jamesb4ef3182015-12-03 17:54:35 -0600160
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500161 @dbus.service.method(DBUS_NAME,
162 in_signature='', out_signature='')
163 def softReboot(self):
164 print "Soft Rebooting"
165 if self.getPowerState() == POWER_OFF:
166 self.powerOn();
167 else:
168 self.Set(DBUS_NAME, "reboot", 1)
169 self.softPowerOff()
170 return None
Norman Jamese2765102015-08-19 22:00:55 -0500171
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500172 @dbus.service.method(DBUS_NAME,
173 in_signature='', out_signature='i')
174 def getPowerState(self):
175 intf = self.getInterface('power_control')
176 return intf.getPowerState()
Norman Jamese2765102015-08-19 22:00:55 -0500177
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500178 ## Signal handler
Norman James362a80f2015-09-14 14:04:39 -0500179
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500180 def SystemStateHandler(self, state_name):
181 if (
182 state_name == "HOST_POWERED_OFF" or state_name == "HOST_POWERED_ON"):
183 intf = self.getInterface('settings')
184 intf.Set("org.openbmc.settings.Host", "system_state", state_name)
Norman Jamesf5edb9e2016-01-31 13:32:24 -0600185
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500186 if (state_name == "HOST_POWERED_OFF" and self.Get(DBUS_NAME,
187 "reboot") == 1):
188 self.powerOn()
Norman James362a80f2015-09-14 14:04:39 -0500189
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500190 def power_button_signal_handler(self):
Adriana Kobylakeeb9b442016-08-15 11:12:53 -0500191 # toggle power, power-on / soft-power-off
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500192 state = self.getPowerState()
193 if state == POWER_OFF:
194 self.powerOn()
195 elif state == POWER_ON:
Adriana Kobylakeeb9b442016-08-15 11:12:53 -0500196 self.softPowerOff();
Norman Jamese2765102015-08-19 22:00:55 -0500197
Adriana Kobylakeeb9b442016-08-15 11:12:53 -0500198 def long_power_button_signal_handler(self):
199 print "Long-press button, hard power off"
200 self.powerOff();
Kenc95eccd2015-12-19 07:02:34 +0800201
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500202 def softreset_button_signal_handler(self):
203 self.softReboot();
Norman James72567ba2016-01-13 16:57:48 -0600204
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500205 def host_watchdog_signal_handler(self):
206 print "Watchdog Error, Hard Rebooting"
207 self.Set(DBUS_NAME, "reboot", 1)
208 self.powerOff()
209
Yi Li4eab1dc2016-07-02 22:29:45 +0800210 def emergency_shutdown_signal_handler(self, message):
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500211 print "Emergency Shutdown!"
Yi Li4eab1dc2016-07-02 22:29:45 +0800212 # Log an event.
213 try:
214 # Exception happens or not, we need to power off.
215 obj = bus.get_object("org.openbmc.records.events",
216 "/org/openbmc/records/events",
217 introspect=False)
218 intf = dbus.Interface(obj, "org.openbmc.recordlog")
219 desc = message
220 sev = "critical error"
221 details = "Get emergency shutdown signal. Shutdown the host."
222 debug = dbus.ByteArray("")
223 intf.acceptBMCMessage(desc, sev, details, debug)
224 except Exception as e:
225 print "Emergency shutdown signal handler: log event error."
226 print e
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500227 self.powerOff()
228
Norman Jamese2765102015-08-19 22:00:55 -0500229
230if __name__ == '__main__':
231 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
232
Brad Bishop84e73b52016-05-12 15:57:52 -0400233 bus = get_dbus()
Norman James3f97c5d2015-08-26 17:44:14 -0500234 obj = ChassisControlObject(bus, OBJ_NAME)
Norman James6f8d0422015-09-14 18:48:00 -0500235 mainloop = gobject.MainLoop()
Brad Bishopf0f3efe2016-06-29 23:20:24 -0400236
237 obj.unmask_signals()
Brad Bishop70852a32016-06-29 22:58:51 -0400238 name = dbus.service.BusName(DBUS_NAME, bus)
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500239
Norman Jamese2765102015-08-19 22:00:55 -0500240 print "Running ChassisControlService"
241 mainloop.run()
242