blob: fcd3f023d22d76fccd87b78fa10edea6000dfb23 [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
13
Matthew Barth336f18a2017-09-26 09:15:56 -050014tmpl = '''\
Matthew Barth7f272fd2017-09-12 16:16:56 -050015<%!
16def indent(str, depth):
17 return ''.join(4*' '*depth+line for line in str.splitlines(True))
Matthew Barth336f18a2017-09-26 09:15:56 -050018%>\
Matthew Barth9f964bf2017-10-02 15:07:00 -050019<%def name="genHandler(sig)" buffered="True">
20%if ('type' in sig['sparams']) and \
21 (sig['sparams']['type'] is not None):
22${sig['signal']}<${sig['sparams']['type']}>(
23%else:
24${sig['signal']}(
25%endif
26%for spk in sig['sparams']['params']:
27${sig['sparams'][spk]},
28%endfor
29%if ('type' in sig['hparams']) and \
30 (sig['hparams']['type'] is not None):
31handler::${sig['handler']}<${sig['hparams']['type']}>(
32%else:
33handler::${sig['handler']}(
34%endif
35%for i, hpk in enumerate(sig['hparams']['params']):
36 %if (i+1) != len(sig['hparams']['params']):
37 ${sig['hparams'][hpk]},
38 %else:
39 ${sig['hparams'][hpk]}
40 %endif
41%endfor
42))
43</%def>\
Matthew Barth7f272fd2017-09-12 16:16:56 -050044<%def name="genSSE(event)" buffered="True">
45Group{
46%for member in event['group']:
47{
Matthew Barth67967f92017-09-22 12:43:57 -050048 "${member['object']}",
Matthew Barth7f272fd2017-09-12 16:16:56 -050049 {"${member['interface']}",
50 "${member['property']}"}
51},
52%endfor
53},
54std::vector<Action>{
55%for a in event['action']:
Matthew Barth4c04a012017-09-15 13:05:30 -050056%if len(a['parameters']) != 0:
Matthew Barth7f272fd2017-09-12 16:16:56 -050057make_action(action::${a['name']}(
Matthew Barth4c04a012017-09-15 13:05:30 -050058%else:
59make_action(action::${a['name']}
60%endif
Matthew Barth7f272fd2017-09-12 16:16:56 -050061%for i, p in enumerate(a['parameters']):
62%if (i+1) != len(a['parameters']):
63 static_cast<${p['type']}>(${p['value']}),
64%else:
Matthew Barth4c04a012017-09-15 13:05:30 -050065 static_cast<${p['type']}>(${p['value']}))
Matthew Barth7f272fd2017-09-12 16:16:56 -050066%endif
67%endfor
Matthew Barth4c04a012017-09-15 13:05:30 -050068),
Matthew Barth7f272fd2017-09-12 16:16:56 -050069%endfor
70},
71Timer{
Matthew Barth7b7ceb82017-10-04 12:59:50 -050072 ${event['timer']['interval']},
73 ${event['timer']['type']}
Matthew Barth7f272fd2017-09-12 16:16:56 -050074},
Matthew Barth67967f92017-09-22 12:43:57 -050075std::vector<Signal>{
76%for s in event['signals']:
77 Signal{
Matthew Barth336f18a2017-09-26 09:15:56 -050078 match::${s['match']}(
Matthew Barth67967f92017-09-22 12:43:57 -050079 %for i, mp in enumerate(s['mparams']):
80 %if (i+1) != len(s['mparams']):
81 "${mp}",
82 %else:
83 "${mp}"
84 %endif
85 %endfor
86 ),
Matthew Barth9f964bf2017-10-02 15:07:00 -050087 make_handler(\
88 ${indent(genHandler(sig=s), 3)}\
89 )
Matthew Barth7f272fd2017-09-12 16:16:56 -050090 },
91%endfor
92}
Matthew Barth336f18a2017-09-26 09:15:56 -050093</%def>\
Matthew Barth7f272fd2017-09-12 16:16:56 -050094/* This is a generated file. */
Matt Spinlerd08dbe22017-04-11 13:52:54 -050095#include "manager.hpp"
Matthew Barthba102b32017-05-16 16:13:56 -050096#include "functor.hpp"
97#include "actions.hpp"
Matthew Barth7e527c12017-05-17 10:14:15 -050098#include "handlers.hpp"
Matthew Barth9af190c2017-08-08 14:20:43 -050099#include "preconditions.hpp"
Matthew Barth336f18a2017-09-26 09:15:56 -0500100#include "matches.hpp"
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500101
102using namespace phosphor::fan::control;
103
Matt Spinleree7f6422017-05-09 11:03:14 -0500104const unsigned int Manager::_powerOnDelay{${mgr_data['power_on_delay']}};
105
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500106const std::vector<ZoneGroup> Manager::_zoneLayouts
107{
108%for zone_group in zones:
Matthew Barth9c726672017-05-18 13:44:46 -0500109 ZoneGroup{
Gunnar Millsee8a2812017-06-02 14:26:47 -0500110 std::vector<Condition>{
111 %for condition in zone_group['conditions']:
112 Condition{
113 "${condition['type']}",
114 std::vector<ConditionProperty>{
115 %for property in condition['properties']:
116 ConditionProperty{
117 "${property['property']}",
118 "${property['interface']}",
119 "${property['path']}",
120 static_cast<${property['type']}>(${property['value']}),
121 },
122 %endfor
123 },
124 },
125 %endfor
126 },
Matthew Barth9c726672017-05-18 13:44:46 -0500127 std::vector<ZoneDefinition>{
128 %for zone in zone_group['zones']:
129 ZoneDefinition{
130 ${zone['num']},
131 ${zone['full_speed']},
Matthew Barth1de66622017-06-12 13:13:02 -0500132 ${zone['default_floor']},
Matthew Bartha9561842017-06-29 11:43:45 -0500133 ${zone['increase_delay']},
134 ${zone['decrease_interval']},
Matthew Barth9c726672017-05-18 13:44:46 -0500135 std::vector<FanDefinition>{
136 %for fan in zone['fans']:
137 FanDefinition{
138 "${fan['name']}",
139 std::vector<std::string>{
140 %for sensor in fan['sensors']:
141 "${sensor}",
142 %endfor
143 }
144 },
145 %endfor
146 },
147 std::vector<SetSpeedEvent>{
148 %for event in zone['events']:
Matthew Barth9af190c2017-08-08 14:20:43 -0500149 %if ('pc' in event) and \
150 (event['pc'] is not None):
151 SetSpeedEvent{
152 Group{
153 %for member in event['pc']['pcgrp']:
154 {
Matthew Barth67967f92017-09-22 12:43:57 -0500155 "${member['object']}",
Matthew Barth9af190c2017-08-08 14:20:43 -0500156 {"${member['interface']}",
157 "${member['property']}"}
158 },
159 %endfor
160 },
Matthew Barth7f272fd2017-09-12 16:16:56 -0500161 std::vector<Action>{
162 %for i, a in enumerate(event['pc']['pcact']):
Matthew Barth4c04a012017-09-15 13:05:30 -0500163 %if len(a['params']) != 0:
Matthew Barth9af190c2017-08-08 14:20:43 -0500164 make_action(
Matthew Barth7f272fd2017-09-12 16:16:56 -0500165 precondition::${a['name']}(
Matthew Barth4c04a012017-09-15 13:05:30 -0500166 %else:
167 make_action(
168 precondition::${a['name']}
169 %endif
Matthew Barth7f272fd2017-09-12 16:16:56 -0500170 %for p in a['params']:
Matthew Barth9af190c2017-08-08 14:20:43 -0500171 ${p['type']}${p['open']}
172 %for j, v in enumerate(p['values']):
173 %if (j+1) != len(p['values']):
174 ${v['value']},
175 %else:
176 ${v['value']}
177 %endif
178 %endfor
179 ${p['close']},
180 %endfor
Matthew Barth7f272fd2017-09-12 16:16:56 -0500181 %if (i+1) != len(event['pc']['pcact']):
Matthew Barth4c04a012017-09-15 13:05:30 -0500182 %if len(a['params']) != 0:
Matthew Barth7f272fd2017-09-12 16:16:56 -0500183 )),
Matthew Barth4c04a012017-09-15 13:05:30 -0500184 %else:
185 ),
186 %endif
Matthew Barth9c726672017-05-18 13:44:46 -0500187 %endif
188 %endfor
Matthew Barth7f272fd2017-09-12 16:16:56 -0500189 std::vector<SetSpeedEvent>{
190 %for pcevt in event['pc']['pcevts']:
191 SetSpeedEvent{\
192 ${indent(genSSE(event=pcevt), 6)}\
193 },
194 %endfor
195 %else:
196 SetSpeedEvent{\
197 ${indent(genSSE(event=event), 6)}
198 %endif
Matthew Barth9af190c2017-08-08 14:20:43 -0500199 %if ('pc' in event) and (event['pc'] is not None):
200 }
Matthew Barth4c04a012017-09-15 13:05:30 -0500201 %if len(event['pc']['pcact'][-1]['params']) != 0:
Matthew Barth9af190c2017-08-08 14:20:43 -0500202 )),
Matthew Barth4c04a012017-09-15 13:05:30 -0500203 %else:
204 ),
205 %endif
Matthew Barth7f272fd2017-09-12 16:16:56 -0500206 },
Matthew Barth90149802017-08-15 10:51:37 -0500207 Timer{
Matthew Barth7b7ceb82017-10-04 12:59:50 -0500208 ${event['pc']['pctime']['interval']},
209 ${event['pc']['pctime']['type']}
Matthew Barth90149802017-08-15 10:51:37 -0500210 },
Matthew Barth67967f92017-09-22 12:43:57 -0500211 std::vector<Signal>{
212 %for s in event['pc']['pcsigs']:
213 Signal{
Matthew Barth336f18a2017-09-26 09:15:56 -0500214 match::${s['match']}(
Matthew Barth67967f92017-09-22 12:43:57 -0500215 %for i, mp in enumerate(s['mparams']):
216 %if (i+1) != len(s['mparams']):
217 "${mp}",
218 %else:
219 "${mp}"
220 %endif
221 %endfor
222 ),
Matthew Barth9f964bf2017-10-02 15:07:00 -0500223 make_handler(\
224 ${indent(genHandler(sig=s), 9)}\
225 )
Matthew Barth9af190c2017-08-08 14:20:43 -0500226 },
227 %endfor
228 }
229 %endif
Matthew Barth9c726672017-05-18 13:44:46 -0500230 },
231 %endfor
232 }
233 },
234 %endfor
235 }
Matt Spinler78498c92017-04-11 13:59:46 -0500236 },
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500237%endfor
238};
239'''
240
Matt Spinler78498c92017-04-11 13:59:46 -0500241
Matthew Barthbb12c922017-06-13 13:57:40 -0500242def convertToMap(listOfDict):
243 """
244 Converts a list of dictionary entries to a std::map initialization list.
245 """
246 listOfDict = listOfDict.replace('[', '{')
247 listOfDict = listOfDict.replace(']', '}')
248 listOfDict = listOfDict.replace(':', ',')
249 return listOfDict
250
251
Matthew Barth7f272fd2017-09-12 16:16:56 -0500252def getEvent(zone_num, zone_conditions, e, events_data):
253 """
254 Parses the sections of an event and populates the properties
255 that construct an event within the generated source.
256 """
257 event = {}
258 # Zone numbers are optional in the events yaml but skip if this
259 # zone's zone number is not in the event's zone numbers
260 if all('zones' in z and
261 z['zones'] is not None and
262 zone_num not in z['zones']
263 for z in e['zone_conditions']):
264 return
265
266 # Zone conditions are optional in the events yaml but skip
267 # if this event's condition is not in this zone's conditions
268 if all('name' in z and z['name'] is not None and
269 not any(c['name'] == z['name'] for c in zone_conditions)
270 for z in e['zone_conditions']):
271 return
272
273 # Add set speed event group
274 group = []
275 groups = next(g for g in events_data['groups']
276 if g['name'] == e['group'])
277 for member in groups['members']:
278 members = {}
Matthew Barth67967f92017-09-22 12:43:57 -0500279 members['object'] = (groups['type'] +
280 member)
Matthew Barth7f272fd2017-09-12 16:16:56 -0500281 members['interface'] = e['interface']
282 members['property'] = e['property']['name']
Matthew Barth67967f92017-09-22 12:43:57 -0500283 members['type'] = e['property']['type']
Matthew Barth7f272fd2017-09-12 16:16:56 -0500284 group.append(members)
285 event['group'] = group
286
287 # Add set speed actions and function parameters
288 action = []
289 for eActions in e['actions']:
290 actions = {}
291 eAction = next(a for a in events_data['actions']
292 if a['name'] == eActions['name'])
293 actions['name'] = eAction['name']
294 params = []
Matthew Barth4c04a012017-09-15 13:05:30 -0500295 if ('parameters' in eAction) and \
296 (eAction['parameters'] is not None):
297 for p in eAction['parameters']:
298 param = {}
299 if type(eActions[p]) is not dict:
300 if p == 'property':
301 param['value'] = str(eActions[p]).lower()
302 param['type'] = str(
303 e['property']['type']).lower()
304 else:
305 # Default type to 'size_t' when not given
306 param['value'] = str(eActions[p]).lower()
307 param['type'] = 'size_t'
308 params.append(param)
Matthew Barth7f272fd2017-09-12 16:16:56 -0500309 else:
Matthew Barth4c04a012017-09-15 13:05:30 -0500310 param['type'] = str(eActions[p]['type']).lower()
311 if p != 'map':
312 param['value'] = str(
313 eActions[p]['value']).lower()
314 else:
315 emap = convertToMap(str(eActions[p]['value']))
316 param['value'] = param['type'] + emap
317 params.append(param)
Matthew Barth7f272fd2017-09-12 16:16:56 -0500318 actions['parameters'] = params
319 action.append(actions)
320 event['action'] = action
321
Matthew Barth67967f92017-09-22 12:43:57 -0500322 # Add signal handlers
323 signals = []
324 for member in group:
325 for eMatches in e['matches']:
326 signal = {}
327 eMatch = next(m for m in events_data['matches']
328 if m['name'] == eMatches['name'])
329 signal['match'] = eMatch['name']
330 params = []
331 if ('parameters' in eMatch) and \
332 (eMatch['parameters'] is not None):
333 for p in eMatch['parameters']:
334 params.append(member[str(p)])
335 signal['mparams'] = params
336 eSignal = next(s for s in events_data['signals']
337 if s['name'] == eMatch['signal'])
338 signal['signal'] = eSignal['name']
339 sparams = {}
340 if ('parameters' in eSignal) and \
341 (eSignal['parameters'] is not None):
Matthew Barth9f964bf2017-10-02 15:07:00 -0500342 splist = []
Matthew Barth67967f92017-09-22 12:43:57 -0500343 for p in eSignal['parameters']:
Matthew Barth9f964bf2017-10-02 15:07:00 -0500344 sp = str(p)
345 if (sp != 'type'):
346 splist.append(sp)
347 if (sp != 'group'):
348 sparams[sp] = "\"" + member[sp] + "\""
349 else:
350 sparams[sp] = "Group{\n"
351 for m in group:
352 sparams[sp] += (
353 "{\n" +
354 "\"" + str(m['object']) + "\",\n" +
355 "{\"" + str(m['interface']) + "\"," +
356 "\"" + str(m['property']) + "\"}\n" +
357 "},\n")
358 sparams[sp] += "}"
359 else:
360 sparams[sp] = member[sp]
361 sparams['params'] = splist
Matthew Barth67967f92017-09-22 12:43:57 -0500362 signal['sparams'] = sparams
Matthew Barth9f964bf2017-10-02 15:07:00 -0500363 # Add signal handler
364 eHandler = next(h for h in events_data['handlers']
365 if h['name'] == eSignal['handler'])
366 signal['handler'] = eHandler['name']
367 hparams = {}
368 if ('parameters' in eHandler) and \
369 (eHandler['parameters'] is not None):
370 hplist = []
371 for p in eHandler['parameters']:
372 hp = str(p)
373 if (hp != 'type'):
374 hplist.append(hp)
375 if (hp != 'group'):
376 hparams[hp] = "\"" + member[hp] + "\""
377 else:
378 hparams[hp] = "Group{\n"
379 for m in group:
380 hparams[hp] += (
381 "{\n" +
382 "\"" + str(m['object']) + "\",\n" +
383 "{\"" + str(m['interface']) + "\"," +
384 "\"" + str(m['property']) + "\"}\n" +
385 "},\n")
386 hparams[hp] += "}"
387 else:
388 hparams[hp] = member[hp]
389 hparams['params'] = hplist
390 signal['hparams'] = hparams
Matthew Barth67967f92017-09-22 12:43:57 -0500391 signals.append(signal)
392 event['signals'] = signals
Matthew Barth7f272fd2017-09-12 16:16:56 -0500393
394 # Add optional action call timer
395 timer = {}
396 interval = "static_cast<std::chrono::seconds>"
397 if ('timer' in e) and \
398 (e['timer'] is not None):
399 timer['interval'] = (interval +
400 "(" +
401 str(e['timer']['interval']) +
402 ")")
403 else:
404 timer['interval'] = (interval +
405 "(" + str(0) + ")")
Matthew Barth7b7ceb82017-10-04 12:59:50 -0500406 timer['type'] = "util::Timer::TimerType::repeating"
Matthew Barth7f272fd2017-09-12 16:16:56 -0500407 event['timer'] = timer
408
409 return event
410
411
412def addPrecondition(zNum, zCond, event, events_data):
Matthew Barth9af190c2017-08-08 14:20:43 -0500413 """
414 Parses the precondition section of an event and populates the necessary
415 structures to generate a precondition for a set speed event.
416 """
417 precond = {}
418 # Add set speed event precondition group
419 group = []
420 for grp in event['precondition']['groups']:
421 groups = next(g for g in events_data['groups']
422 if g['name'] == grp['name'])
423 for member in groups['members']:
424 members = {}
Matthew Barth67967f92017-09-22 12:43:57 -0500425 members['object'] = (groups['type'] +
426 member)
Matthew Barth9af190c2017-08-08 14:20:43 -0500427 members['interface'] = grp['interface']
428 members['property'] = grp['property']['name']
429 members['type'] = grp['property']['type']
430 members['value'] = grp['property']['value']
431 group.append(members)
432 precond['pcgrp'] = group
433
Matthew Barth7f272fd2017-09-12 16:16:56 -0500434 # Add set speed event precondition actions
435 pc = []
436 pcs = {}
437 pcs['name'] = event['precondition']['name']
438 epc = next(p for p in events_data['preconditions']
Matthew Barth9af190c2017-08-08 14:20:43 -0500439 if p['name'] == event['precondition']['name'])
440 params = []
Matthew Barth7f272fd2017-09-12 16:16:56 -0500441 for p in epc['parameters']:
Matthew Barth9af190c2017-08-08 14:20:43 -0500442 param = {}
443 if p == 'groups':
444 param['type'] = "std::vector<PrecondGroup>"
445 param['open'] = "{"
446 param['close'] = "}"
447 values = []
448 for pcgrp in group:
449 value = {}
450 value['value'] = (
451 "PrecondGroup{\"" +
Matthew Barth67967f92017-09-22 12:43:57 -0500452 str(pcgrp['object']) + "\",\"" +
Matthew Barth9af190c2017-08-08 14:20:43 -0500453 str(pcgrp['interface']) + "\",\"" +
454 str(pcgrp['property']) + "\"," +
455 "static_cast<" +
456 str(pcgrp['type']).lower() + ">" +
457 "(" + str(pcgrp['value']).lower() + ")}")
458 values.append(value)
459 param['values'] = values
460 params.append(param)
Matthew Barth7f272fd2017-09-12 16:16:56 -0500461 pcs['params'] = params
462 pc.append(pcs)
Matthew Barth9af190c2017-08-08 14:20:43 -0500463 precond['pcact'] = pc
464
Matthew Barth7f272fd2017-09-12 16:16:56 -0500465 pcevents = []
466 for pce in event['precondition']['events']:
467 pcevent = getEvent(zNum, zCond, pce, events_data)
468 if not pcevent:
469 continue
470 pcevents.append(pcevent)
471 precond['pcevts'] = pcevents
472
Matthew Barth67967f92017-09-22 12:43:57 -0500473 # Add precondition signal handlers
474 signals = []
Matthew Barth9af190c2017-08-08 14:20:43 -0500475 for member in group:
Matthew Barth67967f92017-09-22 12:43:57 -0500476 for eMatches in event['precondition']['matches']:
477 signal = {}
478 eMatch = next(m for m in events_data['matches']
479 if m['name'] == eMatches['name'])
480 signal['match'] = eMatch['name']
481 params = []
482 if ('parameters' in eMatch) and \
483 (eMatch['parameters'] is not None):
484 for p in eMatch['parameters']:
485 params.append(member[str(p)])
486 signal['mparams'] = params
487 eSignal = next(s for s in events_data['signals']
488 if s['name'] == eMatch['signal'])
489 signal['signal'] = eSignal['name']
490 sparams = {}
491 if ('parameters' in eSignal) and \
492 (eSignal['parameters'] is not None):
Matthew Barth9f964bf2017-10-02 15:07:00 -0500493 splist = []
Matthew Barth67967f92017-09-22 12:43:57 -0500494 for p in eSignal['parameters']:
Matthew Barth9f964bf2017-10-02 15:07:00 -0500495 sp = str(p)
496 if (sp != 'type'):
497 splist.append(sp)
498 if (sp != 'group'):
499 sparams[sp] = "\"" + member[sp] + "\""
500 else:
501 sparams[sp] = "Group{\n"
502 for m in group:
503 sparams[sp] += (
504 "{\n" +
505 "\"" + str(m['object']) + "\",\n" +
506 "{\"" + str(m['interface']) + "\"," +
507 "\"" + str(m['property']) + "\"}\n" +
508 "},\n")
509 sparams[sp] += "}"
510 else:
511 sparams[sp] = member[sp]
512 sparams['params'] = splist
Matthew Barth67967f92017-09-22 12:43:57 -0500513 signal['sparams'] = sparams
Matthew Barth9f964bf2017-10-02 15:07:00 -0500514 # Add signal handler
515 eHandler = next(h for h in events_data['handlers']
516 if h['name'] == eSignal['handler'])
517 signal['handler'] = eHandler['name']
518 hparams = {}
519 if ('parameters' in eHandler) and \
520 (eHandler['parameters'] is not None):
521 hplist = []
522 for p in eHandler['parameters']:
523 hp = str(p)
524 if (hp != 'type'):
525 hplist.append(hp)
526 if (hp != 'group'):
527 hparams[hp] = "\"" + member[hp] + "\""
528 else:
529 hparams[hp] = "Group{\n"
530 for m in group:
531 hparams[hp] += (
532 "{\n" +
533 "\"" + str(m['object']) + "\",\n" +
534 "{\"" + str(m['interface']) + "\"," +
535 "\"" + str(m['property']) + "\"}\n" +
536 "},\n")
537 hparams[hp] += "}"
538 else:
539 hparams[hp] = member[hp]
540 hparams['params'] = hplist
541 signal['hparams'] = hparams
Matthew Barth67967f92017-09-22 12:43:57 -0500542 signals.append(signal)
543 precond['pcsigs'] = signals
Matthew Barth9af190c2017-08-08 14:20:43 -0500544
Matthew Barth90149802017-08-15 10:51:37 -0500545 # Add optional action call timer
546 timer = {}
547 interval = "static_cast<std::chrono::seconds>"
548 if ('timer' in event['precondition']) and \
549 (event['precondition']['timer'] is not None):
550 timer['interval'] = (interval +
551 "(" +
552 str(event['precondition']['timer']['interval']) +
553 ")")
554 else:
555 timer['interval'] = (interval +
556 "(" + str(0) + ")")
Matthew Barth7b7ceb82017-10-04 12:59:50 -0500557 timer['type'] = "util::Timer::TimerType::repeating"
Matthew Barth90149802017-08-15 10:51:37 -0500558 precond['pctime'] = timer
559
Matthew Barth9af190c2017-08-08 14:20:43 -0500560 return precond
561
562
Gunnar Millsb751f322017-06-06 15:14:11 -0500563def getEventsInZone(zone_num, zone_conditions, events_data):
Matthew Barthd4d0f082017-05-16 13:51:10 -0500564 """
565 Constructs the event entries defined for each zone using the events yaml
566 provided.
567 """
568 events = []
Matthew Barthba102b32017-05-16 16:13:56 -0500569
Matthew Barthd4d0f082017-05-16 13:51:10 -0500570 if 'events' in events_data:
571 for e in events_data['events']:
Matthew Barthd4d0f082017-05-16 13:51:10 -0500572 event = {}
Matthew Barth9af190c2017-08-08 14:20:43 -0500573 # Add precondition if given
574 if ('precondition' in e) and \
575 (e['precondition'] is not None):
Matthew Barth7f272fd2017-09-12 16:16:56 -0500576 event['pc'] = addPrecondition(zone_num,
577 zone_conditions,
578 e,
579 events_data)
Matthew Barth90149802017-08-15 10:51:37 -0500580 else:
Matthew Barth7f272fd2017-09-12 16:16:56 -0500581 event = getEvent(zone_num, zone_conditions, e, events_data)
582 if not event:
583 continue
Matthew Barthd4d0f082017-05-16 13:51:10 -0500584 events.append(event)
585
586 return events
587
588
Matt Spinler78498c92017-04-11 13:59:46 -0500589def getFansInZone(zone_num, profiles, fan_data):
590 """
591 Parses the fan definition YAML files to find the fans
592 that match both the zone passed in and one of the
593 cooling profiles.
594 """
595
596 fans = []
597
598 for f in fan_data['fans']:
599
600 if zone_num != f['cooling_zone']:
601 continue
602
Gunnar Mills67e95512017-06-02 14:35:18 -0500603 # 'cooling_profile' is optional (use 'all' instead)
Matt Spinler78498c92017-04-11 13:59:46 -0500604 if f.get('cooling_profile') is None:
605 profile = "all"
606 else:
607 profile = f['cooling_profile']
608
609 if profile not in profiles:
610 continue
611
612 fan = {}
613 fan['name'] = f['inventory']
614 fan['sensors'] = f['sensors']
615 fans.append(fan)
616
617 return fans
618
619
Gunnar Millsee8a2812017-06-02 14:26:47 -0500620def getConditionInZoneConditions(zone_condition, zone_conditions_data):
621 """
622 Parses the zone conditions definition YAML files to find the condition
623 that match both the zone condition passed in.
624 """
625
626 condition = {}
627
628 for c in zone_conditions_data['conditions']:
629
630 if zone_condition != c['name']:
631 continue
632 condition['type'] = c['type']
633 properties = []
634 for p in c['properties']:
635 property = {}
636 property['property'] = p['property']
637 property['interface'] = p['interface']
638 property['path'] = p['path']
639 property['type'] = p['type'].lower()
640 property['value'] = str(p['value']).lower()
641 properties.append(property)
642 condition['properties'] = properties
643
644 return condition
645
646
647def buildZoneData(zone_data, fan_data, events_data, zone_conditions_data):
Matt Spinler78498c92017-04-11 13:59:46 -0500648 """
649 Combines the zone definition YAML and fan
650 definition YAML to create a data structure defining
651 the fan cooling zones.
652 """
653
654 zone_groups = []
655
656 for group in zone_data:
657 conditions = []
Gunnar Millsee8a2812017-06-02 14:26:47 -0500658 # zone conditions are optional
659 if 'zone_conditions' in group and group['zone_conditions'] is not None:
660 for c in group['zone_conditions']:
661
662 if not zone_conditions_data:
Gunnar Millsb751f322017-06-06 15:14:11 -0500663 sys.exit("No zone_conditions YAML file but " +
Gunnar Millsee8a2812017-06-02 14:26:47 -0500664 "zone_conditions used in zone YAML")
665
666 condition = getConditionInZoneConditions(c['name'],
667 zone_conditions_data)
668
669 if not condition:
670 sys.exit("Missing zone condition " + c['name'])
671
672 conditions.append(condition)
Matt Spinler78498c92017-04-11 13:59:46 -0500673
674 zone_group = {}
675 zone_group['conditions'] = conditions
676
677 zones = []
678 for z in group['zones']:
679 zone = {}
680
Gunnar Mills67e95512017-06-02 14:35:18 -0500681 # 'zone' is required
682 if ('zone' not in z) or (z['zone'] is None):
Matt Spinler78498c92017-04-11 13:59:46 -0500683 sys.exit("Missing fan zone number in " + zone_yaml)
684
685 zone['num'] = z['zone']
686
687 zone['full_speed'] = z['full_speed']
688
Matthew Barth1de66622017-06-12 13:13:02 -0500689 zone['default_floor'] = z['default_floor']
690
Matthew Bartha9561842017-06-29 11:43:45 -0500691 # 'increase_delay' is optional (use 0 by default)
692 key = 'increase_delay'
693 zone[key] = z.setdefault(key, 0)
694
695 # 'decrease_interval' is optional (use 0 by default)
696 key = 'decrease_interval'
697 zone[key] = z.setdefault(key, 0)
698
Gunnar Mills67e95512017-06-02 14:35:18 -0500699 # 'cooling_profiles' is optional (use 'all' instead)
700 if ('cooling_profiles' not in z) or \
Matt Spinler78498c92017-04-11 13:59:46 -0500701 (z['cooling_profiles'] is None):
702 profiles = ["all"]
703 else:
704 profiles = z['cooling_profiles']
705
706 fans = getFansInZone(z['zone'], profiles, fan_data)
Gunnar Millsb751f322017-06-06 15:14:11 -0500707 events = getEventsInZone(z['zone'], group['zone_conditions'],
708 events_data)
Matt Spinler78498c92017-04-11 13:59:46 -0500709
710 if len(fans) == 0:
711 sys.exit("Didn't find any fans in zone " + str(zone['num']))
712
713 zone['fans'] = fans
Matthew Barthd4d0f082017-05-16 13:51:10 -0500714 zone['events'] = events
Matt Spinler78498c92017-04-11 13:59:46 -0500715 zones.append(zone)
716
717 zone_group['zones'] = zones
718 zone_groups.append(zone_group)
719
720 return zone_groups
721
722
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500723if __name__ == '__main__':
724 parser = ArgumentParser(
725 description="Phosphor fan zone definition parser")
726
727 parser.add_argument('-z', '--zone_yaml', dest='zone_yaml',
728 default="example/zones.yaml",
729 help='fan zone definitional yaml')
730 parser.add_argument('-f', '--fan_yaml', dest='fan_yaml',
731 default="example/fans.yaml",
732 help='fan definitional yaml')
Matthew Barthd4d0f082017-05-16 13:51:10 -0500733 parser.add_argument('-e', '--events_yaml', dest='events_yaml',
734 help='events to set speeds yaml')
Gunnar Millsee8a2812017-06-02 14:26:47 -0500735 parser.add_argument('-c', '--zone_conditions_yaml',
736 dest='zone_conditions_yaml',
737 help='conditions to determine zone yaml')
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500738 parser.add_argument('-o', '--output_dir', dest='output_dir',
739 default=".",
740 help='output directory')
741 args = parser.parse_args()
742
743 if not args.zone_yaml or not args.fan_yaml:
744 parser.print_usage()
745 sys.exit(-1)
746
747 with open(args.zone_yaml, 'r') as zone_input:
748 zone_data = yaml.safe_load(zone_input) or {}
749
750 with open(args.fan_yaml, 'r') as fan_input:
751 fan_data = yaml.safe_load(fan_input) or {}
752
Matthew Barthd4d0f082017-05-16 13:51:10 -0500753 events_data = {}
754 if args.events_yaml:
755 with open(args.events_yaml, 'r') as events_input:
756 events_data = yaml.safe_load(events_input) or {}
757
Gunnar Millsee8a2812017-06-02 14:26:47 -0500758 zone_conditions_data = {}
759 if args.zone_conditions_yaml:
760 with open(args.zone_conditions_yaml, 'r') as zone_conditions_input:
761 zone_conditions_data = yaml.safe_load(zone_conditions_input) or {}
762
Matt Spinleree7f6422017-05-09 11:03:14 -0500763 zone_config = buildZoneData(zone_data.get('zone_configuration', {}),
Gunnar Millsee8a2812017-06-02 14:26:47 -0500764 fan_data, events_data, zone_conditions_data)
Matt Spinleree7f6422017-05-09 11:03:14 -0500765
766 manager_config = zone_data.get('manager_configuration', {})
767
768 if manager_config.get('power_on_delay') is None:
769 manager_config['power_on_delay'] = 0
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500770
771 output_file = os.path.join(args.output_dir, "fan_zone_defs.cpp")
772 with open(output_file, 'w') as output:
Matt Spinleree7f6422017-05-09 11:03:14 -0500773 output.write(Template(tmpl).render(zones=zone_config,
774 mgr_data=manager_config))