blob: c25c2ff853e774211f41d3de41ed4e3adafb462c [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):
Brad Bishop7a4d77a2016-09-08 23:26:17 -040023 uuid = ""
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050024 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):
Brad Bishopf47f5fa2016-09-08 22:29:01 -040037 super(ChassisControlObject, self).__init__(
38 conn=bus,
39 object_path=name)
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050040 ## load utilized objects
41 self.dbus_objects = {
42 'power_control': {
43 'bus_name': 'org.openbmc.control.Power',
44 'object_name': '/org/openbmc/control/power0',
45 'interface_name': 'org.openbmc.control.Power'
46 },
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050047 'host_services': {
48 'bus_name': 'org.openbmc.HostServices',
49 'object_name': '/org/openbmc/HostServices',
50 'interface_name': 'org.openbmc.HostServices'
51 },
52 'settings': {
53 'bus_name': 'org.openbmc.settings.Host',
54 'object_name': '/org/openbmc/settings/host0',
55 'interface_name': 'org.freedesktop.DBus.Properties'
56 },
Brad Bishopabe0f682016-08-22 19:27:18 -040057 'systemd': {
58 'bus_name': 'org.freedesktop.systemd1',
59 'object_name': '/org/freedesktop/systemd1',
60 'interface_name': 'org.freedesktop.systemd1.Manager'
Andrew Geissler6b63e9a2016-06-30 10:45:01 -050061 },
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050062 }
Norman James72567ba2016-01-13 16:57:48 -060063
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050064 # uuid
65 self.Set(DBUS_NAME, "uuid", self.getUuid())
66 self.Set(DBUS_NAME, "reboot", 0)
Norman James72567ba2016-01-13 16:57:48 -060067
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050068 bus.add_signal_receiver(self.power_button_signal_handler,
69 dbus_interface="org.openbmc.Button",
70 signal_name="Released",
71 path="/org/openbmc/buttons/power0")
Adriana Kobylakeeb9b442016-08-15 11:12:53 -050072 bus.add_signal_receiver(self.long_power_button_signal_handler,
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050073 dbus_interface="org.openbmc.Button",
74 signal_name="PressedLong",
75 path="/org/openbmc/buttons/power0")
76 bus.add_signal_receiver(self.softreset_button_signal_handler,
77 dbus_interface="org.openbmc.Button",
78 signal_name="Released",
79 path="/org/openbmc/buttons/reset0")
80
81 bus.add_signal_receiver(self.host_watchdog_signal_handler,
82 dbus_interface="org.openbmc.Watchdog",
83 signal_name="WatchdogError")
84
85 bus.add_signal_receiver(self.emergency_shutdown_signal_handler,
86 dbus_interface="org.openbmc.SensorThresholds",
87 signal_name="Emergency")
88
89 bus.add_signal_receiver(self.SystemStateHandler,
90 signal_name="GotoSystemState")
Norman James471ab592015-08-30 22:29:40 -050091
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050092 def getInterface(self, name):
93 o = self.dbus_objects[name]
94 obj = bus.get_object(o['bus_name'], o['object_name'], introspect=False)
95 return dbus.Interface(obj, o['interface_name'])
Norman Jamese2765102015-08-19 22:00:55 -050096
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050097 @dbus.service.method(DBUS_NAME,
98 in_signature='', out_signature='')
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050099 def powerOn(self):
100 print "Turn on power and boot"
101 self.Set(DBUS_NAME, "reboot", 0)
Brad Bishopabe0f682016-08-22 19:27:18 -0400102 intf = self.getInterface('systemd')
103 f = getattr(intf, 'StartUnit')
Josh D. King2a559542017-04-11 13:48:00 -0500104 f.call_async('obmc-host-start@0.target', 'replace')
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500105 return None
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 powerOff(self):
110 print "Turn off power"
Brad Bishopabe0f682016-08-22 19:27:18 -0400111
112 intf = self.getInterface('systemd')
113 f = getattr(intf, 'StartUnit')
Josh D. King2a559542017-04-11 13:48:00 -0500114 f.call_async('obmc-host-stop@0.target', 'replace')
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500115 return None
Norman James362a80f2015-09-14 14:04:39 -0500116
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500117 @dbus.service.method(DBUS_NAME,
118 in_signature='', out_signature='')
119 def softPowerOff(self):
120 print "Soft off power"
121 intf = self.getInterface('host_services')
122 ## host services will call power off when ready
123 intf.SoftPowerOff()
124 return None
Norman James362a80f2015-09-14 14:04:39 -0500125
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500126 @dbus.service.method(DBUS_NAME,
127 in_signature='', out_signature='')
128 def reboot(self):
129 print "Rebooting"
130 if self.getPowerState() == POWER_OFF:
Brad Bishop7a4d77a2016-09-08 23:26:17 -0400131 self.powerOn()
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500132 else:
133 self.Set(DBUS_NAME, "reboot", 1)
134 self.powerOff()
135 return None
Norman Jamesb4ef3182015-12-03 17:54:35 -0600136
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500137 @dbus.service.method(DBUS_NAME,
138 in_signature='', out_signature='')
139 def softReboot(self):
140 print "Soft Rebooting"
141 if self.getPowerState() == POWER_OFF:
Brad Bishop7a4d77a2016-09-08 23:26:17 -0400142 self.powerOn()
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500143 else:
144 self.Set(DBUS_NAME, "reboot", 1)
145 self.softPowerOff()
146 return None
Norman Jamese2765102015-08-19 22:00:55 -0500147
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500148 @dbus.service.method(DBUS_NAME,
Michael Tritz6d2f6c32017-02-02 17:03:18 -0600149 in_signature='', out_signature='')
150 def quiesce(self):
151 intf = self.getInterface('systemd')
152 f = getattr(intf, 'StartUnit')
Josh D. Kinge02cffd2017-04-11 13:53:11 -0500153 f.call_async('obmc-host-quiesce@0.target', 'replace')
Michael Tritz6d2f6c32017-02-02 17:03:18 -0600154 return None
155
156 @dbus.service.method(DBUS_NAME,
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500157 in_signature='', out_signature='i')
158 def getPowerState(self):
159 intf = self.getInterface('power_control')
160 return intf.getPowerState()
Norman Jamese2765102015-08-19 22:00:55 -0500161
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500162 ## Signal handler
Norman James362a80f2015-09-14 14:04:39 -0500163
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500164 def SystemStateHandler(self, state_name):
Brad Bishop7a4d77a2016-09-08 23:26:17 -0400165 if state_name in ["HOST_POWERED_OFF", "HOST_POWERED_ON"]:
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500166 intf = self.getInterface('settings')
167 intf.Set("org.openbmc.settings.Host", "system_state", state_name)
Norman Jamesf5edb9e2016-01-31 13:32:24 -0600168
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500169 if (state_name == "HOST_POWERED_OFF" and self.Get(DBUS_NAME,
170 "reboot") == 1):
171 self.powerOn()
Norman James362a80f2015-09-14 14:04:39 -0500172
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500173 def power_button_signal_handler(self):
Adriana Kobylakeeb9b442016-08-15 11:12:53 -0500174 # toggle power, power-on / soft-power-off
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500175 state = self.getPowerState()
176 if state == POWER_OFF:
177 self.powerOn()
178 elif state == POWER_ON:
Brad Bishop7a4d77a2016-09-08 23:26:17 -0400179 self.softPowerOff()
Norman Jamese2765102015-08-19 22:00:55 -0500180
Adriana Kobylakeeb9b442016-08-15 11:12:53 -0500181 def long_power_button_signal_handler(self):
182 print "Long-press button, hard power off"
Brad Bishop7a4d77a2016-09-08 23:26:17 -0400183 self.powerOff()
Kenc95eccd2015-12-19 07:02:34 +0800184
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500185 def softreset_button_signal_handler(self):
Brad Bishop7a4d77a2016-09-08 23:26:17 -0400186 self.softReboot()
Norman James72567ba2016-01-13 16:57:48 -0600187
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500188 def host_watchdog_signal_handler(self):
Michael Tritz6d2f6c32017-02-02 17:03:18 -0600189 print "Watchdog Error, Going to quiesce"
190 self.quiesce()
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500191
Yi Li4eab1dc2016-07-02 22:29:45 +0800192 def emergency_shutdown_signal_handler(self, message):
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500193 print "Emergency Shutdown!"
Yi Li4eab1dc2016-07-02 22:29:45 +0800194 # Log an event.
195 try:
196 # Exception happens or not, we need to power off.
197 obj = bus.get_object("org.openbmc.records.events",
198 "/org/openbmc/records/events",
199 introspect=False)
200 intf = dbus.Interface(obj, "org.openbmc.recordlog")
201 desc = message
202 sev = "critical error"
203 details = "Get emergency shutdown signal. Shutdown the host."
204 debug = dbus.ByteArray("")
205 intf.acceptBMCMessage(desc, sev, details, debug)
206 except Exception as e:
207 print "Emergency shutdown signal handler: log event error."
208 print e
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500209 self.powerOff()
210
Norman Jamese2765102015-08-19 22:00:55 -0500211
212if __name__ == '__main__':
213 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
214
Brad Bishop84e73b52016-05-12 15:57:52 -0400215 bus = get_dbus()
Norman James3f97c5d2015-08-26 17:44:14 -0500216 obj = ChassisControlObject(bus, OBJ_NAME)
Norman James6f8d0422015-09-14 18:48:00 -0500217 mainloop = gobject.MainLoop()
Brad Bishopf0f3efe2016-06-29 23:20:24 -0400218
219 obj.unmask_signals()
Brad Bishop70852a32016-06-29 22:58:51 -0400220 name = dbus.service.BusName(DBUS_NAME, bus)
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500221
Norman Jamese2765102015-08-19 22:00:55 -0500222 print "Running ChassisControlService"
223 mainloop.run()
Brad Bishop53066752016-09-21 08:48:04 -0400224
225# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4