blob: fbe0f72b5f6256a250f297ec4812e3182a30e59f [file] [log] [blame]
Brad Bishop87c6b732016-08-30 19:17:57 -04001#!/usr/bin/env python
Norman Jamese2765102015-08-19 22:00:55 -05002
CamVan Nguyend65b2d52018-02-27 15:14:41 -06003# TODO: openbmc/openbmc#2994 remove python 2 support
4try: # python 2
5 import gobject
6except ImportError: # python 3
7 from gi.repository import GObject as gobject
Norman Jamese2765102015-08-19 22:00:55 -05008import dbus
9import dbus.service
10import dbus.mainloop.glib
Brad Bishop84e73b52016-05-12 15:57:52 -040011from obmc.dbuslib.bindings import get_dbus, DbusProperties, DbusObjectManager
Norman Jamese2765102015-08-19 22:00:55 -050012
Norman James3f97c5d2015-08-26 17:44:14 -050013DBUS_NAME = 'org.openbmc.control.Chassis'
Norman James8fee6f22015-10-28 12:48:43 -050014OBJ_NAME = '/org/openbmc/control/chassis0'
Norman Jamesa3e47c42015-10-18 14:43:10 -050015CONTROL_INTF = 'org.openbmc.Control'
Norman James3f97c5d2015-08-26 17:44:14 -050016
Norman Jamesad8c3d32016-02-11 15:19:01 -060017MACHINE_ID = '/etc/machine-id'
18
Norman James2a3d20b2015-08-20 07:09:33 -050019POWER_OFF = 0
20POWER_ON = 1
21
Norman James9e6acf92015-09-08 07:00:04 -050022BOOTED = 100
23
Norman James90baede2015-09-02 20:32:49 -050024
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050025class ChassisControlObject(DbusProperties, DbusObjectManager):
26 def getUuid(self):
Brad Bishop7a4d77a2016-09-08 23:26:17 -040027 uuid = ""
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050028 try:
29 with open(MACHINE_ID) as f:
30 data = f.readline().rstrip('\n')
31 if (len(data) == 32):
32 uuid = data
33 else:
CamVan Nguyend65b2d52018-02-27 15:14:41 -060034 print("ERROR: UUID is not formatted correctly: " + data)
Adriana Kobylak24341f92018-01-26 15:07:23 -060035 except Exception:
CamVan Nguyend65b2d52018-02-27 15:14:41 -060036 print("ERROR: Unable to open uuid file: " + MACHINE_ID)
Adriana Kobylak08d3bdb2015-10-20 16:59:14 -050037
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050038 return uuid
Norman Jamescfc2b442015-10-31 17:31:46 -050039
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050040 def __init__(self, bus, name):
Brad Bishopf47f5fa2016-09-08 22:29:01 -040041 super(ChassisControlObject, self).__init__(
42 conn=bus,
43 object_path=name)
Adriana Kobylak24341f92018-01-26 15:07:23 -060044 # load utilized objects
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050045 self.dbus_objects = {
46 'power_control': {
47 'bus_name': 'org.openbmc.control.Power',
48 'object_name': '/org/openbmc/control/power0',
49 'interface_name': 'org.openbmc.control.Power'
50 },
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050051 'host_services': {
52 'bus_name': 'org.openbmc.HostServices',
53 'object_name': '/org/openbmc/HostServices',
54 'interface_name': 'org.openbmc.HostServices'
55 },
Brad Bishopabe0f682016-08-22 19:27:18 -040056 'systemd': {
57 'bus_name': 'org.freedesktop.systemd1',
58 'object_name': '/org/freedesktop/systemd1',
59 'interface_name': 'org.freedesktop.systemd1.Manager'
Andrew Geissler6b63e9a2016-06-30 10:45:01 -050060 },
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050061 }
Norman James72567ba2016-01-13 16:57:48 -060062
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050063 # uuid
64 self.Set(DBUS_NAME, "uuid", self.getUuid())
65 self.Set(DBUS_NAME, "reboot", 0)
Norman James72567ba2016-01-13 16:57:48 -060066
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050067 bus.add_signal_receiver(self.power_button_signal_handler,
68 dbus_interface="org.openbmc.Button",
69 signal_name="Released",
70 path="/org/openbmc/buttons/power0")
Adriana Kobylakeeb9b442016-08-15 11:12:53 -050071 bus.add_signal_receiver(self.long_power_button_signal_handler,
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050072 dbus_interface="org.openbmc.Button",
73 signal_name="PressedLong",
74 path="/org/openbmc/buttons/power0")
75 bus.add_signal_receiver(self.softreset_button_signal_handler,
76 dbus_interface="org.openbmc.Button",
77 signal_name="Released",
78 path="/org/openbmc/buttons/reset0")
79
80 bus.add_signal_receiver(self.host_watchdog_signal_handler,
81 dbus_interface="org.openbmc.Watchdog",
82 signal_name="WatchdogError")
83
Norman James471ab592015-08-30 22:29:40 -050084
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050085 def getInterface(self, name):
86 o = self.dbus_objects[name]
87 obj = bus.get_object(o['bus_name'], o['object_name'], introspect=False)
88 return dbus.Interface(obj, o['interface_name'])
Norman Jamese2765102015-08-19 22:00:55 -050089
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050090 @dbus.service.method(DBUS_NAME,
91 in_signature='', out_signature='')
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050092 def powerOn(self):
CamVan Nguyend65b2d52018-02-27 15:14:41 -060093 print("Turn on power and boot")
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050094 self.Set(DBUS_NAME, "reboot", 0)
Brad Bishopabe0f682016-08-22 19:27:18 -040095 intf = self.getInterface('systemd')
96 f = getattr(intf, 'StartUnit')
Josh D. King2a559542017-04-11 13:48:00 -050097 f.call_async('obmc-host-start@0.target', 'replace')
Andrew Geisslerb7f40b52016-06-29 15:49:26 -050098 return None
Norman Jamese2765102015-08-19 22:00:55 -050099
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500100 @dbus.service.method(DBUS_NAME,
101 in_signature='', out_signature='')
102 def powerOff(self):
CamVan Nguyend65b2d52018-02-27 15:14:41 -0600103 print("Turn off power")
Brad Bishopabe0f682016-08-22 19:27:18 -0400104 intf = self.getInterface('systemd')
105 f = getattr(intf, 'StartUnit')
Andrew Geissler9903ec62017-07-30 09:36:33 -0500106 f.call_async('obmc-chassis-hard-poweroff@0.target', 'replace')
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500107 return None
Norman James362a80f2015-09-14 14:04:39 -0500108
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500109 @dbus.service.method(DBUS_NAME,
110 in_signature='', out_signature='')
111 def softPowerOff(self):
CamVan Nguyend65b2d52018-02-27 15:14:41 -0600112 print("Soft off power")
Andrew Geissler9903ec62017-07-30 09:36:33 -0500113 intf = self.getInterface('systemd')
114 f = getattr(intf, 'StartUnit')
115 f.call_async('obmc-host-shutdown@0.target', 'replace')
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500116 return None
Norman James362a80f2015-09-14 14:04:39 -0500117
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500118 @dbus.service.method(DBUS_NAME,
119 in_signature='', out_signature='')
120 def reboot(self):
CamVan Nguyend65b2d52018-02-27 15:14:41 -0600121 print("Rebooting")
Alexander Soldatove32e3372018-10-31 14:29:31 +0300122 if self.getPowerState() != POWER_OFF:
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500123 self.Set(DBUS_NAME, "reboot", 1)
124 self.powerOff()
125 return None
Norman Jamesb4ef3182015-12-03 17:54:35 -0600126
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500127 @dbus.service.method(DBUS_NAME,
128 in_signature='', out_signature='')
129 def softReboot(self):
CamVan Nguyend65b2d52018-02-27 15:14:41 -0600130 print("Soft Rebooting")
Alexander Soldatove32e3372018-10-31 14:29:31 +0300131 if self.getPowerState() != POWER_OFF:
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500132 self.Set(DBUS_NAME, "reboot", 1)
133 self.softPowerOff()
134 return None
Norman Jamese2765102015-08-19 22:00:55 -0500135
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500136 @dbus.service.method(DBUS_NAME,
Michael Tritz6d2f6c32017-02-02 17:03:18 -0600137 in_signature='', out_signature='')
138 def quiesce(self):
139 intf = self.getInterface('systemd')
140 f = getattr(intf, 'StartUnit')
Josh D. Kinge02cffd2017-04-11 13:53:11 -0500141 f.call_async('obmc-host-quiesce@0.target', 'replace')
Michael Tritz6d2f6c32017-02-02 17:03:18 -0600142 return None
143
144 @dbus.service.method(DBUS_NAME,
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500145 in_signature='', out_signature='i')
146 def getPowerState(self):
147 intf = self.getInterface('power_control')
148 return intf.getPowerState()
Norman Jamese2765102015-08-19 22:00:55 -0500149
Adriana Kobylak24341f92018-01-26 15:07:23 -0600150 # Signal handler
Norman James362a80f2015-09-14 14:04:39 -0500151
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500152 def power_button_signal_handler(self):
Adriana Kobylakeeb9b442016-08-15 11:12:53 -0500153 # toggle power, power-on / soft-power-off
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500154 state = self.getPowerState()
155 if state == POWER_OFF:
156 self.powerOn()
157 elif state == POWER_ON:
Brad Bishop7a4d77a2016-09-08 23:26:17 -0400158 self.softPowerOff()
Norman Jamese2765102015-08-19 22:00:55 -0500159
Adriana Kobylakeeb9b442016-08-15 11:12:53 -0500160 def long_power_button_signal_handler(self):
CamVan Nguyend65b2d52018-02-27 15:14:41 -0600161 print("Long-press button, hard power off")
Brad Bishop7a4d77a2016-09-08 23:26:17 -0400162 self.powerOff()
Kenc95eccd2015-12-19 07:02:34 +0800163
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500164 def softreset_button_signal_handler(self):
Brad Bishop7a4d77a2016-09-08 23:26:17 -0400165 self.softReboot()
Norman James72567ba2016-01-13 16:57:48 -0600166
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500167 def host_watchdog_signal_handler(self):
CamVan Nguyend65b2d52018-02-27 15:14:41 -0600168 print("Watchdog Error, Going to quiesce")
Michael Tritz6d2f6c32017-02-02 17:03:18 -0600169 self.quiesce()
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500170
Norman Jamese2765102015-08-19 22:00:55 -0500171
172if __name__ == '__main__':
173 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
174
Brad Bishop84e73b52016-05-12 15:57:52 -0400175 bus = get_dbus()
Norman James3f97c5d2015-08-26 17:44:14 -0500176 obj = ChassisControlObject(bus, OBJ_NAME)
Norman James6f8d0422015-09-14 18:48:00 -0500177 mainloop = gobject.MainLoop()
Brad Bishopf0f3efe2016-06-29 23:20:24 -0400178
179 obj.unmask_signals()
Brad Bishop70852a32016-06-29 22:58:51 -0400180 name = dbus.service.BusName(DBUS_NAME, bus)
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500181
CamVan Nguyend65b2d52018-02-27 15:14:41 -0600182 print("Running ChassisControlService")
Norman Jamese2765102015-08-19 22:00:55 -0500183 mainloop.run()
Brad Bishop53066752016-09-21 08:48:04 -0400184
185# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4