blob: 8db1303e3c318afef450f0344f7150dc76c9d038 [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:
100 raise Exception('Unable to find sensor', key, 'from map')
101 return (m[key]['entityID'], m[key]['sensorNamePattern'])
Lei YUa03e55e2018-08-03 17:43:25 +0800102
103
104# Global entity instances
105entityInstances = {}
106
107
108def getEntityInstance(id):
109 instanceId = entityInstances.get(id, 0)
110 instanceId = instanceId + 1
111 entityInstances[id] = instanceId
112 print("EntityId:", id, "InstanceId:", instanceId)
113 return instanceId
114
115
Lei YUd4051652018-08-06 17:02:00 +0800116def loadRpt(rptFile):
117 sensors = []
118 with open(rptFile) as f:
119 next(f)
120 next(f)
121 for line in f:
122 fields = line.strip().split('|')
123 fields = list(map(str.strip, fields))
124 sensor = RptSensor(
125 fields[0],
126 int(fields[2], 16) if fields[2] else None,
127 int(fields[3], 16) if fields[3] else None,
128 int(fields[4], 16) if fields[4] else None,
129 int(fields[5], 16) if fields[5] else None,
130 int(fields[7], 16) if fields[7] else None,
131 fields[9])
132 # print(sensor)
133 sensors.append(sensor)
134 return sensors
135
136
Lei YU206f7c42018-08-07 15:12:19 +0800137def getDimmTempPath(p):
138 # Convert path like: /sys-0/node-0/motherboard-0/dimmconn-0/dimm-0
139 # to: /xyz/openbmc_project/sensors/temperature/dimm0_temp
140 import re
141 dimmconn = re.search(r'dimmconn-\d+', p).group()
142 dimmId = re.search(r'\d+', dimmconn).group()
143 return '/xyz/openbmc_project/sensors/temperature/dimm{}_temp'.format(dimmId)
144
145
146def getCoreTempPath(p):
147 # Convert path like: /sys-0/node-0/motherboard-0/proc_socket-0/module-0/p9_proc_s/eq0/ex0/core0
148 # to: /xyz/openbmc_project/sensors/temperature/p0_core0_temp
149 import re
150 splitted = p.split('/')
151 socket = re.search(r'\d+', splitted[4]).group()
152 core = re.search(r'\d+', splitted[9]).group()
153 return '/xyz/openbmc_project/sensors/temperature/p{}_core{}_temp'.format(socket, core)
154
155
156def getDimmTempConfig(s):
157 r = sampleDimmTemp.copy()
158 r['entityInstance'] = getEntityInstance(r['entityID'])
159 r['path'] = getDimmTempPath(s.targetPath)
160 return r
161
162
163def getCoreTempConfig(s):
164 r = sampleCoreTemp.copy()
165 r['entityInstance'] = getEntityInstance(r['entityID'])
166 r['path'] = getCoreTempPath(s.targetPath)
167 return r
168
169
Lei YUa49f04f2018-08-09 15:14:53 +0800170def isCoreTemp(p):
171 import re
172 m = re.search(r'p\d+_core\d+_temp', p)
173 return m is not None
174
175
176def getDcmiSensor(i, sensor):
177 import re
178 path = sensor['path']
179 name = path.split('/')[-1]
180 m = re.findall(r'\d+', name)
181 socket, core = int(m[0]), int(m[1])
182 instance = socket * 24 + core + 1
183 r = sampleDcmiSensor.copy()
184 r['instance'] = instance
185 r['dbus'] = path
186 r['record_id'] = i
187 return r
188
189
190def saveJson(data, f):
191 import json
192 with open(f, 'w') as outfile:
193 json.dump(data, outfile, indent=4)
194
195
Lei YUa03e55e2018-08-03 17:43:25 +0800196def main():
197 parser = argparse.ArgumentParser(
198 description='Yaml tool for updating ipmi sensor yaml config')
199 parser.add_argument('-i', '--input', required=True, dest='input',
200 help='The ipmi sensor yaml config')
201 parser.add_argument('-o', '--output', required=True, dest='output',
202 help='The output yaml file')
Lei YU9f394032018-08-08 11:25:21 +0800203 parser.add_argument('-m', '--map', dest='map', default='sensor_map.yaml',
204 help='The sample map yaml file')
Lei YUa03e55e2018-08-03 17:43:25 +0800205 parser.add_argument('-r', '--rpt', dest='rpt',
206 help='The .rpt file generated by op-build')
Lei YU9f394032018-08-08 11:25:21 +0800207 parser.add_argument('-f', '--fix', action='store_true',
208 help='Fix entities and sensorNamePattern')
Lei YUa49f04f2018-08-09 15:14:53 +0800209
210 # -g expects output as yaml for mapping of entityID/sensorNamePattern
211 # -d expects output as json config for dcmi sensors
212 # Do not mess the output by enforcing only one argument is passed
213 # TODO: -f and -r could be used together, and they are conflicted with -g or -d
214 group = parser.add_mutually_exclusive_group()
215 group.add_argument('-g', '--generate', action='store_true',
216 help='Generate maps for entityID and sensorNamePattern')
217 group.add_argument('-d', '--dcmi', action='store_true',
218 help='Generate dcmi sensors json config')
Lei YUa03e55e2018-08-03 17:43:25 +0800219
220 args = parser.parse_args()
221 args = vars(args)
222
223 if args['input'] is None or args['output'] is None:
224 parser.print_help()
225 exit(1)
226
Lei YUa03e55e2018-08-03 17:43:25 +0800227 y = openYaml(args['input'])
228
Lei YU9f394032018-08-08 11:25:21 +0800229 if args['fix']:
230 # Fix entities and sensorNamePattern
231 m = openYaml(args['map'])
232
Lei YUa03e55e2018-08-03 17:43:25 +0800233 for i in y:
234 path = y[i]['path']
Lei YU9f394032018-08-08 11:25:21 +0800235 intfs = tuple(sorted(list(y[i]['interfaces'].keys())))
236 entityId, namePattern = getEntityIdAndNamePattern(path, intfs, m)
Lei YUa03e55e2018-08-03 17:43:25 +0800237 y[i]['entityID'] = entityId
238 y[i]['entityInstance'] = getEntityInstance(entityId)
Lei YU9f394032018-08-08 11:25:21 +0800239 y[i]['sensorNamePattern'] = namePattern
Lei YUa03e55e2018-08-03 17:43:25 +0800240 print(y[i]['path'], "id:", entityId,
241 "instance:", y[i]['entityInstance'])
242
Lei YU206f7c42018-08-07 15:12:19 +0800243 sensorIds = list(y.keys())
244 if args['rpt']:
245 rptSensors = loadRpt(args['rpt'])
246 for s in rptSensors:
247 if s.sensorId is not None and s.sensorId not in sensorIds:
248 print("Sensor ID", s.sensorId, "not in yaml:",
249 s.name, ", path:", s.targetPath)
250 if 'temp' in s.name.lower():
251 if 'dimm' in s.targetPath.lower():
252 y[s.sensorId] = getDimmTempConfig(s)
253 print('Added sensor id:', s.sensorId,
254 ', path:', y[s.sensorId]['path'])
255 if 'core' in s.targetPath.lower():
256 y[s.sensorId] = getCoreTempConfig(s)
257 print('Added sensor id:', s.sensorId,
258 ', path:', y[s.sensorId]['path'])
259
Lei YUdf0c4172018-08-08 10:42:08 +0800260 if args['generate']:
261 m = {}
262 for i in y:
263 path = y[i]['path']
264 intfs = tuple(sorted(list(y[i]['interfaces'].keys())))
265 entityId = y[i]['entityID']
266 sensorNamePattern = y[i]['sensorNamePattern']
267 m[(path, intfs)] = {'entityID': entityId,
268 'sensorNamePattern': sensorNamePattern}
269 y = m
270
Lei YUa49f04f2018-08-09 15:14:53 +0800271 if args['dcmi']:
272 d = []
273 for i in y:
274 if isCoreTemp(y[i]['path']):
275 s = getDcmiSensor(i, y[i])
276 d.append(s)
277 print(s)
278 saveJson(d, args['output'])
279 return
Lei YUdf0c4172018-08-08 10:42:08 +0800280
Lei YUa49f04f2018-08-09 15:14:53 +0800281 safe = False if args['generate'] else True
Lei YUdf0c4172018-08-08 10:42:08 +0800282 saveYaml(y, args['output'], safe)
Lei YUa03e55e2018-08-03 17:43:25 +0800283
284
285if __name__ == "__main__":
286 main()