blob: b5efa7a6706c8230a7266d2630393492816d3313 [file] [log] [blame]
#!/usr/bin/env python3
r"""
This module is the python counterpart to openbmc_ffdc.robot..
"""
import os
import gen_print as gp
import gen_robot_keyword as grk
import gen_valid as gv
import state as st
from robot.libraries.BuiltIn import BuiltIn
redfish_support_trans_state = int(
os.environ.get("REDFISH_SUPPORT_TRANS_STATE", 0)
) or int(
BuiltIn().get_variable_value("${REDFISH_SUPPORT_TRANS_STATE}", default=0)
)
def ffdc(
ffdc_dir_path=None,
ffdc_prefix=None,
ffdc_function_list="",
comm_check=True,
):
r"""
Gather First Failure Data Capture (FFDC).
This includes:
- Set global FFDC_TIME.
- Create FFDC work space directory.
- Write test info details.
- Call BMC methods to write/collect FFDC data.
Description of arguments:
ffdc_dir_path The dir path where FFDC data should be put.
ffdc_prefix The prefix to be given to each FFDC file name generated.
ffdc_function_list A colon-delimited list of all the types of FFDC data you wish to have
collected. A blank value means that all possible kinds of FFDC are to be
collected. See FFDC_METHOD_CALL object in lib/openbmc_ffdc_list.py for
possible choices.
comm_check Do a communications check prior to collecting FFDC. If commincation to
the BMC can't be established, abort the FFDC collection.
"""
ffdc_file_list = []
# Check if Ping and SSH connection is alive
OPENBMC_HOST = BuiltIn().get_variable_value("${OPENBMC_HOST}")
if comm_check:
if not redfish_support_trans_state:
interface = "rest"
else:
interface = "redfish"
state = st.get_state(req_states=["ping", "uptime", interface])
gp.qprint_var(state)
if not int(state["ping"]):
gp.print_error(
"BMC is not ping-able. Terminating FFDC collection.\n"
)
return ffdc_file_list
if not int(state[interface]):
gp.print_error("%s commands to the BMC are failing." % interface)
if state["uptime"] == "":
gp.print_error("BMC is not communicating via ssh.\n")
# If SSH and Redfish connection doesn't works, abort.
if not int(state[interface]) and state["uptime"] == "":
gp.print_error(
"BMC is not communicating via ssh or Redfish. Terminating"
" FFDC"
+ " collection.\n"
)
return ffdc_file_list
gp.qprint_timen("Collecting FFDC.")
# Get default values for arguments.
ffdc_dir_path, ffdc_prefix = set_ffdc_defaults(ffdc_dir_path, ffdc_prefix)
gp.qprint_var(ffdc_dir_path)
gp.qprint_var(ffdc_prefix)
# LOG_PREFIX is used by subordinate functions.
LOG_PREFIX = ffdc_dir_path + ffdc_prefix
BuiltIn().set_global_variable("${LOG_PREFIX}", LOG_PREFIX)
cmd_buf = ["Create Directory", ffdc_dir_path]
gp.qprint_issuing(cmd_buf)
status, output = BuiltIn().run_keyword_and_ignore_error(*cmd_buf)
if status != "PASS":
error_message = gp.sprint_error_report(
"Create Directory failed"
+ " with the following"
+ " error:\n"
+ output
)
BuiltIn().fail(error_message)
# FFDC_FILE_PATH is used by Header Message.
FFDC_FILE_PATH = ffdc_dir_path + ffdc_prefix + "BMC_general.txt"
BuiltIn().set_global_variable("${FFDC_FILE_PATH}", FFDC_FILE_PATH)
status, ffdc_file_list = grk.run_key_u("Header Message")
status, ffdc_file_sub_list = grk.run_key_u(
"Call FFDC Methods ffdc_function_list=" + ffdc_function_list
)
# Combine lists, remove duplicates and sort.
ffdc_file_list = sorted(set(ffdc_file_list + ffdc_file_sub_list))
gp.qprint_timen("Finished collecting FFDC.")
return ffdc_file_list
def set_ffdc_defaults(ffdc_dir_path=None, ffdc_prefix=None):
r"""
Set a default value for ffdc_dir_path and ffdc_prefix if they don't
already have values. Return both values.
Description of arguments:
ffdc_dir_path The dir path where FFDC data should be put.
ffdc_prefix The prefix to be given to each FFDC file name generated.
NOTE: If global variable ffdc_dir_path_style is set to ${1}, this function
will create default values in a newer way. Otherwise, its behavior
will remain unchanged.
"""
# Note: Several subordinate functions like 'Get Test Dir and Name' and
# 'Header Message' expect global variable FFDC_TIME to be set.
cmd_buf = ["Get Current Time Stamp"]
gp.dprint_issuing(cmd_buf)
FFDC_TIME = BuiltIn().run_keyword(*cmd_buf)
BuiltIn().set_global_variable("${FFDC_TIME}", FFDC_TIME)
ffdc_dir_path_style = BuiltIn().get_variable_value(
"${ffdc_dir_path_style}"
)
if ffdc_dir_path is None:
if ffdc_dir_path_style:
try:
ffdc_dir_path = os.environ["FFDC_DIR_PATH"]
except KeyError:
ffdc_dir_path = (
os.path.dirname(
BuiltIn().get_variable_value("${LOG_FILE}")
)
+ "/"
)
else:
FFDC_LOG_PATH = os.getcwd() + "/logs/"
if FFDC_LOG_PATH is None:
FFDC_LOG_PATH = ""
if FFDC_LOG_PATH == "":
FFDC_LOG_PATH = (
os.path.dirname(
BuiltIn().get_variable_value("${LOG_FILE}")
)
+ "/"
)
error_message = gv.valid_value(
FFDC_LOG_PATH, var_name="FFDC_LOG_PATH"
)
if error_message != "":
error_message = gp.sprint_error_report(error_message)
BuiltIn().fail(error_message)
FFDC_LOG_PATH = os.path.normpath(FFDC_LOG_PATH) + os.sep
cmd_buf = ["Get Test Dir and Name"]
gp.print_issuing(cmd_buf)
suitename, testname = BuiltIn().run_keyword(*cmd_buf)
ffdc_dir_path = FFDC_LOG_PATH + suitename + "/" + testname + "/"
# Add trailing slash.
ffdc_dir_path = os.path.normpath(ffdc_dir_path) + os.sep
if ffdc_prefix is None:
FFDC_TIME = BuiltIn().get_variable_value("${FFDC_TIME}")
if ffdc_prefix is None:
if ffdc_dir_path_style:
OPENBMC_HOST = BuiltIn().get_variable_value("${OPENBMC_HOST}")
OPENBMC_NICKNAME = BuiltIn().get_variable_value(
"${OPENBMC_NICKNAME}", default=OPENBMC_HOST
)
ffdc_prefix = (
OPENBMC_NICKNAME
+ "."
+ FFDC_TIME[2:8]
+ "."
+ FFDC_TIME[8:14]
+ "."
)
else:
ffdc_prefix = FFDC_TIME + "_"
BuiltIn().set_global_variable("${FFDC_DIR_PATH}", ffdc_dir_path)
BuiltIn().set_global_variable("${FFDC_PREFIX}", ffdc_prefix)
return ffdc_dir_path, ffdc_prefix