blob: 2a6f175026f3a1b11e53c0a6e62e6fa357697f37 [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")
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500122 if self.getPowerState() == POWER_OFF:
Brad Bishop7a4d77a2016-09-08 23:26:17 -0400123 self.powerOn()
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500124 else:
125 self.Set(DBUS_NAME, "reboot", 1)
126 self.powerOff()
127 return None
Norman Jamesb4ef3182015-12-03 17:54:35 -0600128
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500129 @dbus.service.method(DBUS_NAME,
130 in_signature='', out_signature='')
131 def softReboot(self):
CamVan Nguyend65b2d52018-02-27 15:14:41 -0600132 print("Soft Rebooting")
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500133 if self.getPowerState() == POWER_OFF:
Brad Bishop7a4d77a2016-09-08 23:26:17 -0400134 self.powerOn()
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500135 else:
136 self.Set(DBUS_NAME, "reboot", 1)
137 self.softPowerOff()
138 return None
Norman Jamese2765102015-08-19 22:00:55 -0500139
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500140 @dbus.service.method(DBUS_NAME,
Michael Tritz6d2f6c32017-02-02 17:03:18 -0600141 in_signature='', out_signature='')
142 def quiesce(self):
143 intf = self.getInterface('systemd')
144 f = getattr(intf, 'StartUnit')
Josh D. Kinge02cffd2017-04-11 13:53:11 -0500145 f.call_async('obmc-host-quiesce@0.target', 'replace')
Michael Tritz6d2f6c32017-02-02 17:03:18 -0600146 return None
147
148 @dbus.service.method(DBUS_NAME,
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500149 in_signature='', out_signature='i')
150 def getPowerState(self):
151 intf = self.getInterface('power_control')
152 return intf.getPowerState()
Norman Jamese2765102015-08-19 22:00:55 -0500153
Adriana Kobylak24341f92018-01-26 15:07:23 -0600154 # Signal handler
Norman James362a80f2015-09-14 14:04:39 -0500155
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500156 def power_button_signal_handler(self):
Adriana Kobylakeeb9b442016-08-15 11:12:53 -0500157 # toggle power, power-on / soft-power-off
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500158 state = self.getPowerState()
159 if state == POWER_OFF:
160 self.powerOn()
161 elif state == POWER_ON:
Brad Bishop7a4d77a2016-09-08 23:26:17 -0400162 self.softPowerOff()
Norman Jamese2765102015-08-19 22:00:55 -0500163
Adriana Kobylakeeb9b442016-08-15 11:12:53 -0500164 def long_power_button_signal_handler(self):
CamVan Nguyend65b2d52018-02-27 15:14:41 -0600165 print("Long-press button, hard power off")
Brad Bishop7a4d77a2016-09-08 23:26:17 -0400166 self.powerOff()
Kenc95eccd2015-12-19 07:02:34 +0800167
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500168 def softreset_button_signal_handler(self):
Brad Bishop7a4d77a2016-09-08 23:26:17 -0400169 self.softReboot()
Norman James72567ba2016-01-13 16:57:48 -0600170
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500171 def host_watchdog_signal_handler(self):
CamVan Nguyend65b2d52018-02-27 15:14:41 -0600172 print("Watchdog Error, Going to quiesce")
Michael Tritz6d2f6c32017-02-02 17:03:18 -0600173 self.quiesce()
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500174
Norman Jamese2765102015-08-19 22:00:55 -0500175
176if __name__ == '__main__':
177 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
178
Brad Bishop84e73b52016-05-12 15:57:52 -0400179 bus = get_dbus()
Norman James3f97c5d2015-08-26 17:44:14 -0500180 obj = ChassisControlObject(bus, OBJ_NAME)
Norman James6f8d0422015-09-14 18:48:00 -0500181 mainloop = gobject.MainLoop()
Brad Bishopf0f3efe2016-06-29 23:20:24 -0400182
183 obj.unmask_signals()
Brad Bishop70852a32016-06-29 22:58:51 -0400184 name = dbus.service.BusName(DBUS_NAME, bus)
Andrew Geisslerb7f40b52016-06-29 15:49:26 -0500185
CamVan Nguyend65b2d52018-02-27 15:14:41 -0600186 print("Running ChassisControlService")
Norman Jamese2765102015-08-19 22:00:55 -0500187 mainloop.run()
Brad Bishop53066752016-09-21 08:48:04 -0400188
189# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4