1#!/usr/bin/env python3 2 3r""" 4PEL functions. 5""" 6 7import json 8import os 9import sys 10from datetime import datetime 11 12import bmc_ssh_utils as bsu 13import func_args as fa 14 15base_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 16sys.path.append(base_path + "/data/") 17 18import pel_variables # NOQA 19 20 21class peltool_exception(Exception): 22 r""" 23 Base class for peltool related exceptions. 24 """ 25 26 def __init__(self, message): 27 self.message = message 28 super().__init__(self.message) 29 30 31def peltool(option_string, parse_json=True, **bsu_options): 32 r""" 33 Run peltool on the BMC with the caller's option string and return the result. 34 35 Example: 36 37 ${pel_results}= Peltool -l 38 Rprint Vars pel_results 39 40 pel_results: 41 [0x50000031]: 42 [CompID]: 0x1000 43 [PLID]: 0x50000031 44 [Subsystem]: BMC Firmware 45 [Message]: An application had an internal failure 46 [SRC]: BD8D1002 47 [Commit Time]: 02/25/2020 04:51:31 48 [Sev]: Unrecoverable Error 49 [CreatorID]: BMC 50 51 Description of argument(s): 52 option_string A string of options which are to be processed by the peltool command. 53 parse_json Indicates that the raw JSON data should parsed into a list of 54 dictionaries. 55 bsu_options Options to be passed directly to bmc_execute_command. See its prolog for 56 details. 57 """ 58 59 bsu_options = fa.args_to_objects(bsu_options) 60 out_buf, stderr, rc = bsu.bmc_execute_command( 61 "peltool " + option_string, **bsu_options 62 ) 63 if parse_json: 64 try: 65 return json.loads(out_buf) 66 except ValueError: 67 return {} 68 return out_buf 69 70 71def get_pel_data_from_bmc( 72 include_hidden_pels=False, include_informational_pels=False 73): 74 r""" 75 Returns PEL data from BMC else throws exception. 76 77 Description of arguments: 78 include_hidden_pels True/False (default: False). 79 Set True to get hidden PELs else False. 80 include_informational_pels True/False (default: False). 81 Set True to get informational PELs else False. 82 """ 83 try: 84 pel_cmd = " -l" 85 if include_hidden_pels: 86 pel_cmd = pel_cmd + " -h" 87 if include_informational_pels: 88 pel_cmd = pel_cmd + " -f" 89 pel_data = peltool(pel_cmd) 90 if not pel_data: 91 print("No PEL data present in BMC ...") 92 except Exception as e: 93 raise peltool_exception("Failed to get PEL data from BMC : " + str(e)) 94 return pel_data 95 96 97def verify_no_pel_exists_on_bmc(): 98 r""" 99 Verify that no PEL exists in BMC. Raise an exception if it does. 100 """ 101 102 try: 103 pel_data = get_pel_data_from_bmc() 104 105 if len(pel_data) == 0: 106 return True 107 else: 108 print("PEL data present. \n", pel_data) 109 raise peltool_exception("PEL data present in BMC") 110 except Exception as e: 111 raise peltool_exception("Failed to get PEL data from BMC : " + str(e)) 112 113 114def compare_pel_and_redfish_event_log(pel_record, event_record): 115 r""" 116 Compare PEL log attributes like "SRC", "Created at" with Redfish 117 event log attributes like "EventId", "Created". 118 Return False if they do not match. 119 120 Description of arguments: 121 pel_record PEL record. 122 event_record Redfish event which is equivalent of PEL record. 123 """ 124 125 try: 126 # Below is format of PEL record / event record and following 127 # i.e. "SRC", "Created at" from 128 # PEL record is compared with "EventId", "Created" from event record. 129 130 # PEL Log attributes 131 # SRC : XXXXXXXX 132 # Created at : 11/14/2022 12:38:04 133 134 # Event log attributes 135 # EventId : XXXXXXXX XXXXXXXX XXXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX 136 137 # Created : 2022-11-14T12:38:04+00:00 138 139 print("\nPEL records : {0}".format(pel_record)) 140 print("\nEvent records : {0}".format(event_record)) 141 142 pel_src = pel_record["pel_data"]["SRC"] 143 pel_created_time = pel_record["pel_detail_data"]["Private Header"][ 144 "Created at" 145 ] 146 147 event_ids = (event_record["EventId"]).split(" ") 148 149 event_time_format = (event_record["Created"]).split("T") 150 event_date = (event_time_format[0]).split("-") 151 event_date = datetime( 152 int(event_date[0]), int(event_date[1]), int(event_date[2]) 153 ) 154 event_date = event_date.strftime("%m/%d/%Y") 155 event_sub_time_format = (event_time_format[1]).split("+") 156 event_date_time = event_date + " " + event_sub_time_format[0] 157 158 event_created_time = event_date_time.replace("-", "/") 159 160 print( 161 "\nPEL SRC : {0} | PEL Created Time : {1}".format( 162 pel_src, pel_created_time 163 ) 164 ) 165 print( 166 "\nError event ID : {0} | Error Log Created Time : {1}".format( 167 event_ids[0], event_created_time 168 ) 169 ) 170 171 if pel_src == event_ids[0] and pel_created_time == event_created_time: 172 print( 173 "\nPEL SRC and created date time match with " 174 "event ID, created time" 175 ) 176 else: 177 raise peltool_exception( 178 "\nPEL SRC and created date time did not " 179 "match with event ID, created time" 180 ) 181 except Exception as e: 182 raise peltool_exception( 183 "Exception occurred during PEL and Event log " 184 "comparison for SRC or event ID and created " 185 "time : " 186 + str(e) 187 ) 188 189 190def fetch_all_pel_ids_for_src(src_id, severity, include_hidden_pels=False): 191 r""" 192 Fetch all PEL IDs for the input SRC ID based on the severity type 193 in the list format. 194 195 Description of arguments: 196 src_id SRC ID (e.g. BCXXYYYY). 197 severity PEL severity (e.g. "Predictive Error" 198 "Recovered Error"). 199 include_hidden_pels True/False (default: False). 200 Set True to get hidden PELs else False. 201 """ 202 203 try: 204 src_pel_ids = [] 205 pel_data = get_pel_data_from_bmc(include_hidden_pels) 206 pel_id_list = pel_data.keys() 207 for pel_id in pel_id_list: 208 # Check if required SRC ID with severity is present 209 if (pel_data[pel_id]["SRC"] == src_id) and ( 210 pel_data[pel_id]["Sev"] == severity 211 ): 212 src_pel_ids.append(pel_id) 213 214 if not src_pel_ids: 215 raise peltool_exception( 216 src_id + " with severity " + severity + " not present" 217 ) 218 except Exception as e: 219 raise peltool_exception( 220 "Failed to fetch PEL ID for required SRC : " + str(e) 221 ) 222 return src_pel_ids 223 224 225def fetch_all_src(include_hidden_pels=False): 226 r""" 227 Fetch all SRC IDs from peltool in the list format. 228 229 include_hidden_pels True/False (default: False). 230 Set True to get hidden PELs else False. 231 """ 232 try: 233 src_id = [] 234 pel_data = get_pel_data_from_bmc(include_hidden_pels) 235 if pel_data: 236 pel_id_list = pel_data.keys() 237 for pel_id in pel_id_list: 238 src_id.append(pel_data[pel_id]["SRC"]) 239 print("SRC IDs: " + str(src_id)) 240 except Exception as e: 241 raise peltool_exception("Failed to fetch all SRCs : " + str(e)) 242 return src_id 243 244 245def check_for_unexpected_src( 246 unexpected_src_list=[], include_hidden_pels=False 247): 248 r""" 249 From the given unexpected SRC list, check if any unexpected SRC created 250 on the BMC. Returns 0 if no SRC found else throws exception. 251 252 Description of arguments: 253 unexpected_src_list Give unexpected SRCs in the list format. 254 e.g.: ["BBXXYYYY", "AAXXYYYY"]. 255 256 include_hidden_pels True/False (default: False). 257 Set True to get hidden PELs else False. 258 """ 259 try: 260 unexpected_src_count = 0 261 if not unexpected_src_list: 262 print("Unexpected SRC list is empty.") 263 src_data = fetch_all_src(include_hidden_pels) 264 for src in unexpected_src_list: 265 if src in src_data: 266 print("Found an unexpected SRC : " + src) 267 unexpected_src_count = unexpected_src_count + 1 268 if unexpected_src_count >= 1: 269 raise peltool_exception("Unexpected SRC found.") 270 271 except Exception as e: 272 raise peltool_exception( 273 "Failed to verify unexpected SRC list : " + str(e) 274 ) 275 return unexpected_src_count 276 277 278def filter_unexpected_srcs(expected_srcs=None): 279 r""" 280 Return list of SRCs found in BMC after filtering expected SRCs. 281 If expected_srcs is None then all SRCs found in system are returned. 282 283 Description of arguments: 284 expected_srcs List of expected SRCs. E.g. ["BBXXYYYY", "AAXXYYYY"]. 285 """ 286 287 srcs_found = fetch_all_src() 288 if not expected_srcs: 289 expected_srcs = [] 290 print(expected_srcs) 291 return list(set(srcs_found) - set(expected_srcs)) 292 293 294def get_bmc_event_log_id_for_pel(pel_id): 295 r""" 296 Return BMC event log ID for the given PEL ID. 297 298 Description of arguments: 299 pel_id PEL ID. E.g. 0x50000021. 300 """ 301 302 pel_data = peltool("-i " + pel_id) 303 print(pel_data) 304 bmc_id_for_pel = pel_data["Private Header"]["BMC Event Log Id"] 305 return bmc_id_for_pel 306