140a360c2SBrad Bishop#!/usr/bin/python -u 240a360c2SBrad Bishop 340a360c2SBrad Bishopimport sys 440a360c2SBrad Bishopimport subprocess 540a360c2SBrad Bishopimport gobject 640a360c2SBrad Bishopimport dbus 740a360c2SBrad Bishopimport dbus.service 840a360c2SBrad Bishopimport dbus.mainloop.glib 940a360c2SBrad Bishopimport os 1040a360c2SBrad Bishopimport time 1140a360c2SBrad Bishopimport obmc.dbuslib.propertycacher as PropertyCacher 1240a360c2SBrad Bishopfrom obmc.dbuslib.bindings import DbusProperties, DbusObjectManager, get_dbus 1340a360c2SBrad Bishopimport obmc.enums 140b380f7bSBrad Bishopimport obmc_system_config as System 1540a360c2SBrad Bishop 1640a360c2SBrad BishopDBUS_NAME = 'org.openbmc.managers.System' 1740a360c2SBrad BishopOBJ_NAME = '/org/openbmc/managers/System' 1840a360c2SBrad BishopHEARTBEAT_CHECK_INTERVAL = 20000 1940a360c2SBrad BishopSTATE_START_TIMEOUT = 10 2040a360c2SBrad BishopINTF_SENSOR = 'org.openbmc.SensorValue' 2140a360c2SBrad BishopINTF_ITEM = 'org.openbmc.InventoryItem' 2240a360c2SBrad BishopINTF_CONTROL = 'org.openbmc.Control' 2340a360c2SBrad Bishop 2440a360c2SBrad Bishop 2540a360c2SBrad Bishopclass SystemManager(DbusProperties,DbusObjectManager): 2640a360c2SBrad Bishop def __init__(self,bus,obj_name): 2740a360c2SBrad Bishop DbusProperties.__init__(self) 2840a360c2SBrad Bishop DbusObjectManager.__init__(self) 2940a360c2SBrad Bishop dbus.service.Object.__init__(self,bus,obj_name) 3040a360c2SBrad Bishop 3140a360c2SBrad Bishop bus.add_signal_receiver(self.NewObjectHandler, 3240a360c2SBrad Bishop signal_name = "InterfacesAdded", sender_keyword = 'bus_name') 3340a360c2SBrad Bishop bus.add_signal_receiver(self.SystemStateHandler,signal_name = "GotoSystemState") 3440a360c2SBrad Bishop 3540a360c2SBrad Bishop self.Set(DBUS_NAME,"current_state","") 3640a360c2SBrad Bishop self.system_states = {} 3740a360c2SBrad Bishop self.bus_name_lookup = {} 3840a360c2SBrad Bishop self.bin_path = os.path.dirname(os.path.realpath(sys.argv[0])) 3940a360c2SBrad Bishop 4040a360c2SBrad Bishop for name in System.APPS.keys(): 4140a360c2SBrad Bishop sys_state = System.APPS[name]['system_state'] 4240a360c2SBrad Bishop if (self.system_states.has_key(sys_state) == False): 4340a360c2SBrad Bishop self.system_states[sys_state] = [] 4440a360c2SBrad Bishop self.system_states[sys_state].append(name) 4540a360c2SBrad Bishop 4640a360c2SBrad Bishop ## replace symbolic path in ID_LOOKUP 4740a360c2SBrad Bishop for category in System.ID_LOOKUP: 4840a360c2SBrad Bishop for key in System.ID_LOOKUP[category]: 4940a360c2SBrad Bishop val = System.ID_LOOKUP[category][key] 5040a360c2SBrad Bishop new_val = val.replace("<inventory_root>",System.INVENTORY_ROOT) 5140a360c2SBrad Bishop System.ID_LOOKUP[category][key] = new_val 5240a360c2SBrad Bishop 5340a360c2SBrad Bishop self.SystemStateHandler(System.SYSTEM_STATES[0]) 5440a360c2SBrad Bishop 5540a360c2SBrad Bishop if not os.path.exists(PropertyCacher.CACHE_PATH): 5640a360c2SBrad Bishop print "Creating cache directory: "+PropertyCacher.CACHE_PATH 5740a360c2SBrad Bishop os.makedirs(PropertyCacher.CACHE_PATH) 5840a360c2SBrad Bishop 5940a360c2SBrad Bishop self.InterfacesAdded(obj_name,self.properties) 6040a360c2SBrad Bishop print "SystemManager Init Done" 6140a360c2SBrad Bishop 6240a360c2SBrad Bishop 63*4de42643SBrad Bishop def try_next_state(self): 64*4de42643SBrad Bishop current_state = self.Get(DBUS_NAME,"current_state") 65*4de42643SBrad Bishop if current_state not in System.EXIT_STATE_DEPEND: 66*4de42643SBrad Bishop return 67*4de42643SBrad Bishop 68*4de42643SBrad Bishop if all(System.EXIT_STATE_DEPEND[current_state].values()): 69*4de42643SBrad Bishop print "All required objects started for "+current_state 70*4de42643SBrad Bishop self.gotoNextState() 71*4de42643SBrad Bishop 72*4de42643SBrad Bishop 7340a360c2SBrad Bishop def SystemStateHandler(self,state_name): 7440a360c2SBrad Bishop ## clearing object started flags 7540a360c2SBrad Bishop current_state = self.Get(DBUS_NAME,"current_state") 7640a360c2SBrad Bishop try: 7740a360c2SBrad Bishop for obj_path in System.EXIT_STATE_DEPEND[current_state]: 7840a360c2SBrad Bishop System.EXIT_STATE_DEPEND[current_state][obj_path] = 0 7940a360c2SBrad Bishop except: 8040a360c2SBrad Bishop pass 8140a360c2SBrad Bishop 8240a360c2SBrad Bishop print "Running System State: "+state_name 8340a360c2SBrad Bishop if (self.system_states.has_key(state_name)): 8440a360c2SBrad Bishop for name in self.system_states[state_name]: 8540a360c2SBrad Bishop self.start_process(name) 8640a360c2SBrad Bishop 8740a360c2SBrad Bishop if (state_name == "BMC_INIT"): 8840a360c2SBrad Bishop ## Add poll for heartbeat 8940a360c2SBrad Bishop gobject.timeout_add(HEARTBEAT_CHECK_INTERVAL, self.heartbeat_check) 9040a360c2SBrad Bishop 9140a360c2SBrad Bishop try: 9240a360c2SBrad Bishop cb = System.ENTER_STATE_CALLBACK[state_name] 9340a360c2SBrad Bishop for methd in cb.keys(): 9440a360c2SBrad Bishop obj = bus.get_object(cb[methd]['bus_name'],cb[methd]['obj_name'],introspect=False) 9540a360c2SBrad Bishop method = obj.get_dbus_method(methd,cb[methd]['interface_name']) 9640a360c2SBrad Bishop method() 9740a360c2SBrad Bishop except: 9840a360c2SBrad Bishop pass 9940a360c2SBrad Bishop 10040a360c2SBrad Bishop self.Set(DBUS_NAME,"current_state",state_name) 10140a360c2SBrad Bishop 10240a360c2SBrad Bishop def gotoNextState(self): 10340a360c2SBrad Bishop s = 0 10440a360c2SBrad Bishop current_state = self.Get(DBUS_NAME,"current_state") 10540a360c2SBrad Bishop for i in range(len(System.SYSTEM_STATES)): 10640a360c2SBrad Bishop if (System.SYSTEM_STATES[i] == current_state): 10740a360c2SBrad Bishop s = i+1 10840a360c2SBrad Bishop 10940a360c2SBrad Bishop if (s == len(System.SYSTEM_STATES)): 11040a360c2SBrad Bishop print "ERROR SystemManager: No more system states" 11140a360c2SBrad Bishop else: 11240a360c2SBrad Bishop new_state_name = System.SYSTEM_STATES[s] 11340a360c2SBrad Bishop print "SystemManager Goto System State: "+new_state_name 11440a360c2SBrad Bishop self.SystemStateHandler(new_state_name) 11540a360c2SBrad Bishop 11640a360c2SBrad Bishop 11740a360c2SBrad Bishop @dbus.service.method(DBUS_NAME, 11840a360c2SBrad Bishop in_signature='', out_signature='s') 11940a360c2SBrad Bishop def getSystemState(self): 12040a360c2SBrad Bishop return self.Get(DBUS_NAME,"current_state") 12140a360c2SBrad Bishop 12240a360c2SBrad Bishop def doObjectLookup(self,category,key): 12340a360c2SBrad Bishop bus_name = "" 12440a360c2SBrad Bishop obj_path = "" 12540a360c2SBrad Bishop intf_name = INTF_ITEM 12640a360c2SBrad Bishop try: 12740a360c2SBrad Bishop obj_path = System.ID_LOOKUP[category][key] 12840a360c2SBrad Bishop bus_name = self.bus_name_lookup[obj_path] 12940a360c2SBrad Bishop parts = obj_path.split('/') 13040a360c2SBrad Bishop if (parts[3] == 'sensors'): 13140a360c2SBrad Bishop intf_name = INTF_SENSOR 13240a360c2SBrad Bishop except Exception as e: 13340a360c2SBrad Bishop print "ERROR SystemManager: "+str(e)+" not found in lookup" 13440a360c2SBrad Bishop 13540a360c2SBrad Bishop return [bus_name,obj_path,intf_name] 13640a360c2SBrad Bishop 13740a360c2SBrad Bishop @dbus.service.method(DBUS_NAME, 13840a360c2SBrad Bishop in_signature='ss', out_signature='(sss)') 13940a360c2SBrad Bishop def getObjectFromId(self,category,key): 14040a360c2SBrad Bishop return self.doObjectLookup(category,key) 14140a360c2SBrad Bishop 14240a360c2SBrad Bishop @dbus.service.method(DBUS_NAME, 14340a360c2SBrad Bishop in_signature='sy', out_signature='(sss)') 14440a360c2SBrad Bishop def getObjectFromByteId(self,category,key): 14540a360c2SBrad Bishop byte = int(key) 14640a360c2SBrad Bishop return self.doObjectLookup(category,byte) 14740a360c2SBrad Bishop 14840a360c2SBrad Bishop # Get the FRU area names defined in ID_LOOKUP table given a fru_id. 14940a360c2SBrad Bishop # If serval areas are defined for a fru_id, the areas are returned 15040a360c2SBrad Bishop # together as a string with each area name seperated with ','. 15140a360c2SBrad Bishop # If no fru area defined in ID_LOOKUP, an empty string will be returned. 15240a360c2SBrad Bishop @dbus.service.method(DBUS_NAME, 15340a360c2SBrad Bishop in_signature='y', out_signature='s') 15440a360c2SBrad Bishop def getFRUArea(self,fru_id): 15540a360c2SBrad Bishop ret_str = '' 15640a360c2SBrad Bishop fru_id = '_' + str(fru_id) 15740a360c2SBrad Bishop area_list = [area for area in System.ID_LOOKUP['FRU_STR'].keys() \ 15840a360c2SBrad Bishop if area.endswith(fru_id)] 15940a360c2SBrad Bishop for area in area_list: 16040a360c2SBrad Bishop ret_str = area + ',' + ret_str 16140a360c2SBrad Bishop # remove the last ',' 16240a360c2SBrad Bishop return ret_str[:-1] 16340a360c2SBrad Bishop 16440a360c2SBrad Bishop def start_process(self,name): 16540a360c2SBrad Bishop if (System.APPS[name]['start_process'] == True): 16640a360c2SBrad Bishop app = System.APPS[name] 16740a360c2SBrad Bishop process_name = self.bin_path+"/"+app['process_name'] 16840a360c2SBrad Bishop cmdline = [ ] 16940a360c2SBrad Bishop cmdline.append(process_name) 17040a360c2SBrad Bishop if (app.has_key('args')): 17140a360c2SBrad Bishop for a in app['args']: 17240a360c2SBrad Bishop cmdline.append(a) 17340a360c2SBrad Bishop try: 17440a360c2SBrad Bishop print "Starting process: "+" ".join(cmdline)+": "+name 17540a360c2SBrad Bishop if (app['monitor_process'] == True): 17640a360c2SBrad Bishop app['popen'] = subprocess.Popen(cmdline) 17740a360c2SBrad Bishop else: 17840a360c2SBrad Bishop subprocess.Popen(cmdline) 17940a360c2SBrad Bishop 18040a360c2SBrad Bishop except Exception as e: 18140a360c2SBrad Bishop ## TODO: error 18240a360c2SBrad Bishop print "ERROR: starting process: "+" ".join(cmdline) 18340a360c2SBrad Bishop 18440a360c2SBrad Bishop def heartbeat_check(self): 18540a360c2SBrad Bishop for name in System.APPS.keys(): 18640a360c2SBrad Bishop app = System.APPS[name] 18740a360c2SBrad Bishop if (app['start_process'] == True and app.has_key('popen')): 18840a360c2SBrad Bishop ## make sure process is still alive 18940a360c2SBrad Bishop p = app['popen'] 19040a360c2SBrad Bishop p.poll() 19140a360c2SBrad Bishop if (p.returncode != None): 19240a360c2SBrad Bishop print "Process for "+name+" appears to be dead" 19340a360c2SBrad Bishop self.start_process(name) 19440a360c2SBrad Bishop 19540a360c2SBrad Bishop return True 19640a360c2SBrad Bishop 19740a360c2SBrad Bishop def NewObjectHandler(self, obj_path, iprops, bus_name = None): 19840a360c2SBrad Bishop current_state = self.Get(DBUS_NAME,"current_state") 19940a360c2SBrad Bishop if (self.bus_name_lookup.has_key(obj_path)): 20040a360c2SBrad Bishop if (self.bus_name_lookup[obj_path] == bus_name): 20140a360c2SBrad Bishop return 20240a360c2SBrad Bishop self.bus_name_lookup[obj_path] = bus_name 203*4de42643SBrad Bishop if current_state not in System.EXIT_STATE_DEPEND: 204*4de42643SBrad Bishop return 20540a360c2SBrad Bishop 206*4de42643SBrad Bishop if obj_path in System.EXIT_STATE_DEPEND[current_state]: 207*4de42643SBrad Bishop print "New object: "+obj_path+" ("+bus_name+")" 208*4de42643SBrad Bishop System.EXIT_STATE_DEPEND[current_state][obj_path] = 1 209*4de42643SBrad Bishop ## check if all required objects are 210*4de42643SBrad Bishop # started to move to next state 211*4de42643SBrad Bishop self.try_next_state() 21240a360c2SBrad Bishop 21340a360c2SBrad Bishop @dbus.service.method(DBUS_NAME, 21440a360c2SBrad Bishop in_signature='s', out_signature='sis') 21540a360c2SBrad Bishop def gpioInit(self,name): 21640a360c2SBrad Bishop gpio_path = '' 21740a360c2SBrad Bishop gpio_num = -1 21840a360c2SBrad Bishop r = ['',gpio_num,''] 21940a360c2SBrad Bishop if (System.GPIO_CONFIG.has_key(name) == False): 22040a360c2SBrad Bishop # TODO: Error handling 22140a360c2SBrad Bishop print "ERROR: "+name+" not found in GPIO config table" 22240a360c2SBrad Bishop else: 22340a360c2SBrad Bishop 22440a360c2SBrad Bishop gpio_num = -1 22540a360c2SBrad Bishop gpio = System.GPIO_CONFIG[name] 22640a360c2SBrad Bishop if (System.GPIO_CONFIG[name].has_key('gpio_num')): 22740a360c2SBrad Bishop gpio_num = gpio['gpio_num'] 22840a360c2SBrad Bishop else: 22940a360c2SBrad Bishop if (System.GPIO_CONFIG[name].has_key('gpio_pin')): 23040a360c2SBrad Bishop gpio_num = System.convertGpio(gpio['gpio_pin']) 23140a360c2SBrad Bishop else: 23240a360c2SBrad Bishop print "ERROR: SystemManager - GPIO lookup failed for "+name 23340a360c2SBrad Bishop 23440a360c2SBrad Bishop if (gpio_num != -1): 23540a360c2SBrad Bishop r = [obmc.enums.GPIO_DEV, gpio_num, gpio['direction']] 23640a360c2SBrad Bishop return r 23740a360c2SBrad Bishop 23840a360c2SBrad Bishop 23940a360c2SBrad Bishop 24040a360c2SBrad Bishopif __name__ == '__main__': 24140a360c2SBrad Bishop dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) 24240a360c2SBrad Bishop bus = get_dbus() 24340a360c2SBrad Bishop name = dbus.service.BusName(DBUS_NAME,bus) 24440a360c2SBrad Bishop obj = SystemManager(bus,OBJ_NAME) 24540a360c2SBrad Bishop mainloop = gobject.MainLoop() 24640a360c2SBrad Bishop 24740a360c2SBrad Bishop print "Running SystemManager" 24840a360c2SBrad Bishop mainloop.run() 24940a360c2SBrad Bishop 250