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