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