1#!/usr/bin/python -u 2 3import sys 4import subprocess 5import gobject 6import dbus 7import dbus.service 8import dbus.mainloop.glib 9import os 10import obmc.dbuslib.propertycacher as PropertyCacher 11from obmc.dbuslib.bindings import DbusProperties, DbusObjectManager, get_dbus 12import obmc.enums 13import obmc_system_config as System 14import obmc.dbuslib.introspection 15import obmc.utils.misc 16import obmc.mapper.utils 17 18DBUS_NAME = 'org.openbmc.managers.System' 19OBJ_NAME = '/org/openbmc/managers/System' 20INTF_SENSOR = 'org.openbmc.SensorValue' 21INTF_ITEM = 'org.openbmc.InventoryItem' 22INTF_CONTROL = 'org.openbmc.Control' 23 24 25class SystemManager(DbusProperties, DbusObjectManager): 26 def __init__(self, bus, obj_name): 27 DbusProperties.__init__(self) 28 DbusObjectManager.__init__(self) 29 dbus.service.Object.__init__(self, bus, obj_name) 30 self.bus = bus 31 32 bus.add_signal_receiver( 33 self.NewObjectHandler, 34 signal_name="InterfacesAdded", sender_keyword='bus_name') 35 bus.add_signal_receiver( 36 self.SystemStateHandler, signal_name="GotoSystemState") 37 38 self.Set(DBUS_NAME, "current_state", "") 39 self.system_states = {} 40 self.bin_path = os.path.dirname(os.path.realpath(sys.argv[0])) 41 42 for name in System.APPS.keys(): 43 sys_state = System.APPS[name]['system_state'] 44 if sys_state not in self.system_states: 45 self.system_states[sys_state] = [] 46 self.system_states[sys_state].append(name) 47 48 ## replace symbolic path in ID_LOOKUP 49 for category in System.ID_LOOKUP: 50 for key in System.ID_LOOKUP[category]: 51 val = System.ID_LOOKUP[category][key] 52 new_val = val.replace( 53 "<inventory_root>", System.INVENTORY_ROOT) 54 System.ID_LOOKUP[category][key] = new_val 55 56 self.SystemStateHandler(System.SYSTEM_STATES[0]) 57 58 if not os.path.exists(PropertyCacher.CACHE_PATH): 59 print "Creating cache directory: "+PropertyCacher.CACHE_PATH 60 os.makedirs(PropertyCacher.CACHE_PATH) 61 62 print "SystemManager Init Done" 63 64 def SystemStateHandler(self, state_name): 65 print "Running System State: "+state_name 66 if state_name in self.system_states: 67 for name in self.system_states[state_name]: 68 self.start_process(name) 69 70 try: 71 cb = System.ENTER_STATE_CALLBACK[state_name] 72 for methd in cb.keys(): 73 obj = bus.get_object( 74 cb[methd]['bus_name'], 75 cb[methd]['obj_name'], 76 introspect=False) 77 method = obj.get_dbus_method( 78 methd, cb[methd]['interface_name']) 79 method() 80 except: 81 pass 82 83 self.Set(DBUS_NAME, "current_state", state_name) 84 85 waitlist = System.EXIT_STATE_DEPEND.get(state_name, {}).keys() 86 if waitlist: 87 self.waiter = obmc.mapper.utils.Wait( 88 self.bus, waitlist, 89 callback=self.gotoNextState) 90 91 def gotoNextState(self): 92 s = 0 93 current_state = self.Get(DBUS_NAME, "current_state") 94 for i in range(len(System.SYSTEM_STATES)): 95 if (System.SYSTEM_STATES[i] == current_state): 96 s = i+1 97 98 if (s == len(System.SYSTEM_STATES)): 99 print "ERROR SystemManager: No more system states" 100 else: 101 new_state_name = System.SYSTEM_STATES[s] 102 print "SystemManager Goto System State: "+new_state_name 103 self.SystemStateHandler(new_state_name) 104 105 @dbus.service.method(DBUS_NAME, in_signature='', out_signature='s') 106 def getSystemState(self): 107 return self.Get(DBUS_NAME, "current_state") 108 109 def doObjectLookup(self, category, key): 110 obj_path = "" 111 intf_name = INTF_ITEM 112 try: 113 obj_path = System.ID_LOOKUP[category][key] 114 parts = obj_path.split('/') 115 if (parts[3] == 'sensors'): 116 intf_name = INTF_SENSOR 117 except Exception as e: 118 print "ERROR SystemManager: "+str(e)+" not found in lookup" 119 120 return [obj_path, intf_name] 121 122 @dbus.service.method(DBUS_NAME, in_signature='ss', out_signature='(ss)') 123 def getObjectFromId(self, category, key): 124 return self.doObjectLookup(category, key) 125 126 @dbus.service.method(DBUS_NAME, in_signature='sy', out_signature='(ss)') 127 def getObjectFromByteId(self, category, key): 128 byte = int(key) 129 return self.doObjectLookup(category, byte) 130 131 # Get the FRU area names defined in ID_LOOKUP table given a fru_id. 132 # If serval areas are defined for a fru_id, the areas are returned 133 # together as a string with each area name seperated with ','. 134 # If no fru area defined in ID_LOOKUP, an empty string will be returned. 135 @dbus.service.method(DBUS_NAME, in_signature='y', out_signature='s') 136 def getFRUArea(self, fru_id): 137 ret_str = '' 138 fru_id = '_' + str(fru_id) 139 area_list = [ 140 area for area in System.ID_LOOKUP['FRU_STR'].keys() 141 if area.endswith(fru_id)] 142 for area in area_list: 143 ret_str = area + ',' + ret_str 144 # remove the last ',' 145 return ret_str[:-1] 146 147 def start_process(self, name): 148 if System.APPS[name]['start_process']: 149 app = System.APPS[name] 150 process_name = self.bin_path+"/"+app['process_name'] 151 cmdline = [] 152 cmdline.append(process_name) 153 if 'args' in app: 154 for a in app['args']: 155 cmdline.append(a) 156 try: 157 print "Starting process: "+" ".join(cmdline)+": "+name 158 if app['monitor_process']: 159 app['popen'] = subprocess.Popen(cmdline) 160 else: 161 subprocess.Popen(cmdline) 162 163 except Exception as e: 164 ## TODO: error 165 print "ERROR: starting process: "+" ".join(cmdline) 166 167 def NewObjectHandler(self, obj_path, iprops, bus_name=None): 168 current_state = self.Get(DBUS_NAME, "current_state") 169 if current_state not in System.EXIT_STATE_DEPEND: 170 return 171 172 if obj_path in System.EXIT_STATE_DEPEND[current_state]: 173 print "New object: "+obj_path+" ("+bus_name+")" 174 175 @dbus.service.method(DBUS_NAME, in_signature='s', out_signature='sis') 176 def gpioInit(self, name): 177 gpio_path = '' 178 gpio_num = -1 179 r = ['', gpio_num, ''] 180 if name not in System.GPIO_CONFIG: 181 # TODO: Error handling 182 print "ERROR: "+name+" not found in GPIO config table" 183 else: 184 185 gpio_num = -1 186 gpio = System.GPIO_CONFIG[name] 187 if 'gpio_num' in System.GPIO_CONFIG[name]: 188 gpio_num = gpio['gpio_num'] 189 else: 190 if 'gpio_pin' in System.GPIO_CONFIG[name]: 191 gpio_num = System.convertGpio(gpio['gpio_pin']) 192 else: 193 print "ERROR: SystemManager - GPIO lookup failed for "+name 194 195 if (gpio_num != -1): 196 r = [obmc.enums.GPIO_DEV, gpio_num, gpio['direction']] 197 return r 198 199 200if __name__ == '__main__': 201 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) 202 bus = get_dbus() 203 obj = SystemManager(bus, OBJ_NAME) 204 mainloop = gobject.MainLoop() 205 obj.unmask_signals() 206 name = dbus.service.BusName(DBUS_NAME, bus) 207 208 print "Running SystemManager" 209 mainloop.run() 210