1f24d7749SMatthew Barth#!/usr/bin/env python3
285be2e70SMatt Spinler
385be2e70SMatt Spinlerimport os
485be2e70SMatt Spinlerimport sys
585be2e70SMatt Spinlerimport yaml
685be2e70SMatt Spinlerfrom argparse import ArgumentParser
785be2e70SMatt Spinlerfrom mako.template import Template
885be2e70SMatt Spinler
985be2e70SMatt Spinler"""
1085be2e70SMatt SpinlerThis script generates the data structures for the
1185be2e70SMatt Spinlerphosphor-fan-monitor application.
1285be2e70SMatt Spinler
1385be2e70SMatt SpinlerA future improvement is to get the fan inventory names
1485be2e70SMatt Spinlerfrom a separate file, so just that file could be generated
1585be2e70SMatt Spinlerfrom the MRW.
1685be2e70SMatt Spinler"""
1785be2e70SMatt Spinler
1885be2e70SMatt Spinler
1933618bc1SMatthew Barthtmpl = '''\
2033618bc1SMatthew Barth<%!
2133618bc1SMatthew Barthdef indent(str, depth):
2233618bc1SMatthew Barth    return ''.join(4*' '*depth+line for line in str.splitlines(True))
2333618bc1SMatthew Barth%>\
2433618bc1SMatthew Barth<%def name="getCondParams(cond)" buffered="True">
2533618bc1SMatthew Barth%if (cond['name'] == 'propertiesMatch'):
2633618bc1SMatthew Barthstd::vector<PropertyState>{
2733618bc1SMatthew Barth    %for i in cond['properties']:
2833618bc1SMatthew Barth    PropertyState{
2933618bc1SMatthew Barth        {
3033618bc1SMatthew Barth            "${i['object']}",
3133618bc1SMatthew Barth            "${i['interface']}",
3233618bc1SMatthew Barth            "${i['property']['name']}"
3333618bc1SMatthew Barth        },
3433618bc1SMatthew Barth        static_cast<${i['property']['type']}>(${str(i['property']['value']).lower()})
3533618bc1SMatthew Barth    },
3633618bc1SMatthew Barth    %endfor
3733618bc1SMatthew Barth}
3833618bc1SMatthew Barth%endif
3933618bc1SMatthew Barth</%def>\
4033618bc1SMatthew Barth/* This is a generated file. */
4185be2e70SMatt Spinler#include "fan_defs.hpp"
4285be2e70SMatt Spinler#include "types.hpp"
4335108a77SMatt Spinler#include "groups.hpp"
4433618bc1SMatthew Barth#include "conditions.hpp"
4585be2e70SMatt Spinler
4685be2e70SMatt Spinlerusing namespace phosphor::fan::monitor;
4735108a77SMatt Spinlerusing namespace phosphor::fan::trust;
4885be2e70SMatt Spinler
4985be2e70SMatt Spinlerconst std::vector<FanDefinition> fanDefinitions
5085be2e70SMatt Spinler{
5135108a77SMatt Spinler%for fan_data in data.get('fans', {}):
5285be2e70SMatt Spinler    FanDefinition{"${fan_data['inventory']}",
53*69f2f48eSJolie Ku                  ${fan_data.get('method', {})},
549396bcc3SMatthew Barth                  ${fan_data.get('functional_delay', 0)},
55*69f2f48eSJolie Ku                  ${fan_data.get('allowed_out_of_range_time', {})},
5685be2e70SMatt Spinler                  ${fan_data['deviation']},
5785be2e70SMatt Spinler                  ${fan_data['num_sensors_nonfunc_for_fan_nonfunc']},
58b0412d07SMatt Spinler                  0, // Monitor start delay - not used in YAML configs
59f13b42e2SMatt Spinler                  std::nullopt, // nonfuncRotorErrorDelay - also not used here
6027f6b686SMatt Spinler                  std::nullopt, // fanMissingErrorDelay - also not used here
6185be2e70SMatt Spinler                  std::vector<SensorDefinition>{
6285be2e70SMatt Spinler                  %for sensor in fan_data['sensors']:
6385be2e70SMatt Spinler                  <%
6485be2e70SMatt Spinler                      #has_target is a bool, and we need a true instead of True
6585be2e70SMatt Spinler                      has_target = str(sensor['has_target']).lower()
6680f271b2SLei YU                      target_interface = sensor.get(
6780f271b2SLei YU                          'target_interface',
6880f271b2SLei YU                          'xyz.openbmc_project.Control.FanSpeed')
698e5d197bSLei YU                      factor = sensor.get('factor', 1)
708e5d197bSLei YU                      offset = sensor.get('offset', 0)
71*69f2f48eSJolie Ku                      threshold = sensor.get('threshold', 1)
7285be2e70SMatt Spinler                  %> \
738e5d197bSLei YU                      SensorDefinition{"${sensor['name']}",
748e5d197bSLei YU                                       ${has_target},
7580f271b2SLei YU                                       "${target_interface}",
768e5d197bSLei YU                                       ${factor},
77*69f2f48eSJolie Ku                                       ${offset},
78*69f2f48eSJolie Ku                                       ${threshold}},
7985be2e70SMatt Spinler                  %endfor
8085be2e70SMatt Spinler                  },
8133618bc1SMatthew Barth                  %if ('condition' in fan_data) and \
8233618bc1SMatthew Barth                  (fan_data['condition'] is not None):
8333618bc1SMatthew Barth                  make_condition(condition::${fan_data['condition']['name']}(\
8433618bc1SMatthew Barth                      ${indent(getCondParams(cond=fan_data['condition']), 5)}\
8533618bc1SMatthew Barth                  ))
8633618bc1SMatthew Barth                  %else:
8733618bc1SMatthew Barth                  {}
8833618bc1SMatthew Barth                  %endif
8985be2e70SMatt Spinler    },
9085be2e70SMatt Spinler%endfor
9185be2e70SMatt Spinler};
9235108a77SMatt Spinler
9335108a77SMatt Spinler##Function to generate the group creation lambda.
9435108a77SMatt Spinler##If a group were to ever need a different constructor,
9535108a77SMatt Spinler##it could be handled here.
9635108a77SMatt Spinler<%def name="get_lambda_contents(group)">
976f31d19bSMatthew Barth            std::vector<GroupDefinition> group{
986f31d19bSMatthew Barth            %for member in group['group']:
996f31d19bSMatthew Barth            <%
1006f31d19bSMatthew Barth                in_trust = str(member.get('in_trust', "true")).lower()
1016f31d19bSMatthew Barth            %>
1026f31d19bSMatthew Barth                GroupDefinition{"${member['name']}", ${in_trust}},
10335108a77SMatt Spinler            %endfor
10435108a77SMatt Spinler            };
1056f31d19bSMatthew Barth            return std::make_unique<${group['class']}>(group);
10635108a77SMatt Spinler</%def>
10735108a77SMatt Spinlerconst std::vector<CreateGroupFunction> trustGroups
10835108a77SMatt Spinler{
10935108a77SMatt Spinler%for group in data.get('sensor_trust_groups', {}):
11035108a77SMatt Spinler    {
11135108a77SMatt Spinler        []()
11235108a77SMatt Spinler        {\
11335108a77SMatt Spinler${get_lambda_contents(group)}\
11435108a77SMatt Spinler        }
11535108a77SMatt Spinler    },
11635108a77SMatt Spinler%endfor
11735108a77SMatt Spinler};
11885be2e70SMatt Spinler'''
11985be2e70SMatt Spinler
12085be2e70SMatt Spinler
12185be2e70SMatt Spinlerif __name__ == '__main__':
12285be2e70SMatt Spinler    parser = ArgumentParser(
12385be2e70SMatt Spinler        description="Phosphor fan monitor definition parser")
12485be2e70SMatt Spinler
12585be2e70SMatt Spinler    parser.add_argument('-m', '--monitor_yaml', dest='monitor_yaml',
12685be2e70SMatt Spinler                        default="example/monitor.yaml",
12785be2e70SMatt Spinler                        help='fan monitor definitional yaml')
12885be2e70SMatt Spinler    parser.add_argument('-o', '--output_dir', dest='output_dir',
12985be2e70SMatt Spinler                        default=".",
13085be2e70SMatt Spinler                        help='output directory')
13185be2e70SMatt Spinler    args = parser.parse_args()
13285be2e70SMatt Spinler
13385be2e70SMatt Spinler    if not args.monitor_yaml:
13485be2e70SMatt Spinler        parser.print_usage()
1353e781064SWilliam A. Kennington III        sys.exit(1)
13685be2e70SMatt Spinler
13785be2e70SMatt Spinler    with open(args.monitor_yaml, 'r') as monitor_input:
13885be2e70SMatt Spinler        monitor_data = yaml.safe_load(monitor_input) or {}
13985be2e70SMatt Spinler
14085be2e70SMatt Spinler    #Do some minor input validation
14135108a77SMatt Spinler    for fan in monitor_data.get('fans', {}):
14285be2e70SMatt Spinler        if ((fan['deviation'] < 0) or (fan['deviation'] > 100)):
14385be2e70SMatt Spinler            sys.exit("Invalid deviation value " + str(fan['deviation']))
14485be2e70SMatt Spinler
14585be2e70SMatt Spinler    output_file = os.path.join(args.output_dir, "fan_monitor_defs.cpp")
14685be2e70SMatt Spinler    with open(output_file, 'w') as output:
14785be2e70SMatt Spinler        output.write(Template(tmpl).render(data=monitor_data))
148