1*40a360c2SBrad Bishop#!/usr/bin/python -u 2*40a360c2SBrad Bishop 3*40a360c2SBrad Bishopimport sys 4*40a360c2SBrad Bishopimport subprocess 5*40a360c2SBrad Bishopimport gobject 6*40a360c2SBrad Bishopimport dbus 7*40a360c2SBrad Bishopimport dbus.service 8*40a360c2SBrad Bishopimport dbus.mainloop.glib 9*40a360c2SBrad Bishopimport os 10*40a360c2SBrad Bishopimport time 11*40a360c2SBrad Bishopimport obmc.dbuslib.propertycacher as PropertyCacher 12*40a360c2SBrad Bishopfrom obmc.dbuslib.bindings import DbusProperties, DbusObjectManager, get_dbus 13*40a360c2SBrad Bishopimport obmc.enums 14*40a360c2SBrad Bishop 15*40a360c2SBrad Bishopif (len(sys.argv) < 2): 16*40a360c2SBrad Bishop print "Usage: system_manager.py [system name]" 17*40a360c2SBrad Bishop exit(1) 18*40a360c2SBrad Bishop 19*40a360c2SBrad BishopSystem = __import__(sys.argv[1]) 20*40a360c2SBrad Bishop 21*40a360c2SBrad BishopDBUS_NAME = 'org.openbmc.managers.System' 22*40a360c2SBrad BishopOBJ_NAME = '/org/openbmc/managers/System' 23*40a360c2SBrad BishopHEARTBEAT_CHECK_INTERVAL = 20000 24*40a360c2SBrad BishopSTATE_START_TIMEOUT = 10 25*40a360c2SBrad BishopINTF_SENSOR = 'org.openbmc.SensorValue' 26*40a360c2SBrad BishopINTF_ITEM = 'org.openbmc.InventoryItem' 27*40a360c2SBrad BishopINTF_CONTROL = 'org.openbmc.Control' 28*40a360c2SBrad Bishop 29*40a360c2SBrad Bishop 30*40a360c2SBrad Bishopclass SystemManager(DbusProperties,DbusObjectManager): 31*40a360c2SBrad Bishop def __init__(self,bus,obj_name): 32*40a360c2SBrad Bishop DbusProperties.__init__(self) 33*40a360c2SBrad Bishop DbusObjectManager.__init__(self) 34*40a360c2SBrad Bishop dbus.service.Object.__init__(self,bus,obj_name) 35*40a360c2SBrad Bishop 36*40a360c2SBrad Bishop bus.add_signal_receiver(self.NewObjectHandler, 37*40a360c2SBrad Bishop signal_name = "InterfacesAdded", sender_keyword = 'bus_name') 38*40a360c2SBrad Bishop bus.add_signal_receiver(self.SystemStateHandler,signal_name = "GotoSystemState") 39*40a360c2SBrad Bishop 40*40a360c2SBrad Bishop self.Set(DBUS_NAME,"current_state","") 41*40a360c2SBrad Bishop self.system_states = {} 42*40a360c2SBrad Bishop self.bus_name_lookup = {} 43*40a360c2SBrad Bishop self.bin_path = os.path.dirname(os.path.realpath(sys.argv[0])) 44*40a360c2SBrad Bishop 45*40a360c2SBrad Bishop for name in System.APPS.keys(): 46*40a360c2SBrad Bishop sys_state = System.APPS[name]['system_state'] 47*40a360c2SBrad Bishop if (self.system_states.has_key(sys_state) == False): 48*40a360c2SBrad Bishop self.system_states[sys_state] = [] 49*40a360c2SBrad Bishop self.system_states[sys_state].append(name) 50*40a360c2SBrad Bishop 51*40a360c2SBrad Bishop ## replace symbolic path in ID_LOOKUP 52*40a360c2SBrad Bishop for category in System.ID_LOOKUP: 53*40a360c2SBrad Bishop for key in System.ID_LOOKUP[category]: 54*40a360c2SBrad Bishop val = System.ID_LOOKUP[category][key] 55*40a360c2SBrad Bishop new_val = val.replace("<inventory_root>",System.INVENTORY_ROOT) 56*40a360c2SBrad Bishop System.ID_LOOKUP[category][key] = new_val 57*40a360c2SBrad Bishop 58*40a360c2SBrad Bishop self.SystemStateHandler(System.SYSTEM_STATES[0]) 59*40a360c2SBrad Bishop 60*40a360c2SBrad Bishop if not os.path.exists(PropertyCacher.CACHE_PATH): 61*40a360c2SBrad Bishop print "Creating cache directory: "+PropertyCacher.CACHE_PATH 62*40a360c2SBrad Bishop os.makedirs(PropertyCacher.CACHE_PATH) 63*40a360c2SBrad Bishop 64*40a360c2SBrad Bishop self.InterfacesAdded(obj_name,self.properties) 65*40a360c2SBrad Bishop print "SystemManager Init Done" 66*40a360c2SBrad Bishop 67*40a360c2SBrad Bishop 68*40a360c2SBrad Bishop def SystemStateHandler(self,state_name): 69*40a360c2SBrad Bishop ## clearing object started flags 70*40a360c2SBrad Bishop current_state = self.Get(DBUS_NAME,"current_state") 71*40a360c2SBrad Bishop try: 72*40a360c2SBrad Bishop for obj_path in System.EXIT_STATE_DEPEND[current_state]: 73*40a360c2SBrad Bishop System.EXIT_STATE_DEPEND[current_state][obj_path] = 0 74*40a360c2SBrad Bishop except: 75*40a360c2SBrad Bishop pass 76*40a360c2SBrad Bishop 77*40a360c2SBrad Bishop print "Running System State: "+state_name 78*40a360c2SBrad Bishop if (self.system_states.has_key(state_name)): 79*40a360c2SBrad Bishop for name in self.system_states[state_name]: 80*40a360c2SBrad Bishop self.start_process(name) 81*40a360c2SBrad Bishop 82*40a360c2SBrad Bishop if (state_name == "BMC_INIT"): 83*40a360c2SBrad Bishop ## Add poll for heartbeat 84*40a360c2SBrad Bishop gobject.timeout_add(HEARTBEAT_CHECK_INTERVAL, self.heartbeat_check) 85*40a360c2SBrad Bishop 86*40a360c2SBrad Bishop try: 87*40a360c2SBrad Bishop cb = System.ENTER_STATE_CALLBACK[state_name] 88*40a360c2SBrad Bishop for methd in cb.keys(): 89*40a360c2SBrad Bishop obj = bus.get_object(cb[methd]['bus_name'],cb[methd]['obj_name'],introspect=False) 90*40a360c2SBrad Bishop method = obj.get_dbus_method(methd,cb[methd]['interface_name']) 91*40a360c2SBrad Bishop method() 92*40a360c2SBrad Bishop except: 93*40a360c2SBrad Bishop pass 94*40a360c2SBrad Bishop 95*40a360c2SBrad Bishop self.Set(DBUS_NAME,"current_state",state_name) 96*40a360c2SBrad Bishop 97*40a360c2SBrad Bishop def gotoNextState(self): 98*40a360c2SBrad Bishop s = 0 99*40a360c2SBrad Bishop current_state = self.Get(DBUS_NAME,"current_state") 100*40a360c2SBrad Bishop for i in range(len(System.SYSTEM_STATES)): 101*40a360c2SBrad Bishop if (System.SYSTEM_STATES[i] == current_state): 102*40a360c2SBrad Bishop s = i+1 103*40a360c2SBrad Bishop 104*40a360c2SBrad Bishop if (s == len(System.SYSTEM_STATES)): 105*40a360c2SBrad Bishop print "ERROR SystemManager: No more system states" 106*40a360c2SBrad Bishop else: 107*40a360c2SBrad Bishop new_state_name = System.SYSTEM_STATES[s] 108*40a360c2SBrad Bishop print "SystemManager Goto System State: "+new_state_name 109*40a360c2SBrad Bishop self.SystemStateHandler(new_state_name) 110*40a360c2SBrad Bishop 111*40a360c2SBrad Bishop 112*40a360c2SBrad Bishop @dbus.service.method(DBUS_NAME, 113*40a360c2SBrad Bishop in_signature='', out_signature='s') 114*40a360c2SBrad Bishop def getSystemState(self): 115*40a360c2SBrad Bishop return self.Get(DBUS_NAME,"current_state") 116*40a360c2SBrad Bishop 117*40a360c2SBrad Bishop def doObjectLookup(self,category,key): 118*40a360c2SBrad Bishop bus_name = "" 119*40a360c2SBrad Bishop obj_path = "" 120*40a360c2SBrad Bishop intf_name = INTF_ITEM 121*40a360c2SBrad Bishop try: 122*40a360c2SBrad Bishop obj_path = System.ID_LOOKUP[category][key] 123*40a360c2SBrad Bishop bus_name = self.bus_name_lookup[obj_path] 124*40a360c2SBrad Bishop parts = obj_path.split('/') 125*40a360c2SBrad Bishop if (parts[3] == 'sensors'): 126*40a360c2SBrad Bishop intf_name = INTF_SENSOR 127*40a360c2SBrad Bishop except Exception as e: 128*40a360c2SBrad Bishop print "ERROR SystemManager: "+str(e)+" not found in lookup" 129*40a360c2SBrad Bishop 130*40a360c2SBrad Bishop return [bus_name,obj_path,intf_name] 131*40a360c2SBrad Bishop 132*40a360c2SBrad Bishop @dbus.service.method(DBUS_NAME, 133*40a360c2SBrad Bishop in_signature='ss', out_signature='(sss)') 134*40a360c2SBrad Bishop def getObjectFromId(self,category,key): 135*40a360c2SBrad Bishop return self.doObjectLookup(category,key) 136*40a360c2SBrad Bishop 137*40a360c2SBrad Bishop @dbus.service.method(DBUS_NAME, 138*40a360c2SBrad Bishop in_signature='sy', out_signature='(sss)') 139*40a360c2SBrad Bishop def getObjectFromByteId(self,category,key): 140*40a360c2SBrad Bishop byte = int(key) 141*40a360c2SBrad Bishop return self.doObjectLookup(category,byte) 142*40a360c2SBrad Bishop 143*40a360c2SBrad Bishop # Get the FRU area names defined in ID_LOOKUP table given a fru_id. 144*40a360c2SBrad Bishop # If serval areas are defined for a fru_id, the areas are returned 145*40a360c2SBrad Bishop # together as a string with each area name seperated with ','. 146*40a360c2SBrad Bishop # If no fru area defined in ID_LOOKUP, an empty string will be returned. 147*40a360c2SBrad Bishop @dbus.service.method(DBUS_NAME, 148*40a360c2SBrad Bishop in_signature='y', out_signature='s') 149*40a360c2SBrad Bishop def getFRUArea(self,fru_id): 150*40a360c2SBrad Bishop ret_str = '' 151*40a360c2SBrad Bishop fru_id = '_' + str(fru_id) 152*40a360c2SBrad Bishop area_list = [area for area in System.ID_LOOKUP['FRU_STR'].keys() \ 153*40a360c2SBrad Bishop if area.endswith(fru_id)] 154*40a360c2SBrad Bishop for area in area_list: 155*40a360c2SBrad Bishop ret_str = area + ',' + ret_str 156*40a360c2SBrad Bishop # remove the last ',' 157*40a360c2SBrad Bishop return ret_str[:-1] 158*40a360c2SBrad Bishop 159*40a360c2SBrad Bishop def start_process(self,name): 160*40a360c2SBrad Bishop if (System.APPS[name]['start_process'] == True): 161*40a360c2SBrad Bishop app = System.APPS[name] 162*40a360c2SBrad Bishop process_name = self.bin_path+"/"+app['process_name'] 163*40a360c2SBrad Bishop cmdline = [ ] 164*40a360c2SBrad Bishop cmdline.append(process_name) 165*40a360c2SBrad Bishop if (app.has_key('args')): 166*40a360c2SBrad Bishop for a in app['args']: 167*40a360c2SBrad Bishop cmdline.append(a) 168*40a360c2SBrad Bishop try: 169*40a360c2SBrad Bishop print "Starting process: "+" ".join(cmdline)+": "+name 170*40a360c2SBrad Bishop if (app['monitor_process'] == True): 171*40a360c2SBrad Bishop app['popen'] = subprocess.Popen(cmdline) 172*40a360c2SBrad Bishop else: 173*40a360c2SBrad Bishop subprocess.Popen(cmdline) 174*40a360c2SBrad Bishop 175*40a360c2SBrad Bishop except Exception as e: 176*40a360c2SBrad Bishop ## TODO: error 177*40a360c2SBrad Bishop print "ERROR: starting process: "+" ".join(cmdline) 178*40a360c2SBrad Bishop 179*40a360c2SBrad Bishop def heartbeat_check(self): 180*40a360c2SBrad Bishop for name in System.APPS.keys(): 181*40a360c2SBrad Bishop app = System.APPS[name] 182*40a360c2SBrad Bishop if (app['start_process'] == True and app.has_key('popen')): 183*40a360c2SBrad Bishop ## make sure process is still alive 184*40a360c2SBrad Bishop p = app['popen'] 185*40a360c2SBrad Bishop p.poll() 186*40a360c2SBrad Bishop if (p.returncode != None): 187*40a360c2SBrad Bishop print "Process for "+name+" appears to be dead" 188*40a360c2SBrad Bishop self.start_process(name) 189*40a360c2SBrad Bishop 190*40a360c2SBrad Bishop return True 191*40a360c2SBrad Bishop 192*40a360c2SBrad Bishop def NewObjectHandler(self, obj_path, iprops, bus_name = None): 193*40a360c2SBrad Bishop current_state = self.Get(DBUS_NAME,"current_state") 194*40a360c2SBrad Bishop if (self.bus_name_lookup.has_key(obj_path)): 195*40a360c2SBrad Bishop if (self.bus_name_lookup[obj_path] == bus_name): 196*40a360c2SBrad Bishop return 197*40a360c2SBrad Bishop self.bus_name_lookup[obj_path] = bus_name 198*40a360c2SBrad Bishop print "New object: "+obj_path+" ("+bus_name+")" 199*40a360c2SBrad Bishop try: 200*40a360c2SBrad Bishop if (System.EXIT_STATE_DEPEND[current_state].has_key(obj_path) == True): 201*40a360c2SBrad Bishop System.EXIT_STATE_DEPEND[current_state][obj_path] = 1 202*40a360c2SBrad Bishop ## check if all required objects are started to move to next state 203*40a360c2SBrad Bishop state = 1 204*40a360c2SBrad Bishop for obj_path in System.EXIT_STATE_DEPEND[current_state]: 205*40a360c2SBrad Bishop if (System.EXIT_STATE_DEPEND[current_state][obj_path] == 0): 206*40a360c2SBrad Bishop state = 0 207*40a360c2SBrad Bishop ## all required objects have started so go to next state 208*40a360c2SBrad Bishop if (state == 1): 209*40a360c2SBrad Bishop print "All required objects started for "+current_state 210*40a360c2SBrad Bishop self.gotoNextState() 211*40a360c2SBrad Bishop except: 212*40a360c2SBrad Bishop pass 213*40a360c2SBrad Bishop 214*40a360c2SBrad Bishop 215*40a360c2SBrad Bishop @dbus.service.method(DBUS_NAME, 216*40a360c2SBrad Bishop in_signature='s', out_signature='sis') 217*40a360c2SBrad Bishop def gpioInit(self,name): 218*40a360c2SBrad Bishop gpio_path = '' 219*40a360c2SBrad Bishop gpio_num = -1 220*40a360c2SBrad Bishop r = ['',gpio_num,''] 221*40a360c2SBrad Bishop if (System.GPIO_CONFIG.has_key(name) == False): 222*40a360c2SBrad Bishop # TODO: Error handling 223*40a360c2SBrad Bishop print "ERROR: "+name+" not found in GPIO config table" 224*40a360c2SBrad Bishop else: 225*40a360c2SBrad Bishop 226*40a360c2SBrad Bishop gpio_num = -1 227*40a360c2SBrad Bishop gpio = System.GPIO_CONFIG[name] 228*40a360c2SBrad Bishop if (System.GPIO_CONFIG[name].has_key('gpio_num')): 229*40a360c2SBrad Bishop gpio_num = gpio['gpio_num'] 230*40a360c2SBrad Bishop else: 231*40a360c2SBrad Bishop if (System.GPIO_CONFIG[name].has_key('gpio_pin')): 232*40a360c2SBrad Bishop gpio_num = System.convertGpio(gpio['gpio_pin']) 233*40a360c2SBrad Bishop else: 234*40a360c2SBrad Bishop print "ERROR: SystemManager - GPIO lookup failed for "+name 235*40a360c2SBrad Bishop 236*40a360c2SBrad Bishop if (gpio_num != -1): 237*40a360c2SBrad Bishop r = [obmc.enums.GPIO_DEV, gpio_num, gpio['direction']] 238*40a360c2SBrad Bishop return r 239*40a360c2SBrad Bishop 240*40a360c2SBrad Bishop 241*40a360c2SBrad Bishop 242*40a360c2SBrad Bishopif __name__ == '__main__': 243*40a360c2SBrad Bishop dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) 244*40a360c2SBrad Bishop bus = get_dbus() 245*40a360c2SBrad Bishop name = dbus.service.BusName(DBUS_NAME,bus) 246*40a360c2SBrad Bishop obj = SystemManager(bus,OBJ_NAME) 247*40a360c2SBrad Bishop mainloop = gobject.MainLoop() 248*40a360c2SBrad Bishop 249*40a360c2SBrad Bishop print "Running SystemManager" 250*40a360c2SBrad Bishop mainloop.run() 251*40a360c2SBrad Bishop 252