blob: 3cf396c8fc3ca7d070988f72cf373f0608df2048 [file] [log] [blame]
Andrew Geisslerc830e0f2016-10-18 12:51:29 -05001#!/usr/bin/env python
2
3r"""
Deepak Kodihalli160d3e02017-01-17 04:25:22 -06004This script will parse error log yaml file(s) and generate
Andrew Geisslerc830e0f2016-10-18 12:51:29 -05005a 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.
Andrew Geisslerc830e0f2016-10-18 12:51:29 -050012"""
13
14from mako.template import Template
15from optparse import OptionParser
16import yaml
17import sys
18import os
19
Andrew Geissler184690d2016-11-03 08:06:31 -050020
Deepak Kodihalli5d1aace2017-01-18 00:17:39 -060021def order_inherited_errors(i_errors, i_parents):
22 # the ordered list of errors
23 errors = list()
24 has_inheritance = False
25 for error in i_errors:
26 if(i_parents[error] is not None):
27 has_inheritance = True
28 break
29
30 if(has_inheritance):
31 # Order the error codes list such that an error is never placed
32 # before it's parent. This way generated code can ensure parent
33 # definitions preceed child error definitions.
34 while(len(errors) < len(i_errors)):
35 for error in i_errors:
36 if(error in errors):
37 # already ordererd
38 continue
39 if((not i_parents[error]) or (i_parents[error] in errors)):
40 # parent present, or has no parent, either way this error
41 # can be added
42 errors.append(error)
43 else:
44 # no inherited errors
45 errors = i_errors
46
47 return errors
48
49
Deepak Kodihallicbd12c82017-01-17 08:50:55 -060050def check_error_inheritance(i_errors, i_parents):
Deepak Kodihalli5d1aace2017-01-18 00:17:39 -060051 for error in i_errors:
52 if(i_parents[error] and (i_parents[error] not in i_errors)):
Patrick Williams6f299132017-02-16 13:27:39 -060053 print(error + " inherits " + i_parents[error] +
54 " but the latter is not defined")
Deepak Kodihallicbd12c82017-01-17 08:50:55 -060055 return False
56 return True
57
58
Adriana Kobylak6a9db6e2017-02-21 12:58:05 -060059def get_error_yaml_files(i_yaml_dir, i_test_dir):
Adriana Kobylakf4690732017-02-19 09:53:34 -060060 yaml_files = []
Adriana Kobylak6a9db6e2017-02-21 12:58:05 -060061 if i_yaml_dir != "None":
62 for root, dirs, files in os.walk(i_yaml_dir):
63 for files in filter(lambda file:
64 file.endswith('.errors.yaml'), files):
65 yaml_files.append(os.path.join(root, files))
66 for root, dirs, files in os.walk(i_test_dir):
Adriana Kobylakf4690732017-02-19 09:53:34 -060067 for files in filter(lambda file: file.endswith('.errors.yaml'), files):
68 yaml_files.append(os.path.join(root, files))
Deepak Kodihalli160d3e02017-01-17 04:25:22 -060069 return yaml_files
70
71
72def get_meta_yaml_file(i_error_yaml_file):
73 # the meta data will be defined in file name where we replace
74 # <Interface>.errors.yaml with <Interface>.metadata.yaml
75 meta_yaml = i_error_yaml_file.replace("errors", "metadata")
76 return meta_yaml
77
78
Deepak Kodihalli99161192017-01-16 04:00:07 -060079def get_cpp_type(i_type):
80 typeMap = {
81 'int16': 'int16_t',
82 'int32': 'int32_t',
83 'int64': 'int64_t',
84 'uint16': 'uint16_t',
85 'uint32': 'uint32_t',
86 'uint64': 'uint64_t',
87 'double': 'double',
88 # const char* aids usage of constexpr
89 'string': 'const char*'}
90
91 return typeMap[i_type]
92
93
Adriana Kobylak6a9db6e2017-02-21 12:58:05 -060094def gen_elog_hpp(i_yaml_dir, i_test_dir, i_output_hpp,
Deepak Kodihalli160d3e02017-01-17 04:25:22 -060095 i_template_dir, i_elog_mako, i_error_namespace):
Andrew Geisslerc830e0f2016-10-18 12:51:29 -050096 r"""
Deepak Kodihalli160d3e02017-01-17 04:25:22 -060097 Read yaml file(s) under input yaml dir, grab the relevant data and call
98 the mako template to generate the output header file.
Andrew Geisslerc830e0f2016-10-18 12:51:29 -050099
100 Description of arguments:
Adriana Kobylak6a9db6e2017-02-21 12:58:05 -0600101 i_yaml_dir directory containing base error yaml files
102 i_test_dir directory containing test error yaml files
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600103 i_output_hpp name of the to be generated output hpp
104 i_template_dir directory containing error mako templates
105 i_elog_mako error mako template to render
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500106 """
107
108 # Input parameters to mako template
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600109 errors = list() # Main error codes
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500110 error_msg = dict() # Error msg that corresponds to error code
111 error_lvl = dict() # Error code log level (debug, info, error, ...)
Deepak Kodihalli5d1aace2017-01-18 00:17:39 -0600112 meta = dict() # The meta data names associated (ERRNO, FILE_NAME, ...)
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500113 meta_data = dict() # The meta data info (type, format)
Deepak Kodihalli5d1aace2017-01-18 00:17:39 -0600114 parents = dict()
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500115
Adriana Kobylak6a9db6e2017-02-21 12:58:05 -0600116 error_yamls = get_error_yaml_files(i_yaml_dir, i_test_dir)
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600117
118 for error_yaml in error_yamls:
119 # Verify the error yaml file
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600120 if (not (os.path.isfile(error_yaml))):
Patrick Williams6f299132017-02-16 13:27:39 -0600121 print("Can not find input yaml file " + error_yaml)
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600122 exit(1)
123
124 # Verify the metadata yaml file
125 meta_yaml = get_meta_yaml_file(error_yaml)
126 if (not (os.path.isfile(meta_yaml))):
Patrick Williams6f299132017-02-16 13:27:39 -0600127 print("Can not find meta yaml file " + meta_yaml)
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600128 exit(1)
129
130 # Verify the input mako file
131 template_path = "/".join((i_template_dir, i_elog_mako))
132 if (not (os.path.isfile(template_path))):
Patrick Williams6f299132017-02-16 13:27:39 -0600133 print("Can not find input template file " + template_path)
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600134 exit(1)
135
136 get_elog_data(error_yaml,
137 meta_yaml,
138 # 3rd arg is a tuple
139 (errors,
140 error_msg,
141 error_lvl,
142 meta,
Deepak Kodihalli82b7de72017-01-17 07:59:29 -0600143 meta_data,
144 parents))
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600145
Deepak Kodihallicbd12c82017-01-17 08:50:55 -0600146 if(not check_error_inheritance(errors, parents)):
Patrick Williams6f299132017-02-16 13:27:39 -0600147 print("Error - failed to validate error inheritance")
Deepak Kodihallicbd12c82017-01-17 08:50:55 -0600148 exit(1)
149
Deepak Kodihalli5d1aace2017-01-18 00:17:39 -0600150 errors = order_inherited_errors(errors, parents)
151
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600152 # Load the mako template and call it with the required data
153 yaml_dir = i_yaml_dir.strip("./")
154 yaml_dir = yaml_dir.strip("../")
155 template = Template(filename=template_path)
156 f = open(i_output_hpp, 'w')
157 f.write(template.render(
158 errors=errors, error_msg=error_msg,
159 error_lvl=error_lvl, meta=meta,
Deepak Kodihallif2462f02017-01-19 03:40:12 -0600160 meta_data=meta_data, error_namespace=i_error_namespace,
161 parents=parents))
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600162 f.close()
163
164
165def get_elog_data(i_elog_yaml,
166 i_elog_meta_yaml,
167 o_elog_data):
168 r"""
169 Parse the error and metadata yaml files in order to pull out
170 error metadata.
171
172 Description of arguments:
173 i_elog_yaml error yaml file
174 i_elog_meta_yaml metadata yaml file
175 o_elog_data error metadata
176 """
Deepak Kodihalli82b7de72017-01-17 07:59:29 -0600177 errors, error_msg, error_lvl, meta, meta_data, parents = o_elog_data
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600178 ifile = yaml.safe_load(open(i_elog_yaml))
Andrew Geisslere8596302016-11-21 16:06:53 -0600179 mfile = yaml.safe_load(open(i_elog_meta_yaml))
Adriana Kobylak17944e12017-02-13 22:29:21 -0600180 for i in mfile:
Andrew Geisslere8596302016-11-21 16:06:53 -0600181 match = None
182 # Find the corresponding meta data for this entry
Adriana Kobylak17944e12017-02-13 22:29:21 -0600183 for j in ifile:
184 if j['name'] == i['name']:
185 match = j
Andrew Geisslere8596302016-11-21 16:06:53 -0600186 break
187 if (match is None):
Patrick Williams6f299132017-02-16 13:27:39 -0600188 print("Error - Did not find meta data for " + i['name'])
Andrew Geisslere8596302016-11-21 16:06:53 -0600189 exit(1)
Andrew Geisslerdf048c12016-11-10 16:50:35 -0600190 # Grab the main error and it's info
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600191 errors.append(i['name'])
Deepak Kodihalli82b7de72017-01-17 07:59:29 -0600192 parent = None
193 if('inherits' in i):
194 # xyz.openbmc.Foo, we need Foo
195 # Get 0th inherited error (current support - single inheritance)
196 parent = i['inherits'][0].split(".").pop()
Deepak Kodihalli5d1aace2017-01-18 00:17:39 -0600197 parents[i['name']] = parent
Adriana Kobylak17944e12017-02-13 22:29:21 -0600198 error_msg[i['name']] = match['description']
199 error_lvl[i['name']] = i['level']
Andrew Geissler184690d2016-11-03 08:06:31 -0500200 tmp_meta = []
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500201 # grab all the meta data fields and info
Adriana Kobylak17944e12017-02-13 22:29:21 -0600202 for j in i['meta']:
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500203 str_short = j['str'].split('=')[0]
204 tmp_meta.append(str_short)
205 meta_data[str_short] = {}
206 meta_data[str_short]['str'] = j['str']
207 meta_data[str_short]['str_short'] = str_short
Deepak Kodihalli99161192017-01-16 04:00:07 -0600208 meta_data[str_short]['type'] = get_cpp_type(j['type'])
Deepak Kodihalli5d1aace2017-01-18 00:17:39 -0600209 meta[i['name']] = tmp_meta
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500210
211 # Debug
Andrew Geissler184690d2016-11-03 08:06:31 -0500212 # for i in errors:
Andrew Geisslerdf048c12016-11-10 16:50:35 -0600213 # print "ERROR: " + errors[i]
214 # print " MSG: " + error_msg[errors[i]]
215 # print " LVL: " + error_lvl[errors[i]]
216 # print " META: "
217 # print meta[i]
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500218
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500219
220def main(i_args):
221 parser = OptionParser()
222
Andrew Geissler184690d2016-11-03 08:06:31 -0500223 parser.add_option("-m", "--mako", dest="elog_mako",
224 default="elog-gen-template.mako.hpp",
Andrew Geisslerdf048c12016-11-10 16:50:35 -0600225 help="input mako template file to use")
Andrew Geissler184690d2016-11-03 08:06:31 -0500226
227 parser.add_option("-o", "--output", dest="output_hpp",
228 default="elog-gen.hpp",
Andrew Geisslerdf048c12016-11-10 16:50:35 -0600229 help="output hpp to generate, elog-gen.hpp is default")
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500230
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600231 parser.add_option("-y", "--yamldir", dest="yamldir",
Adriana Kobylak6a9db6e2017-02-21 12:58:05 -0600232 default="None",
Andrew Geisslerf1f2cfa2016-11-21 15:16:45 -0600233 help="Base directory of yaml files to process")
234
Adriana Kobylak6a9db6e2017-02-21 12:58:05 -0600235 parser.add_option("-u", "--testdir", dest="testdir",
236 default="./tools/example/",
237 help="Unit test directory of yaml files to process")
238
Andrew Geisslerf1f2cfa2016-11-21 15:16:45 -0600239 parser.add_option("-t", "--templatedir", dest="templatedir",
240 default="phosphor-logging/templates/",
241 help="Base directory of files to process")
242
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600243 parser.add_option("-n", "--namespace", dest="error_namespace",
244 default="example/xyz/openbmc_project/Example",
245 help="Error d-bus namespace")
246
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500247 (options, args) = parser.parse_args(i_args)
248
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600249 gen_elog_hpp(options.yamldir,
Adriana Kobylak6a9db6e2017-02-21 12:58:05 -0600250 options.testdir,
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600251 options.output_hpp,
252 options.templatedir,
253 options.elog_mako,
254 options.error_namespace)
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500255
256# Only run if it's a script
257if __name__ == '__main__':
Andrew Geissler184690d2016-11-03 08:06:31 -0500258 main(sys.argv[1:])