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