blob: b5528c8ab4e2006db7e1318d51518068ad9e1a76 [file] [log] [blame]
#!/usr/bin/env python
# TODO: openbmc/openbmc#2994 remove python 2 support
try: # python 2
import gobject
except ImportError: # python 3
from gi.repository import GObject as gobject
import dbus
import dbus.service
import dbus.mainloop.glib
from obmc.dbuslib.bindings import get_dbus, DbusProperties, DbusObjectManager
DBUS_NAME = "org.openbmc.control.Chassis"
OBJ_NAME = "/org/openbmc/control/chassis0"
CONTROL_INTF = "org.openbmc.Control"
MACHINE_ID = "/etc/machine-id"
POWER_OFF = 0
POWER_ON = 1
BOOTED = 100
class ChassisControlObject(DbusProperties, DbusObjectManager):
def getUuid(self):
uuid = ""
try:
with open(MACHINE_ID) as f:
data = f.readline().rstrip("\n")
if len(data) == 32:
uuid = data
else:
print("ERROR: UUID is not formatted correctly: " + data)
except Exception:
print("ERROR: Unable to open uuid file: " + MACHINE_ID)
return uuid
def __init__(self, bus, name):
super(ChassisControlObject, self).__init__(conn=bus, object_path=name)
# load utilized objects
self.dbus_objects = {
"power_control": {
"bus_name": "org.openbmc.control.Power",
"object_name": "/org/openbmc/control/power0",
"interface_name": "org.openbmc.control.Power",
},
"host_services": {
"bus_name": "org.openbmc.HostServices",
"object_name": "/org/openbmc/HostServices",
"interface_name": "org.openbmc.HostServices",
},
"systemd": {
"bus_name": "org.freedesktop.systemd1",
"object_name": "/org/freedesktop/systemd1",
"interface_name": "org.freedesktop.systemd1.Manager",
},
}
# uuid
self.Set(DBUS_NAME, "uuid", self.getUuid())
self.Set(DBUS_NAME, "reboot", 0)
bus.add_signal_receiver(
self.power_button_signal_handler,
dbus_interface="org.openbmc.Button",
signal_name="Released",
path="/org/openbmc/buttons/power0",
)
bus.add_signal_receiver(
self.long_power_button_signal_handler,
dbus_interface="org.openbmc.Button",
signal_name="PressedLong",
path="/org/openbmc/buttons/power0",
)
bus.add_signal_receiver(
self.softreset_button_signal_handler,
dbus_interface="org.openbmc.Button",
signal_name="Released",
path="/org/openbmc/buttons/reset0",
)
bus.add_signal_receiver(
self.host_watchdog_signal_handler,
dbus_interface="org.openbmc.Watchdog",
signal_name="WatchdogError",
)
def getInterface(self, name):
o = self.dbus_objects[name]
obj = bus.get_object(o["bus_name"], o["object_name"], introspect=False)
return dbus.Interface(obj, o["interface_name"])
@dbus.service.method(DBUS_NAME, in_signature="", out_signature="")
def powerOn(self):
print("Turn on power and boot")
self.Set(DBUS_NAME, "reboot", 0)
intf = self.getInterface("systemd")
f = getattr(intf, "StartUnit")
f.call_async("obmc-host-start@0.target", "replace")
return None
@dbus.service.method(DBUS_NAME, in_signature="", out_signature="")
def powerOff(self):
print("Turn off power")
intf = self.getInterface("systemd")
f = getattr(intf, "StartUnit")
f.call_async("obmc-chassis-hard-poweroff@0.target", "replace")
return None
@dbus.service.method(DBUS_NAME, in_signature="", out_signature="")
def softPowerOff(self):
print("Soft off power")
intf = self.getInterface("systemd")
f = getattr(intf, "StartUnit")
f.call_async("obmc-host-shutdown@0.target", "replace")
return None
@dbus.service.method(DBUS_NAME, in_signature="", out_signature="")
def reboot(self):
print("Rebooting")
if self.getPowerState() != POWER_OFF:
self.Set(DBUS_NAME, "reboot", 1)
self.powerOff()
return None
@dbus.service.method(DBUS_NAME, in_signature="", out_signature="")
def softReboot(self):
print("Soft Rebooting")
if self.getPowerState() != POWER_OFF:
self.Set(DBUS_NAME, "reboot", 1)
self.softPowerOff()
return None
@dbus.service.method(DBUS_NAME, in_signature="", out_signature="")
def quiesce(self):
intf = self.getInterface("systemd")
f = getattr(intf, "StartUnit")
f.call_async("obmc-host-quiesce@0.target", "replace")
return None
@dbus.service.method(DBUS_NAME, in_signature="", out_signature="i")
def getPowerState(self):
intf = self.getInterface("power_control")
return intf.getPowerState()
# Signal handler
def power_button_signal_handler(self):
# toggle power, power-on / soft-power-off
state = self.getPowerState()
if state == POWER_OFF:
self.powerOn()
elif state == POWER_ON:
self.softPowerOff()
def long_power_button_signal_handler(self):
print("Long-press button, hard power off")
self.powerOff()
def softreset_button_signal_handler(self):
self.softReboot()
def host_watchdog_signal_handler(self):
print("Watchdog Error, Going to quiesce")
self.quiesce()
if __name__ == "__main__":
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = get_dbus()
obj = ChassisControlObject(bus, OBJ_NAME)
mainloop = gobject.MainLoop()
obj.unmask_signals()
name = dbus.service.BusName(DBUS_NAME, bus)
print("Running ChassisControlService")
mainloop.run()
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4