blob: d1acb79b36f3180101d0e3085c092f864ef754dd [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 Kodihallicbd12c82017-01-17 08:50:55 -060021def check_error_inheritance(i_errors, i_parents):
22 for parent in i_parents:
23 if(parent and (parent not in i_errors)):
24 print parent + " inhertied from, but not defined"
25 return False
26 return True
27
28
Deepak Kodihalli160d3e02017-01-17 04:25:22 -060029def get_error_yaml_files(i_yaml_dir):
30 yaml_files = filter(
31 lambda file: file.endswith('.errors.yaml'),
32 os.listdir(i_yaml_dir))
33 return yaml_files
34
35
36def get_meta_yaml_file(i_error_yaml_file):
37 # the meta data will be defined in file name where we replace
38 # <Interface>.errors.yaml with <Interface>.metadata.yaml
39 meta_yaml = i_error_yaml_file.replace("errors", "metadata")
40 return meta_yaml
41
42
Deepak Kodihalli99161192017-01-16 04:00:07 -060043def get_cpp_type(i_type):
44 typeMap = {
45 'int16': 'int16_t',
46 'int32': 'int32_t',
47 'int64': 'int64_t',
48 'uint16': 'uint16_t',
49 'uint32': 'uint32_t',
50 'uint64': 'uint64_t',
51 'double': 'double',
52 # const char* aids usage of constexpr
53 'string': 'const char*'}
54
55 return typeMap[i_type]
56
57
Deepak Kodihalli160d3e02017-01-17 04:25:22 -060058def gen_elog_hpp(i_yaml_dir, i_output_hpp,
59 i_template_dir, i_elog_mako, i_error_namespace):
Andrew Geisslerc830e0f2016-10-18 12:51:29 -050060 r"""
Deepak Kodihalli160d3e02017-01-17 04:25:22 -060061 Read yaml file(s) under input yaml dir, grab the relevant data and call
62 the mako template to generate the output header file.
Andrew Geisslerc830e0f2016-10-18 12:51:29 -050063
64 Description of arguments:
Deepak Kodihalli160d3e02017-01-17 04:25:22 -060065 i_yaml_dir directory containing error yaml files
66 i_output_hpp name of the to be generated output hpp
67 i_template_dir directory containing error mako templates
68 i_elog_mako error mako template to render
Andrew Geisslerc830e0f2016-10-18 12:51:29 -050069 """
70
71 # Input parameters to mako template
Deepak Kodihalli160d3e02017-01-17 04:25:22 -060072 errors = list() # Main error codes
Andrew Geisslerc830e0f2016-10-18 12:51:29 -050073 error_msg = dict() # Error msg that corresponds to error code
74 error_lvl = dict() # Error code log level (debug, info, error, ...)
Andrew Geissler184690d2016-11-03 08:06:31 -050075 meta = list() # The meta data names associated (ERRNO, FILE_NAME, ...)
Andrew Geisslerc830e0f2016-10-18 12:51:29 -050076 meta_data = dict() # The meta data info (type, format)
Deepak Kodihalli82b7de72017-01-17 07:59:29 -060077 parents = list()
Andrew Geisslerc830e0f2016-10-18 12:51:29 -050078
Deepak Kodihalli160d3e02017-01-17 04:25:22 -060079 error_yamls = get_error_yaml_files(i_yaml_dir)
80
81 for error_yaml in error_yamls:
82 # Verify the error yaml file
83 error_yaml = "/".join((i_yaml_dir, error_yaml))
84 if (not (os.path.isfile(error_yaml))):
85 print "Can not find input yaml file " + error_yaml
86 exit(1)
87
88 # Verify the metadata yaml file
89 meta_yaml = get_meta_yaml_file(error_yaml)
90 if (not (os.path.isfile(meta_yaml))):
91 print "Can not find meta yaml file " + meta_yaml
92 exit(1)
93
94 # Verify the input mako file
95 template_path = "/".join((i_template_dir, i_elog_mako))
96 if (not (os.path.isfile(template_path))):
97 print "Can not find input template file " + template_path
98 exit(1)
99
100 get_elog_data(error_yaml,
101 meta_yaml,
102 # 3rd arg is a tuple
103 (errors,
104 error_msg,
105 error_lvl,
106 meta,
Deepak Kodihalli82b7de72017-01-17 07:59:29 -0600107 meta_data,
108 parents))
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600109
Deepak Kodihallicbd12c82017-01-17 08:50:55 -0600110 if(not check_error_inheritance(errors, parents)):
111 print "Error - failed to validate error inheritance"
112 exit(1)
113
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600114 # Load the mako template and call it with the required data
115 yaml_dir = i_yaml_dir.strip("./")
116 yaml_dir = yaml_dir.strip("../")
117 template = Template(filename=template_path)
118 f = open(i_output_hpp, 'w')
119 f.write(template.render(
120 errors=errors, error_msg=error_msg,
121 error_lvl=error_lvl, meta=meta,
122 meta_data=meta_data, error_namespace=i_error_namespace))
123 f.close()
124
125
126def get_elog_data(i_elog_yaml,
127 i_elog_meta_yaml,
128 o_elog_data):
129 r"""
130 Parse the error and metadata yaml files in order to pull out
131 error metadata.
132
133 Description of arguments:
134 i_elog_yaml error yaml file
135 i_elog_meta_yaml metadata yaml file
136 o_elog_data error metadata
137 """
Deepak Kodihalli82b7de72017-01-17 07:59:29 -0600138 errors, error_msg, error_lvl, meta, meta_data, parents = o_elog_data
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600139 ifile = yaml.safe_load(open(i_elog_yaml))
Andrew Geisslere8596302016-11-21 16:06:53 -0600140 mfile = yaml.safe_load(open(i_elog_meta_yaml))
Andrew Geissler5e81bfb2016-11-21 12:49:01 -0600141 for i in ifile:
Andrew Geisslere8596302016-11-21 16:06:53 -0600142 match = None
143 # Find the corresponding meta data for this entry
144 for m in mfile:
145 if m['name'] == i['name']:
146 match = m
147 break
148 if (match is None):
149 print "Error - Did not find meta data for " + i['name']
150 exit(1)
Andrew Geisslerdf048c12016-11-10 16:50:35 -0600151 # Grab the main error and it's info
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600152 errors.append(i['name'])
Deepak Kodihalli82b7de72017-01-17 07:59:29 -0600153 parent = None
154 if('inherits' in i):
155 # xyz.openbmc.Foo, we need Foo
156 # Get 0th inherited error (current support - single inheritance)
157 parent = i['inherits'][0].split(".").pop()
158 parents.append(parent)
Andrew Geissler5e81bfb2016-11-21 12:49:01 -0600159 error_msg[i['name']] = i['description']
Andrew Geisslere8596302016-11-21 16:06:53 -0600160 error_lvl[i['name']] = match['level']
Andrew Geissler184690d2016-11-03 08:06:31 -0500161 tmp_meta = []
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500162 # grab all the meta data fields and info
Andrew Geisslere8596302016-11-21 16:06:53 -0600163 for j in match['meta']:
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500164 str_short = j['str'].split('=')[0]
165 tmp_meta.append(str_short)
166 meta_data[str_short] = {}
167 meta_data[str_short]['str'] = j['str']
168 meta_data[str_short]['str_short'] = str_short
Deepak Kodihalli99161192017-01-16 04:00:07 -0600169 meta_data[str_short]['type'] = get_cpp_type(j['type'])
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500170 meta.append(tmp_meta)
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500171
172 # Debug
Andrew Geissler184690d2016-11-03 08:06:31 -0500173 # for i in errors:
Andrew Geisslerdf048c12016-11-10 16:50:35 -0600174 # print "ERROR: " + errors[i]
175 # print " MSG: " + error_msg[errors[i]]
176 # print " LVL: " + error_lvl[errors[i]]
177 # print " META: "
178 # print meta[i]
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500179
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500180
181def main(i_args):
182 parser = OptionParser()
183
Andrew Geissler184690d2016-11-03 08:06:31 -0500184 parser.add_option("-m", "--mako", dest="elog_mako",
185 default="elog-gen-template.mako.hpp",
Andrew Geisslerdf048c12016-11-10 16:50:35 -0600186 help="input mako template file to use")
Andrew Geissler184690d2016-11-03 08:06:31 -0500187
188 parser.add_option("-o", "--output", dest="output_hpp",
189 default="elog-gen.hpp",
Andrew Geisslerdf048c12016-11-10 16:50:35 -0600190 help="output hpp to generate, elog-gen.hpp is default")
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500191
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600192 parser.add_option("-y", "--yamldir", dest="yamldir",
193 default="./example/xyz/openbmc_project/Example",
Andrew Geisslerf1f2cfa2016-11-21 15:16:45 -0600194 help="Base directory of yaml files to process")
195
196 parser.add_option("-t", "--templatedir", dest="templatedir",
197 default="phosphor-logging/templates/",
198 help="Base directory of files to process")
199
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600200 parser.add_option("-n", "--namespace", dest="error_namespace",
201 default="example/xyz/openbmc_project/Example",
202 help="Error d-bus namespace")
203
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500204 (options, args) = parser.parse_args(i_args)
205
Deepak Kodihalli160d3e02017-01-17 04:25:22 -0600206 gen_elog_hpp(options.yamldir,
207 options.output_hpp,
208 options.templatedir,
209 options.elog_mako,
210 options.error_namespace)
Andrew Geisslerc830e0f2016-10-18 12:51:29 -0500211
212# Only run if it's a script
213if __name__ == '__main__':
Andrew Geissler184690d2016-11-03 08:06:31 -0500214 main(sys.argv[1:])