1#!/usr/bin/env python 2 3# 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 8import dbus 9import dbus.service 10import dbus.mainloop.glib 11from obmc.dbuslib.bindings import get_dbus, DbusProperties, DbusObjectManager 12 13DBUS_NAME = 'org.openbmc.control.Chassis' 14OBJ_NAME = '/org/openbmc/control/chassis0' 15CONTROL_INTF = 'org.openbmc.Control' 16 17MACHINE_ID = '/etc/machine-id' 18 19POWER_OFF = 0 20POWER_ON = 1 21 22BOOTED = 100 23 24 25class ChassisControlObject(DbusProperties, DbusObjectManager): 26 def getUuid(self): 27 uuid = "" 28 try: 29 with open(MACHINE_ID) as f: 30 data = f.readline().rstrip('\n') 31 if (len(data) == 32): 32 uuid = data 33 else: 34 print("ERROR: UUID is not formatted correctly: " + data) 35 except Exception: 36 print("ERROR: Unable to open uuid file: " + MACHINE_ID) 37 38 return uuid 39 40 def __init__(self, bus, name): 41 super(ChassisControlObject, self).__init__( 42 conn=bus, 43 object_path=name) 44 # load utilized objects 45 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 }, 51 'host_services': { 52 'bus_name': 'org.openbmc.HostServices', 53 'object_name': '/org/openbmc/HostServices', 54 'interface_name': 'org.openbmc.HostServices' 55 }, 56 'systemd': { 57 'bus_name': 'org.freedesktop.systemd1', 58 'object_name': '/org/freedesktop/systemd1', 59 'interface_name': 'org.freedesktop.systemd1.Manager' 60 }, 61 } 62 63 # uuid 64 self.Set(DBUS_NAME, "uuid", self.getUuid()) 65 self.Set(DBUS_NAME, "reboot", 0) 66 67 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") 71 bus.add_signal_receiver(self.long_power_button_signal_handler, 72 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 84 85 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']) 89 90 @dbus.service.method(DBUS_NAME, 91 in_signature='', out_signature='') 92 def powerOn(self): 93 print("Turn on power and boot") 94 self.Set(DBUS_NAME, "reboot", 0) 95 intf = self.getInterface('systemd') 96 f = getattr(intf, 'StartUnit') 97 f.call_async('obmc-host-start@0.target', 'replace') 98 return None 99 100 @dbus.service.method(DBUS_NAME, 101 in_signature='', out_signature='') 102 def powerOff(self): 103 print("Turn off power") 104 intf = self.getInterface('systemd') 105 f = getattr(intf, 'StartUnit') 106 f.call_async('obmc-chassis-hard-poweroff@0.target', 'replace') 107 return None 108 109 @dbus.service.method(DBUS_NAME, 110 in_signature='', out_signature='') 111 def softPowerOff(self): 112 print("Soft off power") 113 intf = self.getInterface('systemd') 114 f = getattr(intf, 'StartUnit') 115 f.call_async('obmc-host-shutdown@0.target', 'replace') 116 return None 117 118 @dbus.service.method(DBUS_NAME, 119 in_signature='', out_signature='') 120 def reboot(self): 121 print("Rebooting") 122 if self.getPowerState() != POWER_OFF: 123 self.Set(DBUS_NAME, "reboot", 1) 124 self.powerOff() 125 return None 126 127 @dbus.service.method(DBUS_NAME, 128 in_signature='', out_signature='') 129 def softReboot(self): 130 print("Soft Rebooting") 131 if self.getPowerState() != POWER_OFF: 132 self.Set(DBUS_NAME, "reboot", 1) 133 self.softPowerOff() 134 return None 135 136 @dbus.service.method(DBUS_NAME, 137 in_signature='', out_signature='') 138 def quiesce(self): 139 intf = self.getInterface('systemd') 140 f = getattr(intf, 'StartUnit') 141 f.call_async('obmc-host-quiesce@0.target', 'replace') 142 return None 143 144 @dbus.service.method(DBUS_NAME, 145 in_signature='', out_signature='i') 146 def getPowerState(self): 147 intf = self.getInterface('power_control') 148 return intf.getPowerState() 149 150 # Signal handler 151 152 def power_button_signal_handler(self): 153 # toggle power, power-on / soft-power-off 154 state = self.getPowerState() 155 if state == POWER_OFF: 156 self.powerOn() 157 elif state == POWER_ON: 158 self.softPowerOff() 159 160 def long_power_button_signal_handler(self): 161 print("Long-press button, hard power off") 162 self.powerOff() 163 164 def softreset_button_signal_handler(self): 165 self.softReboot() 166 167 def host_watchdog_signal_handler(self): 168 print("Watchdog Error, Going to quiesce") 169 self.quiesce() 170 171 172if __name__ == '__main__': 173 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) 174 175 bus = get_dbus() 176 obj = ChassisControlObject(bus, OBJ_NAME) 177 mainloop = gobject.MainLoop() 178 179 obj.unmask_signals() 180 name = dbus.service.BusName(DBUS_NAME, bus) 181 182 print("Running ChassisControlService") 183 mainloop.run() 184 185# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 186