summaryrefslogtreecommitdiffstats
path: root/extensions/openpower-pels/registry/tools/process_registry.py
blob: 09ad3e0597a6c7547e6b0b5b6730c87d12f8a5c8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#!/usr/bin/env python

import argparse
import json
import sys

r"""
Validates the PEL message registry JSON, which includes checking it against
a JSON schema using the jsonschema module as well as doing some extra checks
that can't be encoded in the schema.
"""


def check_duplicate_names(registry_json):
    r"""
    Check that there aren't any message registry entries with the same
    'Name' field.  There may be a use case for this in the future, but there
    isn't right now.

    registry_json: The message registry JSON
    """

    names = {}
    for entry in registry_json['PELs']:
        if entry['Name'] in names.keys():
            sys.exit("Found multiple uses of error {}".format(entry['Name']))
        else:
            names[entry['Name']] = {}


def check_duplicate_reason_codes(registry_json):
    r"""
    Check that there aren't any message registry entries with the same
    'ReasonCode' field.

    registry_json: The message registry JSON
    """

    reasonCodes = {}
    for entry in registry_json['PELs']:
        if entry['SRC']['ReasonCode'] in reasonCodes.keys():
            sys.exit("Found duplicate SRC reason code {}".format(
                entry['SRC']['ReasonCode']))
        else:
            reasonCodes[entry['SRC']['ReasonCode']] = {}


def check_component_id(registry_json):
    r"""
    Check that the upper byte of the ComponentID field matches the upper byte
    of the ReasonCode field, but not on "11" type SRCs where they aren't
    supposed to match.

    registry_json: The message registry JSON
    """

    for entry in registry_json['PELs']:

        # Don't check on "11" SRCs as those reason codes aren't supposed to
        # match the component ID.
        if entry.get('Type', '') == "11":
            continue

        if 'ComponentID' in entry:
            id = int(entry['ComponentID'], 16)
            reason_code = int(entry['SRC']['ReasonCode'], 16)

            if (id & 0xFF00) != (reason_code & 0xFF00):
                sys.exit("Found mismatching component ID {} vs reason "
                         "code {} for error {}".format(
                             entry['ComponentID'],
                             entry['SRC']['ReasonCode'],
                             entry['Name']))


def check_message_args(registry_json):
    r"""
    Check that if the Message field uses the '%' style placeholders that there
    are that many entries in the MessageArgSources field.  Also checks that
    the MessageArgSources field is present but only if there are placeholders.

    registry_json: The message registry JSON
    """

    for entry in registry_json['PELs']:
        num_placeholders = entry['Documentation']['Message'].count('%')
        if num_placeholders == 0:
            continue

        if 'MessageArgSources' not in entry['Documentation']:
            sys.exit("Missing MessageArgSources property for error {}".
                     format(entry['Name']))

        if num_placeholders != \
                len(entry['Documentation']['MessageArgSources']):
                    sys.exit("Different number of placeholders found in "
                             "Message vs MessageArgSources for error {}".
                             format(entry['Name']))


def validate_schema(registry, schema):
    r"""
    Validates the passed in JSON against the passed in schema JSON

    registry: Path of the file containing the registry JSON
    schema:   Path of the file containing the schema JSON
              Use None to skip the pure schema validation
    """

    with open(registry) as registry_handle:
        registry_json = json.load(registry_handle)

        if schema:

            import jsonschema

            with open(schema) as schema_handle:
                schema_json = json.load(schema_handle)

                try:
                    jsonschema.validate(registry_json, schema_json)
                except jsonschema.ValidationError as e:
                    print(e)
                    sys.exit("Schema validation failed")

        check_duplicate_names(registry_json)

        check_duplicate_reason_codes(registry_json)

        check_component_id(registry_json)

        check_message_args(registry_json)


if __name__ == '__main__':

    parser = argparse.ArgumentParser(
        description='PEL message registry processor')

    parser.add_argument('-v', '--validate', action='store_true',
                        dest='validate',
                        help='Validate the JSON using the schema')

    parser.add_argument('-s', '--schema-file', dest='schema_file',
                        help='The message registry JSON schema file')

    parser.add_argument('-r', '--registry-file', dest='registry_file',
                        help='The message registry JSON file')
    parser.add_argument('-k', '--skip-schema-validation', action='store_true',
                        dest='skip_schema',
                        help='Skip running schema validation. '
                             'Only do the extra checks.')

    args = parser.parse_args()

    if args.validate:
        if not args.schema_file:
            sys.exit("Schema file required")

        if not args.registry_file:
            sys.exit("Registry file required")

        schema = args.schema_file
        if args.skip_schema:
            schema = None

        validate_schema(args.registry_file, schema)
OpenPOWER on IntegriCloud