blob: 96fb2fddc74dd88756b76c446e4abefab99bfa05 [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{
72 ${event['timer']['interval']}
73},
Matthew Barth67967f92017-09-22 12:43:57 -050074std::vector<Signal>{
75%for s in event['signals']:
76 Signal{
Matthew Barth336f18a2017-09-26 09:15:56 -050077 match::${s['match']}(
Matthew Barth67967f92017-09-22 12:43:57 -050078 %for i, mp in enumerate(s['mparams']):
79 %if (i+1) != len(s['mparams']):
80 "${mp}",
81 %else:
82 "${mp}"
83 %endif
84 %endfor
85 ),
Matthew Barth9f964bf2017-10-02 15:07:00 -050086 make_handler(\
87 ${indent(genHandler(sig=s), 3)}\
88 )
Matthew Barth7f272fd2017-09-12 16:16:56 -050089 },
90%endfor
91}
Matthew Barth336f18a2017-09-26 09:15:56 -050092</%def>\
Matthew Barth7f272fd2017-09-12 16:16:56 -050093/* This is a generated file. */
Matt Spinlerd08dbe22017-04-11 13:52:54 -050094#include "manager.hpp"
Matthew Barthba102b32017-05-16 16:13:56 -050095#include "functor.hpp"
96#include "actions.hpp"
Matthew Barth7e527c12017-05-17 10:14:15 -050097#include "handlers.hpp"
Matthew Barth9af190c2017-08-08 14:20:43 -050098#include "preconditions.hpp"
Matthew Barth336f18a2017-09-26 09:15:56 -050099#include "matches.hpp"
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500100
101using namespace phosphor::fan::control;
102
Matt Spinleree7f6422017-05-09 11:03:14 -0500103const unsigned int Manager::_powerOnDelay{${mgr_data['power_on_delay']}};
104
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500105const std::vector<ZoneGroup> Manager::_zoneLayouts
106{
107%for zone_group in zones:
Matthew Barth9c726672017-05-18 13:44:46 -0500108 ZoneGroup{
Gunnar Millsee8a2812017-06-02 14:26:47 -0500109 std::vector<Condition>{
110 %for condition in zone_group['conditions']:
111 Condition{
112 "${condition['type']}",
113 std::vector<ConditionProperty>{
114 %for property in condition['properties']:
115 ConditionProperty{
116 "${property['property']}",
117 "${property['interface']}",
118 "${property['path']}",
119 static_cast<${property['type']}>(${property['value']}),
120 },
121 %endfor
122 },
123 },
124 %endfor
125 },
Matthew Barth9c726672017-05-18 13:44:46 -0500126 std::vector<ZoneDefinition>{
127 %for zone in zone_group['zones']:
128 ZoneDefinition{
129 ${zone['num']},
130 ${zone['full_speed']},
Matthew Barth1de66622017-06-12 13:13:02 -0500131 ${zone['default_floor']},
Matthew Bartha9561842017-06-29 11:43:45 -0500132 ${zone['increase_delay']},
133 ${zone['decrease_interval']},
Matthew Barth9c726672017-05-18 13:44:46 -0500134 std::vector<FanDefinition>{
135 %for fan in zone['fans']:
136 FanDefinition{
137 "${fan['name']}",
138 std::vector<std::string>{
139 %for sensor in fan['sensors']:
140 "${sensor}",
141 %endfor
142 }
143 },
144 %endfor
145 },
146 std::vector<SetSpeedEvent>{
147 %for event in zone['events']:
Matthew Barth9af190c2017-08-08 14:20:43 -0500148 %if ('pc' in event) and \
149 (event['pc'] is not None):
150 SetSpeedEvent{
151 Group{
152 %for member in event['pc']['pcgrp']:
153 {
Matthew Barth67967f92017-09-22 12:43:57 -0500154 "${member['object']}",
Matthew Barth9af190c2017-08-08 14:20:43 -0500155 {"${member['interface']}",
156 "${member['property']}"}
157 },
158 %endfor
159 },
Matthew Barth7f272fd2017-09-12 16:16:56 -0500160 std::vector<Action>{
161 %for i, a in enumerate(event['pc']['pcact']):
Matthew Barth4c04a012017-09-15 13:05:30 -0500162 %if len(a['params']) != 0:
Matthew Barth9af190c2017-08-08 14:20:43 -0500163 make_action(
Matthew Barth7f272fd2017-09-12 16:16:56 -0500164 precondition::${a['name']}(
Matthew Barth4c04a012017-09-15 13:05:30 -0500165 %else:
166 make_action(
167 precondition::${a['name']}
168 %endif
Matthew Barth7f272fd2017-09-12 16:16:56 -0500169 %for p in a['params']:
Matthew Barth9af190c2017-08-08 14:20:43 -0500170 ${p['type']}${p['open']}
171 %for j, v in enumerate(p['values']):
172 %if (j+1) != len(p['values']):
173 ${v['value']},
174 %else:
175 ${v['value']}
176 %endif
177 %endfor
178 ${p['close']},
179 %endfor
Matthew Barth7f272fd2017-09-12 16:16:56 -0500180 %if (i+1) != len(event['pc']['pcact']):
Matthew Barth4c04a012017-09-15 13:05:30 -0500181 %if len(a['params']) != 0:
Matthew Barth7f272fd2017-09-12 16:16:56 -0500182 )),
Matthew Barth4c04a012017-09-15 13:05:30 -0500183 %else:
184 ),
185 %endif
Matthew Barth9c726672017-05-18 13:44:46 -0500186 %endif
187 %endfor
Matthew Barth7f272fd2017-09-12 16:16:56 -0500188 std::vector<SetSpeedEvent>{
189 %for pcevt in event['pc']['pcevts']:
190 SetSpeedEvent{\
191 ${indent(genSSE(event=pcevt), 6)}\
192 },
193 %endfor
194 %else:
195 SetSpeedEvent{\
196 ${indent(genSSE(event=event), 6)}
197 %endif
Matthew Barth9af190c2017-08-08 14:20:43 -0500198 %if ('pc' in event) and (event['pc'] is not None):
199 }
Matthew Barth4c04a012017-09-15 13:05:30 -0500200 %if len(event['pc']['pcact'][-1]['params']) != 0:
Matthew Barth9af190c2017-08-08 14:20:43 -0500201 )),
Matthew Barth4c04a012017-09-15 13:05:30 -0500202 %else:
203 ),
204 %endif
Matthew Barth7f272fd2017-09-12 16:16:56 -0500205 },
Matthew Barth90149802017-08-15 10:51:37 -0500206 Timer{
207 ${event['pc']['pctime']['interval']}
208 },
Matthew Barth67967f92017-09-22 12:43:57 -0500209 std::vector<Signal>{
210 %for s in event['pc']['pcsigs']:
211 Signal{
Matthew Barth336f18a2017-09-26 09:15:56 -0500212 match::${s['match']}(
Matthew Barth67967f92017-09-22 12:43:57 -0500213 %for i, mp in enumerate(s['mparams']):
214 %if (i+1) != len(s['mparams']):
215 "${mp}",
216 %else:
217 "${mp}"
218 %endif
219 %endfor
220 ),
Matthew Barth9f964bf2017-10-02 15:07:00 -0500221 make_handler(\
222 ${indent(genHandler(sig=s), 9)}\
223 )
Matthew Barth9af190c2017-08-08 14:20:43 -0500224 },
225 %endfor
226 }
227 %endif
Matthew Barth9c726672017-05-18 13:44:46 -0500228 },
229 %endfor
230 }
231 },
232 %endfor
233 }
Matt Spinler78498c92017-04-11 13:59:46 -0500234 },
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500235%endfor
236};
237'''
238
Matt Spinler78498c92017-04-11 13:59:46 -0500239
Matthew Barthbb12c922017-06-13 13:57:40 -0500240def convertToMap(listOfDict):
241 """
242 Converts a list of dictionary entries to a std::map initialization list.
243 """
244 listOfDict = listOfDict.replace('[', '{')
245 listOfDict = listOfDict.replace(']', '}')
246 listOfDict = listOfDict.replace(':', ',')
247 return listOfDict
248
249
Matthew Barth7f272fd2017-09-12 16:16:56 -0500250def getEvent(zone_num, zone_conditions, e, events_data):
251 """
252 Parses the sections of an event and populates the properties
253 that construct an event within the generated source.
254 """
255 event = {}
256 # Zone numbers are optional in the events yaml but skip if this
257 # zone's zone number is not in the event's zone numbers
258 if all('zones' in z and
259 z['zones'] is not None and
260 zone_num not in z['zones']
261 for z in e['zone_conditions']):
262 return
263
264 # Zone conditions are optional in the events yaml but skip
265 # if this event's condition is not in this zone's conditions
266 if all('name' in z and z['name'] is not None and
267 not any(c['name'] == z['name'] for c in zone_conditions)
268 for z in e['zone_conditions']):
269 return
270
271 # Add set speed event group
272 group = []
273 groups = next(g for g in events_data['groups']
274 if g['name'] == e['group'])
275 for member in groups['members']:
276 members = {}
Matthew Barth67967f92017-09-22 12:43:57 -0500277 members['object'] = (groups['type'] +
278 member)
Matthew Barth7f272fd2017-09-12 16:16:56 -0500279 members['interface'] = e['interface']
280 members['property'] = e['property']['name']
Matthew Barth67967f92017-09-22 12:43:57 -0500281 members['type'] = e['property']['type']
Matthew Barth7f272fd2017-09-12 16:16:56 -0500282 group.append(members)
283 event['group'] = group
284
285 # Add set speed actions and function parameters
286 action = []
287 for eActions in e['actions']:
288 actions = {}
289 eAction = next(a for a in events_data['actions']
290 if a['name'] == eActions['name'])
291 actions['name'] = eAction['name']
292 params = []
Matthew Barth4c04a012017-09-15 13:05:30 -0500293 if ('parameters' in eAction) and \
294 (eAction['parameters'] is not None):
295 for p in eAction['parameters']:
296 param = {}
297 if type(eActions[p]) is not dict:
298 if p == 'property':
299 param['value'] = str(eActions[p]).lower()
300 param['type'] = str(
301 e['property']['type']).lower()
302 else:
303 # Default type to 'size_t' when not given
304 param['value'] = str(eActions[p]).lower()
305 param['type'] = 'size_t'
306 params.append(param)
Matthew Barth7f272fd2017-09-12 16:16:56 -0500307 else:
Matthew Barth4c04a012017-09-15 13:05:30 -0500308 param['type'] = str(eActions[p]['type']).lower()
309 if p != 'map':
310 param['value'] = str(
311 eActions[p]['value']).lower()
312 else:
313 emap = convertToMap(str(eActions[p]['value']))
314 param['value'] = param['type'] + emap
315 params.append(param)
Matthew Barth7f272fd2017-09-12 16:16:56 -0500316 actions['parameters'] = params
317 action.append(actions)
318 event['action'] = action
319
Matthew Barth67967f92017-09-22 12:43:57 -0500320 # Add signal handlers
321 signals = []
322 for member in group:
323 for eMatches in e['matches']:
324 signal = {}
325 eMatch = next(m for m in events_data['matches']
326 if m['name'] == eMatches['name'])
327 signal['match'] = eMatch['name']
328 params = []
329 if ('parameters' in eMatch) and \
330 (eMatch['parameters'] is not None):
331 for p in eMatch['parameters']:
332 params.append(member[str(p)])
333 signal['mparams'] = params
334 eSignal = next(s for s in events_data['signals']
335 if s['name'] == eMatch['signal'])
336 signal['signal'] = eSignal['name']
337 sparams = {}
338 if ('parameters' in eSignal) and \
339 (eSignal['parameters'] is not None):
Matthew Barth9f964bf2017-10-02 15:07:00 -0500340 splist = []
Matthew Barth67967f92017-09-22 12:43:57 -0500341 for p in eSignal['parameters']:
Matthew Barth9f964bf2017-10-02 15:07:00 -0500342 sp = str(p)
343 if (sp != 'type'):
344 splist.append(sp)
345 if (sp != 'group'):
346 sparams[sp] = "\"" + member[sp] + "\""
347 else:
348 sparams[sp] = "Group{\n"
349 for m in group:
350 sparams[sp] += (
351 "{\n" +
352 "\"" + str(m['object']) + "\",\n" +
353 "{\"" + str(m['interface']) + "\"," +
354 "\"" + str(m['property']) + "\"}\n" +
355 "},\n")
356 sparams[sp] += "}"
357 else:
358 sparams[sp] = member[sp]
359 sparams['params'] = splist
Matthew Barth67967f92017-09-22 12:43:57 -0500360 signal['sparams'] = sparams
Matthew Barth9f964bf2017-10-02 15:07:00 -0500361 # Add signal handler
362 eHandler = next(h for h in events_data['handlers']
363 if h['name'] == eSignal['handler'])
364 signal['handler'] = eHandler['name']
365 hparams = {}
366 if ('parameters' in eHandler) and \
367 (eHandler['parameters'] is not None):
368 hplist = []
369 for p in eHandler['parameters']:
370 hp = str(p)
371 if (hp != 'type'):
372 hplist.append(hp)
373 if (hp != 'group'):
374 hparams[hp] = "\"" + member[hp] + "\""
375 else:
376 hparams[hp] = "Group{\n"
377 for m in group:
378 hparams[hp] += (
379 "{\n" +
380 "\"" + str(m['object']) + "\",\n" +
381 "{\"" + str(m['interface']) + "\"," +
382 "\"" + str(m['property']) + "\"}\n" +
383 "},\n")
384 hparams[hp] += "}"
385 else:
386 hparams[hp] = member[hp]
387 hparams['params'] = hplist
388 signal['hparams'] = hparams
Matthew Barth67967f92017-09-22 12:43:57 -0500389 signals.append(signal)
390 event['signals'] = signals
Matthew Barth7f272fd2017-09-12 16:16:56 -0500391
392 # Add optional action call timer
393 timer = {}
394 interval = "static_cast<std::chrono::seconds>"
395 if ('timer' in e) and \
396 (e['timer'] is not None):
397 timer['interval'] = (interval +
398 "(" +
399 str(e['timer']['interval']) +
400 ")")
401 else:
402 timer['interval'] = (interval +
403 "(" + str(0) + ")")
404 event['timer'] = timer
405
406 return event
407
408
409def addPrecondition(zNum, zCond, event, events_data):
Matthew Barth9af190c2017-08-08 14:20:43 -0500410 """
411 Parses the precondition section of an event and populates the necessary
412 structures to generate a precondition for a set speed event.
413 """
414 precond = {}
415 # Add set speed event precondition group
416 group = []
417 for grp in event['precondition']['groups']:
418 groups = next(g for g in events_data['groups']
419 if g['name'] == grp['name'])
420 for member in groups['members']:
421 members = {}
Matthew Barth67967f92017-09-22 12:43:57 -0500422 members['object'] = (groups['type'] +
423 member)
Matthew Barth9af190c2017-08-08 14:20:43 -0500424 members['interface'] = grp['interface']
425 members['property'] = grp['property']['name']
426 members['type'] = grp['property']['type']
427 members['value'] = grp['property']['value']
428 group.append(members)
429 precond['pcgrp'] = group
430
Matthew Barth7f272fd2017-09-12 16:16:56 -0500431 # Add set speed event precondition actions
432 pc = []
433 pcs = {}
434 pcs['name'] = event['precondition']['name']
435 epc = next(p for p in events_data['preconditions']
Matthew Barth9af190c2017-08-08 14:20:43 -0500436 if p['name'] == event['precondition']['name'])
437 params = []
Matthew Barth7f272fd2017-09-12 16:16:56 -0500438 for p in epc['parameters']:
Matthew Barth9af190c2017-08-08 14:20:43 -0500439 param = {}
440 if p == 'groups':
441 param['type'] = "std::vector<PrecondGroup>"
442 param['open'] = "{"
443 param['close'] = "}"
444 values = []
445 for pcgrp in group:
446 value = {}
447 value['value'] = (
448 "PrecondGroup{\"" +
Matthew Barth67967f92017-09-22 12:43:57 -0500449 str(pcgrp['object']) + "\",\"" +
Matthew Barth9af190c2017-08-08 14:20:43 -0500450 str(pcgrp['interface']) + "\",\"" +
451 str(pcgrp['property']) + "\"," +
452 "static_cast<" +
453 str(pcgrp['type']).lower() + ">" +
454 "(" + str(pcgrp['value']).lower() + ")}")
455 values.append(value)
456 param['values'] = values
457 params.append(param)
Matthew Barth7f272fd2017-09-12 16:16:56 -0500458 pcs['params'] = params
459 pc.append(pcs)
Matthew Barth9af190c2017-08-08 14:20:43 -0500460 precond['pcact'] = pc
461
Matthew Barth7f272fd2017-09-12 16:16:56 -0500462 pcevents = []
463 for pce in event['precondition']['events']:
464 pcevent = getEvent(zNum, zCond, pce, events_data)
465 if not pcevent:
466 continue
467 pcevents.append(pcevent)
468 precond['pcevts'] = pcevents
469
Matthew Barth67967f92017-09-22 12:43:57 -0500470 # Add precondition signal handlers
471 signals = []
Matthew Barth9af190c2017-08-08 14:20:43 -0500472 for member in group:
Matthew Barth67967f92017-09-22 12:43:57 -0500473 for eMatches in event['precondition']['matches']:
474 signal = {}
475 eMatch = next(m for m in events_data['matches']
476 if m['name'] == eMatches['name'])
477 signal['match'] = eMatch['name']
478 params = []
479 if ('parameters' in eMatch) and \
480 (eMatch['parameters'] is not None):
481 for p in eMatch['parameters']:
482 params.append(member[str(p)])
483 signal['mparams'] = params
484 eSignal = next(s for s in events_data['signals']
485 if s['name'] == eMatch['signal'])
486 signal['signal'] = eSignal['name']
487 sparams = {}
488 if ('parameters' in eSignal) and \
489 (eSignal['parameters'] is not None):
Matthew Barth9f964bf2017-10-02 15:07:00 -0500490 splist = []
Matthew Barth67967f92017-09-22 12:43:57 -0500491 for p in eSignal['parameters']:
Matthew Barth9f964bf2017-10-02 15:07:00 -0500492 sp = str(p)
493 if (sp != 'type'):
494 splist.append(sp)
495 if (sp != 'group'):
496 sparams[sp] = "\"" + member[sp] + "\""
497 else:
498 sparams[sp] = "Group{\n"
499 for m in group:
500 sparams[sp] += (
501 "{\n" +
502 "\"" + str(m['object']) + "\",\n" +
503 "{\"" + str(m['interface']) + "\"," +
504 "\"" + str(m['property']) + "\"}\n" +
505 "},\n")
506 sparams[sp] += "}"
507 else:
508 sparams[sp] = member[sp]
509 sparams['params'] = splist
Matthew Barth67967f92017-09-22 12:43:57 -0500510 signal['sparams'] = sparams
Matthew Barth9f964bf2017-10-02 15:07:00 -0500511 # Add signal handler
512 eHandler = next(h for h in events_data['handlers']
513 if h['name'] == eSignal['handler'])
514 signal['handler'] = eHandler['name']
515 hparams = {}
516 if ('parameters' in eHandler) and \
517 (eHandler['parameters'] is not None):
518 hplist = []
519 for p in eHandler['parameters']:
520 hp = str(p)
521 if (hp != 'type'):
522 hplist.append(hp)
523 if (hp != 'group'):
524 hparams[hp] = "\"" + member[hp] + "\""
525 else:
526 hparams[hp] = "Group{\n"
527 for m in group:
528 hparams[hp] += (
529 "{\n" +
530 "\"" + str(m['object']) + "\",\n" +
531 "{\"" + str(m['interface']) + "\"," +
532 "\"" + str(m['property']) + "\"}\n" +
533 "},\n")
534 hparams[hp] += "}"
535 else:
536 hparams[hp] = member[hp]
537 hparams['params'] = hplist
538 signal['hparams'] = hparams
Matthew Barth67967f92017-09-22 12:43:57 -0500539 signals.append(signal)
540 precond['pcsigs'] = signals
Matthew Barth9af190c2017-08-08 14:20:43 -0500541
Matthew Barth90149802017-08-15 10:51:37 -0500542 # Add optional action call timer
543 timer = {}
544 interval = "static_cast<std::chrono::seconds>"
545 if ('timer' in event['precondition']) and \
546 (event['precondition']['timer'] is not None):
547 timer['interval'] = (interval +
548 "(" +
549 str(event['precondition']['timer']['interval']) +
550 ")")
551 else:
552 timer['interval'] = (interval +
553 "(" + str(0) + ")")
554 precond['pctime'] = timer
555
Matthew Barth9af190c2017-08-08 14:20:43 -0500556 return precond
557
558
Gunnar Millsb751f322017-06-06 15:14:11 -0500559def getEventsInZone(zone_num, zone_conditions, events_data):
Matthew Barthd4d0f082017-05-16 13:51:10 -0500560 """
561 Constructs the event entries defined for each zone using the events yaml
562 provided.
563 """
564 events = []
Matthew Barthba102b32017-05-16 16:13:56 -0500565
Matthew Barthd4d0f082017-05-16 13:51:10 -0500566 if 'events' in events_data:
567 for e in events_data['events']:
Matthew Barthd4d0f082017-05-16 13:51:10 -0500568 event = {}
Matthew Barth9af190c2017-08-08 14:20:43 -0500569 # Add precondition if given
570 if ('precondition' in e) and \
571 (e['precondition'] is not None):
Matthew Barth7f272fd2017-09-12 16:16:56 -0500572 event['pc'] = addPrecondition(zone_num,
573 zone_conditions,
574 e,
575 events_data)
Matthew Barth90149802017-08-15 10:51:37 -0500576 else:
Matthew Barth7f272fd2017-09-12 16:16:56 -0500577 event = getEvent(zone_num, zone_conditions, e, events_data)
578 if not event:
579 continue
Matthew Barthd4d0f082017-05-16 13:51:10 -0500580 events.append(event)
581
582 return events
583
584
Matt Spinler78498c92017-04-11 13:59:46 -0500585def getFansInZone(zone_num, profiles, fan_data):
586 """
587 Parses the fan definition YAML files to find the fans
588 that match both the zone passed in and one of the
589 cooling profiles.
590 """
591
592 fans = []
593
594 for f in fan_data['fans']:
595
596 if zone_num != f['cooling_zone']:
597 continue
598
Gunnar Mills67e95512017-06-02 14:35:18 -0500599 # 'cooling_profile' is optional (use 'all' instead)
Matt Spinler78498c92017-04-11 13:59:46 -0500600 if f.get('cooling_profile') is None:
601 profile = "all"
602 else:
603 profile = f['cooling_profile']
604
605 if profile not in profiles:
606 continue
607
608 fan = {}
609 fan['name'] = f['inventory']
610 fan['sensors'] = f['sensors']
611 fans.append(fan)
612
613 return fans
614
615
Gunnar Millsee8a2812017-06-02 14:26:47 -0500616def getConditionInZoneConditions(zone_condition, zone_conditions_data):
617 """
618 Parses the zone conditions definition YAML files to find the condition
619 that match both the zone condition passed in.
620 """
621
622 condition = {}
623
624 for c in zone_conditions_data['conditions']:
625
626 if zone_condition != c['name']:
627 continue
628 condition['type'] = c['type']
629 properties = []
630 for p in c['properties']:
631 property = {}
632 property['property'] = p['property']
633 property['interface'] = p['interface']
634 property['path'] = p['path']
635 property['type'] = p['type'].lower()
636 property['value'] = str(p['value']).lower()
637 properties.append(property)
638 condition['properties'] = properties
639
640 return condition
641
642
643def buildZoneData(zone_data, fan_data, events_data, zone_conditions_data):
Matt Spinler78498c92017-04-11 13:59:46 -0500644 """
645 Combines the zone definition YAML and fan
646 definition YAML to create a data structure defining
647 the fan cooling zones.
648 """
649
650 zone_groups = []
651
652 for group in zone_data:
653 conditions = []
Gunnar Millsee8a2812017-06-02 14:26:47 -0500654 # zone conditions are optional
655 if 'zone_conditions' in group and group['zone_conditions'] is not None:
656 for c in group['zone_conditions']:
657
658 if not zone_conditions_data:
Gunnar Millsb751f322017-06-06 15:14:11 -0500659 sys.exit("No zone_conditions YAML file but " +
Gunnar Millsee8a2812017-06-02 14:26:47 -0500660 "zone_conditions used in zone YAML")
661
662 condition = getConditionInZoneConditions(c['name'],
663 zone_conditions_data)
664
665 if not condition:
666 sys.exit("Missing zone condition " + c['name'])
667
668 conditions.append(condition)
Matt Spinler78498c92017-04-11 13:59:46 -0500669
670 zone_group = {}
671 zone_group['conditions'] = conditions
672
673 zones = []
674 for z in group['zones']:
675 zone = {}
676
Gunnar Mills67e95512017-06-02 14:35:18 -0500677 # 'zone' is required
678 if ('zone' not in z) or (z['zone'] is None):
Matt Spinler78498c92017-04-11 13:59:46 -0500679 sys.exit("Missing fan zone number in " + zone_yaml)
680
681 zone['num'] = z['zone']
682
683 zone['full_speed'] = z['full_speed']
684
Matthew Barth1de66622017-06-12 13:13:02 -0500685 zone['default_floor'] = z['default_floor']
686
Matthew Bartha9561842017-06-29 11:43:45 -0500687 # 'increase_delay' is optional (use 0 by default)
688 key = 'increase_delay'
689 zone[key] = z.setdefault(key, 0)
690
691 # 'decrease_interval' is optional (use 0 by default)
692 key = 'decrease_interval'
693 zone[key] = z.setdefault(key, 0)
694
Gunnar Mills67e95512017-06-02 14:35:18 -0500695 # 'cooling_profiles' is optional (use 'all' instead)
696 if ('cooling_profiles' not in z) or \
Matt Spinler78498c92017-04-11 13:59:46 -0500697 (z['cooling_profiles'] is None):
698 profiles = ["all"]
699 else:
700 profiles = z['cooling_profiles']
701
702 fans = getFansInZone(z['zone'], profiles, fan_data)
Gunnar Millsb751f322017-06-06 15:14:11 -0500703 events = getEventsInZone(z['zone'], group['zone_conditions'],
704 events_data)
Matt Spinler78498c92017-04-11 13:59:46 -0500705
706 if len(fans) == 0:
707 sys.exit("Didn't find any fans in zone " + str(zone['num']))
708
709 zone['fans'] = fans
Matthew Barthd4d0f082017-05-16 13:51:10 -0500710 zone['events'] = events
Matt Spinler78498c92017-04-11 13:59:46 -0500711 zones.append(zone)
712
713 zone_group['zones'] = zones
714 zone_groups.append(zone_group)
715
716 return zone_groups
717
718
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500719if __name__ == '__main__':
720 parser = ArgumentParser(
721 description="Phosphor fan zone definition parser")
722
723 parser.add_argument('-z', '--zone_yaml', dest='zone_yaml',
724 default="example/zones.yaml",
725 help='fan zone definitional yaml')
726 parser.add_argument('-f', '--fan_yaml', dest='fan_yaml',
727 default="example/fans.yaml",
728 help='fan definitional yaml')
Matthew Barthd4d0f082017-05-16 13:51:10 -0500729 parser.add_argument('-e', '--events_yaml', dest='events_yaml',
730 help='events to set speeds yaml')
Gunnar Millsee8a2812017-06-02 14:26:47 -0500731 parser.add_argument('-c', '--zone_conditions_yaml',
732 dest='zone_conditions_yaml',
733 help='conditions to determine zone yaml')
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500734 parser.add_argument('-o', '--output_dir', dest='output_dir',
735 default=".",
736 help='output directory')
737 args = parser.parse_args()
738
739 if not args.zone_yaml or not args.fan_yaml:
740 parser.print_usage()
741 sys.exit(-1)
742
743 with open(args.zone_yaml, 'r') as zone_input:
744 zone_data = yaml.safe_load(zone_input) or {}
745
746 with open(args.fan_yaml, 'r') as fan_input:
747 fan_data = yaml.safe_load(fan_input) or {}
748
Matthew Barthd4d0f082017-05-16 13:51:10 -0500749 events_data = {}
750 if args.events_yaml:
751 with open(args.events_yaml, 'r') as events_input:
752 events_data = yaml.safe_load(events_input) or {}
753
Gunnar Millsee8a2812017-06-02 14:26:47 -0500754 zone_conditions_data = {}
755 if args.zone_conditions_yaml:
756 with open(args.zone_conditions_yaml, 'r') as zone_conditions_input:
757 zone_conditions_data = yaml.safe_load(zone_conditions_input) or {}
758
Matt Spinleree7f6422017-05-09 11:03:14 -0500759 zone_config = buildZoneData(zone_data.get('zone_configuration', {}),
Gunnar Millsee8a2812017-06-02 14:26:47 -0500760 fan_data, events_data, zone_conditions_data)
Matt Spinleree7f6422017-05-09 11:03:14 -0500761
762 manager_config = zone_data.get('manager_configuration', {})
763
764 if manager_config.get('power_on_delay') is None:
765 manager_config['power_on_delay'] = 0
Matt Spinlerd08dbe22017-04-11 13:52:54 -0500766
767 output_file = os.path.join(args.output_dir, "fan_zone_defs.cpp")
768 with open(output_file, 'w') as output:
Matt Spinleree7f6422017-05-09 11:03:14 -0500769 output.write(Template(tmpl).render(zones=zone_config,
770 mgr_data=manager_config))