blob: 1118e83bbd8f0767e1265a7433d5522eafb5b1be [file] [log] [blame]
Matthew Barthf24d7742020-03-17 16:12:15 -05001#!/usr/bin/env python3
Matt Spinler85be2e72017-04-28 15:16:48 -05002
3import os
4import sys
5import yaml
6from argparse import ArgumentParser
7from mako.template import Template
8
9"""
10This script generates the data structures for the
11phosphor-fan-monitor application.
12
13A future improvement is to get the fan inventory names
14from a separate file, so just that file could be generated
15from the MRW.
16"""
17
18
Matthew Barth33618bc2018-05-03 10:55:11 -050019tmpl = '''\
20<%!
21def indent(str, depth):
22 return ''.join(4*' '*depth+line for line in str.splitlines(True))
23%>\
24<%def name="getCondParams(cond)" buffered="True">
25%if (cond['name'] == 'propertiesMatch'):
26std::vector<PropertyState>{
27 %for i in cond['properties']:
28 PropertyState{
29 {
30 "${i['object']}",
31 "${i['interface']}",
32 "${i['property']['name']}"
33 },
34 static_cast<${i['property']['type']}>(${str(i['property']['value']).lower()})
35 },
36 %endfor
37}
38%endif
39</%def>\
40/* This is a generated file. */
Matt Spinler85be2e72017-04-28 15:16:48 -050041#include "fan_defs.hpp"
42#include "types.hpp"
Matt Spinler35108a72017-09-28 13:02:32 -050043#include "groups.hpp"
Matthew Barth33618bc2018-05-03 10:55:11 -050044#include "conditions.hpp"
Matt Spinler85be2e72017-04-28 15:16:48 -050045
46using namespace phosphor::fan::monitor;
Matt Spinler35108a72017-09-28 13:02:32 -050047using namespace phosphor::fan::trust;
Matt Spinler85be2e72017-04-28 15:16:48 -050048
49const std::vector<FanDefinition> fanDefinitions
50{
Matt Spinler35108a72017-09-28 13:02:32 -050051%for fan_data in data.get('fans', {}):
Matt Spinler85be2e72017-04-28 15:16:48 -050052 FanDefinition{"${fan_data['inventory']}",
Jolie Ku69f2f482020-10-21 09:59:43 +080053 ${fan_data.get('method', {})},
Matthew Barth9396bcc2018-02-19 14:13:20 -060054 ${fan_data.get('functional_delay', 0)},
Jolie Ku69f2f482020-10-21 09:59:43 +080055 ${fan_data.get('allowed_out_of_range_time', {})},
Matt Spinler85be2e72017-04-28 15:16:48 -050056 ${fan_data['deviation']},
57 ${fan_data['num_sensors_nonfunc_for_fan_nonfunc']},
Matt Spinlerb0412d02020-10-12 16:53:52 -050058 0, // Monitor start delay - not used in YAML configs
Matt Spinler623635c2021-03-29 13:13:59 -050059 0, // Count interval - not used in YAML configs
Matt Spinlerf13b42e2020-10-26 15:29:49 -050060 std::nullopt, // nonfuncRotorErrorDelay - also not used here
Matt Spinler27f6b682020-10-27 08:43:37 -050061 std::nullopt, // fanMissingErrorDelay - also not used here
Matt Spinler85be2e72017-04-28 15:16:48 -050062 std::vector<SensorDefinition>{
63 %for sensor in fan_data['sensors']:
64 <%
65 #has_target is a bool, and we need a true instead of True
66 has_target = str(sensor['has_target']).lower()
Lei YU80f271b2018-01-31 15:24:46 +080067 target_interface = sensor.get(
68 'target_interface',
69 'xyz.openbmc_project.Control.FanSpeed')
Chau Ly27cc39f2022-09-20 08:16:56 +000070 target_path = sensor.get(
71 'target_path',
72 '')
Lei YU8e5d1972018-01-26 17:14:00 +080073 factor = sensor.get('factor', 1)
74 offset = sensor.get('offset', 0)
Jolie Ku69f2f482020-10-21 09:59:43 +080075 threshold = sensor.get('threshold', 1)
Matthew Barth8a8aa442021-11-19 14:13:13 -060076 ignore_above_max = str(sensor.get(
77 'ignore_above_max', False)).lower()
Matt Spinler85be2e72017-04-28 15:16:48 -050078 %> \
Lei YU8e5d1972018-01-26 17:14:00 +080079 SensorDefinition{"${sensor['name']}",
80 ${has_target},
Lei YU80f271b2018-01-31 15:24:46 +080081 "${target_interface}",
Chau Ly27cc39f2022-09-20 08:16:56 +000082 "${target_path}",
Lei YU8e5d1972018-01-26 17:14:00 +080083 ${factor},
Jolie Ku69f2f482020-10-21 09:59:43 +080084 ${offset},
Matthew Barth8a8aa442021-11-19 14:13:13 -060085 ${threshold},
86 ${ignore_above_max}},
Matt Spinler85be2e72017-04-28 15:16:48 -050087 %endfor
88 },
Matthew Barth33618bc2018-05-03 10:55:11 -050089 %if ('condition' in fan_data) and \
90 (fan_data['condition'] is not None):
91 make_condition(condition::${fan_data['condition']['name']}(\
92 ${indent(getCondParams(cond=fan_data['condition']), 5)}\
93 ))
94 %else:
Matt Spinlera3584bd2021-03-29 15:48:30 -050095 {},
96 false // set_func_on_present. Hardcoded to false.
Matthew Barth33618bc2018-05-03 10:55:11 -050097 %endif
Matt Spinler85be2e72017-04-28 15:16:48 -050098 },
99%endfor
100};
Matt Spinler35108a72017-09-28 13:02:32 -0500101
102##Function to generate the group creation lambda.
103##If a group were to ever need a different constructor,
104##it could be handled here.
105<%def name="get_lambda_contents(group)">
Matthew Barth6f31d192018-01-30 13:06:27 -0600106 std::vector<GroupDefinition> group{
107 %for member in group['group']:
108 <%
109 in_trust = str(member.get('in_trust', "true")).lower()
110 %>
111 GroupDefinition{"${member['name']}", ${in_trust}},
Matt Spinler35108a72017-09-28 13:02:32 -0500112 %endfor
113 };
Matthew Barth6f31d192018-01-30 13:06:27 -0600114 return std::make_unique<${group['class']}>(group);
Matt Spinler35108a72017-09-28 13:02:32 -0500115</%def>
116const std::vector<CreateGroupFunction> trustGroups
117{
118%for group in data.get('sensor_trust_groups', {}):
119 {
120 []()
121 {\
122${get_lambda_contents(group)}\
123 }
124 },
125%endfor
126};
Matt Spinler85be2e72017-04-28 15:16:48 -0500127'''
128
129
130if __name__ == '__main__':
131 parser = ArgumentParser(
132 description="Phosphor fan monitor definition parser")
133
134 parser.add_argument('-m', '--monitor_yaml', dest='monitor_yaml',
135 default="example/monitor.yaml",
136 help='fan monitor definitional yaml')
137 parser.add_argument('-o', '--output_dir', dest='output_dir',
138 default=".",
139 help='output directory')
140 args = parser.parse_args()
141
142 if not args.monitor_yaml:
143 parser.print_usage()
William A. Kennington III3e781062018-10-19 17:18:34 -0700144 sys.exit(1)
Matt Spinler85be2e72017-04-28 15:16:48 -0500145
146 with open(args.monitor_yaml, 'r') as monitor_input:
147 monitor_data = yaml.safe_load(monitor_input) or {}
148
149 #Do some minor input validation
Matt Spinler35108a72017-09-28 13:02:32 -0500150 for fan in monitor_data.get('fans', {}):
Matt Spinler85be2e72017-04-28 15:16:48 -0500151 if ((fan['deviation'] < 0) or (fan['deviation'] > 100)):
152 sys.exit("Invalid deviation value " + str(fan['deviation']))
153
154 output_file = os.path.join(args.output_dir, "fan_monitor_defs.cpp")
155 with open(output_file, 'w') as output:
156 output.write(Template(tmpl).render(data=monitor_data))