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