blob: b02be024c69a78b58b38bf91837359e1c742ae86 [file] [log] [blame]
Norman James42c1be82015-10-22 14:34:26 -05001#!/usr/bin/python -u
Norman James89de9162015-08-27 21:41:36 -05002
Norman James471ab592015-08-30 22:29:40 -05003import sys
Yi Li03a8b1c2016-08-18 17:08:13 +08004import signal
Norman James89de9162015-08-27 21:41:36 -05005import subprocess
Norman James6f8d0422015-09-14 18:48:00 -05006import gobject
Norman James89de9162015-08-27 21:41:36 -05007import dbus
8import dbus.service
9import dbus.mainloop.glib
Norman James90baede2015-09-02 20:32:49 -050010import os
Brad Bishopee1b1542016-05-12 16:55:00 -040011import obmc.dbuslib.propertycacher as PropertyCacher
Brad Bishop84e73b52016-05-12 15:57:52 -040012from obmc.dbuslib.bindings import DbusProperties, DbusObjectManager, get_dbus
13import obmc.enums
Brad Bishop0b380f72016-06-10 00:29:50 -040014import obmc_system_config as System
Brad Bishopfa736492016-06-29 22:21:49 -040015import obmc.dbuslib.introspection
16import obmc.utils.misc
Brad Bishop6173a892016-07-24 10:04:09 -040017import obmc.mapper.utils
Norman James89de9162015-08-27 21:41:36 -050018
19DBUS_NAME = 'org.openbmc.managers.System'
20OBJ_NAME = '/org/openbmc/managers/System'
Norman James66c02692015-10-15 10:23:12 -050021INTF_SENSOR = 'org.openbmc.SensorValue'
22INTF_ITEM = 'org.openbmc.InventoryItem'
Norman Jamesa3e47c42015-10-18 14:43:10 -050023INTF_CONTROL = 'org.openbmc.Control'
Norman James89de9162015-08-27 21:41:36 -050024
Norman Jamescf74f952015-10-28 12:45:18 -050025
Brad Bishop416539d2016-07-22 07:22:42 -040026class SystemManager(DbusProperties, DbusObjectManager):
27 def __init__(self, bus, obj_name):
28 DbusProperties.__init__(self)
29 DbusObjectManager.__init__(self)
30 dbus.service.Object.__init__(self, bus, obj_name)
31 self.bus = bus
Norman James9e6acf92015-09-08 07:00:04 -050032
Brad Bishop416539d2016-07-22 07:22:42 -040033 bus.add_signal_receiver(
Brad Bishop416539d2016-07-22 07:22:42 -040034 self.NewObjectHandler,
35 signal_name="InterfacesAdded", sender_keyword='bus_name')
36 bus.add_signal_receiver(
37 self.SystemStateHandler, signal_name="GotoSystemState")
Norman James88872672015-09-21 16:51:35 -050038
Brad Bishop416539d2016-07-22 07:22:42 -040039 self.Set(DBUS_NAME, "current_state", "")
40 self.system_states = {}
Brad Bishop416539d2016-07-22 07:22:42 -040041 self.bin_path = os.path.dirname(os.path.realpath(sys.argv[0]))
Norman Jamesc36372d2015-10-08 07:03:07 -050042
Brad Bishop416539d2016-07-22 07:22:42 -040043 for name in System.APPS.keys():
44 sys_state = System.APPS[name]['system_state']
45 if sys_state not in self.system_states:
46 self.system_states[sys_state] = []
47 self.system_states[sys_state].append(name)
Norman Jamescfc2b442015-10-31 17:31:46 -050048
Brad Bishop416539d2016-07-22 07:22:42 -040049 ## replace symbolic path in ID_LOOKUP
50 for category in System.ID_LOOKUP:
51 for key in System.ID_LOOKUP[category]:
52 val = System.ID_LOOKUP[category][key]
53 new_val = val.replace(
54 "<inventory_root>", System.INVENTORY_ROOT)
55 System.ID_LOOKUP[category][key] = new_val
Norman Jamescfc2b442015-10-31 17:31:46 -050056
Brad Bishop416539d2016-07-22 07:22:42 -040057 self.SystemStateHandler(System.SYSTEM_STATES[0])
Brad Bishopfa736492016-06-29 22:21:49 -040058
Brad Bishop416539d2016-07-22 07:22:42 -040059 print "SystemManager Init Done"
Brad Bishop4de42642016-06-29 21:55:47 -040060
Brad Bishop416539d2016-07-22 07:22:42 -040061 def SystemStateHandler(self, state_name):
Brad Bishop416539d2016-07-22 07:22:42 -040062 print "Running System State: "+state_name
63 if state_name in self.system_states:
64 for name in self.system_states[state_name]:
65 self.start_process(name)
Norman James471ab592015-08-30 22:29:40 -050066
Brad Bishop416539d2016-07-22 07:22:42 -040067 try:
68 cb = System.ENTER_STATE_CALLBACK[state_name]
69 for methd in cb.keys():
70 obj = bus.get_object(
71 cb[methd]['bus_name'],
72 cb[methd]['obj_name'],
73 introspect=False)
74 method = obj.get_dbus_method(
75 methd, cb[methd]['interface_name'])
76 method()
77 except:
78 pass
Norman James7aeefa72015-10-19 11:13:25 -050079
Brad Bishop416539d2016-07-22 07:22:42 -040080 self.Set(DBUS_NAME, "current_state", state_name)
Norman Jamesd9f1d4e2015-10-14 09:40:18 -050081
Brad Bishop6173a892016-07-24 10:04:09 -040082 waitlist = System.EXIT_STATE_DEPEND.get(state_name, {}).keys()
83 if waitlist:
84 self.waiter = obmc.mapper.utils.Wait(
85 self.bus, waitlist,
86 callback=self.gotoNextState)
87
Brad Bishop416539d2016-07-22 07:22:42 -040088 def gotoNextState(self):
89 s = 0
90 current_state = self.Get(DBUS_NAME, "current_state")
91 for i in range(len(System.SYSTEM_STATES)):
92 if (System.SYSTEM_STATES[i] == current_state):
93 s = i+1
Norman Jamesd9f1d4e2015-10-14 09:40:18 -050094
Brad Bishop416539d2016-07-22 07:22:42 -040095 if (s == len(System.SYSTEM_STATES)):
96 print "ERROR SystemManager: No more system states"
97 else:
98 new_state_name = System.SYSTEM_STATES[s]
99 print "SystemManager Goto System State: "+new_state_name
100 self.SystemStateHandler(new_state_name)
Norman James7aeefa72015-10-19 11:13:25 -0500101
Brad Bishop416539d2016-07-22 07:22:42 -0400102 @dbus.service.method(DBUS_NAME, in_signature='', out_signature='s')
103 def getSystemState(self):
104 return self.Get(DBUS_NAME, "current_state")
Yi Li5cf1e112016-04-15 15:30:30 +0800105
Brad Bishop416539d2016-07-22 07:22:42 -0400106 def doObjectLookup(self, category, key):
Brad Bishop416539d2016-07-22 07:22:42 -0400107 obj_path = ""
108 intf_name = INTF_ITEM
109 try:
110 obj_path = System.ID_LOOKUP[category][key]
Brad Bishop416539d2016-07-22 07:22:42 -0400111 parts = obj_path.split('/')
112 if (parts[3] == 'sensors'):
113 intf_name = INTF_SENSOR
114 except Exception as e:
115 print "ERROR SystemManager: "+str(e)+" not found in lookup"
Yi Li5cf1e112016-04-15 15:30:30 +0800116
Brad Bishopfc38a572016-07-22 08:56:09 -0400117 return [obj_path, intf_name]
Norman James471ab592015-08-30 22:29:40 -0500118
Brad Bishopfc38a572016-07-22 08:56:09 -0400119 @dbus.service.method(DBUS_NAME, in_signature='ss', out_signature='(ss)')
Brad Bishop416539d2016-07-22 07:22:42 -0400120 def getObjectFromId(self, category, key):
121 return self.doObjectLookup(category, key)
Norman James89de9162015-08-27 21:41:36 -0500122
Brad Bishopfc38a572016-07-22 08:56:09 -0400123 @dbus.service.method(DBUS_NAME, in_signature='sy', out_signature='(ss)')
Brad Bishop416539d2016-07-22 07:22:42 -0400124 def getObjectFromByteId(self, category, key):
125 byte = int(key)
126 return self.doObjectLookup(category, byte)
Brad Bishopfa736492016-06-29 22:21:49 -0400127
Brad Bishop416539d2016-07-22 07:22:42 -0400128 # Get the FRU area names defined in ID_LOOKUP table given a fru_id.
129 # If serval areas are defined for a fru_id, the areas are returned
130 # together as a string with each area name seperated with ','.
131 # If no fru area defined in ID_LOOKUP, an empty string will be returned.
132 @dbus.service.method(DBUS_NAME, in_signature='y', out_signature='s')
133 def getFRUArea(self, fru_id):
134 ret_str = ''
135 fru_id = '_' + str(fru_id)
136 area_list = [
137 area for area in System.ID_LOOKUP['FRU_STR'].keys()
138 if area.endswith(fru_id)]
139 for area in area_list:
140 ret_str = area + ',' + ret_str
141 # remove the last ','
142 return ret_str[:-1]
Brad Bishopfa736492016-06-29 22:21:49 -0400143
Brad Bishop416539d2016-07-22 07:22:42 -0400144 def start_process(self, name):
145 if System.APPS[name]['start_process']:
146 app = System.APPS[name]
147 process_name = self.bin_path+"/"+app['process_name']
148 cmdline = []
149 cmdline.append(process_name)
150 if 'args' in app:
151 for a in app['args']:
152 cmdline.append(a)
153 try:
154 print "Starting process: "+" ".join(cmdline)+": "+name
155 if app['monitor_process']:
156 app['popen'] = subprocess.Popen(cmdline)
157 else:
158 subprocess.Popen(cmdline)
Brad Bishopfa736492016-06-29 22:21:49 -0400159
Brad Bishop416539d2016-07-22 07:22:42 -0400160 except Exception as e:
161 ## TODO: error
162 print "ERROR: starting process: "+" ".join(cmdline)
Brad Bishopfa736492016-06-29 22:21:49 -0400163
Brad Bishop416539d2016-07-22 07:22:42 -0400164 def NewObjectHandler(self, obj_path, iprops, bus_name=None):
165 current_state = self.Get(DBUS_NAME, "current_state")
Brad Bishop416539d2016-07-22 07:22:42 -0400166 if current_state not in System.EXIT_STATE_DEPEND:
167 return
168
169 if obj_path in System.EXIT_STATE_DEPEND[current_state]:
170 print "New object: "+obj_path+" ("+bus_name+")"
Brad Bishop416539d2016-07-22 07:22:42 -0400171
172 @dbus.service.method(DBUS_NAME, in_signature='s', out_signature='sis')
173 def gpioInit(self, name):
174 gpio_path = ''
175 gpio_num = -1
176 r = ['', gpio_num, '']
177 if name not in System.GPIO_CONFIG:
178 # TODO: Error handling
179 print "ERROR: "+name+" not found in GPIO config table"
180 else:
181
182 gpio_num = -1
183 gpio = System.GPIO_CONFIG[name]
184 if 'gpio_num' in System.GPIO_CONFIG[name]:
185 gpio_num = gpio['gpio_num']
186 else:
187 if 'gpio_pin' in System.GPIO_CONFIG[name]:
188 gpio_num = System.convertGpio(gpio['gpio_pin'])
189 else:
190 print "ERROR: SystemManager - GPIO lookup failed for "+name
191
192 if (gpio_num != -1):
193 r = [obmc.enums.GPIO_DEV, gpio_num, gpio['direction']]
194 return r
195
Norman James89de9162015-08-27 21:41:36 -0500196
197if __name__ == '__main__':
Yi Li03a8b1c2016-08-18 17:08:13 +0800198 # Ignore SIGCHLD signal, to prevent child process becoming zombie
199 signal.signal(signal.SIGCHLD, signal.SIG_IGN)
Norman James89de9162015-08-27 21:41:36 -0500200 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
Brad Bishop84e73b52016-05-12 15:57:52 -0400201 bus = get_dbus()
Brad Bishop416539d2016-07-22 07:22:42 -0400202 obj = SystemManager(bus, OBJ_NAME)
Norman James6f8d0422015-09-14 18:48:00 -0500203 mainloop = gobject.MainLoop()
Brad Bishopf0f3efe2016-06-29 23:20:24 -0400204 obj.unmask_signals()
Brad Bishop416539d2016-07-22 07:22:42 -0400205 name = dbus.service.BusName(DBUS_NAME, bus)
Norman James89de9162015-08-27 21:41:36 -0500206
Norman James89de9162015-08-27 21:41:36 -0500207 print "Running SystemManager"
208 mainloop.run()