blob: dac5de7354ecd517ae75c5878d1d29044f48e677 [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
Matt Spinler85be2e72017-04-28 15:16:48 -05005from argparse import ArgumentParser
Patrick Williams0f2588f2022-12-05 10:17:03 -06006
7import yaml
Matt Spinler85be2e72017-04-28 15:16:48 -05008from mako.template import Template
9
10"""
11This script generates the data structures for the
12phosphor-fan-monitor application.
13
14A future improvement is to get the fan inventory names
15from a separate file, so just that file could be generated
16from the MRW.
17"""
18
19
Patrick Williams0f2588f2022-12-05 10:17:03 -060020tmpl = """\
Matthew Barth33618bc2018-05-03 10:55:11 -050021<%!
22def indent(str, depth):
23 return ''.join(4*' '*depth+line for line in str.splitlines(True))
24%>\
25<%def name="getCondParams(cond)" buffered="True">
26%if (cond['name'] == 'propertiesMatch'):
27std::vector<PropertyState>{
28 %for i in cond['properties']:
29 PropertyState{
30 {
31 "${i['object']}",
32 "${i['interface']}",
33 "${i['property']['name']}"
34 },
35 static_cast<${i['property']['type']}>(${str(i['property']['value']).lower()})
36 },
37 %endfor
38}
39%endif
40</%def>\
41/* This is a generated file. */
Matt Spinler85be2e72017-04-28 15:16:48 -050042#include "fan_defs.hpp"
43#include "types.hpp"
Matt Spinler35108a72017-09-28 13:02:32 -050044#include "groups.hpp"
Matthew Barth33618bc2018-05-03 10:55:11 -050045#include "conditions.hpp"
Matt Spinler85be2e72017-04-28 15:16:48 -050046
47using namespace phosphor::fan::monitor;
Matt Spinler35108a72017-09-28 13:02:32 -050048using namespace phosphor::fan::trust;
Matt Spinler85be2e72017-04-28 15:16:48 -050049
50const std::vector<FanDefinition> fanDefinitions
51{
Matt Spinler35108a72017-09-28 13:02:32 -050052%for fan_data in data.get('fans', {}):
Matt Spinler85be2e72017-04-28 15:16:48 -050053 FanDefinition{"${fan_data['inventory']}",
Jolie Ku69f2f482020-10-21 09:59:43 +080054 ${fan_data.get('method', {})},
Matthew Barth9396bcc2018-02-19 14:13:20 -060055 ${fan_data.get('functional_delay', 0)},
Jolie Ku69f2f482020-10-21 09:59:43 +080056 ${fan_data.get('allowed_out_of_range_time', {})},
Matt Spinler85be2e72017-04-28 15:16:48 -050057 ${fan_data['deviation']},
Matt Spinlerf724c162023-05-10 11:14:37 -050058 ${fan_data.get('upper_deviation', fan_data['deviation'])},
Matt Spinler85be2e72017-04-28 15:16:48 -050059 ${fan_data['num_sensors_nonfunc_for_fan_nonfunc']},
Matt Spinlerb0412d02020-10-12 16:53:52 -050060 0, // Monitor start delay - not used in YAML configs
Matt Spinler623635c2021-03-29 13:13:59 -050061 0, // Count interval - not used in YAML configs
Matt Spinlerf13b42e2020-10-26 15:29:49 -050062 std::nullopt, // nonfuncRotorErrorDelay - also not used here
Matt Spinler27f6b682020-10-27 08:43:37 -050063 std::nullopt, // fanMissingErrorDelay - also not used here
Matt Spinler85be2e72017-04-28 15:16:48 -050064 std::vector<SensorDefinition>{
65 %for sensor in fan_data['sensors']:
66 <%
67 #has_target is a bool, and we need a true instead of True
68 has_target = str(sensor['has_target']).lower()
Lei YU80f271b2018-01-31 15:24:46 +080069 target_interface = sensor.get(
70 'target_interface',
71 'xyz.openbmc_project.Control.FanSpeed')
Chau Ly27cc39f2022-09-20 08:16:56 +000072 target_path = sensor.get(
73 'target_path',
74 '')
Lei YU8e5d1972018-01-26 17:14:00 +080075 factor = sensor.get('factor', 1)
76 offset = sensor.get('offset', 0)
Jolie Ku69f2f482020-10-21 09:59:43 +080077 threshold = sensor.get('threshold', 1)
Matthew Barth8a8aa442021-11-19 14:13:13 -060078 ignore_above_max = str(sensor.get(
79 'ignore_above_max', False)).lower()
Matt Spinler85be2e72017-04-28 15:16:48 -050080 %> \
Lei YU8e5d1972018-01-26 17:14:00 +080081 SensorDefinition{"${sensor['name']}",
82 ${has_target},
Lei YU80f271b2018-01-31 15:24:46 +080083 "${target_interface}",
Chau Ly27cc39f2022-09-20 08:16:56 +000084 "${target_path}",
Lei YU8e5d1972018-01-26 17:14:00 +080085 ${factor},
Jolie Ku69f2f482020-10-21 09:59:43 +080086 ${offset},
Matthew Barth8a8aa442021-11-19 14:13:13 -060087 ${threshold},
88 ${ignore_above_max}},
Matt Spinler85be2e72017-04-28 15:16:48 -050089 %endfor
90 },
Matthew Barth33618bc2018-05-03 10:55:11 -050091 %if ('condition' in fan_data) and \
92 (fan_data['condition'] is not None):
93 make_condition(condition::${fan_data['condition']['name']}(\
94 ${indent(getCondParams(cond=fan_data['condition']), 5)}\
Matt Spinler086e8162023-05-09 11:14:41 -050095 )),
Matthew Barth33618bc2018-05-03 10:55:11 -050096 %else:
Matt Spinlera3584bd2021-03-29 15:48:30 -050097 {},
Matthew Barth33618bc2018-05-03 10:55:11 -050098 %endif
Matt Spinler086e8162023-05-09 11:14:41 -050099 false // set_func_on_present. Hardcoded to false.
Matt Spinler85be2e72017-04-28 15:16:48 -0500100 },
101%endfor
102};
Matt Spinler35108a72017-09-28 13:02:32 -0500103
104##Function to generate the group creation lambda.
105##If a group were to ever need a different constructor,
106##it could be handled here.
107<%def name="get_lambda_contents(group)">
Matthew Barth6f31d192018-01-30 13:06:27 -0600108 std::vector<GroupDefinition> group{
109 %for member in group['group']:
110 <%
111 in_trust = str(member.get('in_trust', "true")).lower()
112 %>
113 GroupDefinition{"${member['name']}", ${in_trust}},
Matt Spinler35108a72017-09-28 13:02:32 -0500114 %endfor
115 };
Matthew Barth6f31d192018-01-30 13:06:27 -0600116 return std::make_unique<${group['class']}>(group);
Matt Spinler35108a72017-09-28 13:02:32 -0500117</%def>
118const std::vector<CreateGroupFunction> trustGroups
119{
120%for group in data.get('sensor_trust_groups', {}):
121 {
122 []()
123 {\
124${get_lambda_contents(group)}\
125 }
126 },
127%endfor
128};
Patrick Williams0f2588f2022-12-05 10:17:03 -0600129"""
Matt Spinler85be2e72017-04-28 15:16:48 -0500130
131
Patrick Williams0f2588f2022-12-05 10:17:03 -0600132if __name__ == "__main__":
Matt Spinler85be2e72017-04-28 15:16:48 -0500133 parser = ArgumentParser(
Patrick Williams0f2588f2022-12-05 10:17:03 -0600134 description="Phosphor fan monitor definition parser"
135 )
Matt Spinler85be2e72017-04-28 15:16:48 -0500136
Patrick Williams0f2588f2022-12-05 10:17:03 -0600137 parser.add_argument(
138 "-m",
139 "--monitor_yaml",
140 dest="monitor_yaml",
141 default="example/monitor.yaml",
142 help="fan monitor definitional yaml",
143 )
144 parser.add_argument(
145 "-o",
146 "--output_dir",
147 dest="output_dir",
148 default=".",
149 help="output directory",
150 )
Matt Spinler85be2e72017-04-28 15:16:48 -0500151 args = parser.parse_args()
152
153 if not args.monitor_yaml:
154 parser.print_usage()
William A. Kennington III3e781062018-10-19 17:18:34 -0700155 sys.exit(1)
Matt Spinler85be2e72017-04-28 15:16:48 -0500156
Patrick Williams0f2588f2022-12-05 10:17:03 -0600157 with open(args.monitor_yaml, "r") as monitor_input:
Matt Spinler85be2e72017-04-28 15:16:48 -0500158 monitor_data = yaml.safe_load(monitor_input) or {}
159
Patrick Williams0f2588f2022-12-05 10:17:03 -0600160 # Do some minor input validation
161 for fan in monitor_data.get("fans", {}):
162 if (fan["deviation"] < 0) or (fan["deviation"] > 100):
163 sys.exit("Invalid deviation value " + str(fan["deviation"]))
Matt Spinler85be2e72017-04-28 15:16:48 -0500164
165 output_file = os.path.join(args.output_dir, "fan_monitor_defs.cpp")
Patrick Williams0f2588f2022-12-05 10:17:03 -0600166 with open(output_file, "w") as output:
Matt Spinler85be2e72017-04-28 15:16:48 -0500167 output.write(Template(tmpl).render(data=monitor_data))