blob: 015aa8dcba634d401a7c0fe822c674bfaa08cf8f [file] [log] [blame]
Norman James89de9162015-08-27 21:41:36 -05001#!/usr/bin/env python
2
Norman James471ab592015-08-30 22:29:40 -05003import sys
Norman James89de9162015-08-27 21:41:36 -05004import subprocess
Norman James6f8d0422015-09-14 18:48:00 -05005#from gi.repository import GObject
6import 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
11import PropertyManager
Norman James88872672015-09-21 16:51:35 -050012import time
13import json
Norman James9e6acf92015-09-08 07:00:04 -050014import Openbmc
15
Norman James471ab592015-08-30 22:29:40 -050016if (len(sys.argv) < 2):
17 print "Usage: system_manager.py [system name]"
18 exit(1)
19
20System = __import__(sys.argv[1])
21import Openbmc
Norman James89de9162015-08-27 21:41:36 -050022
23DBUS_NAME = 'org.openbmc.managers.System'
24OBJ_NAME = '/org/openbmc/managers/System'
Norman James471ab592015-08-30 22:29:40 -050025HEARTBEAT_CHECK_INTERVAL = 20000
Norman James89de9162015-08-27 21:41:36 -050026
Norman James89de9162015-08-27 21:41:36 -050027
28class SystemManager(dbus.service.Object):
29 def __init__(self,bus,name):
30 dbus.service.Object.__init__(self,bus,name)
Norman James5d78b4d2015-09-05 13:34:34 -050031 self.property_manager = PropertyManager.PropertyManager(bus,System.CACHE_PATH)
Norman James9e6acf92015-09-08 07:00:04 -050032
Norman James90baede2015-09-02 20:32:49 -050033 ## Signal handlers
34 bus.add_signal_receiver(self.NewBusHandler,
Norman James89de9162015-08-27 21:41:36 -050035 dbus_interface = 'org.freedesktop.DBus',
36 signal_name = "NameOwnerChanged")
Norman James9e6acf92015-09-08 07:00:04 -050037 bus.add_signal_receiver(self.HeartbeatHandler, signal_name = "Heartbeat")
Norman James362a80f2015-09-14 14:04:39 -050038 bus.add_signal_receiver(self.SystemStateHandler,signal_name = "GotoSystemState")
Norman James88872672015-09-21 16:51:35 -050039 bus.add_signal_receiver(self.event_log_signal_handler,
40 dbus_interface = "org.openbmc.EventLog",
41 signal_name = "EventLog",
42 path_keyword='path')
43
44
Norman James90baede2015-09-02 20:32:49 -050045
Norman James362a80f2015-09-14 14:04:39 -050046 self.current_state = ""
47 self.system_states = {}
48 self.IPMI_ID_LOOKUP = {}
49 for bus_name in System.SYSTEM_CONFIG.keys():
50 sys_state = System.SYSTEM_CONFIG[bus_name]['system_state']
51 if (self.system_states.has_key(sys_state) == False):
52 self.system_states[sys_state] = []
53 self.system_states[sys_state].append(bus_name)
54 self.SystemStateHandler("INIT")
55 print "SystemManager Init Done"
56
57
58 def SystemStateHandler(self,state_name):
59 print "Running System State: "+state_name
60 if (self.system_states.has_key(state_name)):
61 for bus_name in self.system_states[state_name]:
Norman James90baede2015-09-02 20:32:49 -050062 self.start_process(bus_name)
Norman James90baede2015-09-02 20:32:49 -050063
Norman James362a80f2015-09-14 14:04:39 -050064 if (state_name == "INIT"):
65 ## Add poll for heartbeat
Norman James6f8d0422015-09-14 18:48:00 -050066 gobject.timeout_add(HEARTBEAT_CHECK_INTERVAL, self.heartbeat_check)
Norman James9e6acf92015-09-08 07:00:04 -050067
Norman James362a80f2015-09-14 14:04:39 -050068 if (System.ENTER_STATE_CALLBACK.has_key(state_name)):
69 cb = System.ENTER_STATE_CALLBACK[state_name]
70 obj = bus.get_object(cb['bus_name'],cb['obj_name'])
71 method = obj.get_dbus_method(cb['method_name'],cb['interface_name'])
72 method()
Norman James471ab592015-08-30 22:29:40 -050073
Norman James362a80f2015-09-14 14:04:39 -050074 current_state = state_name
75
Norman James471ab592015-08-30 22:29:40 -050076 def start_process(self,bus_name):
Norman James5d78b4d2015-09-05 13:34:34 -050077 if (System.SYSTEM_CONFIG[bus_name]['start_process'] == True):
78 process_name = System.BIN_PATH+System.SYSTEM_CONFIG[bus_name]['process_name']
79 cmdline = [ ]
80 cmdline.append(process_name)
81 for instance in System.SYSTEM_CONFIG[bus_name]['instances']:
82 cmdline.append(instance['name'])
83 try:
Norman James362a80f2015-09-14 14:04:39 -050084 print "Starting process: "+" ".join(cmdline)+": "+bus_name
Norman James5d78b4d2015-09-05 13:34:34 -050085 System.SYSTEM_CONFIG[bus_name]['popen'] = subprocess.Popen(cmdline);
86 except Exception as e:
87 ## TODO: error
88 print "Error starting process: "+" ".join(cmdline)
Norman James471ab592015-08-30 22:29:40 -050089
Norman James89de9162015-08-27 21:41:36 -050090 def heartbeat_check(self):
Norman James362a80f2015-09-14 14:04:39 -050091 #print "heartbeat check"
Norman James471ab592015-08-30 22:29:40 -050092 for bus_name in System.SYSTEM_CONFIG.keys():
Norman James362a80f2015-09-14 14:04:39 -050093 if (System.SYSTEM_CONFIG[bus_name]['start_process'] == True and
Norman James6f8d0422015-09-14 18:48:00 -050094 System.SYSTEM_CONFIG[bus_name].has_key('popen') and
95 System.SYSTEM_CONFIG[bus_name]['monitor_process'] == True):
Norman James5d78b4d2015-09-05 13:34:34 -050096 ## even if process doesn't request heartbeat check,
97 ## make sure process is still alive
98 p = System.SYSTEM_CONFIG[bus_name]['popen']
99 p.poll()
100 if (p.returncode != None):
101 print "Process for "+bus_name+" appears to be dead"
102 self.start_process(bus_name)
103
104 ## process is alive, now check if heartbeat received
105 ## during previous interval
106 elif (System.SYSTEM_CONFIG[bus_name]['heartbeat'] == 'yes'):
107 if (System.SYSTEM_CONFIG[bus_name]['heartbeat_count'] == 0):
108 print "Heartbeat error: "+bus_name
109 p = System.SYSTEM_CONFIG[bus_name]['popen']
110 ## TODO: error checking
111 p.poll()
112 if (p.returncode == None):
113 print "Process must be hung, so killing"
114 p.kill()
Norman James471ab592015-08-30 22:29:40 -0500115
Norman James5d78b4d2015-09-05 13:34:34 -0500116 self.start_process(bus_name)
117 else:
118 System.SYSTEM_CONFIG[bus_name]['heartbeat_count'] = 0
Norman James362a80f2015-09-14 14:04:39 -0500119 #print "Heartbeat ok: "+bus_name
Norman James471ab592015-08-30 22:29:40 -0500120
121 return True
Norman James89de9162015-08-27 21:41:36 -0500122
Norman James90baede2015-09-02 20:32:49 -0500123 def HeartbeatHandler(self,bus_name):
Norman James362a80f2015-09-14 14:04:39 -0500124 #print "Heartbeat seen: "+bus_name
Norman James471ab592015-08-30 22:29:40 -0500125 System.SYSTEM_CONFIG[bus_name]['heartbeat_count']=1
Norman James89de9162015-08-27 21:41:36 -0500126
Norman James90baede2015-09-02 20:32:49 -0500127 def NewBusHandler(self, bus_name, a, b):
Norman James471ab592015-08-30 22:29:40 -0500128 if (len(b) > 0 and bus_name.find(Openbmc.BUS_PREFIX) == 0):
129 if (System.SYSTEM_CONFIG.has_key(bus_name)):
130 System.SYSTEM_CONFIG[bus_name]['heartbeat_count'] = 0
Norman James362a80f2015-09-14 14:04:39 -0500131 objects = {}
132 Openbmc.get_objs(bus,bus_name,Openbmc.OBJ_PREFIX,objects)
133
134 for instance_name in objects.keys():
135 obj_path = objects[instance_name]['PATH']
136 for instance in System.SYSTEM_CONFIG[bus_name]['instances']:
137 if (instance.has_key('properties') and instance['name'] == instance_name):
138 props = instance['properties']
139 print "Load Properties: "+obj_path
140 self.property_manager.loadProperties(bus_name,obj_path,props)
141 ## create a lookup for ipmi id to object path
142 if (props.has_key('org.openbmc.SensorValue')):
143 if (props['org.openbmc.SensorValue'].has_key('ipmi_id')):
144 ipmi_id = props['org.openbmc.SensorValue']['ipmi_id']
145 ## TODO: check for duplicate ipmi id
146 self.IPMI_ID_LOOKUP[ipmi_id]=[bus_name,obj_path]
Norman James90baede2015-09-02 20:32:49 -0500147
Norman James362a80f2015-09-14 14:04:39 -0500148 ## If object has an init method, call it
149 for init_intf in objects[instance_name]['INIT']:
150 obj = bus.get_object(bus_name,obj_path)
151 intf = dbus.Interface(obj,init_intf)
152 print "Calling init method: " +obj_path+" : "+init_intf
153 intf.init()
154#
155 @dbus.service.method(DBUS_NAME,
156 in_signature='y', out_signature='ss')
157 def getObjFromIpmi(self,ipmi_id):
158 obj_path = ""
159 ## TODO: handle lookup failing
160 if (self.IPMI_ID_LOOKUP.has_key(ipmi_id) == True):
161 obj_info = self.IPMI_ID_LOOKUP[ipmi_id]
162 return obj_info
Norman James89de9162015-08-27 21:41:36 -0500163
164 @dbus.service.method(DBUS_NAME,
165 in_signature='s', out_signature='sis')
166 def gpioInit(self,name):
167 gpio_path = ''
168 gpio_num = 0
Norman James471ab592015-08-30 22:29:40 -0500169 if (System.GPIO_CONFIG.has_key(name) == False):
Norman James89de9162015-08-27 21:41:36 -0500170 # TODO: Error handling
171 print "ERROR: "+name+" not found in GPIO config table"
172 return ['',0,'']
173 else:
Norman James471ab592015-08-30 22:29:40 -0500174 gpio_num = System.GPIO_CONFIG[name]['gpio_num']
Norman James89de9162015-08-27 21:41:36 -0500175
Norman James471ab592015-08-30 22:29:40 -0500176 return [Openbmc.GPIO_DEV, gpio_num, System.GPIO_CONFIG[name]['direction']]
Norman James89de9162015-08-27 21:41:36 -0500177
Norman James88872672015-09-21 16:51:35 -0500178 ## Signal handler
179 def event_log_signal_handler(self,priority,msg,rc,path = None):
180 message = {}
181 ts = time.time()
182
183 message['priority'] = priority
184 message['object_path'] = path
185 message['message'] = msg
186 message['rc'] = rc
187
188 json_dump = json.dumps(message)
189 print "EVENT_LOG: "+json_dump
190 #syslog.openlog('OpenBmc',logoption=syslog.LOG_PID)
191 #syslog.syslog(priority,json_dump)
192 #syslog.closelog()
193
Norman James89de9162015-08-27 21:41:36 -0500194
195if __name__ == '__main__':
196 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
197 bus = dbus.SessionBus()
198 name = dbus.service.BusName(DBUS_NAME,bus)
199 obj = SystemManager(bus,OBJ_NAME)
Norman James6f8d0422015-09-14 18:48:00 -0500200 mainloop = gobject.MainLoop()
Norman James89de9162015-08-27 21:41:36 -0500201
Norman James89de9162015-08-27 21:41:36 -0500202 print "Running SystemManager"
203 mainloop.run()
204