1*** Settings *** 2Documentation This module provides general keywords for dump. 3 4Library bmc_ssh_utils.py 5Variables ../data/variables.py 6 7*** Variables *** 8 9*** Keywords *** 10 11Create User Initiated Dump 12 [Documentation] Generate user initiated dump and return 13 ... the dump id number (e.g., "5"). Optionally return EMPTY 14 ... if out of dump space. 15 [Arguments] ${check_out_of_space}=${False} 16 17 # Description of Argument(s): 18 # check_out_of_space If ${False}, a dump will be created and 19 # its dump_id will be returned. 20 # If ${True}, either the dump_id will be 21 # returned, or the value ${EMPTY} will be 22 # returned if out of dump space was 23 # detected when creating the dump. 24 25 ${resp}= OpenBMC Get Request ${REST_DUMP_URI} 26 IF '${resp.status_code}' == '${HTTP_NOT_FOUND}' 27 Set Global Variable ${REST_DUMP_URI} /xyz/openbmc_project/dump/ 28 END 29 30 ${data}= Create Dictionary data=@{EMPTY} 31 ${resp}= OpenBMC Post Request 32 ... ${REST_DUMP_URI}action/CreateDump data=${data} quiet=${1} 33 34 IF '${check_out_of_space}' == '${False}' 35 Run Keyword And Return Get The Dump Id ${resp} 36 ELSE 37 Run Keyword And Return Check For Too Many Dumps ${resp} 38 END 39 40Get The Dump Id 41 [Documentation] Wait for the dump to be created. Return the 42 ... dump id number (e.g., "5"). 43 [Arguments] ${resp} 44 45 # Description of Argument(s): 46 # resp Response object from action/Create Dump attempt. 47 # Example object: 48 # { 49 # "data": 5, 50 # "message": "200 OK", 51 # "status": "ok" 52 # }, 53 # The "data" field conveys the id number of the created dump. 54 55 Should Be Equal As Strings ${resp.status_code} ${HTTP_OK} 56 57 IF ${resp.json()["data"]} == ${None} 58 Fail Dump id returned null. 59 END 60 61 ${dump_id}= Set Variable ${json["data"]} 62 63 Wait Until Keyword Succeeds 3 min 15 sec Check Dump Existence 64 ... ${dump_id} 65 66 RETURN ${dump_id} 67 68 69Check For Too Many Dumps 70 [Documentation] Return the dump_id number, or return ${EMPTY} if dump 71 ... creation failed due to too many dumps. 72 [Arguments] ${resp} 73 74 # Description of Argument(s): 75 # resp Response object from action/Create Dump attempt. 76 # Example object if there are too many dumps: 77 # { 78 # "data": { 79 # "description": "xyz.openbmc_project.Dump.Create.Error.QuotaExceeded" 80 # }, 81 # "message": "Dump not captured due to a cap.", 82 # "status": "error" 83 # } 84 85 # If dump was created normally, return the dump_id number. 86 IF '${resp.status_code}' == '${HTTP_OK}' 87 Run Keyword And Return Get The Dump Id ${resp} 88 END 89 90 ${exception}= Set Variable ${resp.json()["message"]} 91 ${at_capacity}= Set Variable Dump not captured due to a cap 92 ${too_many_dumps}= Evaluate $at_capacity in $exception 93 Printn 94 Rprint Vars exception too_many_dumps 95 # If there are too many dumps, return ${EMPTY}, otherwise Fail. 96 ${status}= IF ${too_many_dumps} Set Variable ${EMPTY} 97 ... ELSE Fail msg=${exception}. 98 99 RETURN ${status} 100 101 102Verify No Dump In Progress 103 [Documentation] Verify no dump in progress. 104 105 ${dump_progress} ${stderr} ${rc}= BMC Execute Command ls /tmp 106 Should Not Contain ${dump_progress} obmcdump 107 108 109Check Dump Existence 110 [Documentation] Verify if given dump exist. 111 [Arguments] ${dump_id} 112 113 # Description of Argument(s): 114 # dump_id An integer value that identifies a particular dump 115 # object(e.g. 1, 3, 5). 116 117 ${resp}= OpenBMC Get Request ${REST_DUMP_URI} 118 IF '${resp.status_code}' == '${HTTP_NOT_FOUND}' 119 Set Global Variable ${DUMP_ENTRY_URI} /xyz/openbmc_project/dump/entry/ 120 END 121 122 ${resp}= OpenBMC Get Request ${DUMP_ENTRY_URI}${dump_id} 123 Should Be Equal As Strings ${resp.status_code} ${HTTP_OK} 124 125 126Delete BMC Dump 127 [Documentation] Deletes a given bmc dump. 128 [Arguments] ${dump_id} 129 130 # Description of Argument(s): 131 # dump_id An integer value that identifies a particular dump (e.g. 1, 3). 132 133 ${resp}= OpenBMC Get Request ${REST_DUMP_URI} 134 IF '${resp.status_code}' == '${HTTP_NOT_FOUND}' 135 Set Global Variable ${DUMP_ENTRY_URI} /xyz/openbmc_project/dump/entry/ 136 END 137 138 ${args}= Set Variable {"data": []} 139 ${resp}= OpenBMC Post Request 140 ... ${DUMP_ENTRY_URI}${dump_id}/action/Delete data=${args} 141 142 Should Be Equal As Strings ${resp.status_code} ${HTTP_OK} 143 144Delete All Dumps 145 [Documentation] Delete all dumps. 146 147 ${resp}= OpenBMC Get Request ${REST_DUMP_URI} 148 IF '${resp.status_code}' == '${HTTP_NOT_FOUND}' 149 Set Global Variable ${DUMP_ENTRY_URI} /xyz/openbmc_project/dump/entry/ 150 END 151 152 # Check if dump entries exist, if not return. 153 ${resp}= OpenBMC Get Request ${DUMP_ENTRY_URI}list quiet=${1} 154 Return From Keyword If ${resp.status_code} == ${HTTP_NOT_FOUND} 155 156 # Get the list of dump entries and delete them all. 157 ${dump_entries}= Get URL List ${DUMP_ENTRY_URI} 158 FOR ${entry} IN @{dump_entries} 159 ${dump_id}= Fetch From Right ${entry} / 160 Delete BMC Dump ${dump_id} 161 END 162 163 164Redfish Delete BMC Dump 165 [Documentation] Deletes a given BMC dump via Redfish. 166 [Arguments] ${dump_id} 167 168 # Description of Argument(s): 169 # dump_id An integer value that identifies a particular dump (e.g. 1, 3). 170 171 Redfish.Delete /redfish/v1/Managers/${MANAGER_ID}/LogServices/Dump/Entries/${dump_id} 172 173 174Redfish Delete All BMC Dumps 175 [Documentation] Delete all BMC dumps via Redfish. 176 177 # Check if dump entries exist, if not return. 178 ${resp}= Redfish.Get /redfish/v1/Managers/${MANAGER_ID}/LogServices/Dump/Entries 179 Return From Keyword If ${resp.dict["Members@odata.count"]} == ${0} 180 181 Redfish.Post /redfish/v1/Managers/${MANAGER_ID}/LogServices/Dump/Actions/LogService.ClearLog 182 183 184Redfish Get All System Dumps 185 [Documentation] Get the system dump log entries. 186 187 ${resp}= Redfish.Get ${REDFISH_SYSTEM_DUMP} 188 189 RETURN ${resp.dict} 190 191 192Get Redfish BMC Dump Log Entries 193 [Documentation] Get the BMC dump log entries. 194 195 ${resp}= Redfish.Get ${REDFISH_DUMP_URI} 196 197 RETURN ${resp.dict} 198 199 200Redfish Delete All System Dumps 201 [Documentation] Delete all system dumps via Redfish. 202 203 Redfish.Post /redfish/v1/Systems/${SYSTEM_ID}/LogServices/Dump/Actions/LogService.ClearLog 204 205 206Redfish BMC Dump Should Not Exist 207 [Documentation] Verify that there is no BMC dump at dump URI. 208 209 # Verify no dump exists. 210 ${dump_entries}= Get Redfish BMC Dump Log Entries 211 Should Be Equal As Integers 0 ${dump_entries['Members@odata.count']} 212 213 214Redfish BMC Dump Should Exist 215 [Documentation] Check if BMC dump is generated. 216 217 ${dump_entries}= Get Redfish BMC Dump Log Entries 218 Should Be True ${dump_entries['Members@odata.count']} >= 1 msg=No BMC dump generated. 219 220 221Delete All BMC Dump 222 [Documentation] Delete all BMC dump entries using "DeleteAll" interface. 223 224 ${resp}= OpenBMC Get Request ${REST_DUMP_URI} 225 IF '${resp.status_code}' == '${HTTP_NOT_FOUND}' 226 Set Global Variable ${REST_DUMP_URI} /xyz/openbmc_project/dump/ 227 END 228 229 ${args}= Set Variable {"data": []} 230 ${resp}= Openbmc Post Request ${REST_DUMP_URI}action/DeleteAll data=${args} 231 Should Be Equal As Strings ${resp.status_code} ${HTTP_OK} 232 233Dump Should Not Exist 234 [Documentation] Verify that BMC dumps do not exist. 235 236 ${resp}= OpenBMC Get Request ${REST_DUMP_URI} 237 IF '${resp.status_code}' == '${HTTP_NOT_FOUND}' 238 Set Global Variable ${DUMP_ENTRY_URI} /xyz/openbmc_project/dump/entry/ 239 END 240 241 ${resp}= OpenBMC Get Request ${DUMP_ENTRY_URI}list quiet=${1} 242 Should Be Equal As Strings ${resp.status_code} ${HTTP_NOT_FOUND} 243 244Check Existence Of BMC Dump File 245 [Documentation] Verify existence of BMC dump file. 246 [Arguments] ${dump_id} 247 248 # Description of argument(s): 249 # dump_id BMC dump identifier 250 251 ${dump_check_cmd}= Set Variable 252 ... ls /var/lib/phosphor-debug-collector/dumps 253 254 # Output of sample BMC Execute command with '2' as dump id is as follows 255 # ls /var/lib/phosphor-debug-collector/dumps/2 256 # obmcdump_2_XXXXXXXXXX.tar.xz 257 ${file_there} ${stderr} ${rc}= BMC Execute Command 258 ... ${dump_check_cmd}/${dump_id} 259 Should End With ${file_there} tar.xz msg=BMC dump file not found. 260 261Get Dump Entries 262 [Documentation] Return dump entries list. 263 264 ${resp}= OpenBMC Get Request ${REST_DUMP_URI} 265 IF '${resp.status_code}' == '${HTTP_NOT_FOUND}' 266 Set Global Variable ${DUMP_ENTRY_URI} /xyz/openbmc_project/dump/entry/ 267 END 268 269 ${dump_entries}= Get URL List ${DUMP_ENTRY_URI} 270 RETURN ${dump_entries} 271 272Trigger Core Dump 273 [Documentation] Trigger core dump. 274 275 # Find the pid of the active ipmid and kill it. 276 ${cmd_buf}= Catenate kill -s SEGV $(ps | egrep ' ipmid$' | 277 ... egrep -v grep | \ cut -c1-6) 278 279 ${cmd_output} ${stderr} ${rc}= BMC Execute Command ${cmd_buf} 280 Should Be Empty ${stderr} msg=BMC execute command error. 281 Should Be Equal As Integers ${rc} ${0} 282 ... msg=BMC execute command return code is not zero. 283 284Initiate BMC Dump Using Redfish And Return Task Id 285 [Documentation] Initiate BMC dump via Redfish and return its task ID. 286 287 ${payload}= Create Dictionary DiagnosticDataType=Manager 288 ${resp}= Redfish.Post 289 ... /redfish/v1/Managers/${MANAGER_ID}/LogServices/Dump/Actions/LogService.CollectDiagnosticData 290 ... body=${payload} valid_status_codes=[${HTTP_ACCEPTED}] 291 292 # Example of response from above Redfish POST request. 293 # "@odata.id": "/redfish/v1/TaskService/Tasks/0", 294 # "@odata.type": "#Task.v1_4_3.Task", 295 # "Id": "0", 296 # "TaskState": "Running", 297 # "TaskStatus": "OK" 298 299 RETURN ${resp.dict['Id']} 300 301Create User Initiated BMC Dump Via Redfish 302 [Documentation] Generate user initiated BMC dump via Redfish and return the dump id number (e.g., "5"). 303 [Arguments] ${skip_dump_completion}=0 304 305 # Description of Argument(s): 306 # skip_dump_completion If skip_dump_completion is set to 0, this 307 # keyword will waiting for BMC dump to 308 # complete and returns the dump id. 309 # Otherwise, the keyword is skipped after 310 # initiating BMC dump and returns dump task id. 311 312 ${payload}= Create Dictionary DiagnosticDataType=Manager 313 ${resp}= Redfish.Post /redfish/v1/Managers/${MANAGER_ID}/LogServices/Dump/Actions/LogService.CollectDiagnosticData 314 ... body=${payload} valid_status_codes=[${HTTP_ACCEPTED}] 315 316 # Example of response from above Redfish POST request. 317 # "@odata.id": "/redfish/v1/TaskService/Tasks/0", 318 # "@odata.type": "#Task.v1_4_3.Task", 319 # "Id": "0", 320 # "TaskState": "Running", 321 # "TaskStatus": "OK" 322 323 IF ${skip_dump_completion} != 0 Return From Keyword ${resp.dict['Id']} 324 Wait Until Keyword Succeeds 5 min 15 sec Check Task Completion ${resp.dict['Id']} 325 ${task_id}= Set Variable ${resp.dict['Id']} 326 327 ${task_dict}= Redfish.Get Properties /redfish/v1/TaskService/Tasks/${task_id} 328 329 # Example of HttpHeaders field of task details. 330 # "Payload": { 331 # "HttpHeaders": [ 332 # "Host: <BMC_IP>", 333 # "Accept-Encoding: identity", 334 # "Connection: Keep-Alive", 335 # "Accept: */*", 336 # "Content-Length: 33", 337 # "Location: /redfish/v1/Managers/${MANAGER_ID}/LogServices/Dump/Entries/2"] 338 # ], 339 # "HttpOperation": "POST", 340 # "JsonBody": "{\"DiagnosticDataType\":\"Manager\"}", 341 # "TargetUri": "/redfish/v1/Managers/${MANAGER_ID}/LogServices/Dump/Actions/LogService.CollectDiagnosticData" 342 # } 343 344 RETURN ${task_dict["Payload"]["HttpHeaders"][-1].split("/")[-1]} 345 346Auto Generate BMC Dump 347 [Documentation] Auto generate BMC dump. 348 349 ${cmd}= Catenate busctl --verbose call xyz.openbmc_project.Dump.Manager 350 ... /xyz/openbmc_project/dump/bmc xyz.openbmc_project.Dump.Create CreateDump a{sv} 0 351 ${stdout} ${stderr} ${rc}= 352 ... BMC Execute Command ${cmd} 353 RETURN ${stdout} ${stderr} ${rc} 354 355Get Dump Size 356 [Documentation] Get dump size. 357 [Arguments] ${dump_uri} 358 359 # Description of argument(s): 360 # dump_uri Dump URI 361 # (Eg. /xyz/openbmc_project/dump/bmc/entry/1). 362 363 # Example of Dump entry. 364 # "data": { 365 # "CompletedTime": 1616760931, 366 # "Elapsed": 1616760931, 367 # "OffloadUri": "", 368 # "Offloaded": false, 369 # "Password": "", 370 # "Size": 3056, 371 # "SourceDumpId": 117440513, 372 # "StartTime": 1616760931, 373 # "Status": "xyz.openbmc_project.Common.Progress.OperationStatus.Completed", 374 # "VSPString": "" 375 # }, 376 377 Log ${dump_uri} 378 ${dump_data}= Redfish.Get Properties ${dump_uri} 379 RETURN ${dump_data["data"]["Size"]} 380 381Get Dump ID 382 [Documentation] Return dump ID. 383 [Arguments] ${task_id} 384 385 # Description of argument(s): 386 # task_id Task ID. 387 388 # Example of HttpHeaders field of task details. 389 # "Payload": { 390 # "HttpHeaders": [ 391 # "Host: <BMC_IP>", 392 # "Accept-Encoding: identity", 393 # "Connection: Keep-Alive", 394 # "Accept: */*", 395 # "Content-Length: 33", 396 # "Location: /redfish/v1/Managers/${MANAGER_ID}/LogServices/Dump/Entries/2"] 397 # ], 398 # "HttpOperation": "POST", 399 # "JsonBody": "{\"DiagnosticDataType\":\"Manager\"}", 400 # "TargetUri": 401 # "/redfish/v1/Managers/${MANAGER_ID}/LogServices/Dump/Actions/LogService.CollectDiagnosticData" 402 # } 403 404 ${task_dict}= Redfish.Get Properties /redfish/v1/TaskService/Tasks/${task_id} 405 ${key} ${value}= Set Variable ${task_dict["Payload"]["HttpHeaders"][-1].split(":")} 406 IF '${key}' != 'Location' Fail 407 RETURN ${value.strip('/').split('/')[-1]} 408 409Get Task Status 410 [Documentation] Return task status. 411 [Arguments] ${task_id} 412 413 # Description of argument(s): 414 # task_id Task ID. 415 416 ${resp}= Redfish.Get Properties /redfish/v1/TaskService/Tasks/${task_id} 417 RETURN ${resp['TaskState']} 418 419Check Task Completion 420 [Documentation] Check if the task is complete. 421 [Arguments] ${task_id} 422 423 # Description of argument(s): 424 # task_id Task ID. 425 426 ${task_dict}= Redfish.Get Properties /redfish/v1/TaskService/Tasks/${task_id} 427 Should Be Equal As Strings ${task_dict['TaskState']} Completed 428 429Get Dump ID And Status 430 [Documentation] Return dump ID and status. 431 [Arguments] ${task_id} 432 433 # Description of argument(s): 434 # task_id Task ID. 435 436 Wait Until Keyword Succeeds 10 min 15 sec Check Task Completion ${task_id} 437 ${dump_id}= Get Dump ID ${task_id} 438 RETURN ${dump_id} Completed 439 440 441Create BMC User Dump 442 [Documentation] Generate user initiated BMC dump via Redfish and return 443 ... the task instance Id and response object (e.g., "5"). 444 445 ${payload}= Create Dictionary DiagnosticDataType=Manager 446 ${resp}= Redfish.Post /redfish/v1/Managers/${MANAGER_ID}/LogServices/Dump/Actions/LogService.CollectDiagnosticData 447 ... body=${payload} valid_status_codes=[${HTTP_ACCEPTED}] 448 449 ${ip_resp}= Evaluate json.loads(r'''${resp.text}''') json 450 451 Return From Keyword ${ip_resp["Id"]} ${resp} 452 453 454Wait For Task Completion 455 [Documentation] Check whether the state of task instance matches any of the 456 ... expected completion states before maximum number of retries exceeds and 457 ... exit loop in case completion state is met. 458 [Arguments] ${task_id} ${expected_status} ${retry_max_count}=300 459 ... ${check_state}=${FALSE} 460 461 # Description of argument(s): 462 # task_id the task id for which completion is 463 # to be monitored. 464 # expected_status the task state which is to be considered as the 465 # end of task life cycle. 466 # retry_max_count the maximum number of retry count to wait for 467 # task to reach its completion state. Default 468 # value of retry_max_count is 300. 469 # check_state if set as TRUE, the task state will be 470 # monitored whether the task state value is 471 # valid throughout task life cycle until 472 # expected completion state is reached. 473 # Default value of check_state is FALSE. 474 475 FOR ${retry} IN RANGE ${retry_max_count} 476 ${resp}= Redfish.Get Properties /redfish/v1/TaskService/Tasks/${task_id} 477 ${current_task_state}= Set Variable ${resp["TaskState"]} 478 Rprint Vars current_task_state 479 480 IF ${check_state} == ${TRUE} 481 Should Be True '${resp["TaskState"]}' in ${allowed_task_state} 482 ... msg=Verify task state is valid 483 END 484 Exit For Loop If 485 ... '${resp["TaskState"]}' in ${expected_status} 486 487 Sleep 5s 488 END 489 490Get Dump Status In BMC 491 [Documentation] Get dump status from BMC using busctl method. 492 [Arguments] ${dump_uri} 493 494 # Description of argument(s): 495 # dump_uri Dump URI E.g: /xyz/openbmc_project/dump/bmc/entry/7. 496 497 ${cmd}= Catenate busctl get-property xyz.openbmc_project.Dump.Manager 498 ... ${dump_uri} xyz.openbmc_project.Common.Progress Status 499 500 ${stdout} ${stderr} ${rc}= BMC Execute Command ${cmd} 501 Log ${stdout} 502 # Example output: 503 # s "xyz.openbmc_project.Common.Progress.OperationStatus.Completed". 504 505 ${status}= Set Variable ${stdout.split('.')[-1].strip('"')} 506 RETURN ${status} 507 508Verify Dump Status In BMC 509 [Documentation] Verify Dump Status in BMC. 510 [Arguments] ${dump_uri} ${expected_dump_status} 511 512 # Description of argument(s): 513 # dump_uri Dump URI E.g: /xyz/openbmc_project/dump/bmc/entry/7. 514 # expected_dump_status Expected Dump Status (Completed or Failed etc). 515 516 ${dump_status}= Get Dump Status In BMC ${dump_uri} 517 Should Be Equal ${dump_status} ${expected_dump_status} 518