1f24d7749SMatthew Barth#!/usr/bin/env python3 285be2e70SMatt Spinler 385be2e70SMatt Spinlerimport os 485be2e70SMatt Spinlerimport sys 585be2e70SMatt Spinlerfrom argparse import ArgumentParser 60f2588f2SPatrick Williams 70f2588f2SPatrick Williamsimport yaml 885be2e70SMatt Spinlerfrom mako.template import Template 985be2e70SMatt Spinler 1085be2e70SMatt Spinler""" 1185be2e70SMatt SpinlerThis script generates the data structures for the 1285be2e70SMatt Spinlerphosphor-fan-monitor application. 1385be2e70SMatt Spinler 1485be2e70SMatt SpinlerA future improvement is to get the fan inventory names 1585be2e70SMatt Spinlerfrom a separate file, so just that file could be generated 1685be2e70SMatt Spinlerfrom the MRW. 1785be2e70SMatt Spinler""" 1885be2e70SMatt Spinler 1985be2e70SMatt Spinler 200f2588f2SPatrick Williamstmpl = """\ 2133618bc1SMatthew Barth<%! 2233618bc1SMatthew Barthdef indent(str, depth): 2333618bc1SMatthew Barth return ''.join(4*' '*depth+line for line in str.splitlines(True)) 2433618bc1SMatthew Barth%>\ 2533618bc1SMatthew Barth<%def name="getCondParams(cond)" buffered="True"> 2633618bc1SMatthew Barth%if (cond['name'] == 'propertiesMatch'): 2733618bc1SMatthew Barthstd::vector<PropertyState>{ 2833618bc1SMatthew Barth %for i in cond['properties']: 2933618bc1SMatthew Barth PropertyState{ 3033618bc1SMatthew Barth { 3133618bc1SMatthew Barth "${i['object']}", 3233618bc1SMatthew Barth "${i['interface']}", 3333618bc1SMatthew Barth "${i['property']['name']}" 3433618bc1SMatthew Barth }, 3533618bc1SMatthew Barth static_cast<${i['property']['type']}>(${str(i['property']['value']).lower()}) 3633618bc1SMatthew Barth }, 3733618bc1SMatthew Barth %endfor 3833618bc1SMatthew Barth} 3933618bc1SMatthew Barth%endif 4033618bc1SMatthew Barth</%def>\ 4133618bc1SMatthew Barth/* This is a generated file. */ 4285be2e70SMatt Spinler#include "fan_defs.hpp" 4385be2e70SMatt Spinler#include "types.hpp" 4435108a77SMatt Spinler#include "groups.hpp" 4533618bc1SMatthew Barth#include "conditions.hpp" 4685be2e70SMatt Spinler 4785be2e70SMatt Spinlerusing namespace phosphor::fan::monitor; 4835108a77SMatt Spinlerusing namespace phosphor::fan::trust; 4985be2e70SMatt Spinler 5085be2e70SMatt Spinlerconst std::vector<FanDefinition> fanDefinitions 5185be2e70SMatt Spinler{ 5235108a77SMatt Spinler%for fan_data in data.get('fans', {}): 5385be2e70SMatt Spinler FanDefinition{"${fan_data['inventory']}", 5469f2f48eSJolie Ku ${fan_data.get('method', {})}, 559396bcc3SMatthew Barth ${fan_data.get('functional_delay', 0)}, 5669f2f48eSJolie Ku ${fan_data.get('allowed_out_of_range_time', {})}, 5785be2e70SMatt Spinler ${fan_data['deviation']}, 58*f724c16bSMatt Spinler ${fan_data.get('upper_deviation', fan_data['deviation'])}, 5985be2e70SMatt Spinler ${fan_data['num_sensors_nonfunc_for_fan_nonfunc']}, 60b0412d07SMatt Spinler 0, // Monitor start delay - not used in YAML configs 61623635c6SMatt Spinler 0, // Count interval - not used in YAML configs 62f13b42e2SMatt Spinler std::nullopt, // nonfuncRotorErrorDelay - also not used here 6327f6b686SMatt Spinler std::nullopt, // fanMissingErrorDelay - also not used here 6485be2e70SMatt Spinler std::vector<SensorDefinition>{ 6585be2e70SMatt Spinler %for sensor in fan_data['sensors']: 6685be2e70SMatt Spinler <% 6785be2e70SMatt Spinler #has_target is a bool, and we need a true instead of True 6885be2e70SMatt Spinler has_target = str(sensor['has_target']).lower() 6980f271b2SLei YU target_interface = sensor.get( 7080f271b2SLei YU 'target_interface', 7180f271b2SLei YU 'xyz.openbmc_project.Control.FanSpeed') 7227cc39f1SChau Ly target_path = sensor.get( 7327cc39f1SChau Ly 'target_path', 7427cc39f1SChau Ly '') 758e5d197bSLei YU factor = sensor.get('factor', 1) 768e5d197bSLei YU offset = sensor.get('offset', 0) 7769f2f48eSJolie Ku threshold = sensor.get('threshold', 1) 788a8aa442SMatthew Barth ignore_above_max = str(sensor.get( 798a8aa442SMatthew Barth 'ignore_above_max', False)).lower() 8085be2e70SMatt Spinler %> \ 818e5d197bSLei YU SensorDefinition{"${sensor['name']}", 828e5d197bSLei YU ${has_target}, 8380f271b2SLei YU "${target_interface}", 8427cc39f1SChau Ly "${target_path}", 858e5d197bSLei YU ${factor}, 8669f2f48eSJolie Ku ${offset}, 878a8aa442SMatthew Barth ${threshold}, 888a8aa442SMatthew Barth ${ignore_above_max}}, 8985be2e70SMatt Spinler %endfor 9085be2e70SMatt Spinler }, 9133618bc1SMatthew Barth %if ('condition' in fan_data) and \ 9233618bc1SMatthew Barth (fan_data['condition'] is not None): 9333618bc1SMatthew Barth make_condition(condition::${fan_data['condition']['name']}(\ 9433618bc1SMatthew Barth ${indent(getCondParams(cond=fan_data['condition']), 5)}\ 95086e8168SMatt Spinler )), 9633618bc1SMatthew Barth %else: 97a3584bd2SMatt Spinler {}, 9833618bc1SMatthew Barth %endif 99086e8168SMatt Spinler false // set_func_on_present. Hardcoded to false. 10085be2e70SMatt Spinler }, 10185be2e70SMatt Spinler%endfor 10285be2e70SMatt Spinler}; 10335108a77SMatt Spinler 10435108a77SMatt Spinler##Function to generate the group creation lambda. 10535108a77SMatt Spinler##If a group were to ever need a different constructor, 10635108a77SMatt Spinler##it could be handled here. 10735108a77SMatt Spinler<%def name="get_lambda_contents(group)"> 1086f31d19bSMatthew Barth std::vector<GroupDefinition> group{ 1096f31d19bSMatthew Barth %for member in group['group']: 1106f31d19bSMatthew Barth <% 1116f31d19bSMatthew Barth in_trust = str(member.get('in_trust', "true")).lower() 1126f31d19bSMatthew Barth %> 1136f31d19bSMatthew Barth GroupDefinition{"${member['name']}", ${in_trust}}, 11435108a77SMatt Spinler %endfor 11535108a77SMatt Spinler }; 1166f31d19bSMatthew Barth return std::make_unique<${group['class']}>(group); 11735108a77SMatt Spinler</%def> 11835108a77SMatt Spinlerconst std::vector<CreateGroupFunction> trustGroups 11935108a77SMatt Spinler{ 12035108a77SMatt Spinler%for group in data.get('sensor_trust_groups', {}): 12135108a77SMatt Spinler { 12235108a77SMatt Spinler []() 12335108a77SMatt Spinler {\ 12435108a77SMatt Spinler${get_lambda_contents(group)}\ 12535108a77SMatt Spinler } 12635108a77SMatt Spinler }, 12735108a77SMatt Spinler%endfor 12835108a77SMatt Spinler}; 1290f2588f2SPatrick Williams""" 13085be2e70SMatt Spinler 13185be2e70SMatt Spinler 1320f2588f2SPatrick Williamsif __name__ == "__main__": 13385be2e70SMatt Spinler parser = ArgumentParser( 1340f2588f2SPatrick Williams description="Phosphor fan monitor definition parser" 1350f2588f2SPatrick Williams ) 13685be2e70SMatt Spinler 1370f2588f2SPatrick Williams parser.add_argument( 1380f2588f2SPatrick Williams "-m", 1390f2588f2SPatrick Williams "--monitor_yaml", 1400f2588f2SPatrick Williams dest="monitor_yaml", 14185be2e70SMatt Spinler default="example/monitor.yaml", 1420f2588f2SPatrick Williams help="fan monitor definitional yaml", 1430f2588f2SPatrick Williams ) 1440f2588f2SPatrick Williams parser.add_argument( 1450f2588f2SPatrick Williams "-o", 1460f2588f2SPatrick Williams "--output_dir", 1470f2588f2SPatrick Williams dest="output_dir", 14885be2e70SMatt Spinler default=".", 1490f2588f2SPatrick Williams help="output directory", 1500f2588f2SPatrick Williams ) 15185be2e70SMatt Spinler args = parser.parse_args() 15285be2e70SMatt Spinler 15385be2e70SMatt Spinler if not args.monitor_yaml: 15485be2e70SMatt Spinler parser.print_usage() 1553e781064SWilliam A. Kennington III sys.exit(1) 15685be2e70SMatt Spinler 1570f2588f2SPatrick Williams with open(args.monitor_yaml, "r") as monitor_input: 15885be2e70SMatt Spinler monitor_data = yaml.safe_load(monitor_input) or {} 15985be2e70SMatt Spinler 16085be2e70SMatt Spinler # Do some minor input validation 1610f2588f2SPatrick Williams for fan in monitor_data.get("fans", {}): 1620f2588f2SPatrick Williams if (fan["deviation"] < 0) or (fan["deviation"] > 100): 1630f2588f2SPatrick Williams sys.exit("Invalid deviation value " + str(fan["deviation"])) 16485be2e70SMatt Spinler 16585be2e70SMatt Spinler output_file = os.path.join(args.output_dir, "fan_monitor_defs.cpp") 1660f2588f2SPatrick Williams with open(output_file, "w") as output: 16785be2e70SMatt Spinler output.write(Template(tmpl).render(data=monitor_data)) 168