1de6ed120SBrad Bishop#!/usr/bin/env python
240a360c2SBrad Bishop
340a360c2SBrad Bishopimport gobject
440a360c2SBrad Bishopimport dbus
540a360c2SBrad Bishopimport dbus.service
640a360c2SBrad Bishopimport dbus.mainloop.glib
740a360c2SBrad Bishopimport os
840a360c2SBrad Bishopimport obmc.dbuslib.propertycacher as PropertyCacher
940a360c2SBrad Bishopfrom obmc.dbuslib.bindings import DbusProperties, DbusObjectManager, get_dbus
1040a360c2SBrad Bishopimport obmc.enums
110b380f7bSBrad Bishopimport obmc_system_config as System
126173a896SBrad Bishopimport obmc.mapper.utils
137e5ec46dSBrad Bishopimport obmc.inventory
14a7ac805bSBrad Bishopimport obmc.system
1540a360c2SBrad Bishop
1640a360c2SBrad BishopDBUS_NAME = 'org.openbmc.managers.System'
1740a360c2SBrad BishopOBJ_NAME = '/org/openbmc/managers/System'
1840a360c2SBrad BishopINTF_SENSOR = 'org.openbmc.SensorValue'
1940a360c2SBrad BishopINTF_ITEM = 'org.openbmc.InventoryItem'
2040a360c2SBrad Bishop
21*520f8b05SRatan GuptaSYS_STATE_FILE = '/var/lib/obmc/last-system-state'
22*520f8b05SRatan GuptaPOWER_OFF = "0"
23*520f8b05SRatan Gupta
2440a360c2SBrad Bishop
2540a360c2SBrad Bishopclass SystemManager(DbusProperties, DbusObjectManager):
2640a360c2SBrad Bishop    def __init__(self, bus, obj_name):
27f47f5faaSBrad Bishop        super(SystemManager, self).__init__(
28f47f5faaSBrad Bishop            conn=bus,
29f47f5faaSBrad Bishop            object_path=obj_name)
30fa736499SBrad Bishop        self.bus = bus
3140a360c2SBrad Bishop
32fa736499SBrad Bishop        bus.add_signal_receiver(
33416539dfSBrad Bishop            self.NewObjectHandler,
3440a360c2SBrad Bishop            signal_name="InterfacesAdded", sender_keyword='bus_name')
35416539dfSBrad Bishop        bus.add_signal_receiver(
36416539dfSBrad Bishop            self.SystemStateHandler, signal_name="GotoSystemState")
3740a360c2SBrad Bishop
38*520f8b05SRatan Gupta        bus.add_signal_receiver(
39*520f8b05SRatan Gupta            self.chassisPowerStateHandler,
40*520f8b05SRatan Gupta            dbus_interface="org.freedesktop.DBus.Properties",
41*520f8b05SRatan Gupta            signal_name="PropertiesChanged",
42*520f8b05SRatan Gupta            path="/org/openbmc/control/power0")
4340a360c2SBrad Bishop
44*520f8b05SRatan Gupta        self.Set(DBUS_NAME, "current_state", "")
45*520f8b05SRatan Gupta        self.Set(DBUS_NAME, "system_last_state", POWER_OFF)
46*520f8b05SRatan Gupta        self.import_system_state_from_disk()
47*520f8b05SRatan Gupta        # replace symbolic path in ID_LOOKUP
4840a360c2SBrad Bishop        for category in System.ID_LOOKUP:
4940a360c2SBrad Bishop            for key in System.ID_LOOKUP[category]:
5040a360c2SBrad Bishop                val = System.ID_LOOKUP[category][key]
51416539dfSBrad Bishop                new_val = val.replace(
527e5ec46dSBrad Bishop                    "<inventory_root>", obmc.inventory.INVENTORY_ROOT)
5340a360c2SBrad Bishop                System.ID_LOOKUP[category][key] = new_val
5440a360c2SBrad Bishop
5540a360c2SBrad Bishop        self.SystemStateHandler(System.SYSTEM_STATES[0])
5640a360c2SBrad Bishop
5740a360c2SBrad Bishop        print "SystemManager Init Done"
5840a360c2SBrad Bishop
59*520f8b05SRatan Gupta    def chassisPowerStateHandler(self, interface_name, changed_properties,
60*520f8b05SRatan Gupta                                 invalidated_properties):
61*520f8b05SRatan Gupta        value = changed_properties.get('state')
62*520f8b05SRatan Gupta        if value is not None:
63*520f8b05SRatan Gupta            self.write_to_disk_and_update(str(value))
64*520f8b05SRatan Gupta
6540a360c2SBrad Bishop    def SystemStateHandler(self, state_name):
6640a360c2SBrad Bishop        print "Running System State: "+state_name
6740a360c2SBrad Bishop
6840a360c2SBrad Bishop        self.Set(DBUS_NAME, "current_state", state_name)
6940a360c2SBrad Bishop
706173a896SBrad Bishop        waitlist = System.EXIT_STATE_DEPEND.get(state_name, {}).keys()
716173a896SBrad Bishop        if waitlist:
726173a896SBrad Bishop            self.waiter = obmc.mapper.utils.Wait(
736173a896SBrad Bishop                self.bus, waitlist,
746173a896SBrad Bishop                callback=self.gotoNextState)
756173a896SBrad Bishop
7640a360c2SBrad Bishop    def gotoNextState(self):
7740a360c2SBrad Bishop        s = 0
7840a360c2SBrad Bishop        current_state = self.Get(DBUS_NAME, "current_state")
7940a360c2SBrad Bishop        for i in range(len(System.SYSTEM_STATES)):
8040a360c2SBrad Bishop            if (System.SYSTEM_STATES[i] == current_state):
8140a360c2SBrad Bishop                s = i+1
8240a360c2SBrad Bishop
8340a360c2SBrad Bishop        if (s == len(System.SYSTEM_STATES)):
8440a360c2SBrad Bishop            print "ERROR SystemManager: No more system states"
8540a360c2SBrad Bishop        else:
8640a360c2SBrad Bishop            new_state_name = System.SYSTEM_STATES[s]
8740a360c2SBrad Bishop            print "SystemManager Goto System State: "+new_state_name
8840a360c2SBrad Bishop            self.SystemStateHandler(new_state_name)
8940a360c2SBrad Bishop
90*520f8b05SRatan Gupta    def import_system_state_from_disk(self):
91*520f8b05SRatan Gupta        state = str(POWER_OFF)
92*520f8b05SRatan Gupta        try:
93*520f8b05SRatan Gupta            with open(SYS_STATE_FILE, 'r+') as f:
94*520f8b05SRatan Gupta                state = f.readline().rstrip('\n')
95*520f8b05SRatan Gupta        except IOError:
96*520f8b05SRatan Gupta            pass
97*520f8b05SRatan Gupta        self.Set(DBUS_NAME, "system_last_state", state)
98*520f8b05SRatan Gupta        return state
99*520f8b05SRatan Gupta
100*520f8b05SRatan Gupta    def write_to_disk_and_update(self, state):
101*520f8b05SRatan Gupta        try:
102*520f8b05SRatan Gupta            with open(SYS_STATE_FILE, 'w+') as f:
103*520f8b05SRatan Gupta                f.write(str(state))
104*520f8b05SRatan Gupta                self.Set(DBUS_NAME, "system_last_state", state)
105*520f8b05SRatan Gupta        except IOError:
106*520f8b05SRatan Gupta            pass
107*520f8b05SRatan Gupta
108416539dfSBrad Bishop    @dbus.service.method(DBUS_NAME, in_signature='', out_signature='s')
10940a360c2SBrad Bishop    def getSystemState(self):
11040a360c2SBrad Bishop        return self.Get(DBUS_NAME, "current_state")
11140a360c2SBrad Bishop
11240a360c2SBrad Bishop    def doObjectLookup(self, category, key):
11340a360c2SBrad Bishop        obj_path = ""
11440a360c2SBrad Bishop        intf_name = INTF_ITEM
11540a360c2SBrad Bishop        try:
11640a360c2SBrad Bishop            obj_path = System.ID_LOOKUP[category][key]
11740a360c2SBrad Bishop            parts = obj_path.split('/')
11840a360c2SBrad Bishop            if (parts[3] == 'sensors'):
11940a360c2SBrad Bishop                intf_name = INTF_SENSOR
12040a360c2SBrad Bishop        except Exception as e:
12140a360c2SBrad Bishop            print "ERROR SystemManager: "+str(e)+" not found in lookup"
12240a360c2SBrad Bishop
123fc38a575SBrad Bishop        return [obj_path, intf_name]
12440a360c2SBrad Bishop
125fc38a575SBrad Bishop    @dbus.service.method(DBUS_NAME, in_signature='ss', out_signature='(ss)')
12640a360c2SBrad Bishop    def getObjectFromId(self, category, key):
12740a360c2SBrad Bishop        return self.doObjectLookup(category, key)
12840a360c2SBrad Bishop
129fc38a575SBrad Bishop    @dbus.service.method(DBUS_NAME, in_signature='sy', out_signature='(ss)')
13040a360c2SBrad Bishop    def getObjectFromByteId(self, category, key):
13140a360c2SBrad Bishop        byte = int(key)
13240a360c2SBrad Bishop        return self.doObjectLookup(category, byte)
13340a360c2SBrad Bishop
13440a360c2SBrad Bishop    # Get the FRU area names defined in ID_LOOKUP table given a fru_id.
13540a360c2SBrad Bishop    # If serval areas are defined for a fru_id, the areas are returned
13640a360c2SBrad Bishop    # together as a string with each area name seperated with ','.
13740a360c2SBrad Bishop    # If no fru area defined in ID_LOOKUP, an empty string will be returned.
138416539dfSBrad Bishop    @dbus.service.method(DBUS_NAME, in_signature='y', out_signature='s')
13940a360c2SBrad Bishop    def getFRUArea(self, fru_id):
14040a360c2SBrad Bishop        ret_str = ''
14140a360c2SBrad Bishop        fru_id = '_' + str(fru_id)
142416539dfSBrad Bishop        area_list = [
143416539dfSBrad Bishop            area for area in System.ID_LOOKUP['FRU_STR'].keys()
14440a360c2SBrad Bishop            if area.endswith(fru_id)]
14540a360c2SBrad Bishop        for area in area_list:
14640a360c2SBrad Bishop            ret_str = area + ',' + ret_str
14740a360c2SBrad Bishop        # remove the last ','
14840a360c2SBrad Bishop        return ret_str[:-1]
14940a360c2SBrad Bishop
15040a360c2SBrad Bishop    def NewObjectHandler(self, obj_path, iprops, bus_name=None):
15140a360c2SBrad Bishop        current_state = self.Get(DBUS_NAME, "current_state")
1524de42643SBrad Bishop        if current_state not in System.EXIT_STATE_DEPEND:
1534de42643SBrad Bishop            return
15440a360c2SBrad Bishop
1554de42643SBrad Bishop        if obj_path in System.EXIT_STATE_DEPEND[current_state]:
1564de42643SBrad Bishop            print "New object: "+obj_path+" ("+bus_name+")"
15740a360c2SBrad Bishop
158416539dfSBrad Bishop    @dbus.service.method(DBUS_NAME, in_signature='s', out_signature='sis')
15940a360c2SBrad Bishop    def gpioInit(self, name):
16040a360c2SBrad Bishop        gpio_path = ''
16140a360c2SBrad Bishop        gpio_num = -1
16240a360c2SBrad Bishop        r = ['', gpio_num, '']
163416539dfSBrad Bishop        if name not in System.GPIO_CONFIG:
16440a360c2SBrad Bishop            # TODO: Error handling
16540a360c2SBrad Bishop            print "ERROR: "+name+" not found in GPIO config table"
16640a360c2SBrad Bishop        else:
16740a360c2SBrad Bishop
16840a360c2SBrad Bishop            gpio_num = -1
16940a360c2SBrad Bishop            gpio = System.GPIO_CONFIG[name]
170416539dfSBrad Bishop            if 'gpio_num' in System.GPIO_CONFIG[name]:
17140a360c2SBrad Bishop                gpio_num = gpio['gpio_num']
17240a360c2SBrad Bishop            else:
173416539dfSBrad Bishop                if 'gpio_pin' in System.GPIO_CONFIG[name]:
174a7ac805bSBrad Bishop                    gpio_num = obmc.system.convertGpio(gpio['gpio_pin'])
17540a360c2SBrad Bishop                else:
17640a360c2SBrad Bishop                    print "ERROR: SystemManager - GPIO lookup failed for "+name
17740a360c2SBrad Bishop
17840a360c2SBrad Bishop            if (gpio_num != -1):
17940a360c2SBrad Bishop                r = [obmc.enums.GPIO_DEV, gpio_num, gpio['direction']]
18040a360c2SBrad Bishop        return r
18140a360c2SBrad Bishop
18240a360c2SBrad Bishop
18340a360c2SBrad Bishopif __name__ == '__main__':
18440a360c2SBrad Bishop    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
18540a360c2SBrad Bishop    bus = get_dbus()
18640a360c2SBrad Bishop    obj = SystemManager(bus, OBJ_NAME)
18740a360c2SBrad Bishop    mainloop = gobject.MainLoop()
188f0f3efe1SBrad Bishop    obj.unmask_signals()
18970852a38SBrad Bishop    name = dbus.service.BusName(DBUS_NAME, bus)
19040a360c2SBrad Bishop
19140a360c2SBrad Bishop    print "Running SystemManager"
19240a360c2SBrad Bishop    mainloop.run()
19353066750SBrad Bishop
19453066750SBrad Bishop# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
195