1#!/usr/bin/env python 2 3r""" 4This script will parse error log yaml file(s) and generate 5a header file which will then be used by the error logging client and 6server to collect and validate the error information generated by the 7openbmc software components. 8 9This code uses a mako template to provide the basic template of the header 10file we're going to generate. We then call it with information from the 11yaml to generate the header file. 12""" 13 14from mako.template import Template 15from optparse import OptionParser 16import yaml 17import sys 18import os 19 20 21def get_error_yaml_files(i_yaml_dir): 22 yaml_files = filter( 23 lambda file: file.endswith('.errors.yaml'), 24 os.listdir(i_yaml_dir)) 25 return yaml_files 26 27 28def get_meta_yaml_file(i_error_yaml_file): 29 # the meta data will be defined in file name where we replace 30 # <Interface>.errors.yaml with <Interface>.metadata.yaml 31 meta_yaml = i_error_yaml_file.replace("errors", "metadata") 32 return meta_yaml 33 34 35def get_cpp_type(i_type): 36 typeMap = { 37 'int16': 'int16_t', 38 'int32': 'int32_t', 39 'int64': 'int64_t', 40 'uint16': 'uint16_t', 41 'uint32': 'uint32_t', 42 'uint64': 'uint64_t', 43 'double': 'double', 44 # const char* aids usage of constexpr 45 'string': 'const char*'} 46 47 return typeMap[i_type] 48 49 50def gen_elog_hpp(i_yaml_dir, i_output_hpp, 51 i_template_dir, i_elog_mako, i_error_namespace): 52 r""" 53 Read yaml file(s) under input yaml dir, grab the relevant data and call 54 the mako template to generate the output header file. 55 56 Description of arguments: 57 i_yaml_dir directory containing error yaml files 58 i_output_hpp name of the to be generated output hpp 59 i_template_dir directory containing error mako templates 60 i_elog_mako error mako template to render 61 """ 62 63 # Input parameters to mako template 64 errors = list() # Main error codes 65 error_msg = dict() # Error msg that corresponds to error code 66 error_lvl = dict() # Error code log level (debug, info, error, ...) 67 meta = list() # The meta data names associated (ERRNO, FILE_NAME, ...) 68 meta_data = dict() # The meta data info (type, format) 69 70 error_yamls = get_error_yaml_files(i_yaml_dir) 71 72 for error_yaml in error_yamls: 73 # Verify the error yaml file 74 error_yaml = "/".join((i_yaml_dir, error_yaml)) 75 if (not (os.path.isfile(error_yaml))): 76 print "Can not find input yaml file " + error_yaml 77 exit(1) 78 79 # Verify the metadata yaml file 80 meta_yaml = get_meta_yaml_file(error_yaml) 81 if (not (os.path.isfile(meta_yaml))): 82 print "Can not find meta yaml file " + meta_yaml 83 exit(1) 84 85 # Verify the input mako file 86 template_path = "/".join((i_template_dir, i_elog_mako)) 87 if (not (os.path.isfile(template_path))): 88 print "Can not find input template file " + template_path 89 exit(1) 90 91 get_elog_data(error_yaml, 92 meta_yaml, 93 # 3rd arg is a tuple 94 (errors, 95 error_msg, 96 error_lvl, 97 meta, 98 meta_data)) 99 100 # Load the mako template and call it with the required data 101 yaml_dir = i_yaml_dir.strip("./") 102 yaml_dir = yaml_dir.strip("../") 103 template = Template(filename=template_path) 104 f = open(i_output_hpp, 'w') 105 f.write(template.render( 106 errors=errors, error_msg=error_msg, 107 error_lvl=error_lvl, meta=meta, 108 meta_data=meta_data, error_namespace=i_error_namespace)) 109 f.close() 110 111 112def get_elog_data(i_elog_yaml, 113 i_elog_meta_yaml, 114 o_elog_data): 115 r""" 116 Parse the error and metadata yaml files in order to pull out 117 error metadata. 118 119 Description of arguments: 120 i_elog_yaml error yaml file 121 i_elog_meta_yaml metadata yaml file 122 o_elog_data error metadata 123 """ 124 errors, error_msg, error_lvl, meta, meta_data = o_elog_data 125 ifile = yaml.safe_load(open(i_elog_yaml)) 126 mfile = yaml.safe_load(open(i_elog_meta_yaml)) 127 for i in ifile: 128 match = None 129 # Find the corresponding meta data for this entry 130 for m in mfile: 131 if m['name'] == i['name']: 132 match = m 133 break 134 if (match is None): 135 print "Error - Did not find meta data for " + i['name'] 136 exit(1) 137 # Grab the main error and it's info 138 errors.append(i['name']) 139 error_msg[i['name']] = i['description'] 140 error_lvl[i['name']] = match['level'] 141 tmp_meta = [] 142 # grab all the meta data fields and info 143 for j in match['meta']: 144 str_short = j['str'].split('=')[0] 145 tmp_meta.append(str_short) 146 meta_data[str_short] = {} 147 meta_data[str_short]['str'] = j['str'] 148 meta_data[str_short]['str_short'] = str_short 149 meta_data[str_short]['type'] = get_cpp_type(j['type']) 150 meta.append(tmp_meta) 151 152 # Debug 153 # for i in errors: 154 # print "ERROR: " + errors[i] 155 # print " MSG: " + error_msg[errors[i]] 156 # print " LVL: " + error_lvl[errors[i]] 157 # print " META: " 158 # print meta[i] 159 160 161def main(i_args): 162 parser = OptionParser() 163 164 parser.add_option("-m", "--mako", dest="elog_mako", 165 default="elog-gen-template.mako.hpp", 166 help="input mako template file to use") 167 168 parser.add_option("-o", "--output", dest="output_hpp", 169 default="elog-gen.hpp", 170 help="output hpp to generate, elog-gen.hpp is default") 171 172 parser.add_option("-y", "--yamldir", dest="yamldir", 173 default="./example/xyz/openbmc_project/Example", 174 help="Base directory of yaml files to process") 175 176 parser.add_option("-t", "--templatedir", dest="templatedir", 177 default="phosphor-logging/templates/", 178 help="Base directory of files to process") 179 180 parser.add_option("-n", "--namespace", dest="error_namespace", 181 default="example/xyz/openbmc_project/Example", 182 help="Error d-bus namespace") 183 184 (options, args) = parser.parse_args(i_args) 185 186 gen_elog_hpp(options.yamldir, 187 options.output_hpp, 188 options.templatedir, 189 options.elog_mako, 190 options.error_namespace) 191 192# Only run if it's a script 193if __name__ == '__main__': 194 main(sys.argv[1:]) 195