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