blob: 75cc390c5b6a4b3ff5c8e14c062316270ea67149 [file] [log] [blame]
Norman James65a295a2015-09-26 22:21:10 -05001#!/usr/bin/env python
2
3import os
4import sys
5import gobject
6import dbus
7import dbus.service
8import dbus.mainloop.glib
9import cPickle
10import json
11
12if (len(sys.argv) < 2):
13 print "Usage: inventory_manager.py [system name]"
14 exit(1)
15System = __import__(sys.argv[1])
16import Openbmc
17
18DBUS_NAME = 'org.openbmc.managers.Inventory'
19OBJ_NAME = '/org/openbmc/managers/Inventory'
20FRUS = System.FRU_INSTANCES
21FRU_PATH = System.FRU_PATH
22
23## accessor class to FRU data structure
24class Fru:
25 def __init__(self,fru):
26 ## validation
27 if (FRUS.has_key(fru) == False):
28 # TODO: event log
29 raise Exception("Invalid FRU path: "+fru)
30
31 self.fru = fru
32
33 def getField(self,field):
34 if (FRUS[self.fru].has_key(field) == False):
35 # TODO: event log
36 raise Exception("Invalid field: "+field)
37
38 return FRUS[self.fru][field]
39
40 def isFru(self):
41 return FRUS[self.fru]['fru']
42
43 def update(self,data):
44 for k in data.keys():
45 FRUS[self.fru][k] = data[k]
46
47 def isCached(self):
48 return True
49
50 def getCacheFilename(self):
51 global FRU_PATH
Norman James7caa10e2015-09-27 22:39:52 -050052 name = self.fru.replace('/','.')
53 filename = FRU_PATH+name[1:]+".fru"
Norman James65a295a2015-09-26 22:21:10 -050054 return filename
55
56 def saveToCache(self):
57 if (self.isCached() == False):
58 return
59 print "Caching: "+self.fru
Norman James7caa10e2015-09-27 22:39:52 -050060 # TODO: error handling
Norman James65a295a2015-09-26 22:21:10 -050061 output = open(self.getCacheFilename(), 'wb')
62 ## just pickle dict not whole object
Norman James65a295a2015-09-26 22:21:10 -050063 cPickle.dump(FRUS[self.fru],output)
64 output.close()
65
66 def loadFromCache(self):
67 if (self.isCached() == False):
68 return;
69 ## overlay with pickled data
70 filename=self.getCacheFilename()
71 if (os.path.isfile(filename)):
72 print "Loading from cache: "+filename
Norman James7caa10e2015-09-27 22:39:52 -050073 # TODO: error handling
Norman James65a295a2015-09-26 22:21:10 -050074 p = open(filename, 'rb')
75 data2 = cPickle.load(p)
76 for k in data2.keys():
77 FRUS[self.fru][k] = data2[k]
78
79 def __str__(self):
80 r = "Fru: "+str(self.fru_id)+"\n"
81 for f in self.data.keys():
82 r = r+f+" = "+str(self.data[f])+"\n"
83 return r
84
85
86
87class InventoryManager(dbus.service.Object):
88 def __init__(self,bus,name):
89 dbus.service.Object.__init__(self,bus,name)
90
91 bus.add_signal_receiver(self.UpdateFruHandler,
Norman Jamesdfdaca92015-09-27 22:11:15 -050092 dbus_interface = "org.openbmc.sensors.IpmiBt",
Norman James65a295a2015-09-26 22:21:10 -050093 signal_name = 'UpdateFru')
94
Norman Jamesdfdaca92015-09-27 22:11:15 -050095 bus.add_signal_receiver(self.SetSensorHandler,
96 dbus_interface = "org.openbmc.sensors.IpmiBt",
97 signal_name = "SetSensor")
98
Norman James65a295a2015-09-26 22:21:10 -050099 self.fru_db = {}
100 self.fru_id_lookup = {}
101 self.sensor_id_lookup = {}
102
103 for fru_path in FRUS.keys():
104 self.addFru(fru_path)
105 f = FRUS[fru_path]
106 if (f.has_key('fru_id')):
107 self.fru_id_lookup[f['fru_id']] = fru_path
108 if (f.has_key('sensor_id')):
109 self.sensor_id_lookup[f['sensor_id']] = fru_path
110
Norman James7caa10e2015-09-27 22:39:52 -0500111 @dbus.service.signal('org.openbmc.EventLog')
112 def EventLog(self, priority, message, rc):
113 pass
114
Norman James65a295a2015-09-26 22:21:10 -0500115 def UpdateFruHandler(self,fru_id,data):
Norman Jamesdfdaca92015-09-27 22:11:15 -0500116 self.updateFruFromId(fru_id,data)
Norman James65a295a2015-09-26 22:21:10 -0500117
Norman Jamesdfdaca92015-09-27 22:11:15 -0500118 def SetSensorHandler(self,sensor_id,data):
119 fru_path = self.getFruSensor(sensor_id)
120 if (fru_path != ""):
121 state = { 'state' : data }
122 self.updateFru(fru_path,state)
123
Norman James65a295a2015-09-26 22:21:10 -0500124 @dbus.service.method(DBUS_NAME,
125 in_signature='y', out_signature='s')
126 def getFruSensor(self,sensor_id):
127 if (self.sensor_id_lookup.has_key(sensor_id) == False):
128 return ""
129 return self.sensor_id_lookup[sensor_id]
130
131 def addFru(self,fru_path):
132 new_fru = Fru(fru_path)
133 new_fru.loadFromCache()
134 self.fru_db[fru_path] = new_fru
135
136 @dbus.service.method(DBUS_NAME,
137 in_signature='ia{sv}', out_signature='')
138 def updateFruFromId(self,fru_id,data):
139 iid = int(fru_id)
140 if (self.fru_id_lookup.has_key(iid) == False):
Norman James7caa10e2015-09-27 22:39:52 -0500141 self.EventLog(1,"FRU ID not found: "+str(iid),1)
Norman James65a295a2015-09-26 22:21:10 -0500142 else:
143 self.updateFru(self.fru_id_lookup[iid],data)
144
145
146 @dbus.service.method(DBUS_NAME,
147 in_signature='sa{sv}', out_signature='')
148 def updateFru(self,fru_path,data):
149 ## translate dbus data into basic data types
150 clean_data = {}
151 for k in data.keys():
152 d = Openbmc.DbusProperty(k,data[k])
153 clean_data[str(k)] = d.getBaseValue()
154
155 if (self.fru_db.has_key(fru_path)):
156 ## update properties then save to cache
157 print "Updating FRU: "+fru_path
158 self.fru_db[fru_path].update(clean_data)
159 self.fru_db[fru_path].saveToCache()
160
161
162 @dbus.service.method(DBUS_NAME,
163 in_signature='', out_signature='a{sa{sv}}')
164 def getFrus(self):
165 return FRUS
166
167
168if __name__ == '__main__':
169 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
170 bus = dbus.SessionBus()
171 name = dbus.service.BusName(DBUS_NAME,bus)
172 obj = InventoryManager(bus,OBJ_NAME)
173 mainloop = gobject.MainLoop()
174
175 print "Running Inventory Manager"
176 mainloop.run()
177