| #!/usr/bin/env python3 |
| |
| r""" |
| This module is the python counterpart to openbmc_ffdc.robot.. |
| """ |
| |
| import os |
| |
| import gen_print as gp |
| import gen_valid as gv |
| import gen_robot_keyword as grk |
| 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 |
| + " Terminating FFDC collection.\n") |
| return ffdc_file_list |
| |
| if state['uptime'] == "": |
| gp.print_error("BMC is not communicating via ssh. 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 |