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 PeltoolException(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 53 processed by the peltool command. 54 parse_json Indicates that the raw JSON data should 55 parsed into a list of dictionaries. 56 bsu_options Options to be passed directly to 57 bmc_execute_command. See its prolog for 58 details. 59 """ 60 61 bsu_options = fa.args_to_objects(bsu_options) 62 out_buf, _, _ = bsu.bmc_execute_command( 63 "peltool " + option_string, **bsu_options 64 ) 65 if parse_json: 66 try: 67 return json.loads(out_buf) 68 except ValueError as e: 69 if type(out_buf) is str: 70 return out_buf 71 else: 72 print(str(e)) 73 return {} 74 return out_buf 75 76 77def get_pel_data_from_bmc( 78 include_hidden_pels=False, include_informational_pels=False 79): 80 r""" 81 Returns PEL data from BMC else throws exception. 82 83 Description of arguments: 84 include_hidden_pels True/False (default: False). 85 Set True to get hidden PELs else False. 86 include_informational_pels True/False (default: False). 87 Set True to get informational PELs else False. 88 """ 89 try: 90 pel_cmd = " -l" 91 if include_hidden_pels: 92 pel_cmd = pel_cmd + " -h" 93 if include_informational_pels: 94 pel_cmd = pel_cmd + " -f" 95 pel_data = peltool(pel_cmd) 96 if not pel_data: 97 print("No PEL data present in BMC ...") 98 except Exception as exception: 99 raise PeltoolException( 100 "Failed to get PEL data from BMC : " + str(exception) 101 ) from exception 102 return pel_data 103 104 105def verify_no_pel_exists_on_bmc(): 106 r""" 107 Verify that no PEL exists in BMC. Raise an exception if it does. 108 """ 109 110 try: 111 pel_data = get_pel_data_from_bmc() 112 113 if len(pel_data) == 0: 114 return True 115 116 print("PEL data present. \n", pel_data) 117 raise PeltoolException("PEL data present in BMC") 118 except Exception as exception: 119 raise PeltoolException( 120 "Failed to get PEL data from BMC : " + str(exception) 121 ) from exception 122 123 124def compare_pel_and_redfish_event_log(pel_record, event_record): 125 r""" 126 Compare PEL log attributes like "SRC", "Created at" with Redfish 127 event log attributes like "EventId", "Created". 128 Return False if they do not match. 129 130 Description of arguments: 131 pel_record PEL record. 132 event_record Redfish event which is equivalent of PEL record. 133 """ 134 135 try: 136 # Below is format of PEL record / event record and following 137 # i.e. "SRC", "Created at" from 138 # PEL record is compared with "EventId", "Created" from event record. 139 140 # PEL Log attributes 141 # SRC : XXXXXXXX 142 # Created at : 11/14/2022 12:38:04 143 144 # Event log attributes 145 # EventId : XXXXXXXX XXXXXXXX XXXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX 146 147 # Created : 2022-11-14T12:38:04+00:00 148 149 print(f"\nPEL records : {pel_record}") 150 print(f"\nEvent records : {event_record}") 151 152 pel_src = pel_record["pel_data"]["SRC"] 153 pel_created_time = pel_record["pel_detail_data"]["Private Header"][ 154 "Created at" 155 ] 156 157 event_ids = (event_record["EventId"]).split(" ") 158 159 event_time_format = (event_record["Created"]).split("T") 160 event_date = (event_time_format[0]).split("-") 161 event_date = datetime( 162 int(event_date[0]), int(event_date[1]), int(event_date[2]) 163 ) 164 event_date = event_date.strftime("%m/%d/%Y") 165 event_sub_time_format = (event_time_format[1]).split("+") 166 event_date_time = event_date + " " + event_sub_time_format[0] 167 168 event_created_time = event_date_time.replace("-", "/") 169 170 print(f"\nPEL SRC : {pel_src} | PEL Created Time : {pel_created_time}") 171 172 print( 173 f"\nError event ID : {event_ids[0]} | Error Log Created Time " 174 + ": {event_created_time}" 175 ) 176 177 if pel_src == event_ids[0] and pel_created_time == event_created_time: 178 print( 179 "\nPEL SRC and created date time match with " 180 "event ID, created time" 181 ) 182 else: 183 raise PeltoolException( 184 "\nPEL SRC and created date time did not " 185 "match with event ID, created time" 186 ) 187 except Exception as exception: 188 raise PeltoolException( 189 "Exception occurred during PEL and Event log " 190 "comparison for SRC or event ID and created " 191 "time : " + str(exception) 192 ) from exception 193 194 195def fetch_all_pel_ids_for_src(src_id, severity, include_hidden_pels=False): 196 r""" 197 Fetch all PEL IDs for the input SRC ID based on the severity type 198 in the list format. 199 200 Description of arguments: 201 src_id SRC ID (e.g. BCXXYYYY). 202 severity PEL severity (e.g. "Predictive Error" 203 "Recovered Error"). 204 include_hidden_pels True/False (default: False). 205 Set True to get hidden PELs else False. 206 """ 207 208 try: 209 src_pel_ids = [] 210 pel_data = get_pel_data_from_bmc(include_hidden_pels) 211 pel_id_list = pel_data.keys() 212 for pel_id in pel_id_list: 213 # Check if required SRC ID with severity is present 214 if src_id in pel_data[pel_id]["SRC"]: 215 if pel_data[pel_id]["Sev"] == severity: 216 src_pel_ids.append(pel_id) 217 218 if not src_pel_ids: 219 raise PeltoolException( 220 src_id + " with severity " + severity + " not present" 221 ) 222 except Exception as exception: 223 raise PeltoolException( 224 "Failed to fetch PEL ID for required SRC : " + str(exception) 225 ) from exception 226 return src_pel_ids 227 228 229def fetch_all_src(include_hidden_pels=False): 230 r""" 231 Fetch all SRC IDs from peltool in the list format. 232 233 include_hidden_pels True/False (default: False). 234 Set True to get hidden PELs else False. 235 """ 236 try: 237 src_id = [] 238 pel_data = get_pel_data_from_bmc(include_hidden_pels) 239 if pel_data: 240 pel_id_list = pel_data.keys() 241 for pel_id in pel_id_list: 242 src_id.append(pel_data[pel_id]["SRC"]) 243 print("SRC IDs: " + str(src_id)) 244 except Exception as exception: 245 raise PeltoolException( 246 "Failed to fetch all SRCs : " + str(exception) 247 ) from exception 248 return src_id 249 250 251def check_for_unexpected_src( 252 unexpected_src_list=None, include_hidden_pels=False 253): 254 r""" 255 From the given unexpected SRC list, check if any unexpected SRC created 256 on the BMC. Returns 0 if no SRC found else throws exception. 257 258 Description of arguments: 259 unexpected_src_list Give unexpected SRCs in the list format. 260 e.g.: ["BBXXYYYY", "AAXXYYYY"]. 261 262 include_hidden_pels True/False (default: False). 263 Set True to get hidden PELs else False. 264 """ 265 try: 266 unexpected_src_count = 0 267 if not unexpected_src_list: 268 print("Unexpected SRC list is empty.") 269 src_data = fetch_all_src(include_hidden_pels) 270 for src in unexpected_src_list: 271 if src in src_data: 272 print("Found an unexpected SRC : " + src) 273 unexpected_src_count = unexpected_src_count + 1 274 if unexpected_src_count >= 1: 275 raise PeltoolException("Unexpected SRC found.") 276 277 except Exception as exception: 278 raise PeltoolException( 279 "Failed to verify unexpected SRC list : " + str(exception) 280 ) from exception 281 return unexpected_src_count 282 283 284def filter_unexpected_srcs(expected_srcs=None): 285 r""" 286 Return list of SRCs found in BMC after filtering expected SRCs. 287 If expected_srcs is None then all SRCs found in system are returned. 288 289 Description of arguments: 290 expected_srcs List of expected SRCs. E.g. ["BBXXYYYY", "AAXXYYYY"]. 291 """ 292 293 srcs_found = fetch_all_src() 294 if not expected_srcs: 295 expected_srcs = [] 296 print(expected_srcs) 297 return list(set(srcs_found) - set(expected_srcs)) 298 299 300def get_bmc_event_log_id_for_pel(pel_id): 301 r""" 302 Return BMC event log ID for the given PEL ID. 303 304 Description of arguments: 305 pel_id PEL ID. E.g. 0x50000021. 306 """ 307 308 pel_data = peltool("-i " + pel_id) 309 print(pel_data) 310 bmc_id_for_pel = pel_data["Private Header"]["BMC Event Log Id"] 311 return bmc_id_for_pel 312 313 314def get_latest_pels(number_of_pels=1): 315 r""" 316 Return latest PEL IDs. 317 318 Description of arguments: 319 number_of_pels Number of PELS to be returned. 320 """ 321 322 pel_data = peltool("-lr") 323 pel_ids = list(pel_data.keys()) 324 return pel_ids[:number_of_pels] 325