| *** Settings *** | 
 | Documentation  This module provides general keywords for dump. | 
 |  | 
 | Library         bmc_ssh_utils.py | 
 |  | 
 | *** Variables *** | 
 |  | 
 | *** Keywords *** | 
 |  | 
 | Create User Initiated Dump | 
 |     [Documentation]  Generate user initiated dump and return | 
 |     ...  the dump id number (e.g., "5").  Optionally return EMPTY | 
 |     ...  if out of dump space. | 
 |     [Arguments]   ${check_out_of_space}=${False} | 
 |  | 
 |     # Description of Argument(s): | 
 |     # check_out_of_space   If ${False}, a dump will be created and | 
 |     #                      its dump_id will be returned. | 
 |     #                      If ${True}, either the dump_id will be | 
 |     #                      returned, or the value ${EMPTY} will be | 
 |     #                      returned if out of dump space was | 
 |     #                      detected when creating the dump. | 
 |  | 
 |     ${resp}=  OpenBMC Get Request  ${DUMP_URI} | 
 |     Run Keyword If  '${resp.status_code}' == '${HTTP_NOT_FOUND}' | 
 |     ...  Set Global Variable  ${DUMP_URI}  /xyz/openbmc_project/dump/ | 
 |  | 
 |     ${data}=  Create Dictionary  data=@{EMPTY} | 
 |     ${resp}=  OpenBMC Post Request | 
 |     ...  ${DUMP_URI}action/CreateDump  data=${data}  quiet=${1} | 
 |  | 
 |     Run Keyword If  '${check_out_of_space}' == '${False}' | 
 |     ...      Run Keyword And Return  Get The Dump Id  ${resp} | 
 |     ...  ELSE | 
 |     ...      Run Keyword And Return  Check For Too Many Dumps  ${resp} | 
 |  | 
 |  | 
 | Get The Dump Id | 
 |     [Documentation]  Wait for the dump to be created. Return the | 
 |     ...  dump id number (e.g., "5"). | 
 |     [Arguments]  ${resp} | 
 |  | 
 |     # Description of Argument(s): | 
 |     # resp   Response object from action/Create Dump attempt. | 
 |     #        Example object: | 
 |     #        { | 
 |     #           "data": 5, | 
 |     #           "message": "200 OK", | 
 |     #           "status": "ok" | 
 |     #        }, | 
 |     #        The "data" field conveys the id number of the created dump. | 
 |  | 
 |     Should Be Equal As Strings  ${resp.status_code}  ${HTTP_OK} | 
 |     ${json}=  To JSON  ${resp.content} | 
 |  | 
 |     Run Keyword If  ${json["data"]} == ${None} | 
 |     ...  Fail  Dump id returned null. | 
 |  | 
 |     ${dump_id}=  Set Variable  ${json["data"]} | 
 |  | 
 |     Wait Until Keyword Succeeds  3 min  15 sec  Check Dump Existence | 
 |     ...  ${dump_id} | 
 |  | 
 |     [Return]  ${dump_id} | 
 |  | 
 |  | 
 | Check For Too Many Dumps | 
 |     [Documentation]  Return the dump_id number, or return ${EMPTY} if dump | 
 |     ...  creation failed due to too many dumps. | 
 |     [Arguments]  ${resp} | 
 |  | 
 |     # Description of Argument(s): | 
 |     # resp   Response object from action/Create Dump attempt. | 
 |     #        Example object if there are too many dumps: | 
 |     #       { | 
 |     #           "data": { | 
 |     #               "description": "xyz.openbmc_project.Dump.Create.Error.QuotaExceeded" | 
 |     #           }, | 
 |     #           "message": "Dump not captured due to a cap.", | 
 |     #           "status": "error" | 
 |     #       } | 
 |  | 
 |     # If dump was created normally, return the dump_id number. | 
 |     Run Keyword If  '${resp.status_code}' == '${HTTP_OK}' | 
 |     ...  Run Keyword And Return  Get The Dump Id  ${resp} | 
 |  | 
 |     ${json}=  To JSON   ${resp.content} | 
 |     ${exception}=  Set Variable  ${json["message"]} | 
 |     ${at_capacity}=  Set Variable  Dump not captured due to a cap | 
 |     ${too_many_dumps}=  Evaluate  $at_capacity in $exception | 
 |     Printn | 
 |     Rprint Vars   exception  too_many_dumps | 
 |     # If there are too many dumps, return ${EMPTY}, otherwise Fail. | 
 |     ${status}=  Run Keyword If  ${too_many_dumps}  Set Variable  ${EMPTY} | 
 |     ...  ELSE  Fail  msg=${exception}. | 
 |  | 
 |     [Return]  ${status} | 
 |  | 
 |  | 
 | Verify No Dump In Progress | 
 |     [Documentation]  Verify no dump in progress. | 
 |  | 
 |     ${dump_progress}  ${stderr}  ${rc}=  BMC Execute Command  ls /tmp | 
 |     Should Not Contain  ${dump_progress}  obmcdump | 
 |  | 
 |  | 
 | Check Dump Existence | 
 |     [Documentation]  Verify if given dump exist. | 
 |     [Arguments]  ${dump_id} | 
 |  | 
 |     # Description of Argument(s): | 
 |     # dump_id  An integer value that identifies a particular dump | 
 |     #          object(e.g. 1, 3, 5). | 
 |  | 
 |     ${resp}=  OpenBMC Get Request  ${DUMP_URI} | 
 |     Run Keyword If  '${resp.status_code}' == '${HTTP_NOT_FOUND}' | 
 |     ...  Set Global Variable  ${DUMP_ENTRY_URI}  /xyz/openbmc_project/dump/entry/ | 
 |  | 
 |     ${resp}=  OpenBMC Get Request  ${DUMP_ENTRY_URI}${dump_id} | 
 |     Should Be Equal As Strings  ${resp.status_code}  ${HTTP_OK} | 
 |  | 
 |  | 
 | Delete BMC Dump | 
 |     [Documentation]  Deletes a given bmc dump. | 
 |     [Arguments]  ${dump_id} | 
 |  | 
 |     # Description of Argument(s): | 
 |     # dump_id  An integer value that identifies a particular dump (e.g. 1, 3). | 
 |  | 
 |     ${resp}=  OpenBMC Get Request  ${DUMP_URI} | 
 |     Run Keyword If  '${resp.status_code}' == '${HTTP_NOT_FOUND}' | 
 |     ...  Set Global Variable  ${DUMP_ENTRY_URI}  /xyz/openbmc_project/dump/entry/ | 
 |  | 
 |     ${data}=  Create Dictionary  data=@{EMPTY} | 
 |     ${resp}=  OpenBMC Post Request | 
 |     ...  ${DUMP_ENTRY_URI}${dump_id}/action/Delete  data=${data} | 
 |  | 
 |     Should Be Equal As Strings  ${resp.status_code}  ${HTTP_OK} | 
 |  | 
 | Delete All Dumps | 
 |     [Documentation]  Delete all dumps. | 
 |  | 
 |     ${resp}=  OpenBMC Get Request  ${DUMP_URI} | 
 |     Run Keyword If  '${resp.status_code}' == '${HTTP_NOT_FOUND}' | 
 |     ...  Set Global Variable  ${DUMP_ENTRY_URI}  /xyz/openbmc_project/dump/entry/ | 
 |  | 
 |     # Check if dump entries exist, if not return. | 
 |     ${resp}=  OpenBMC Get Request  ${DUMP_ENTRY_URI}list  quiet=${1} | 
 |     Return From Keyword If  ${resp.status_code} == ${HTTP_NOT_FOUND} | 
 |  | 
 |     # Get the list of dump entries and delete them all. | 
 |     ${dump_entries}=  Get URL List  ${DUMP_ENTRY_URI} | 
 |     FOR  ${entry}  IN  @{dump_entries} | 
 |         ${dump_id}=  Fetch From Right  ${entry}  / | 
 |         Delete BMC Dump  ${dump_id} | 
 |     END | 
 |  | 
 |  | 
 | Redfish Delete BMC Dump | 
 |     [Documentation]  Deletes a given BMC dump via Redfish.. | 
 |     [Arguments]  ${dump_id} | 
 |  | 
 |     # Description of Argument(s): | 
 |     # dump_id  An integer value that identifies a particular dump (e.g. 1, 3). | 
 |  | 
 |     Redfish.Delete  /redfish/v1/Managers/bmc/LogServices/Dump/Entries/${dump_id} | 
 |  | 
 |  | 
 | Redfish Delete All BMC Dumps | 
 |     [Documentation]  Delete all BMC dumps via Redfish. | 
 |  | 
 |     # Check if dump entries exist, if not return. | 
 |     ${resp}=  Redfish.Get  /redfish/v1/Managers/bmc/LogServices/Dump/Entries | 
 |     Return From Keyword If  ${resp.dict["Members@odata.count"]} == ${0} | 
 |  | 
 |     Redfish.Post  /redfish/v1/Managers/bmc/LogServices/Dump/Actions/LogService.ClearLog | 
 |  | 
 |  | 
 | Redfish Delete All System Dumps | 
 |     [Documentation]  Delete all system  dumps via Redfish. | 
 |  | 
 |     Redfish.Post  /redfish/v1/Systems/system/LogServices/Dump/Actions/LogService.ClearLog | 
 |  | 
 |  | 
 | Delete All BMC Dump | 
 |     [Documentation]  Delete all BMC dump entries using "DeleteAll" interface. | 
 |  | 
 |     ${resp}=  OpenBMC Get Request  ${DUMP_URI} | 
 |     Run Keyword If  '${resp.status_code}' == '${HTTP_NOT_FOUND}' | 
 |     ...  Set Global Variable  ${DUMP_URI}  /xyz/openbmc_project/dump/ | 
 |  | 
 |     ${data}=  Create Dictionary  data=@{EMPTY} | 
 |     ${resp}=  Openbmc Post Request  ${DUMP_URI}action/DeleteAll  data=${data} | 
 |     Should Be Equal As Strings  ${resp.status_code}  ${HTTP_OK} | 
 |  | 
 | Dump Should Not Exist | 
 |     [Documentation]  Verify that BMC dumps do not exist. | 
 |  | 
 |     ${resp}=  OpenBMC Get Request  ${DUMP_URI} | 
 |     Run Keyword If  '${resp.status_code}' == '${HTTP_NOT_FOUND}' | 
 |     ...  Set Global Variable  ${DUMP_ENTRY_URI}  /xyz/openbmc_project/dump/entry/ | 
 |  | 
 |     ${resp}=  OpenBMC Get Request  ${DUMP_ENTRY_URI}list  quiet=${1} | 
 |     Should Be Equal As Strings  ${resp.status_code}  ${HTTP_NOT_FOUND} | 
 |  | 
 | Check Existence Of BMC Dump File | 
 |     [Documentation]  Verify existence of BMC dump file. | 
 |     [Arguments]  ${dump_id} | 
 |  | 
 |     # Description of argument(s): | 
 |     # dump_id  BMC dump identifier | 
 |  | 
 |     ${dump_check_cmd}=  Set Variable | 
 |     ...  ls /var/lib/phosphor-debug-collector/dumps | 
 |  | 
 |     # Output of sample BMC Execute command with '2' as dump id is as follows | 
 |     # ls /var/lib/phosphor-debug-collector/dumps/2 | 
 |     # obmcdump_2_XXXXXXXXXX.tar.xz | 
 |     ${file_there}  ${stderr}  ${rc}=  BMC Execute Command | 
 |     ...  ${dump_check_cmd}/${dump_id} | 
 |     Should End With  ${file_there}  tar.xz  msg=BMC dump file not found. | 
 |  | 
 | Get Dump Entries | 
 |     [Documentation]  Return dump entries list. | 
 |  | 
 |     ${resp}=  OpenBMC Get Request  ${DUMP_URI} | 
 |     Run Keyword If  '${resp.status_code}' == '${HTTP_NOT_FOUND}' | 
 |     ...  Set Global Variable  ${DUMP_ENTRY_URI}  /xyz/openbmc_project/dump/entry/ | 
 |  | 
 |     ${dump_entries}=  Get URL List  ${DUMP_ENTRY_URI} | 
 |     [Return]  ${dump_entries} | 
 |  | 
 | Trigger Core Dump | 
 |     [Documentation]  Trigger core dump. | 
 |  | 
 |     # Find the pid of the active ipmid and kill it. | 
 |     ${cmd_buf}=  Catenate  kill -s SEGV $(ps | egrep ' ipmid$' | | 
 |     ...  egrep -v grep | \ cut -c1-6) | 
 |  | 
 |     ${cmd_output}  ${stderr}  ${rc}=  BMC Execute Command  ${cmd_buf} | 
 |     Should Be Empty  ${stderr}  msg=BMC execute command error. | 
 |     Should Be Equal As Integers  ${rc}  ${0} | 
 |     ...  msg=BMC execute command return code is not zero. | 
 |  | 
 | Create User Initiated BMC Dump Using Redfish | 
 |     [Documentation]  Trigger user initiated BMC dump via Redfish and return task id. | 
 |  | 
 |     ${payload}=  Create Dictionary  DiagnosticDataType=Manager | 
 |     ${resp}=  Redfish.Post | 
 |     ...  /redfish/v1/Managers/bmc/LogServices/Dump/Actions/LogService.CollectDiagnosticData | 
 |     ...  body=${payload}  valid_status_codes=[${HTTP_ACCEPTED}, ${HTTP_OK}] | 
 |  | 
 |     # Example of response from above Redfish POST request. | 
 |     # "@odata.id": "/redfish/v1/TaskService/Tasks/0", | 
 |     # "@odata.type": "#Task.v1_4_3.Task", | 
 |     # "Id": "0", | 
 |     # "TaskState": "Running", | 
 |     # "TaskStatus": "OK" | 
 |  | 
 |     ${task_id}=  Set Variable  ${resp.dict['Id']} | 
 |     [Return]  ${task_id} | 
 |  | 
 | Auto Generate BMC Dump | 
 |     [Documentation]  Auto generate BMC dump. | 
 |  | 
 |     ${cmd}=  Catenate  busctl --verbose call xyz.openbmc_project.Dump.Manager | 
 |     ...  /xyz/openbmc_project/dump/bmc xyz.openbmc_project.Dump.Create CreateDump a{ss} 0 | 
 |     ${stdout}  ${stderr}  ${rc}= | 
 |     ...  BMC Execute Command  ${cmd} | 
 |     [Return]  ${stdout}  ${stderr}  ${rc} | 
 |  | 
 | Get Dump Size | 
 |     [Documentation]  Get dump size. | 
 |     [Arguments]  ${dump_uri} | 
 |  | 
 |     # Description of argument(s): | 
 |     # dump_uri        Dump URI | 
 |     #                 (Eg. 	/xyz/openbmc_project/dump/bmc/entry/1). | 
 |  | 
 |     # Example of Dump entry. | 
 |     # "data": { | 
 |     #   "CompletedTime": 1616760931, | 
 |     #   "Elapsed": 1616760931, | 
 |     #   "OffloadUri": "", | 
 |     #   "Offloaded": false, | 
 |     #   "Password": "", | 
 |     #   "Size": 3056, | 
 |     #   "SourceDumpId": 117440513, | 
 |     #   "StartTime": 1616760931, | 
 |     #   "Status": "xyz.openbmc_project.Common.Progress.OperationStatus.Completed", | 
 |     #   "VSPString": "" | 
 |     #  }, | 
 |  | 
 |     Log  ${dump_uri} | 
 |     ${dump_data}=  Redfish.Get Properties  ${dump_uri} | 
 |     [Return]  ${dump_data["data"]["Size"]} | 
 |  | 
 | Get Dump ID | 
 |     [Documentation]  Return dump ID. | 
 |     [Arguments]   ${task_id} | 
 |  | 
 |     # Description of argument(s): | 
 |     # task_id        Task ID. | 
 |  | 
 |     # Example of HttpHeaders field of task details. | 
 |     # "Payload": { | 
 |     #   "HttpHeaders": [ | 
 |     #     "Host: <BMC_IP>", | 
 |     #      "Accept-Encoding: identity", | 
 |     #      "Connection: Keep-Alive", | 
 |     #      "Accept: */*", | 
 |     #      "Content-Length: 33", | 
 |     #      "Location: /redfish/v1/Managers/bmc/LogServices/Dump/Entries/2"] | 
 |     #    ], | 
 |     #    "HttpOperation": "POST", | 
 |     #    "JsonBody": "{\"DiagnosticDataType\":\"Manager\"}", | 
 |     #     "TargetUri": | 
 |     # "/redfish/v1/Managers/bmc/LogServices/Dump/Actions/LogService.CollectDiagnosticData" | 
 |     # } | 
 |  | 
 |     ${task_dict}=  Redfish.Get Properties  /redfish/v1/TaskService/Tasks/${task_id} | 
 |     ${key}  ${value}=  Set Variable  ${task_dict["Payload"]["HttpHeaders"][-1].split(":")} | 
 |     Run Keyword If  '${key}' != 'Location'  Fail | 
 |     [Return]  ${value.strip('/').split('/')[-1]} | 
 |  | 
 | Get Task Status | 
 |     [Documentation]  Return task status. | 
 |     [Arguments]   ${task_id} | 
 |  | 
 |     # Description of argument(s): | 
 |     # task_id        Task ID. | 
 |  | 
 |     ${resp}=  Redfish.Get Properties  /redfish/v1/TaskService/Tasks/${task_id} | 
 |     [Return]  ${resp['TaskState']} | 
 |  | 
 | Check Task Completion | 
 |     [Documentation]  Check if the task is complete. | 
 |     [Arguments]   ${task_id} | 
 |  | 
 |     # Description of argument(s): | 
 |     # task_id        Task ID. | 
 |  | 
 |     ${status}=  Get Task Status  ${task_id} | 
 |     Run Keyword Unless  '${status}' == 'Cancelled' or '${status}' == 'Completed' | 
 |     ...  Fail  Task is still running. | 
 |     [Return]  ${status} | 
 |  | 
 | Get Dump ID And Status | 
 |     [Documentation]  Return dump ID and status. | 
 |     [Arguments]   ${task_id} | 
 |  | 
 |     # Description of argument(s): | 
 |     # task_id        Task ID. | 
 |  | 
 |     ${task_status}=  Wait Until Keyword Succeeds  10 min  15 sec  Check Task Completion  ${task_id} | 
 |     ${dump_id}=  Run Keyword If  '${task_status}' == 'Completed'  Get Dump ID  ${task_id} | 
 |     ...  ELSE  Set Variable  None | 
 |     [Return]  ${dump_id}  ${task_status} |