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