xref: /openbmc/phosphor-fan-presence/monitor/gen-fan-monitor-defs.py (revision 9396bcc3d3a60fdad5875433210038c1b9d20ac5)
1#!/usr/bin/env python
2
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
19tmpl = '''/* This is a generated file. */
20#include "fan_defs.hpp"
21#include "types.hpp"
22#include "groups.hpp"
23
24using namespace phosphor::fan::monitor;
25using namespace phosphor::fan::trust;
26
27const std::vector<FanDefinition> fanDefinitions
28{
29%for fan_data in data.get('fans', {}):
30    FanDefinition{"${fan_data['inventory']}",
31                  ${fan_data.get('functional_delay', 0)},
32                  ${fan_data['allowed_out_of_range_time']},
33                  ${fan_data['deviation']},
34                  ${fan_data['num_sensors_nonfunc_for_fan_nonfunc']},
35                  std::vector<SensorDefinition>{
36                  %for sensor in fan_data['sensors']:
37                  <%
38                      #has_target is a bool, and we need a true instead of True
39                      has_target = str(sensor['has_target']).lower()
40                      target_interface = sensor.get(
41                          'target_interface',
42                          'xyz.openbmc_project.Control.FanSpeed')
43                      factor = sensor.get('factor', 1)
44                      offset = sensor.get('offset', 0)
45                  %> \
46                      SensorDefinition{"${sensor['name']}",
47                                       ${has_target},
48                                       "${target_interface}",
49                                       ${factor},
50                                       ${offset}},
51                  %endfor
52                  },
53    },
54%endfor
55};
56
57##Function to generate the group creation lambda.
58##If a group were to ever need a different constructor,
59##it could be handled here.
60<%def name="get_lambda_contents(group)">
61            std::vector<GroupDefinition> group{
62            %for member in group['group']:
63            <%
64                in_trust = str(member.get('in_trust', "true")).lower()
65            %>
66                GroupDefinition{"${member['name']}", ${in_trust}},
67            %endfor
68            };
69            return std::make_unique<${group['class']}>(group);
70</%def>
71const std::vector<CreateGroupFunction> trustGroups
72{
73%for group in data.get('sensor_trust_groups', {}):
74    {
75        []()
76        {\
77${get_lambda_contents(group)}\
78        }
79    },
80%endfor
81};
82'''
83
84
85if __name__ == '__main__':
86    parser = ArgumentParser(
87        description="Phosphor fan monitor definition parser")
88
89    parser.add_argument('-m', '--monitor_yaml', dest='monitor_yaml',
90                        default="example/monitor.yaml",
91                        help='fan monitor definitional yaml')
92    parser.add_argument('-o', '--output_dir', dest='output_dir',
93                        default=".",
94                        help='output directory')
95    args = parser.parse_args()
96
97    if not args.monitor_yaml:
98        parser.print_usage()
99        sys.exit(-1)
100
101    with open(args.monitor_yaml, 'r') as monitor_input:
102        monitor_data = yaml.safe_load(monitor_input) or {}
103
104    #Do some minor input validation
105    for fan in monitor_data.get('fans', {}):
106        if ((fan['deviation'] < 0) or (fan['deviation'] > 100)):
107            sys.exit("Invalid deviation value " + str(fan['deviation']))
108
109    output_file = os.path.join(args.output_dir, "fan_monitor_defs.cpp")
110    with open(output_file, 'w') as output:
111        output.write(Template(tmpl).render(data=monitor_data))
112