1#!/usr/bin/env python
2
3import gobject
4import dbus
5import dbus.service
6import dbus.mainloop.glib
7from obmc.dbuslib.bindings import get_dbus, DbusProperties, DbusObjectManager
8
9DBUS_NAME = 'org.openbmc.control.Chassis'
10OBJ_NAME = '/org/openbmc/control/chassis0'
11CONTROL_INTF = 'org.openbmc.Control'
12
13MACHINE_ID = '/etc/machine-id'
14
15POWER_OFF = 0
16POWER_ON = 1
17
18BOOTED = 100
19
20
21class ChassisControlObject(DbusProperties, DbusObjectManager):
22    def getUuid(self):
23        uuid = ""
24        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 Exception:
32            print "ERROR: Unable to open uuid file: " + MACHINE_ID
33
34        return uuid
35
36    def __init__(self, bus, name):
37        super(ChassisControlObject, self).__init__(
38            conn=bus,
39            object_path=name)
40        # 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            },
47            'host_services': {
48                'bus_name': 'org.openbmc.HostServices',
49                'object_name': '/org/openbmc/HostServices',
50                'interface_name': 'org.openbmc.HostServices'
51            },
52            'systemd': {
53                'bus_name': 'org.freedesktop.systemd1',
54                'object_name': '/org/freedesktop/systemd1',
55                'interface_name': 'org.freedesktop.systemd1.Manager'
56            },
57        }
58
59        # uuid
60        self.Set(DBUS_NAME, "uuid", self.getUuid())
61        self.Set(DBUS_NAME, "reboot", 0)
62
63        bus.add_signal_receiver(self.power_button_signal_handler,
64                                dbus_interface="org.openbmc.Button",
65                                signal_name="Released",
66                                path="/org/openbmc/buttons/power0")
67        bus.add_signal_receiver(self.long_power_button_signal_handler,
68                                dbus_interface="org.openbmc.Button",
69                                signal_name="PressedLong",
70                                path="/org/openbmc/buttons/power0")
71        bus.add_signal_receiver(self.softreset_button_signal_handler,
72                                dbus_interface="org.openbmc.Button",
73                                signal_name="Released",
74                                path="/org/openbmc/buttons/reset0")
75
76        bus.add_signal_receiver(self.host_watchdog_signal_handler,
77                                dbus_interface="org.openbmc.Watchdog",
78                                signal_name="WatchdogError")
79
80
81    def getInterface(self, name):
82        o = self.dbus_objects[name]
83        obj = bus.get_object(o['bus_name'], o['object_name'], introspect=False)
84        return dbus.Interface(obj, o['interface_name'])
85
86    @dbus.service.method(DBUS_NAME,
87                         in_signature='', out_signature='')
88    def powerOn(self):
89        print "Turn on power and boot"
90        self.Set(DBUS_NAME, "reboot", 0)
91        intf = self.getInterface('systemd')
92        f = getattr(intf, 'StartUnit')
93        f.call_async('obmc-host-start@0.target', 'replace')
94        return None
95
96    @dbus.service.method(DBUS_NAME,
97                         in_signature='', out_signature='')
98    def powerOff(self):
99        print "Turn off power"
100        intf = self.getInterface('systemd')
101        f = getattr(intf, 'StartUnit')
102        f.call_async('obmc-chassis-hard-poweroff@0.target', 'replace')
103        return None
104
105    @dbus.service.method(DBUS_NAME,
106                         in_signature='', out_signature='')
107    def softPowerOff(self):
108        print "Soft off power"
109        intf = self.getInterface('systemd')
110        f = getattr(intf, 'StartUnit')
111        f.call_async('obmc-host-shutdown@0.target', 'replace')
112        return None
113
114    @dbus.service.method(DBUS_NAME,
115                         in_signature='', out_signature='')
116    def reboot(self):
117        print "Rebooting"
118        if self.getPowerState() == POWER_OFF:
119            self.powerOn()
120        else:
121            self.Set(DBUS_NAME, "reboot", 1)
122            self.powerOff()
123        return None
124
125    @dbus.service.method(DBUS_NAME,
126                         in_signature='', out_signature='')
127    def softReboot(self):
128        print "Soft Rebooting"
129        if self.getPowerState() == POWER_OFF:
130            self.powerOn()
131        else:
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