1#!/usr/bin/env python3 2 3r""" 4This module is the python counterpart to openbmc_ffdc.robot.. 5""" 6 7import os 8 9import gen_print as gp 10import gen_robot_keyword as grk 11import gen_valid as gv 12import state as st 13from robot.libraries.BuiltIn import BuiltIn 14 15redfish_support_trans_state = int( 16 os.environ.get("REDFISH_SUPPORT_TRANS_STATE", 0) 17) or int( 18 BuiltIn().get_variable_value("${REDFISH_SUPPORT_TRANS_STATE}", default=0) 19) 20 21 22def ffdc( 23 ffdc_dir_path=None, 24 ffdc_prefix=None, 25 ffdc_function_list="", 26 comm_check=True, 27): 28 r""" 29 Gather First Failure Data Capture (FFDC). 30 31 This includes: 32 - Set global FFDC_TIME. 33 - Create FFDC work space directory. 34 - Write test info details. 35 - Call BMC methods to write/collect FFDC data. 36 37 Description of arguments: 38 ffdc_dir_path The dir path where FFDC data should be put. 39 ffdc_prefix The prefix to be given to each FFDC file name generated. 40 ffdc_function_list A colon-delimited list of all the types of FFDC data you wish to have 41 collected. A blank value means that all possible kinds of FFDC are to be 42 collected. See FFDC_METHOD_CALL object in lib/openbmc_ffdc_list.py for 43 possible choices. 44 comm_check Do a communications check prior to collecting FFDC. If commincation to 45 the BMC can't be established, abort the FFDC collection. 46 """ 47 48 ffdc_file_list = [] 49 50 # Check if Ping and SSH connection is alive 51 OPENBMC_HOST = BuiltIn().get_variable_value("${OPENBMC_HOST}") 52 53 if comm_check: 54 if not redfish_support_trans_state: 55 interface = "rest" 56 else: 57 interface = "redfish" 58 59 state = st.get_state(req_states=["ping", "uptime", interface]) 60 gp.qprint_var(state) 61 if not int(state["ping"]): 62 gp.print_error( 63 "BMC is not ping-able. Terminating FFDC collection.\n" 64 ) 65 return ffdc_file_list 66 67 if not int(state[interface]): 68 gp.print_error("%s commands to the BMC are failing." % interface) 69 70 if state["uptime"] == "": 71 gp.print_error("BMC is not communicating via ssh.\n") 72 73 # If SSH and Redfish connection doesn't works, abort. 74 if not int(state[interface]) and state["uptime"] == "": 75 gp.print_error( 76 "BMC is not communicating via ssh or Redfish. Terminating" 77 " FFDC" 78 + " collection.\n" 79 ) 80 return ffdc_file_list 81 82 gp.qprint_timen("Collecting FFDC.") 83 84 # Get default values for arguments. 85 ffdc_dir_path, ffdc_prefix = set_ffdc_defaults(ffdc_dir_path, ffdc_prefix) 86 gp.qprint_var(ffdc_dir_path) 87 gp.qprint_var(ffdc_prefix) 88 89 # LOG_PREFIX is used by subordinate functions. 90 LOG_PREFIX = ffdc_dir_path + ffdc_prefix 91 BuiltIn().set_global_variable("${LOG_PREFIX}", LOG_PREFIX) 92 93 cmd_buf = ["Create Directory", ffdc_dir_path] 94 gp.qprint_issuing(cmd_buf) 95 status, output = BuiltIn().run_keyword_and_ignore_error(*cmd_buf) 96 if status != "PASS": 97 error_message = gp.sprint_error_report( 98 "Create Directory failed" 99 + " with the following" 100 + " error:\n" 101 + output 102 ) 103 BuiltIn().fail(error_message) 104 105 # FFDC_FILE_PATH is used by Header Message. 106 FFDC_FILE_PATH = ffdc_dir_path + ffdc_prefix + "BMC_general.txt" 107 BuiltIn().set_global_variable("${FFDC_FILE_PATH}", FFDC_FILE_PATH) 108 109 status, ffdc_file_list = grk.run_key_u("Header Message") 110 status, ffdc_file_sub_list = grk.run_key_u( 111 "Call FFDC Methods ffdc_function_list=" + ffdc_function_list 112 ) 113 114 # Combine lists, remove duplicates and sort. 115 ffdc_file_list = sorted(set(ffdc_file_list + ffdc_file_sub_list)) 116 117 gp.qprint_timen("Finished collecting FFDC.") 118 119 return ffdc_file_list 120 121 122def set_ffdc_defaults(ffdc_dir_path=None, ffdc_prefix=None): 123 r""" 124 Set a default value for ffdc_dir_path and ffdc_prefix if they don't 125 already have values. Return both values. 126 127 Description of arguments: 128 ffdc_dir_path The dir path where FFDC data should be put. 129 ffdc_prefix The prefix to be given to each FFDC file name generated. 130 131 NOTE: If global variable ffdc_dir_path_style is set to ${1}, this function 132 will create default values in a newer way. Otherwise, its behavior 133 will remain unchanged. 134 """ 135 136 # Note: Several subordinate functions like 'Get Test Dir and Name' and 137 # 'Header Message' expect global variable FFDC_TIME to be set. 138 cmd_buf = ["Get Current Time Stamp"] 139 gp.dprint_issuing(cmd_buf) 140 FFDC_TIME = BuiltIn().run_keyword(*cmd_buf) 141 BuiltIn().set_global_variable("${FFDC_TIME}", FFDC_TIME) 142 143 ffdc_dir_path_style = BuiltIn().get_variable_value( 144 "${ffdc_dir_path_style}" 145 ) 146 147 if ffdc_dir_path is None: 148 if ffdc_dir_path_style: 149 try: 150 ffdc_dir_path = os.environ["FFDC_DIR_PATH"] 151 except KeyError: 152 ffdc_dir_path = ( 153 os.path.dirname( 154 BuiltIn().get_variable_value("${LOG_FILE}") 155 ) 156 + "/" 157 ) 158 else: 159 FFDC_LOG_PATH = os.getcwd() + "/logs/" 160 if FFDC_LOG_PATH is None: 161 FFDC_LOG_PATH = "" 162 if FFDC_LOG_PATH == "": 163 FFDC_LOG_PATH = ( 164 os.path.dirname( 165 BuiltIn().get_variable_value("${LOG_FILE}") 166 ) 167 + "/" 168 ) 169 error_message = gv.valid_value( 170 FFDC_LOG_PATH, var_name="FFDC_LOG_PATH" 171 ) 172 if error_message != "": 173 error_message = gp.sprint_error_report(error_message) 174 BuiltIn().fail(error_message) 175 FFDC_LOG_PATH = os.path.normpath(FFDC_LOG_PATH) + os.sep 176 177 cmd_buf = ["Get Test Dir and Name"] 178 gp.print_issuing(cmd_buf) 179 suitename, testname = BuiltIn().run_keyword(*cmd_buf) 180 181 ffdc_dir_path = FFDC_LOG_PATH + suitename + "/" + testname + "/" 182 183 # Add trailing slash. 184 ffdc_dir_path = os.path.normpath(ffdc_dir_path) + os.sep 185 186 if ffdc_prefix is None: 187 FFDC_TIME = BuiltIn().get_variable_value("${FFDC_TIME}") 188 if ffdc_prefix is None: 189 if ffdc_dir_path_style: 190 OPENBMC_HOST = BuiltIn().get_variable_value("${OPENBMC_HOST}") 191 OPENBMC_NICKNAME = BuiltIn().get_variable_value( 192 "${OPENBMC_NICKNAME}", default=OPENBMC_HOST 193 ) 194 ffdc_prefix = ( 195 OPENBMC_NICKNAME 196 + "." 197 + FFDC_TIME[2:8] 198 + "." 199 + FFDC_TIME[8:14] 200 + "." 201 ) 202 else: 203 ffdc_prefix = FFDC_TIME + "_" 204 205 BuiltIn().set_global_variable("${FFDC_DIR_PATH}", ffdc_dir_path) 206 BuiltIn().set_global_variable("${FFDC_PREFIX}", ffdc_prefix) 207 208 return ffdc_dir_path, ffdc_prefix 209