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