blob: 6c6d9bd9ca7be7ca481802c8c4e6aadbda8fb15a [file] [log] [blame]
Norman James42c1be82015-10-22 14:34:26 -05001#!/usr/bin/python -u
Norman Jamese2765102015-08-19 22:00:55 -05002
Norman James471ab592015-08-30 22:29:40 -05003import sys
Adriana Kobylak08d3bdb2015-10-20 16:59:14 -05004import uuid
Norman James6f8d0422015-09-14 18:48:00 -05005import gobject
Norman Jamese2765102015-08-19 22:00:55 -05006import dbus
7import dbus.service
8import dbus.mainloop.glib
Brad Bishop84e73b52016-05-12 15:57:52 -04009from obmc.dbuslib.bindings import get_dbus, DbusProperties, DbusObjectManager
Norman Jamese2765102015-08-19 22:00:55 -050010
Norman James3f97c5d2015-08-26 17:44:14 -050011DBUS_NAME = 'org.openbmc.control.Chassis'
Norman James8fee6f22015-10-28 12:48:43 -050012OBJ_NAME = '/org/openbmc/control/chassis0'
Norman Jamesa3e47c42015-10-18 14:43:10 -050013CONTROL_INTF = 'org.openbmc.Control'
Norman James3f97c5d2015-08-26 17:44:14 -050014
Norman Jamesad8c3d32016-02-11 15:19:01 -060015MACHINE_ID = '/etc/machine-id'
16
Norman James2a3d20b2015-08-20 07:09:33 -050017POWER_OFF = 0
18POWER_ON = 1
19
Norman James9e6acf92015-09-08 07:00:04 -050020BOOTED = 100
21
Norman James90baede2015-09-02 20:32:49 -050022
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050023class 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
Adriana Kobylak08d3bdb2015-10-20 16:59:14 -050035
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050036 return uuid
Norman Jamescfc2b442015-10-31 17:31:46 -050037
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050038 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 },
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050055 '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 },
Brad Bishopabe0f682016-08-22 19:27:18 -040065 'systemd': {
66 'bus_name': 'org.freedesktop.systemd1',
67 'object_name': '/org/freedesktop/systemd1',
68 'interface_name': 'org.freedesktop.systemd1.Manager'
Andrew Geissler6b63e9a2016-06-30 10:45:01 -050069 },
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050070 }
Norman James72567ba2016-01-13 16:57:48 -060071
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050072 # uuid
73 self.Set(DBUS_NAME, "uuid", self.getUuid())
74 self.Set(DBUS_NAME, "reboot", 0)
Norman James72567ba2016-01-13 16:57:48 -060075
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050076 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")
Adriana Kobylakeeb9b442016-08-15 11:12:53 -050080 bus.add_signal_receiver(self.long_power_button_signal_handler,
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050081 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")
Norman James471ab592015-08-30 22:29:40 -050099
Norman James9e6acf92015-09-08 07:00:04 -0500100
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500101 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'])
Norman Jamese2765102015-08-19 22:00:55 -0500105
Norman Jamese2765102015-08-19 22:00:55 -0500106
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500107 @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
Norman Jamese2765102015-08-19 22:00:55 -0500114
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500115 @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
Norman Jamese2765102015-08-19 22:00:55 -0500122
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500123 @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)
Brad Bishopabe0f682016-08-22 19:27:18 -0400128 intf = self.getInterface('systemd')
129 f = getattr(intf, 'StartUnit')
130 f.call_async('obmc-chassis-start@0.target', 'replace')
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500131 return None
Norman Jamese2765102015-08-19 22:00:55 -0500132
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500133 @dbus.service.method(DBUS_NAME,
134 in_signature='', out_signature='')
135 def powerOff(self):
136 print "Turn off power"
Brad Bishopabe0f682016-08-22 19:27:18 -0400137
138 intf = self.getInterface('systemd')
139 f = getattr(intf, 'StartUnit')
140 f.call_async('obmc-chassis-stop@0.target', 'replace')
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500141 return None
Norman James362a80f2015-09-14 14:04:39 -0500142
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500143 @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
Norman James362a80f2015-09-14 14:04:39 -0500151
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500152 @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
Norman Jamesb4ef3182015-12-03 17:54:35 -0600162
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500163 @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
Norman Jamese2765102015-08-19 22:00:55 -0500173
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500174 @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()
Norman Jamese2765102015-08-19 22:00:55 -0500179
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500180 ## Signal handler
Norman James362a80f2015-09-14 14:04:39 -0500181
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500182 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)
Norman Jamesf5edb9e2016-01-31 13:32:24 -0600187
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500188 if (state_name == "HOST_POWERED_OFF" and self.Get(DBUS_NAME,
189 "reboot") == 1):
190 self.powerOn()
Norman James362a80f2015-09-14 14:04:39 -0500191
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500192 def power_button_signal_handler(self):
Adriana Kobylakeeb9b442016-08-15 11:12:53 -0500193 # toggle power, power-on / soft-power-off
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500194 state = self.getPowerState()
195 if state == POWER_OFF:
196 self.powerOn()
197 elif state == POWER_ON:
Adriana Kobylakeeb9b442016-08-15 11:12:53 -0500198 self.softPowerOff();
Norman Jamese2765102015-08-19 22:00:55 -0500199
Adriana Kobylakeeb9b442016-08-15 11:12:53 -0500200 def long_power_button_signal_handler(self):
201 print "Long-press button, hard power off"
202 self.powerOff();
Kenc95eccd2015-12-19 07:02:34 +0800203
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500204 def softreset_button_signal_handler(self):
205 self.softReboot();
Norman James72567ba2016-01-13 16:57:48 -0600206
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500207 def host_watchdog_signal_handler(self):
208 print "Watchdog Error, Hard Rebooting"
209 self.Set(DBUS_NAME, "reboot", 1)
210 self.powerOff()
211
Yi Li4eab1dc2016-07-02 22:29:45 +0800212 def emergency_shutdown_signal_handler(self, message):
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500213 print "Emergency Shutdown!"
Yi Li4eab1dc2016-07-02 22:29:45 +0800214 # 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
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500229 self.powerOff()
230
Norman Jamese2765102015-08-19 22:00:55 -0500231
232if __name__ == '__main__':
233 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
234
Brad Bishop84e73b52016-05-12 15:57:52 -0400235 bus = get_dbus()
Norman James3f97c5d2015-08-26 17:44:14 -0500236 obj = ChassisControlObject(bus, OBJ_NAME)
Norman James6f8d0422015-09-14 18:48:00 -0500237 mainloop = gobject.MainLoop()
Brad Bishopf0f3efe2016-06-29 23:20:24 -0400238
239 obj.unmask_signals()
Brad Bishop70852a32016-06-29 22:58:51 -0400240 name = dbus.service.BusName(DBUS_NAME, bus)
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500241
Norman Jamese2765102015-08-19 22:00:55 -0500242 print "Running ChassisControlService"
243 mainloop.run()
244