blob: e83512a087a0b89af873e21a7a9678d81f973038 [file] [log] [blame]
Matt Spinlerd08dbe22017-04-11 13:52:54 -05001#!/usr/bin/env python
2
3"""
4This script reads in fan definition and zone definition YAML
5files and generates a set of structures for use by the fan control code.
6"""
7
8import os
9import sys
10import yaml
11from argparse import ArgumentParser
12from mako.template import Template
Matthew Barth702c4a52018-02-28 16:23:11 -060013from mako.lookup import TemplateLookup
Matt Spinlerd08dbe22017-04-11 13:52:54 -050014
Matt Spinler78498c92017-04-11 13:59:46 -050015
Matthew Barthbb12c922017-06-13 13:57:40 -050016def convertToMap(listOfDict):
17 """
18 Converts a list of dictionary entries to a std::map initialization list.
19 """
Matthew Barth9a5b6992018-01-23 15:32:26 -060020 listOfDict = listOfDict.replace('\'', '\"')
Matthew Barthbb12c922017-06-13 13:57:40 -050021 listOfDict = listOfDict.replace('[', '{')
22 listOfDict = listOfDict.replace(']', '}')
23 listOfDict = listOfDict.replace(':', ',')
24 return listOfDict
25
26
Matthew Bartha1aef7a2019-01-16 11:02:57 -060027def genEvent(event):
28 """
29 Generates the source code of an event and returns it as a string
30 """
31 e = "SetSpeedEvent{\n"
32
33 e += "Group{\n"
34 for group in event['groups']:
35 for member in group['members']:
36 e += "{\n"
37 e += "\"" + member['object'] + "\",\n"
38 e += "{\"" + member['interface'] + "\",\n"
39 e += " \"" + member['property'] + "\"}\n"
40 e += "},\n"
41 e += "},\n"
42
43 e += "std::vector<Action>{\n"
44 for a in event['action']:
45 if len(a['parameters']) != 0:
46 e += "make_action(action::" + a['name'] + "(\n"
47 else:
48 e += "make_action(action::" + a['name'] + "\n"
49 for i, p in enumerate(a['parameters']):
50 if (i+1) != len(a['parameters']):
51 e += p + ",\n"
52 else:
53 e += p + ")\n"
54 e += "),\n"
55 e += "},\n"
56
57 e += "TimerConf{\n"
58 e += "\t" + event['timer']['interval'] + ",\n"
59 e += "\t" + event['timer']['type'] + "\n"
60 e += "},\n"
61
62 e += "std::vector<Signal>{\n"
63 for s in event['signals']:
64 e += "Signal{\n"
65 e += "match::" + s['match'] + "(\n"
66 for i, mp in enumerate(s['mparams']):
67 if (i+1) != len(s['mparams']):
68 e += "\"" + mp + "\",\n"
69 else:
70 e += "\"" + mp + "\"\n"
71 e += "),\n"
72 e += "make_handler(\n"
73 if ('type' in s['sparams']) and (s['sparams']['type'] is not None):
74 e += s['signal'] + "<" + s['sparams']['type'] + ">(\n"
75 else:
76 e += s['signal'] + "(\n"
77 for sp in s['sparams']['params']:
78 e += s['sparams'][sp] + ",\n"
79 if ('type' in s['hparams']) and (s['hparams']['type'] is not None):
80 e += ("handler::" + s['handler'] +
81 "<" + s['hparams']['type'] + ">(\n")
82 else:
83 e += "handler::" + s['handler'] + "(\n)"
84 for i, hp in enumerate(s['hparams']['params']):
85 if (i+1) != len(s['hparams']['params']):
86 e += s['hparams'][hp] + ",\n"
87 else:
88 e += s['hparams'][hp] + "\n"
89 e += "))\n"
90 e += ")\n"
91 e += "},\n"
92 e += "}\n"
93
94 e += "}"
95
96 return e
97
98
Matthew Barth6c050692017-12-05 15:30:09 -060099def getGroups(zNum, zCond, edata, events):
100 """
101 Extract and construct the groups for the given event.
102 """
103 groups = []
104 for eGroups in edata['groups']:
105 if ('zone_conditions' in eGroups) and \
106 (eGroups['zone_conditions'] is not None):
107 # Zone conditions are optional in the events yaml but skip
108 # if this event's condition is not in this zone's conditions
109 if all('name' in z and z['name'] is not None and
110 not any(c['name'] == z['name'] for c in zCond)
111 for z in eGroups['zone_conditions']):
112 continue
113
114 # Zone numbers are optional in the events yaml but skip if this
115 # zone's zone number is not in the event's zone numbers
116 if all('zones' in z and z['zones'] is not None and
117 zNum not in z['zones']
118 for z in eGroups['zone_conditions']):
119 continue
Matthew Barth6c050692017-12-05 15:30:09 -0600120 eGroup = next(g for g in events['groups']
121 if g['name'] == eGroups['name'])
122
123 group = {}
124 members = []
125 group['name'] = eGroup['name']
126 for m in eGroup['members']:
127 member = {}
128 member['path'] = eGroup['type']
129 member['object'] = (eGroup['type'] + m)
130 member['interface'] = eGroups['interface']
131 member['property'] = eGroups['property']['name']
132 member['type'] = eGroups['property']['type']
133 # Add expected group member's property value if given
134 if ('value' in eGroups['property']) and \
135 (eGroups['property']['value'] is not None):
136 if isinstance(eGroups['property']['value'], str) or \
137 "string" in str(member['type']).lower():
138 member['value'] = (
139 "\"" + eGroups['property']['value'] + "\"")
140 else:
141 member['value'] = eGroups['property']['value']
142 members.append(member)
143 group['members'] = members
144 groups.append(group)
145 return groups
146
147
Matthew Bartha1aef7a2019-01-16 11:02:57 -0600148def getActions(zNum, zCond, edata, actions, events):
Matthew Barth9df74752017-10-11 14:39:31 -0500149 """
150 Extracts and constructs the make_action function call for
151 all the actions within the given event.
152 """
153 action = []
154 for eActions in actions['actions']:
155 actions = {}
156 eAction = next(a for a in events['actions']
157 if a['name'] == eActions['name'])
158 actions['name'] = eAction['name']
159 params = []
160 if ('parameters' in eAction) and \
161 (eAction['parameters'] is not None):
162 for p in eAction['parameters']:
163 param = "static_cast<"
164 if type(eActions[p]) is not dict:
165 if p == 'actions':
166 param = "std::vector<Action>{"
Matthew Bartha1aef7a2019-01-16 11:02:57 -0600167 pActs = getActions(zNum,
168 zCond,
169 edata,
170 eActions,
171 events)
Matthew Barth9df74752017-10-11 14:39:31 -0500172 for a in pActs:
173 if (len(a['parameters']) != 0):
174 param += (
175 "make_action(action::" +
176 a['name'] +
177 "(\n")
178 for i, ap in enumerate(a['parameters']):
179 if (i+1) != len(a['parameters']):
180 param += (ap + ",")
181 else:
182 param += (ap + ")")
183 else:
184 param += ("make_action(action::" + a['name'])
185 param += "),"
186 param += "}"
Matthew Bartha1aef7a2019-01-16 11:02:57 -0600187 elif p == 'defevents' or p == 'altevents':
188 param = "std::vector<SetSpeedEvent>{\n"
189 for i, e in enumerate(eActions[p]):
190 aEvent = getEvent(zNum, zCond, e, events)
191 if not aEvent:
192 continue
193 if (i+1) != len(eActions[p]):
194 param += genEvent(aEvent) + ",\n"
195 else:
196 param += genEvent(aEvent) + "\n"
197 param += "\t}"
Matthew Barth9df74752017-10-11 14:39:31 -0500198 elif p == 'property':
Matthew Barth9a5b6992018-01-23 15:32:26 -0600199 if isinstance(eActions[p], str) or \
Matthew Barth6c050692017-12-05 15:30:09 -0600200 "string" in str(eActions[p]['type']).lower():
Matthew Barth9a5b6992018-01-23 15:32:26 -0600201 param += (
Matthew Barth6c050692017-12-05 15:30:09 -0600202 str(eActions[p]['type']).lower() +
Matthew Barth9a5b6992018-01-23 15:32:26 -0600203 ">(\"" + str(eActions[p]) + "\")")
204 else:
205 param += (
Matthew Barth6c050692017-12-05 15:30:09 -0600206 str(eActions[p]['type']).lower() +
207 ">(" + str(eActions[p]['value']).lower() + ")")
Matthew Barth9df74752017-10-11 14:39:31 -0500208 else:
209 # Default type to 'size_t' when not given
210 param += ("size_t>(" + str(eActions[p]).lower() + ")")
211 else:
212 if p == 'timer':
213 param = (
William A. Kennington III122b8432018-10-30 18:39:21 -0700214 "TimerConf{static_cast<std::chrono::seconds>(" +
Matthew Barth9df74752017-10-11 14:39:31 -0500215 str(eActions[p]['delay']) + "), " +
William A. Kennington III0ce353e2018-10-30 18:30:36 -0700216 "TimerType::" +
Matthew Barth9df74752017-10-11 14:39:31 -0500217 str(eActions[p]['type']) + "}")
218 else:
219 param += (str(eActions[p]['type']).lower() + ">(")
220 if p != 'map':
Matthew Barth9a5b6992018-01-23 15:32:26 -0600221 if isinstance(eActions[p]['value'], str) or \
222 "string" in str(eActions[p]['type']).lower():
223 param += \
224 "\"" + str(eActions[p]['value']) + "\")"
225 else:
226 param += \
227 str(eActions[p]['value']).lower() + ")"
Matthew Barth9df74752017-10-11 14:39:31 -0500228 else:
229 param += (
230 str(eActions[p]['type']).lower() +
231 convertToMap(str(eActions[p]['value'])) + ")")
232 params.append(param)
233 actions['parameters'] = params
234 action.append(actions)
235 return action
236
237
Matthew Barth7f272fd2017-09-12 16:16:56 -0500238def getEvent(zone_num, zone_conditions, e, events_data):
239 """
240 Parses the sections of an event and populates the properties
241 that construct an event within the generated source.
242 """
243 event = {}
Matthew Barth7f272fd2017-09-12 16:16:56 -0500244
Matthew Barth6c050692017-12-05 15:30:09 -0600245 # Add set speed event groups
246 grps = getGroups(zone_num, zone_conditions, e, events_data)
247 if not grps:
Matthew Barth7f272fd2017-09-12 16:16:56 -0500248 return
Matthew Barth6c050692017-12-05 15:30:09 -0600249 event['groups'] = grps
Matthew Barth7f272fd2017-09-12 16:16:56 -0500250
Matthew Barthe3d1c4a2018-01-11 13:53:49 -0600251 # Add optional set speed actions and function parameters
252 event['action'] = []
253 if ('actions' in e) and \
254 (e['actions'] is not None):
Matthew Bartha1aef7a2019-01-16 11:02:57 -0600255 event['action'] = getActions(zone_num,
256 zone_conditions,
257 e,
258 e,
259 events_data)
Matthew Barth7f272fd2017-09-12 16:16:56 -0500260
Matthew Barth67967f92017-09-22 12:43:57 -0500261 # Add signal handlers
262 signals = []
Matthew Barth6c050692017-12-05 15:30:09 -0600263 for group in event['groups']:
264 for member in group['members']:
265 for eMatches in e['matches']:
266 signal = {}
267 eMatch = next(m for m in events_data['matches']
268 if m['name'] == eMatches['name'])
269 signal['match'] = eMatch['name']
270 params = []
271 if ('parameters' in eMatch) and \
272 (eMatch['parameters'] is not None):
273 for p in eMatch['parameters']:
274 params.append(member[str(p)])
275 signal['mparams'] = params
Matthew Barthe7d87052018-03-21 13:58:31 -0500276 if ('parameters' in eMatch['signal']) and \
277 (eMatch['signal']['parameters'] is not None):
278 eSignal = eMatch['signal']
279 else:
280 eSignal = next(s for s in events_data['signals']
281 if s['name'] == eMatch['signal'])
Matthew Barth6c050692017-12-05 15:30:09 -0600282 signal['signal'] = eSignal['name']
283 sparams = {}
284 if ('parameters' in eSignal) and \
285 (eSignal['parameters'] is not None):
286 splist = []
287 for p in eSignal['parameters']:
288 sp = str(p)
289 if (sp != 'type'):
290 splist.append(sp)
291 if (sp != 'group'):
292 sparams[sp] = "\"" + member[sp] + "\""
293 else:
294 sparams[sp] = "Group{\n"
295 for m in group['members']:
296 sparams[sp] += (
297 "{\n" +
298 "\"" + str(m['object']) + "\",\n" +
299 "{\"" + str(m['interface']) + "\"," +
300 "\"" + str(m['property']) + "\"}\n" +
301 "},\n")
302 sparams[sp] += "}"
Matthew Barth9f964bf2017-10-02 15:07:00 -0500303 else:
Matthew Barth6c050692017-12-05 15:30:09 -0600304 sparams[sp] = member[sp]
305 sparams['params'] = splist
306 signal['sparams'] = sparams
307 # Add signal handler
308 eHandler = next(h for h in events_data['handlers']
309 if h['name'] == eSignal['handler'])
310 signal['handler'] = eHandler['name']
311 hparams = {}
312 if ('parameters' in eHandler) and \
313 (eHandler['parameters'] is not None):
314 hplist = []
315 for p in eHandler['parameters']:
316 hp = str(p)
317 if (hp != 'type'):
318 hplist.append(hp)
319 if (hp != 'group'):
320 hparams[hp] = "\"" + member[hp] + "\""
321 else:
322 hparams[hp] = "Group{\n"
323 for m in group['members']:
324 hparams[hp] += (
325 "{\n" +
326 "\"" + str(m['object']) + "\",\n" +
327 "{\"" + str(m['interface']) + "\"," +
328 "\"" + str(m['property']) + "\"}\n" +
329 "},\n")
330 hparams[hp] += "}"
Matthew Barth9f964bf2017-10-02 15:07:00 -0500331 else:
Matthew Barth6c050692017-12-05 15:30:09 -0600332 hparams[hp] = member[hp]
333 hparams['params'] = hplist
334 signal['hparams'] = hparams
335 signals.append(signal)
Matthew Barth67967f92017-09-22 12:43:57 -0500336 event['signals'] = signals
Matthew Barth7f272fd2017-09-12 16:16:56 -0500337
338 # Add optional action call timer
339 timer = {}
340 interval = "static_cast<std::chrono::seconds>"
341 if ('timer' in e) and \
342 (e['timer'] is not None):
343 timer['interval'] = (interval +
344 "(" +
345 str(e['timer']['interval']) +
346 ")")
347 else:
348 timer['interval'] = (interval +
349 "(" + str(0) + ")")
William A. Kennington III0ce353e2018-10-30 18:30:36 -0700350 timer['type'] = "TimerType::repeating"
Matthew Barth7f272fd2017-09-12 16:16:56 -0500351 event['timer'] = timer
352
353 return event
354
355
356def addPrecondition(zNum, zCond, event, events_data):
Matthew Barth9af190c2017-08-08 14:20:43 -0500357 """
358 Parses the precondition section of an event and populates the necessary
359 structures to generate a precondition for a set speed event.
360 """
361 precond = {}
362 # Add set speed event precondition group
Matthew Barth6c050692017-12-05 15:30:09 -0600363 grps = getGroups(zNum, zCond, event['precondition'], events_data)
364 if not grps:
365 return
366 precond['pcgrps'] = grps
Matthew Barth9af190c2017-08-08 14:20:43 -0500367
Matthew Barth7f272fd2017-09-12 16:16:56 -0500368 # Add set speed event precondition actions
369 pc = []
370 pcs = {}
371 pcs['name'] = event['precondition']['name']
372 epc = next(p for p in events_data['preconditions']
Matthew Barth9af190c2017-08-08 14:20:43 -0500373 if p['name'] == event['precondition']['name'])
374 params = []
Matthew Barth7f272fd2017-09-12 16:16:56 -0500375 for p in epc['parameters']:
Matthew Barth9af190c2017-08-08 14:20:43 -0500376 param = {}
377 if p == 'groups':
378 param['type'] = "std::vector<PrecondGroup>"
379 param['open'] = "{"
380 param['close'] = "}"
381 values = []
Matthew Barth6c050692017-12-05 15:30:09 -0600382 for group in precond['pcgrps']:
383 for pcgrp in group['members']:
384 value = {}
385 value['value'] = (
386 "PrecondGroup{\"" +
387 str(pcgrp['object']) + "\",\"" +
388 str(pcgrp['interface']) + "\",\"" +
389 str(pcgrp['property']) + "\"," +
390 "static_cast<" +
391 str(pcgrp['type']).lower() + ">")
392 if isinstance(pcgrp['value'], str) or \
393 "string" in str(pcgrp['type']).lower():
394 value['value'] += ("(" + str(pcgrp['value']) + ")}")
395 else:
396 value['value'] += \
397 ("(" + str(pcgrp['value']).lower() + ")}")
398 values.append(value)
Matthew Barth9af190c2017-08-08 14:20:43 -0500399 param['values'] = values
400 params.append(param)
Matthew Barth7f272fd2017-09-12 16:16:56 -0500401 pcs['params'] = params
402 pc.append(pcs)
Matthew Barth9af190c2017-08-08 14:20:43 -0500403 precond['pcact'] = pc
404
Matthew Barth7f272fd2017-09-12 16:16:56 -0500405 pcevents = []
406 for pce in event['precondition']['events']:
407 pcevent = getEvent(zNum, zCond, pce, events_data)
408 if not pcevent:
409 continue
410 pcevents.append(pcevent)
411 precond['pcevts'] = pcevents
412
Matthew Barth67967f92017-09-22 12:43:57 -0500413 # Add precondition signal handlers
414 signals = []
Matthew Barth6c050692017-12-05 15:30:09 -0600415 for group in precond['pcgrps']:
416 for member in group['members']:
417 for eMatches in event['precondition']['matches']:
418 signal = {}
419 eMatch = next(m for m in events_data['matches']
420 if m['name'] == eMatches['name'])
421 signal['match'] = eMatch['name']
422 params = []
423 if ('parameters' in eMatch) and \
424 (eMatch['parameters'] is not None):
425 for p in eMatch['parameters']:
426 params.append(member[str(p)])
427 signal['mparams'] = params
Matthew Barthe7d87052018-03-21 13:58:31 -0500428 if ('parameters' in eMatch['signal']) and \
429 (eMatch['signal']['parameters'] is not None):
430 eSignal = eMatch['signal']
431 else:
432 eSignal = next(s for s in events_data['signals']
433 if s['name'] == eMatch['signal'])
Matthew Barth6c050692017-12-05 15:30:09 -0600434 signal['signal'] = eSignal['name']
435 sparams = {}
436 if ('parameters' in eSignal) and \
437 (eSignal['parameters'] is not None):
438 splist = []
439 for p in eSignal['parameters']:
440 sp = str(p)
441 if (sp != 'type'):
442 splist.append(sp)
443 if (sp != 'group'):
444 sparams[sp] = "\"" + member[sp] + "\""
445 else:
446 sparams[sp] = "Group{\n"
447 for m in group:
448 sparams[sp] += (
449 "{\n" +
450 "\"" + str(m['object']) + "\",\n" +
451 "{\"" + str(m['interface']) + "\"," +
452 "\"" + str(m['property']) + "\"}\n" +
453 "},\n")
454 sparams[sp] += "}"
Matthew Barth9f964bf2017-10-02 15:07:00 -0500455 else:
Matthew Barth6c050692017-12-05 15:30:09 -0600456 sparams[sp] = member[sp]
457 sparams['params'] = splist
458 signal['sparams'] = sparams
459 # Add signal handler
460 eHandler = next(h for h in events_data['handlers']
461 if h['name'] == eSignal['handler'])
462 signal['handler'] = eHandler['name']
463 hparams = {}
464 if ('parameters' in eHandler) and \
465 (eHandler['parameters'] is not None):
466 hplist = []
467 for p in eHandler['parameters']:
468 hp = str(p)
469 if (hp != 'type'):
470 hplist.append(hp)
471 if (hp != 'group'):
472 hparams[hp] = "\"" + member[hp] + "\""
473 else:
474 hparams[hp] = "Group{\n"
475 for m in group:
476 hparams[hp] += (
477 "{\n" +
478 "\"" + str(m['object']) + "\",\n" +
479 "{\"" + str(m['interface']) + "\"," +
480 "\"" + str(m['property']) + "\"}\n" +
481 "},\n")
482 hparams[hp] += "}"
Matthew Barth9f964bf2017-10-02 15:07:00 -0500483 else:
Matthew Barth6c050692017-12-05 15:30:09 -0600484 hparams[hp] = member[hp]
485 hparams['params'] = hplist
486 signal['hparams'] = hparams
487 signals.append(signal)
Matthew Barth67967f92017-09-22 12:43:57 -0500488 precond['pcsigs'] = signals
Matthew Barth9af190c2017-08-08 14:20:43 -0500489
Matthew Barth90149802017-08-15 10:51:37 -0500490 # Add optional action call timer
491 timer = {}
492 interval = "static_cast<std::chrono::seconds>"
493 if ('timer' in event['precondition']) and \
494 (event['precondition']['timer'] is not None):
495 timer['interval'] = (interval +
496 "(" +
497 str(event['precondition']['timer']['interval']) +
498 ")")
499 else:
500 timer['interval'] = (interval +
501 "(" + str(0) + ")")
William A. Kennington III0ce353e2018-10-30 18:30:36 -0700502 timer['type'] = "TimerType::repeating"
Matthew Barth90149802017-08-15 10:51:37 -0500503 precond['pctime'] = timer
504
Matthew Barth9af190c2017-08-08 14:20:43 -0500505 return precond
506
507
Gunnar Millsb751f322017-06-06 15:14:11 -0500508def getEventsInZone(zone_num, zone_conditions, events_data):
Matthew Barthd4d0f082017-05-16 13:51:10 -0500509 """
510 Constructs the event entries defined for each zone using the events yaml
511 provided.
512 """
513 events = []
Matthew Barthba102b32017-05-16 16:13:56 -0500514
Matthew Barthd4d0f082017-05-16 13:51:10 -0500515 if 'events' in events_data:
516 for e in events_data['events']:
Matthew Barthd4d0f082017-05-16 13:51:10 -0500517 event = {}
Matthew Barth9af190c2017-08-08 14:20:43 -0500518 # Add precondition if given
519 if ('precondition' in e) and \
520 (e['precondition'] is not None):
Matthew Barth7f272fd2017-09-12 16:16:56 -0500521 event['pc'] = addPrecondition(zone_num,
522 zone_conditions,
523 e,
524 events_data)
Matthew Barth90149802017-08-15 10:51:37 -0500525 else:
Matthew Barth7f272fd2017-09-12 16:16:56 -0500526 event = getEvent(zone_num, zone_conditions, e, events_data)
527 if not event:
528 continue
Matthew Barthd4d0f082017-05-16 13:51:10 -0500529 events.append(event)
530
531 return events
532
533
Matt Spinler78498c92017-04-11 13:59:46 -0500534def getFansInZone(zone_num, profiles, fan_data):
535 """
536 Parses the fan definition YAML files to find the fans
537 that match both the zone passed in and one of the
538 cooling profiles.
539 """
540
541 fans = []
542
543 for f in fan_data['fans']:
544
545 if zone_num != f['cooling_zone']:
546 continue
547
Gunnar Mills67e95512017-06-02 14:35:18 -0500548 # 'cooling_profile' is optional (use 'all' instead)
Matt Spinler78498c92017-04-11 13:59:46 -0500549 if f.get('cooling_profile') is None:
550 profile = "all"
551 else:
552 profile = f['cooling_profile']
553
554 if profile not in profiles:
555 continue
556
557 fan = {}
558 fan['name'] = f['inventory']
559 fan['sensors'] = f['sensors']
Lei YU069e4402018-01-31 16:47:37 +0800560 fan['target_interface'] = f.get(
561 'target_interface',
562 'xyz.openbmc_project.Control.FanSpeed')
Matt Spinler78498c92017-04-11 13:59:46 -0500563 fans.append(fan)
564
565 return fans
566
567
Gunnar Millsee8a2812017-06-02 14:26:47 -0500568def getConditionInZoneConditions(zone_condition, zone_conditions_data):
569 """
570 Parses the zone conditions definition YAML files to find the condition
571 that match both the zone condition passed in.
572 """
573
574 condition = {}
575
576 for c in zone_conditions_data['conditions']:
577
578 if zone_condition != c['name']:
579 continue
580 condition['type'] = c['type']
581 properties = []
582 for p in c['properties']:
583 property = {}
584 property['property'] = p['property']
585 property['interface'] = p['interface']
586 property['path'] = p['path']
587 property['type'] = p['type'].lower()
588 property['value'] = str(p['value']).lower()
589 properties.append(property)
590 condition['properties'] = properties
591
592 return condition
593
594
595def buildZoneData(zone_data, fan_data, events_data, zone_conditions_data):
Matt Spinler78498c92017-04-11 13:59:46 -0500596 """
597 Combines the zone definition YAML and fan
598 definition YAML to create a data structure defining
599 the fan cooling zones.
600 """
601
602 zone_groups = []
603
604 for group in zone_data:
605 conditions = []
Gunnar Millsee8a2812017-06-02 14:26:47 -0500606 # zone conditions are optional
607 if 'zone_conditions' in group and group['zone_conditions'] is not None:
608 for c in group['zone_conditions']:
609
610 if not zone_conditions_data:
Gunnar Millsb751f322017-06-06 15:14:11 -0500611 sys.exit("No zone_conditions YAML file but " +
Gunnar Millsee8a2812017-06-02 14:26:47 -0500612 "zone_conditions used in zone YAML")
613
614 condition = getConditionInZoneConditions(c['name'],
615 zone_conditions_data)
616
617 if not condition:
618 sys.exit("Missing zone condition " + c['name'])
619
620 conditions.append(condition)
Matt Spinler78498c92017-04-11 13:59:46 -0500621
622 zone_group = {}
623 zone_group['conditions'] = conditions
624
625 zones = []
626 for z in group['zones']:
627 zone = {}
628
Gunnar Mills67e95512017-06-02 14:35:18 -0500629 # 'zone' is required
630 if ('zone' not in z) or (z['zone'] is None):
Matt Spinler78498c92017-04-11 13:59:46 -0500631 sys.exit("Missing fan zone number in " + zone_yaml)
632
633 zone['num'] = z['zone']
634
635 zone['full_speed'] = z['full_speed']
636
Matthew Barth1de66622017-06-12 13:13:02 -0500637 zone['default_floor'] = z['default_floor']
638
Matthew Bartha9561842017-06-29 11:43:45 -0500639 # 'increase_delay' is optional (use 0 by default)
640 key = 'increase_delay'
641 zone[key] = z.setdefault(key, 0)
642
643 # 'decrease_interval' is optional (use 0 by default)
644 key = 'decrease_interval'
645 zone[key] = z.setdefault(key, 0)
646
Gunnar Mills67e95512017-06-02 14:35:18 -0500647 # 'cooling_profiles' is optional (use 'all' instead)
648 if ('cooling_profiles' not in z) or \
Matt Spinler78498c92017-04-11 13:59:46 -0500649 (z['cooling_profiles'] is None):
650 profiles = ["all"]
651 else:
652 profiles = z['cooling_profiles']
653
654 fans = getFansInZone(z['zone'], profiles, fan_data)
Gunnar Millsb751f322017-06-06 15:14:11 -0500655 events = getEventsInZone(z['zone'], group['zone_conditions'],
656 events_data)
Matt Spinler78498c92017-04-11 13:59:46 -0500657
658 if len(fans) == 0:
659 sys.exit("Didn't find any fans in zone " + str(zone['num']))
660
661 zone['fans'] = fans
Matthew Barthd4d0f082017-05-16 13:51:10 -0500662 zone['events'] = events
Matt Spinler78498c92017-04-11 13:59:46 -0500663 zones.append(zone)
664
665 zone_group['zones'] = zones
666 zone_groups.append(zone_group)
667
668 return zone_groups
669
670
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500671if __name__ == '__main__':
672 parser = ArgumentParser(
673 description="Phosphor fan zone definition parser")
674
675 parser.add_argument('-z', '--zone_yaml', dest='zone_yaml',
676 default="example/zones.yaml",
677 help='fan zone definitional yaml')
678 parser.add_argument('-f', '--fan_yaml', dest='fan_yaml',
679 default="example/fans.yaml",
680 help='fan definitional yaml')
Matthew Barthd4d0f082017-05-16 13:51:10 -0500681 parser.add_argument('-e', '--events_yaml', dest='events_yaml',
682 help='events to set speeds yaml')
Gunnar Millsee8a2812017-06-02 14:26:47 -0500683 parser.add_argument('-c', '--zone_conditions_yaml',
684 dest='zone_conditions_yaml',
685 help='conditions to determine zone yaml')
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500686 parser.add_argument('-o', '--output_dir', dest='output_dir',
687 default=".",
688 help='output directory')
689 args = parser.parse_args()
690
691 if not args.zone_yaml or not args.fan_yaml:
692 parser.print_usage()
William A. Kennington III3e781062018-10-19 17:18:34 -0700693 sys.exit(1)
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500694
695 with open(args.zone_yaml, 'r') as zone_input:
696 zone_data = yaml.safe_load(zone_input) or {}
697
698 with open(args.fan_yaml, 'r') as fan_input:
699 fan_data = yaml.safe_load(fan_input) or {}
700
Matthew Barthd4d0f082017-05-16 13:51:10 -0500701 events_data = {}
702 if args.events_yaml:
703 with open(args.events_yaml, 'r') as events_input:
704 events_data = yaml.safe_load(events_input) or {}
705
Gunnar Millsee8a2812017-06-02 14:26:47 -0500706 zone_conditions_data = {}
707 if args.zone_conditions_yaml:
708 with open(args.zone_conditions_yaml, 'r') as zone_conditions_input:
709 zone_conditions_data = yaml.safe_load(zone_conditions_input) or {}
710
Matt Spinleree7f6422017-05-09 11:03:14 -0500711 zone_config = buildZoneData(zone_data.get('zone_configuration', {}),
Gunnar Millsee8a2812017-06-02 14:26:47 -0500712 fan_data, events_data, zone_conditions_data)
Matt Spinleree7f6422017-05-09 11:03:14 -0500713
714 manager_config = zone_data.get('manager_configuration', {})
715
716 if manager_config.get('power_on_delay') is None:
717 manager_config['power_on_delay'] = 0
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500718
Matthew Barth702c4a52018-02-28 16:23:11 -0600719 tmpls_dir = os.path.join(
720 os.path.dirname(os.path.realpath(__file__)),
721 "templates")
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500722 output_file = os.path.join(args.output_dir, "fan_zone_defs.cpp")
Matthew Barth702c4a52018-02-28 16:23:11 -0600723 if sys.version_info < (3, 0):
724 lkup = TemplateLookup(
725 directories=tmpls_dir.split(),
726 disable_unicode=True)
727 else:
728 lkup = TemplateLookup(
729 directories=tmpls_dir.split())
730 tmpl = lkup.get_template('fan_zone_defs.mako.cpp')
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500731 with open(output_file, 'w') as output:
Matthew Barth702c4a52018-02-28 16:23:11 -0600732 output.write(tmpl.render(zones=zone_config,
733 mgr_data=manager_config))