1#!/usr/bin/python -u 2 3import sys 4import signal 5import subprocess 6import gobject 7import dbus 8import dbus.service 9import dbus.mainloop.glib 10import os 11import obmc.dbuslib.propertycacher as PropertyCacher 12from obmc.dbuslib.bindings import DbusProperties, DbusObjectManager, get_dbus 13import obmc.enums 14import obmc_system_config as System 15import obmc.dbuslib.introspection 16import obmc.utils.misc 17import obmc.mapper.utils 18 19DBUS_NAME = 'org.openbmc.managers.System' 20OBJ_NAME = '/org/openbmc/managers/System' 21INTF_SENSOR = 'org.openbmc.SensorValue' 22INTF_ITEM = 'org.openbmc.InventoryItem' 23INTF_CONTROL = 'org.openbmc.Control' 24 25 26class 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 32 33 bus.add_signal_receiver( 34 self.NewObjectHandler, 35 signal_name="InterfacesAdded", sender_keyword='bus_name') 36 bus.add_signal_receiver( 37 self.SystemStateHandler, signal_name="GotoSystemState") 38 39 self.Set(DBUS_NAME, "current_state", "") 40 self.system_states = {} 41 self.bin_path = os.path.dirname(os.path.realpath(sys.argv[0])) 42 43 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) 48 49 ## 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 56 57 self.SystemStateHandler(System.SYSTEM_STATES[0]) 58 59 print "SystemManager Init Done" 60 61 def SystemStateHandler(self, state_name): 62 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) 66 67 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 79 80 self.Set(DBUS_NAME, "current_state", state_name) 81 82 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 88 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 94 95 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) 101 102 @dbus.service.method(DBUS_NAME, in_signature='', out_signature='s') 103 def getSystemState(self): 104 return self.Get(DBUS_NAME, "current_state") 105 106 def doObjectLookup(self, category, key): 107 obj_path = "" 108 intf_name = INTF_ITEM 109 try: 110 obj_path = System.ID_LOOKUP[category][key] 111 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" 116 117 return [obj_path, intf_name] 118 119 @dbus.service.method(DBUS_NAME, in_signature='ss', out_signature='(ss)') 120 def getObjectFromId(self, category, key): 121 return self.doObjectLookup(category, key) 122 123 @dbus.service.method(DBUS_NAME, in_signature='sy', out_signature='(ss)') 124 def getObjectFromByteId(self, category, key): 125 byte = int(key) 126 return self.doObjectLookup(category, byte) 127 128 # 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] 143 144 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) 159 160 except Exception as e: 161 ## TODO: error 162 print "ERROR: starting process: "+" ".join(cmdline) 163 164 def NewObjectHandler(self, obj_path, iprops, bus_name=None): 165 current_state = self.Get(DBUS_NAME, "current_state") 166 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+")" 171 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 196 197if __name__ == '__main__': 198 # Ignore SIGCHLD signal, to prevent child process becoming zombie 199 signal.signal(signal.SIGCHLD, signal.SIG_IGN) 200 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) 201 bus = get_dbus() 202 obj = SystemManager(bus, OBJ_NAME) 203 mainloop = gobject.MainLoop() 204 obj.unmask_signals() 205 name = dbus.service.BusName(DBUS_NAME, bus) 206 207 print "Running SystemManager" 208 mainloop.run() 209