blob: 5f6fcd206184ae6912368db274bf7b53688cd958 [file] [log] [blame]
Lei YUa03e55e2018-08-03 17:43:25 +08001#!/usr/bin/env python3
2
3import yaml
4import argparse
5
Lei YUd4051652018-08-06 17:02:00 +08006from typing import NamedTuple
7
8
9class RptSensor(NamedTuple):
10 name: str
11 entityId: int
12 typeId: int
13 evtType: int
14 sensorId: int
15 fru: int
16 targetPath: str
17
18
Lei YU206f7c42018-08-07 15:12:19 +080019sampleDimmTemp = {
20 'bExp': 0,
21 'entityID': 32,
22 'entityInstance': 2,
23 'interfaces': {
24 'xyz.openbmc_project.Sensor.Value': {
25 'Value': {
26 'Offsets': {
27 255: {
28 'type': 'int64_t'
29 }
30 }
31 }
32 }
33 },
34 'multiplierM': 1,
35 'mutability': 'Mutability::Write|Mutability::Read',
36 'offsetB': -127,
37 'path': '/xyz/openbmc_project/sensors/temperature/dimm0_temp',
38 'rExp': 0,
39 'readingType': 'readingData',
40 'scale': -3,
41 'sensorNamePattern': 'nameLeaf',
42 'sensorReadingType': 1,
43 'sensorType': 1,
44 'serviceInterface': 'org.freedesktop.DBus.Properties',
45 'unit': 'xyz.openbmc_project.Sensor.Value.Unit.DegreesC'
46}
47sampleCoreTemp = {
48 'bExp': 0,
49 'entityID': 208,
50 'entityInstance': 2,
51 'interfaces': {
52 'xyz.openbmc_project.Sensor.Value': {
53 'Value': {
54 'Offsets': {
55 255: {
56 'type': 'int64_t'
57 }
58 }
59 }
60 }
61 },
62 'multiplierM': 1,
63 'mutability': 'Mutability::Write|Mutability::Read',
64 'offsetB': -127,
65 'path': '/xyz/openbmc_project/sensors/temperature/p0_core0_temp',
66 'rExp': 0,
67 'readingType': 'readingData',
68 'scale': -3,
69 'sensorNamePattern': 'nameLeaf',
70 'sensorReadingType': 1,
71 'sensorType': 1,
72 'serviceInterface': 'org.freedesktop.DBus.Properties',
73 'unit': 'xyz.openbmc_project.Sensor.Value.Unit.DegreesC'
74}
Lei YUa49f04f2018-08-09 15:14:53 +080075sampleDcmiSensor = {
76 "instance": 1,
77 "dbus": "/xyz/openbmc_project/sensors/temperature/p0_core0_temp",
78 "record_id": 91
79}
Lei YU206f7c42018-08-07 15:12:19 +080080
81
Lei YUa03e55e2018-08-03 17:43:25 +080082def openYaml(f):
83 return yaml.load(open(f))
84
85
Lei YUdf0c4172018-08-08 10:42:08 +080086def saveYaml(y, f, safe=True):
87 if safe:
88 noaliasDumper = yaml.dumper.SafeDumper
89 noaliasDumper.ignore_aliases = lambda self, data: True
90 yaml.dump(y, open(f, "w"), default_flow_style=False,
91 Dumper=noaliasDumper)
92 else:
93 yaml.dump(y, open(f, "w"))
Lei YUa03e55e2018-08-03 17:43:25 +080094
95
Lei YU9f394032018-08-08 11:25:21 +080096def getEntityIdAndNamePattern(p, intfs, m):
97 key = (p, intfs)
98 match = m.get(key, None)
99 if match is None:
Lei YU25ecc552018-08-23 14:20:45 +0800100 # Workaround for P8's occ sensors, where the path look like
101 # /org/open_power/control/occ_3_0050
102 if '/org/open_power/control/occ' in p \
103 and 'org.open_power.OCC.Status' in intfs:
104 return (210, 'nameLeaf')
Lei YU9f394032018-08-08 11:25:21 +0800105 raise Exception('Unable to find sensor', key, 'from map')
106 return (m[key]['entityID'], m[key]['sensorNamePattern'])
Lei YUa03e55e2018-08-03 17:43:25 +0800107
108
109# Global entity instances
110entityInstances = {}
111
112
113def getEntityInstance(id):
114 instanceId = entityInstances.get(id, 0)
115 instanceId = instanceId + 1
116 entityInstances[id] = instanceId
117 print("EntityId:", id, "InstanceId:", instanceId)
118 return instanceId
119
120
Lei YUd4051652018-08-06 17:02:00 +0800121def loadRpt(rptFile):
122 sensors = []
123 with open(rptFile) as f:
124 next(f)
125 next(f)
126 for line in f:
127 fields = line.strip().split('|')
128 fields = list(map(str.strip, fields))
129 sensor = RptSensor(
130 fields[0],
131 int(fields[2], 16) if fields[2] else None,
132 int(fields[3], 16) if fields[3] else None,
133 int(fields[4], 16) if fields[4] else None,
134 int(fields[5], 16) if fields[5] else None,
135 int(fields[7], 16) if fields[7] else None,
136 fields[9])
137 # print(sensor)
138 sensors.append(sensor)
139 return sensors
140
141
Lei YU206f7c42018-08-07 15:12:19 +0800142def getDimmTempPath(p):
143 # Convert path like: /sys-0/node-0/motherboard-0/dimmconn-0/dimm-0
144 # to: /xyz/openbmc_project/sensors/temperature/dimm0_temp
145 import re
146 dimmconn = re.search(r'dimmconn-\d+', p).group()
147 dimmId = re.search(r'\d+', dimmconn).group()
148 return '/xyz/openbmc_project/sensors/temperature/dimm{}_temp'.format(dimmId)
149
150
Lei YU25ecc552018-08-23 14:20:45 +0800151def getMembufTempPath(name):
152 # Convert names like MEMBUF0_Temp or CENTAUR0_Temp
153 # to: /xyz/openbmc_project/sensors/temperature/membuf0_temp
154 # to: /xyz/openbmc_project/sensors/temperature/centaur0_temp
155 return '/xyz/openbmc_project/sensors/temperature/{}'.format(name.lower())
156
157
158def getCoreTempPath(name, p):
159 # For different rpts:
160 # Convert path like:
161 # /sys-0/node-0/motherboard-0/proc_socket-0/module-0/p9_proc_s/eq0/ex0/core0 (for P9)
Lei YU206f7c42018-08-07 15:12:19 +0800162 # to: /xyz/openbmc_project/sensors/temperature/p0_core0_temp
Lei YU25ecc552018-08-23 14:20:45 +0800163 # or name like: CORE0_Temp (for P8)
164 # to: /xyz/openbmc_project/sensors/temperature/core0_temp (for P8)
Lei YU206f7c42018-08-07 15:12:19 +0800165 import re
Lei YU25ecc552018-08-23 14:20:45 +0800166 if 'p9_proc' in p:
167 splitted = p.split('/')
168 socket = re.search(r'\d+', splitted[4]).group()
169 core = re.search(r'\d+', splitted[9]).group()
170 return '/xyz/openbmc_project/sensors/temperature/p{}_core{}_temp'.format(socket, core)
171 else:
172 core = re.search(r'\d+', name).group()
173 return '/xyz/openbmc_project/sensors/temperature/core{}_temp'.format(core)
Lei YU206f7c42018-08-07 15:12:19 +0800174
175
176def getDimmTempConfig(s):
177 r = sampleDimmTemp.copy()
178 r['entityInstance'] = getEntityInstance(r['entityID'])
179 r['path'] = getDimmTempPath(s.targetPath)
180 return r
181
182
Lei YU25ecc552018-08-23 14:20:45 +0800183def getMembufTempConfig(s):
184 r = sampleDimmTemp.copy()
185 r['entityID'] = 0xD1
186 r['entityInstance'] = getEntityInstance(r['entityID'])
187 r['path'] = getMembufTempPath(s.name)
188 return r
189
190
Lei YU206f7c42018-08-07 15:12:19 +0800191def getCoreTempConfig(s):
192 r = sampleCoreTemp.copy()
193 r['entityInstance'] = getEntityInstance(r['entityID'])
Lei YU25ecc552018-08-23 14:20:45 +0800194 r['path'] = getCoreTempPath(s.name, s.targetPath)
Lei YU206f7c42018-08-07 15:12:19 +0800195 return r
196
197
Lei YUa49f04f2018-08-09 15:14:53 +0800198def isCoreTemp(p):
199 import re
200 m = re.search(r'p\d+_core\d+_temp', p)
201 return m is not None
202
203
204def getDcmiSensor(i, sensor):
205 import re
206 path = sensor['path']
207 name = path.split('/')[-1]
208 m = re.findall(r'\d+', name)
209 socket, core = int(m[0]), int(m[1])
210 instance = socket * 24 + core + 1
211 r = sampleDcmiSensor.copy()
212 r['instance'] = instance
213 r['dbus'] = path
214 r['record_id'] = i
215 return r
216
217
218def saveJson(data, f):
219 import json
220 with open(f, 'w') as outfile:
221 json.dump(data, outfile, indent=4)
222
223
Lei YUa03e55e2018-08-03 17:43:25 +0800224def main():
225 parser = argparse.ArgumentParser(
226 description='Yaml tool for updating ipmi sensor yaml config')
227 parser.add_argument('-i', '--input', required=True, dest='input',
228 help='The ipmi sensor yaml config')
229 parser.add_argument('-o', '--output', required=True, dest='output',
230 help='The output yaml file')
Lei YU9f394032018-08-08 11:25:21 +0800231 parser.add_argument('-m', '--map', dest='map', default='sensor_map.yaml',
232 help='The sample map yaml file')
Lei YUa03e55e2018-08-03 17:43:25 +0800233 parser.add_argument('-r', '--rpt', dest='rpt',
234 help='The .rpt file generated by op-build')
Lei YU9f394032018-08-08 11:25:21 +0800235 parser.add_argument('-f', '--fix', action='store_true',
236 help='Fix entities and sensorNamePattern')
Lei YUa49f04f2018-08-09 15:14:53 +0800237
238 # -g expects output as yaml for mapping of entityID/sensorNamePattern
239 # -d expects output as json config for dcmi sensors
240 # Do not mess the output by enforcing only one argument is passed
241 # TODO: -f and -r could be used together, and they are conflicted with -g or -d
242 group = parser.add_mutually_exclusive_group()
243 group.add_argument('-g', '--generate', action='store_true',
244 help='Generate maps for entityID and sensorNamePattern')
245 group.add_argument('-d', '--dcmi', action='store_true',
246 help='Generate dcmi sensors json config')
Lei YUa03e55e2018-08-03 17:43:25 +0800247
248 args = parser.parse_args()
249 args = vars(args)
250
251 if args['input'] is None or args['output'] is None:
252 parser.print_help()
253 exit(1)
254
Lei YUa03e55e2018-08-03 17:43:25 +0800255 y = openYaml(args['input'])
256
Lei YU9f394032018-08-08 11:25:21 +0800257 if args['fix']:
258 # Fix entities and sensorNamePattern
259 m = openYaml(args['map'])
260
Lei YUa03e55e2018-08-03 17:43:25 +0800261 for i in y:
262 path = y[i]['path']
Lei YU9f394032018-08-08 11:25:21 +0800263 intfs = tuple(sorted(list(y[i]['interfaces'].keys())))
264 entityId, namePattern = getEntityIdAndNamePattern(path, intfs, m)
Lei YUa03e55e2018-08-03 17:43:25 +0800265 y[i]['entityID'] = entityId
266 y[i]['entityInstance'] = getEntityInstance(entityId)
Lei YU9f394032018-08-08 11:25:21 +0800267 y[i]['sensorNamePattern'] = namePattern
Lei YUa03e55e2018-08-03 17:43:25 +0800268 print(y[i]['path'], "id:", entityId,
269 "instance:", y[i]['entityInstance'])
270
Lei YU206f7c42018-08-07 15:12:19 +0800271 sensorIds = list(y.keys())
272 if args['rpt']:
Lei YU25ecc552018-08-23 14:20:45 +0800273 unhandledSensors = []
Lei YU206f7c42018-08-07 15:12:19 +0800274 rptSensors = loadRpt(args['rpt'])
275 for s in rptSensors:
276 if s.sensorId is not None and s.sensorId not in sensorIds:
277 print("Sensor ID", s.sensorId, "not in yaml:",
278 s.name, ", path:", s.targetPath)
279 if 'temp' in s.name.lower():
280 if 'dimm' in s.targetPath.lower():
281 y[s.sensorId] = getDimmTempConfig(s)
282 print('Added sensor id:', s.sensorId,
283 ', path:', y[s.sensorId]['path'])
Lei YU25ecc552018-08-23 14:20:45 +0800284 elif 'core' in s.targetPath.lower():
Lei YU206f7c42018-08-07 15:12:19 +0800285 y[s.sensorId] = getCoreTempConfig(s)
286 print('Added sensor id:', s.sensorId,
287 ', path:', y[s.sensorId]['path'])
Lei YU25ecc552018-08-23 14:20:45 +0800288 elif 'centaur' in s.name.lower() or 'membuf' in s.name.lower():
289 y[s.sensorId] = getMembufTempConfig(s)
290 print('Added sensor id:', s.sensorId,
291 ', path:', y[s.sensorId]['path'])
292 else:
293 unhandledSensors.append(s)
294 else:
295 unhandledSensors.append(s)
296
297 print('Unhandled sensors:')
298 for s in unhandledSensors:
299 print(s)
Lei YU206f7c42018-08-07 15:12:19 +0800300
Lei YUdf0c4172018-08-08 10:42:08 +0800301 if args['generate']:
302 m = {}
303 for i in y:
304 path = y[i]['path']
305 intfs = tuple(sorted(list(y[i]['interfaces'].keys())))
306 entityId = y[i]['entityID']
307 sensorNamePattern = y[i]['sensorNamePattern']
308 m[(path, intfs)] = {'entityID': entityId,
309 'sensorNamePattern': sensorNamePattern}
310 y = m
311
Lei YUa49f04f2018-08-09 15:14:53 +0800312 if args['dcmi']:
313 d = []
314 for i in y:
315 if isCoreTemp(y[i]['path']):
316 s = getDcmiSensor(i, y[i])
317 d.append(s)
318 print(s)
319 saveJson(d, args['output'])
320 return
Lei YUdf0c4172018-08-08 10:42:08 +0800321
Lei YUa49f04f2018-08-09 15:14:53 +0800322 safe = False if args['generate'] else True
Lei YUdf0c4172018-08-08 10:42:08 +0800323 saveYaml(y, args['output'], safe)
Lei YUa03e55e2018-08-03 17:43:25 +0800324
325
326if __name__ == "__main__":
327 main()