xref: /openbmc/phosphor-logging/tools/elog-gen.py (revision e8596300873a33e220d275e714e8ae2fb9aaf42a)
1#!/usr/bin/env python
2
3r"""
4This script will parse the input error log yaml file 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"""
14
15from mako.template import Template
16from optparse import OptionParser
17import yaml
18import sys
19import os
20
21
22def gen_elog_hpp(i_rootdir, i_elog_yaml, i_elog_meta_yaml,
23                 i_input_mako, i_output_hpp):
24    r"""
25    Read the input yaml file, grab the relevant data and call the mako
26    template to generate the header file.
27
28    Description of arguments:
29    i_rootdir                    base directory to search for yaml files
30    i_elog_yaml                  yaml file describing the error logs
31    i_elog_meta_yaml             yaml file describing the meta data for elogs
32    i_input_mako                 input mako template file to use
33    i_output_hpp                 header file to output the generated code to
34    """
35
36    # Input parameters to mako template
37    errors = dict()  # Main error codes
38    error_msg = dict()  # Error msg that corresponds to error code
39    error_lvl = dict()  # Error code log level (debug, info, error, ...)
40    meta = list()  # The meta data names associated (ERRNO, FILE_NAME, ...)
41    meta_data = dict()  # The meta data info (type, format)
42
43    # see elog.yaml for reference
44    ifile = yaml.safe_load(open("/".join((i_rootdir, i_elog_yaml))))
45    mfile = yaml.safe_load(open(i_elog_meta_yaml))
46    err_count = 0
47    for i in ifile:
48        match = None
49        # Find the corresponding meta data for this entry
50        for m in mfile:
51            if m['name'] == i['name']:
52                match = m
53                break
54        if (match is None):
55            print "Error - Did not find meta data for " + i['name']
56            exit(1)
57        # Grab the main error and it's info
58        errors[err_count] = i['name']
59        error_msg[i['name']] = i['description']
60        error_lvl[i['name']] = match['level']
61        tmp_meta = []
62        # grab all the meta data fields and info
63        for j in match['meta']:
64            str_short = j['str'].split('=')[0]
65            tmp_meta.append(str_short)
66            meta_data[str_short] = {}
67            meta_data[str_short]['str'] = j['str']
68            meta_data[str_short]['str_short'] = str_short
69            meta_data[str_short]['type'] = j['type']
70        meta.append(tmp_meta)
71        err_count += 1
72
73    # Debug
74    # for i in errors:
75    #   print "ERROR: " + errors[i]
76    #   print " MSG:  " + error_msg[errors[i]]
77    #   print " LVL:  " + error_lvl[errors[i]]
78    #   print " META: "
79    #   print meta[i]
80
81    # Load the mako template and call it with the required data
82    mytemplate = Template(filename=i_input_mako)
83    f = open(i_output_hpp, 'w')
84    f.write(mytemplate.render(errors=errors, error_msg=error_msg,
85                              error_lvl=error_lvl, meta=meta,
86                              meta_data=meta_data,elog_yaml=i_elog_yaml))
87    f.close()
88
89
90def main(i_args):
91    parser = OptionParser()
92
93    parser.add_option("-e", "--elog", dest="elog_yaml",
94                      default="xyz/openbmc_project/Example/Elog.errors.yaml",
95                      help="input error yaml file to parse")
96
97    parser.add_option("-m", "--mako", dest="elog_mako",
98                      default="elog-gen-template.mako.hpp",
99                      help="input mako template file to use")
100
101    parser.add_option("-o", "--output", dest="output_hpp",
102                      default="elog-gen.hpp",
103                      help="output hpp to generate, elog-gen.hpp is default")
104
105    parser.add_option("-r", "--rootdir", dest="rootdir",
106                      default="example",
107                      help="Base directory of yaml files to process")
108
109    parser.add_option("-t", "--templatedir", dest="templatedir",
110                      default="phosphor-logging/templates/",
111                      help="Base directory of files to process")
112
113    (options, args) = parser.parse_args(i_args)
114
115    # Verify the input yaml file
116    yaml_path = "/".join((options.rootdir, options.elog_yaml))
117    if (not (os.path.isfile(yaml_path))):
118        print "Can not find input yaml file " + yaml_path
119        exit(1)
120
121    # the meta data will be defined in a similar file name where we replace
122    # <Interface>.errors.yaml with <Interface>.logging.yaml
123    meta_file = options.elog_yaml.replace("errors", "logging")
124    meta_file = "/".join((options.rootdir, meta_file))
125    if (not (os.path.isfile(meta_file))):
126        print "Can not find meta yaml file " + meta_file
127        exit(1)
128
129    # Verify the input mako file
130    template_path = "/".join((options.templatedir, options.elog_mako))
131    if (not (os.path.isfile(template_path))):
132        print "Can not find input template file " + template_path
133        exit(1)
134
135    gen_elog_hpp(options.rootdir,
136                 options.elog_yaml,
137                 meta_file,
138                 template_path,
139                 options.output_hpp)
140
141# Only run if it's a script
142if __name__ == '__main__':
143    main(sys.argv[1:])
144