blob: b6fc4fefde31ed5a064e12006282039b3ce0dd17 [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
Deepak Kodihalli160d3e02017-01-17 04:25:22 -060059def get_error_yaml_files(i_yaml_dir):
60 yaml_files = filter(
61 lambda file: file.endswith('.errors.yaml'),
62 os.listdir(i_yaml_dir))
63 return yaml_files
64
65
66def get_meta_yaml_file(i_error_yaml_file):
67 # the meta data will be defined in file name where we replace
68 # <Interface>.errors.yaml with <Interface>.metadata.yaml
69 meta_yaml = i_error_yaml_file.replace("errors", "metadata")
70 return meta_yaml
71
72
Deepak Kodihalli99161192017-01-16 04:00:07 -060073def get_cpp_type(i_type):
74 typeMap = {
75 'int16': 'int16_t',
76 'int32': 'int32_t',
77 'int64': 'int64_t',
78 'uint16': 'uint16_t',
79 'uint32': 'uint32_t',
80 'uint64': 'uint64_t',
81 'double': 'double',
82 # const char* aids usage of constexpr
83 'string': 'const char*'}
84
85 return typeMap[i_type]
86
87
Deepak Kodihalli160d3e02017-01-17 04:25:22 -060088def gen_elog_hpp(i_yaml_dir, i_output_hpp,
89 i_template_dir, i_elog_mako, i_error_namespace):
Andrew Geisslerc830e0f2016-10-18 12:51:29 -050090 r"""
Deepak Kodihalli160d3e02017-01-17 04:25:22 -060091 Read yaml file(s) under input yaml dir, grab the relevant data and call
92 the mako template to generate the output header file.
Andrew Geisslerc830e0f2016-10-18 12:51:29 -050093
94 Description of arguments:
Deepak Kodihalli160d3e02017-01-17 04:25:22 -060095 i_yaml_dir directory containing error yaml files
96 i_output_hpp name of the to be generated output hpp
97 i_template_dir directory containing error mako templates
98 i_elog_mako error mako template to render
Andrew Geisslerc830e0f2016-10-18 12:51:29 -050099 """
100
101 # Input parameters to mako template
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600102 errors = list() # Main error codes
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500103 error_msg = dict() # Error msg that corresponds to error code
104 error_lvl = dict() # Error code log level (debug, info, error, ...)
Deepak Kodihalli5d1aace2017-01-18 00:17:39 -0600105 meta = dict() # The meta data names associated (ERRNO, FILE_NAME, ...)
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500106 meta_data = dict() # The meta data info (type, format)
Deepak Kodihalli5d1aace2017-01-18 00:17:39 -0600107 parents = dict()
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500108
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600109 error_yamls = get_error_yaml_files(i_yaml_dir)
110
111 for error_yaml in error_yamls:
112 # Verify the error yaml file
113 error_yaml = "/".join((i_yaml_dir, error_yaml))
114 if (not (os.path.isfile(error_yaml))):
Patrick Williams6f299132017-02-16 13:27:39 -0600115 print("Can not find input yaml file " + error_yaml)
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600116 exit(1)
117
118 # Verify the metadata yaml file
119 meta_yaml = get_meta_yaml_file(error_yaml)
120 if (not (os.path.isfile(meta_yaml))):
Patrick Williams6f299132017-02-16 13:27:39 -0600121 print("Can not find meta yaml file " + meta_yaml)
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600122 exit(1)
123
124 # Verify the input mako file
125 template_path = "/".join((i_template_dir, i_elog_mako))
126 if (not (os.path.isfile(template_path))):
Patrick Williams6f299132017-02-16 13:27:39 -0600127 print("Can not find input template file " + template_path)
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600128 exit(1)
129
130 get_elog_data(error_yaml,
131 meta_yaml,
132 # 3rd arg is a tuple
133 (errors,
134 error_msg,
135 error_lvl,
136 meta,
Deepak Kodihalli82b7de72017-01-17 07:59:29 -0600137 meta_data,
138 parents))
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600139
Deepak Kodihallicbd12c82017-01-17 08:50:55 -0600140 if(not check_error_inheritance(errors, parents)):
Patrick Williams6f299132017-02-16 13:27:39 -0600141 print("Error - failed to validate error inheritance")
Deepak Kodihallicbd12c82017-01-17 08:50:55 -0600142 exit(1)
143
Deepak Kodihalli5d1aace2017-01-18 00:17:39 -0600144 errors = order_inherited_errors(errors, parents)
145
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600146 # Load the mako template and call it with the required data
147 yaml_dir = i_yaml_dir.strip("./")
148 yaml_dir = yaml_dir.strip("../")
149 template = Template(filename=template_path)
150 f = open(i_output_hpp, 'w')
151 f.write(template.render(
152 errors=errors, error_msg=error_msg,
153 error_lvl=error_lvl, meta=meta,
Deepak Kodihallif2462f02017-01-19 03:40:12 -0600154 meta_data=meta_data, error_namespace=i_error_namespace,
155 parents=parents))
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600156 f.close()
157
158
159def get_elog_data(i_elog_yaml,
160 i_elog_meta_yaml,
161 o_elog_data):
162 r"""
163 Parse the error and metadata yaml files in order to pull out
164 error metadata.
165
166 Description of arguments:
167 i_elog_yaml error yaml file
168 i_elog_meta_yaml metadata yaml file
169 o_elog_data error metadata
170 """
Deepak Kodihalli82b7de72017-01-17 07:59:29 -0600171 errors, error_msg, error_lvl, meta, meta_data, parents = o_elog_data
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600172 ifile = yaml.safe_load(open(i_elog_yaml))
Andrew Geisslere8596302016-11-21 16:06:53 -0600173 mfile = yaml.safe_load(open(i_elog_meta_yaml))
Andrew Geissler5e81bfb2016-11-21 12:49:01 -0600174 for i in ifile:
Andrew Geisslere8596302016-11-21 16:06:53 -0600175 match = None
176 # Find the corresponding meta data for this entry
177 for m in mfile:
178 if m['name'] == i['name']:
179 match = m
180 break
181 if (match is None):
Patrick Williams6f299132017-02-16 13:27:39 -0600182 print("Error - Did not find meta data for " + i['name'])
Andrew Geisslere8596302016-11-21 16:06:53 -0600183 exit(1)
Andrew Geisslerdf048c12016-11-10 16:50:35 -0600184 # Grab the main error and it's info
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600185 errors.append(i['name'])
Deepak Kodihalli82b7de72017-01-17 07:59:29 -0600186 parent = None
187 if('inherits' in i):
188 # xyz.openbmc.Foo, we need Foo
189 # Get 0th inherited error (current support - single inheritance)
190 parent = i['inherits'][0].split(".").pop()
Deepak Kodihalli5d1aace2017-01-18 00:17:39 -0600191 parents[i['name']] = parent
Andrew Geissler5e81bfb2016-11-21 12:49:01 -0600192 error_msg[i['name']] = i['description']
Andrew Geisslere8596302016-11-21 16:06:53 -0600193 error_lvl[i['name']] = match['level']
Andrew Geissler184690d2016-11-03 08:06:31 -0500194 tmp_meta = []
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500195 # grab all the meta data fields and info
Andrew Geisslere8596302016-11-21 16:06:53 -0600196 for j in match['meta']:
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500197 str_short = j['str'].split('=')[0]
198 tmp_meta.append(str_short)
199 meta_data[str_short] = {}
200 meta_data[str_short]['str'] = j['str']
201 meta_data[str_short]['str_short'] = str_short
Deepak Kodihalli99161192017-01-16 04:00:07 -0600202 meta_data[str_short]['type'] = get_cpp_type(j['type'])
Deepak Kodihalli5d1aace2017-01-18 00:17:39 -0600203 meta[i['name']] = tmp_meta
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500204
205 # Debug
Andrew Geissler184690d2016-11-03 08:06:31 -0500206 # for i in errors:
Andrew Geisslerdf048c12016-11-10 16:50:35 -0600207 # print "ERROR: " + errors[i]
208 # print " MSG: " + error_msg[errors[i]]
209 # print " LVL: " + error_lvl[errors[i]]
210 # print " META: "
211 # print meta[i]
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500212
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500213
214def main(i_args):
215 parser = OptionParser()
216
Andrew Geissler184690d2016-11-03 08:06:31 -0500217 parser.add_option("-m", "--mako", dest="elog_mako",
218 default="elog-gen-template.mako.hpp",
Andrew Geisslerdf048c12016-11-10 16:50:35 -0600219 help="input mako template file to use")
Andrew Geissler184690d2016-11-03 08:06:31 -0500220
221 parser.add_option("-o", "--output", dest="output_hpp",
222 default="elog-gen.hpp",
Andrew Geisslerdf048c12016-11-10 16:50:35 -0600223 help="output hpp to generate, elog-gen.hpp is default")
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500224
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600225 parser.add_option("-y", "--yamldir", dest="yamldir",
226 default="./example/xyz/openbmc_project/Example",
Andrew Geisslerf1f2cfa2016-11-21 15:16:45 -0600227 help="Base directory of yaml files to process")
228
229 parser.add_option("-t", "--templatedir", dest="templatedir",
230 default="phosphor-logging/templates/",
231 help="Base directory of files to process")
232
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600233 parser.add_option("-n", "--namespace", dest="error_namespace",
234 default="example/xyz/openbmc_project/Example",
235 help="Error d-bus namespace")
236
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500237 (options, args) = parser.parse_args(i_args)
238
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600239 gen_elog_hpp(options.yamldir,
240 options.output_hpp,
241 options.templatedir,
242 options.elog_mako,
243 options.error_namespace)
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500244
245# Only run if it's a script
246if __name__ == '__main__':
Andrew Geissler184690d2016-11-03 08:06:31 -0500247 main(sys.argv[1:])