xref: /openbmc/openbmc-test-automation/lib/pel_utils.py (revision 5ca5c999e077f534b2420e3b5ad63838263fee01)
1#!/usr/bin/env python3
2
3r"""
4PEL functions.
5"""
6
7import func_args as fa
8import bmc_ssh_utils as bsu
9import json
10import os
11import sys
12from robot.libraries.BuiltIn import BuiltIn
13
14base_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
15sys.path.append(base_path + "/data/")
16
17import pel_variables
18
19
20class peltool_exception(Exception):
21    r"""
22    Base class for peltool related exceptions.
23    """
24
25    def __init__(self, message):
26        self.message = message
27        super().__init__(self.message)
28
29
30def peltool(option_string, parse_json=True, **bsu_options):
31    r"""
32    Run peltool on the BMC with the caller's option string and return the result.
33
34    Example:
35
36    ${pel_results}=  Peltool  -l
37    Rprint Vars  pel_results
38
39    pel_results:
40      [0x50000031]:
41        [CompID]:                       0x1000
42        [PLID]:                         0x50000031
43        [Subsystem]:                    BMC Firmware
44        [Message]:                      An application had an internal failure
45        [SRC]:                          BD8D1002
46        [Commit Time]:                  02/25/2020  04:51:31
47        [Sev]:                          Unrecoverable Error
48        [CreatorID]:                    BMC
49
50    Description of argument(s):
51    option_string                   A string of options which are to be processed by the peltool command.
52    parse_json                      Indicates that the raw JSON data should parsed into a list of
53                                    dictionaries.
54    bsu_options                     Options to be passed directly to bmc_execute_command. See its prolog for
55                                    details.
56    """
57
58    bsu_options = fa.args_to_objects(bsu_options)
59    out_buf, stderr, rc = bsu.bmc_execute_command('peltool ' + option_string, **bsu_options)
60    if parse_json:
61        try:
62            return json.loads(out_buf)
63        except ValueError:
64            return {}
65    return out_buf
66
67
68def get_pel_data_from_bmc(include_hidden_pels=False,
69                          include_informational_pels=False):
70    r"""
71    Returns PEL data from BMC else throws exception.
72
73    Description of arguments:
74    include_hidden_pels           True/False (default: False).
75                                  Set True to get hidden PELs else False.
76    include_informational_pels    True/False (default: False).
77                                  Set True to get informational PELs else False.
78    """
79    try:
80        pel_cmd = " -l"
81        if include_hidden_pels:
82            pel_cmd = pel_cmd + " -h"
83        if include_informational_pels:
84            pel_cmd = pel_cmd + " -f"
85        pel_data = peltool(pel_cmd)
86        if not pel_data:
87            print("No PEL data present in BMC ...")
88    except Exception as e:
89        raise peltool_exception("Failed to get PEL data from BMC : " + str(e))
90    return pel_data
91
92
93def fetch_all_pel_ids_for_src(src_id, severity, include_hidden_pels=False):
94    r"""
95    Fetch all PEL IDs for the input SRC ID based on the severity type
96    in the list format.
97
98    Description of arguments:
99    src_id                SRC ID (e.g. BCXXYYYY).
100    severity              PEL severity (e.g. "Predictive Error"
101                                             "Recovered Error").
102    include_hidden_pels   True/False (default: False).
103                          Set True to get hidden PELs else False.
104    """
105
106    try:
107        src_pel_ids = []
108        pel_data = get_pel_data_from_bmc(include_hidden_pels)
109        pel_id_list = pel_data.keys()
110        for pel_id in pel_id_list:
111            # Check if required SRC ID with severity is present
112            if ((pel_data[pel_id]["SRC"] == src_id) and (pel_data[pel_id]["Sev"] == severity)):
113                src_pel_ids.append(pel_id)
114
115        if not src_pel_ids:
116            raise peltool_exception(src_id + " with severity " + severity + " not present")
117    except Exception as e:
118        raise peltool_exception("Failed to fetch PEL ID for required SRC : " + str(e))
119    return src_pel_ids
120
121
122def verify_src_signature_and_threshold(pel_id, attn_type, signature_desc, th_limit):
123    r"""
124    Verifies SRC details for the given PEL ID based on the required
125    attention type, signature description, threshold limits.
126
127    Description of arguments:
128    pel_id          PEL ID for the required SRC details to verify.
129    attn_type       Attention type (e.g. RE, CS, UNIT_CS).
130    signature_desc  Signature description of the error inject.
131    th_limit        Threshold limit (e.g. 1, 5, 32).
132    """
133
134    try:
135        pel_cmd = " -i " + pel_id
136        src_data = peltool(pel_cmd)
137        src_dict = src_data["Primary SRC"]["SRC Details"]
138        usr_data = src_data["User Data 1"]
139
140        # Example for signature in recoverable error
141        #
142        # "SRC Details": {
143        # "Attention Type": "RECOVERABLE",
144        # "Node": 0,
145        # "Target Type": "TYPE_OMIC",
146        # "Target Instance": 0,
147        # "Signature": "MC_OMI_DL_FIR[1]: OMI-DL0 UE on data flit"
148        # }
149        if (attn_type == "RE"):
150            if (src_dict["Attention Type"] != "RECOVERABLE"):
151                raise peltool_exception("Required Attention type " + attn_type + " not found")
152
153        # Example for signature in system checkstop error
154        #
155        # "SRC Details": {
156        # "Primary Attention": "system checkstop",
157        # "Signature Description": {
158        #    "Chip Desc": "node 0 proc 0 (P10 2.0)",
159        #    "Signature": "EQ_L2_FIR(0)[7] L2 directory read UE",
160        #    "Attn Type": "checkstop"
161        # }
162
163        elif (attn_type == "CS"):
164            if (src_dict["Primary Attention"] != "system checkstop"):
165                raise peltool_exception("Required Attention type " + attn_type + " not found")
166
167        elif (attn_type == "UNIT_CS"):
168            if (src_dict["Attention Type"] != "UNIT_CS"):
169                raise peltool_exception("Required Attention type " + attn_type + " not found")
170        else:
171            raise peltool_exception("Required Attention type " + attn_type + " not found")
172
173        if signature_desc not in src_dict["Signature"]:
174            raise peltool_exception("Required Signature " + signature_desc + " not found")
175
176        if (int(th_limit) != usr_data["Error Count"]):
177            raise peltool_exception("Required Threshold limit " + th_limit + " not found")
178
179    except Exception as e:
180        raise peltool_exception("Failed to verify SRC details : " + str(e))
181    return True
182
183
184def fetch_all_src(include_hidden_pels=False):
185    r"""
186    Fetch all SRC IDs from peltool in the list format.
187
188    include_hidden_pels       True/False (default: False).
189                              Set True to get hidden PELs else False.
190    """
191    try:
192        src_id = []
193        pel_data = get_pel_data_from_bmc(include_hidden_pels)
194        if pel_data:
195            pel_id_list = pel_data.keys()
196            for pel_id in pel_id_list:
197                src_id.append(pel_data[pel_id]["SRC"])
198        print("SRC IDs: " + str(src_id))
199    except Exception as e:
200        raise peltool_exception("Failed to fetch all SRCs : " + str(e))
201    return src_id
202
203
204def check_for_unexpected_src(unexpected_src_list=[], include_hidden_pels=False):
205    r"""
206    From the given unexpected SRC list, check if any unexpected SRC created
207    on the BMC. Returns 0 if no SRC found else throws exception.
208
209    Description of arguments:
210    unexpected_src_list       Give unexpected SRCs in the list format.
211                              e.g.: ["BBXXYYYY", "AAXXYYYY"].
212
213    include_hidden_pels       True/False (default: False).
214                              Set True to get hidden PELs else False.
215    """
216    try:
217        unexpected_src_count = 0
218        if not unexpected_src_list:
219            print("Unexpected SRC list is empty.")
220        src_data = fetch_all_src(include_hidden_pels)
221        for src in unexpected_src_list:
222            if src in src_data:
223                print("Found an unexpected SRC : " + src)
224                unexpected_src_count = unexpected_src_count + 1
225        if (unexpected_src_count >= 1):
226            raise peltool_exception("Unexpected SRC found.")
227
228    except Exception as e:
229        raise peltool_exception("Failed to verify unexpected SRC list : " + str(e))
230    return unexpected_src_count
231
232
233def filter_unexpected_srcs(expected_srcs=None):
234    r"""
235    Return list of SRCs found in BMC after filtering expected SRCs.
236    If expected_srcs is None then all SRCs found in system are returned.
237
238    Description of arguments:
239    expected_srcs       List of expected SRCs. E.g. ["BBXXYYYY", "AAXXYYYY"].
240    """
241
242    srcs_found = fetch_all_src()
243    if not expected_srcs:
244        expected_srcs = []
245    print(expected_srcs)
246    return list(set(srcs_found) - set(expected_srcs))
247
248
249def get_bmc_event_log_id_for_pel(pel_id):
250    r"""
251    Return BMC event log ID for the given PEL ID.
252
253    Description of arguments:
254    pel_id       PEL ID. E.g. 0x50000021.
255    """
256
257    pel_data = peltool("-i " + pel_id)
258    print(pel_data)
259    bmc_id_for_pel = pel_data["Private Header"]["BMC Event Log Id"]
260    return bmc_id_for_pel
261