1*** Settings *** 2Documentation Methods to execute commands on BMC and collect 3... data to a list of FFDC files 4 5Resource openbmc_ffdc_utils.robot 6Resource rest_client.robot 7Resource utils.robot 8Library SSHLibrary 9Library OperatingSystem 10Library Collections 11Library String 12Library gen_robot_keyword.py 13 14*** Keywords *** 15 16################################################################ 17# Method : Call FFDC Methods # 18# Execute the user define keywords from the FFDC List # 19# Unlike any other keywords this will call into the # 20# list of keywords defined in the FFDC list at one go # 21################################################################ 22 23Call FFDC Methods 24 [Documentation] Call into FFDC Keyword index list. 25 [Arguments] ${ffdc_function_list}=${EMPTY} 26 27 # Description of argument(s): 28 # ffdc_function_list A colon-delimited list naming the kinds of FFDC that 29 # is to be collected 30 # (e.g. "FFDC Generic Report:BMC Specific Files"). 31 # Acceptable values can be found in the description 32 # field of FFDC_METHOD_CALL in 33 # lib/openbmc_ffdc_list.py. Those values can be 34 # obtained via a call to 'Get FFDC Method Desc' (also 35 # from lib/openbmc_ffdc_list.py). 36 37 @{entries}= Get FFDC Method Index 38 :FOR ${index} IN @{entries} 39 \ Method Call Keyword List ${index} ${ffdc_function_list} 40 SSHLibrary.Close All Connections 41 42Method Call Keyword List 43 [Documentation] Iterate the list through keyword index. 44 [Arguments] ${index} ${ffdc_function_list}=${EMPTY} 45 46 # Description of argument(s): 47 # index The index into the FFDC_METHOD_CALL dictionary (e.g. 48 # 'BMC LOGS'). 49 # ffdc_function_list See ffdc_function_list description in 50 # "Call FFDC Methods" (above). 51 52 @{method_list}= Get ffdc method call ${index} 53 54 # If function list is empty assign default (i.e. a list of all allowable 55 # values). In either case, convert ffdc_function_list from a string to 56 # a list. 57 @{ffdc_function_list}= 58 ... Run Keyword If '${ffdc_function_list}' == '${EMPTY}' 59 ... Get FFDC Method Desc ${index} 60 ... ELSE 61 ... Split String ${ffdc_function_list} separator=: 62 63 :FOR ${method} IN @{method_list} 64 \ Execute Keyword Method ${method[0]} ${method[1]} 65 ... @{ffdc_function_list} 66 67Execute Keyword Method 68 [Documentation] Call into BMC method keywords. Don't let one 69 ... failure skip the remaining. Get whatever data 70 ... it could gather at worse case scenario. 71 [Arguments] ${description} ${keyword_name} @{ffdc_function_list} 72 73 # Description of argument(s): 74 # description The description of the FFDC to be collected. This 75 # would be any value returned by 76 # 'Get FFDC Method Desc' (e.g. "FFDC Generic Report"). 77 # keyword_name The name of the keyword to call to collect the FFDC 78 # data (again, see FFDC_METHOD_CALL). 79 # ffdc_function_list See ffdc_function_list description in 80 # "Call FFDC Methods" (above). The only difference is 81 # in this case, it should be a list rather than a 82 # colon-delimited value. 83 84 ${status} ${ret_values}= Run Keyword And Ignore Error 85 ... List Should Contain Value ${ffdc_function_list} ${description} 86 Run Keyword If '${status}' != 'PASS' Return from Keyword 87 88 Run Key ${keyword_name} ignore=1 89 90################################################################ 91# Method : BMC FFDC Manifest # 92# Execute command on BMC and write to ffdc_report.txt # 93################################################################ 94 95BMC FFDC Manifest 96 [Documentation] Get the commands index for the FFDC_BMC_CMD, 97 ... login to BMC and execute commands. 98 Open Connection And Log In 99 100 @{entries}= Get ffdc cmd index 101 :FOR ${index} IN @{entries} 102 \ Iterate BMC Command List Pairs ${index} 103 104 105Iterate BMC Command List Pairs 106 [Documentation] Feed in key pair list from dictionary to execute 107 [Arguments] ${key_index} 108 109 @{cmd_list}= Get ffdc bmc cmd ${key_index} 110 Set Suite Variable ${ENTRY_INDEX} ${key_index} 111 :FOR ${cmd} IN @{cmd_list} 112 \ Execute Command and Write FFDC ${cmd[0]} ${cmd[1]} 113 114 115Execute Command and Write FFDC 116 [Documentation] Execute command on BMC or OS and write to ffdc 117 ... By default to ffdc_report.txt file else to 118 ... specified file path. 119 [Arguments] ${key_index} 120 ... ${cmd} 121 ... ${logpath}=${FFDC_FILE_PATH} 122 123 Run Keyword If '${logpath}' == '${FFDC_FILE_PATH}' 124 ... Write Cmd Output to FFDC File ${key_index} ${cmd} 125 126 ${stdout} ${stderr}= 127 ... Execute Command ${cmd} return_stderr=True 128 129 # Write stdout on success and stderr/stdout to the file on failure. 130 Run Keyword If $stderr == '${EMPTY}' 131 ... Write Data To File ${stdout}${\n} ${logpath} 132 ... ELSE Write Data To File 133 ... ERROR output:${\n}${stderr}${\n}Output:${\n}${stdout}${\n} 134 ... ${logpath} 135 136 137################################################################ 138# Method : BMC FFDC Files # 139# Execute command on BMC and write to individual file # 140# based on the file name pre-defined in the list # 141################################################################ 142 143BMC FFDC Files 144 [Documentation] Get the command list and iterate 145 Open Connection And Log In 146 @{entries}= Get ffdc file index 147 :FOR ${index} IN @{entries} 148 \ Create File and Write Data ${index} 149 150 151Create File and Write Data 152 [Documentation] Create files to current FFDC log directory, 153 ... executes command and write to corresponding 154 ... file name in the current FFDC directory. 155 [Arguments] ${key_index} 156 157 @{cmd_list}= Get ffdc bmc file ${key_index} 158 :FOR ${cmd} IN @{cmd_list} 159 \ ${logpath}= Catenate SEPARATOR= ${LOG_PREFIX} ${cmd[0]}.txt 160 \ Execute Command and Write FFDC ${cmd[0]} ${cmd[1]} ${logpath} 161 162 163 164################################################################ 165# Method : Log Test Case Status # 166# Creates test result history footprint for reference # 167################################################################ 168 169Log Test Case Status 170 [Documentation] Test case execution result history. 171 ... Create once and append to this file 172 ... logs/test_history.txt 173 ... Format Date:Test suite:Test case:Status 174 ... 20160909214053719992:Test Warmreset:Test WarmReset via REST:FAIL 175 176 ${FFDC_DIR_PATH_STYLE}= Get Variable Value ${FFDC_DIR_PATH_STYLE} 177 ... ${EMPTY} 178 ${FFDC_DIR_PATH}= Get Variable Value ${FFDC_DIR_PATH} ${EMPTY} 179 180 Run Keyword If '${FFDC_DIR_PATH}' == '${EMPTY}' Set FFDC Defaults 181 182 Run Keyword If '${FFDC_DIR_PATH_STYLE}' == '${1}' Run Keywords 183 ... Set Global Variable ${FFDC_LOG_PATH} ${FFDC_DIR_PATH} AND 184 ... Set Global Variable ${TEST_HISTORY} ${FFDC_DIR_PATH}test_history.txt 185 186 Create Directory ${FFDC_LOG_PATH} 187 188 ${exist}= Run Keyword and Return Status 189 ... OperatingSystem.File Should Exist ${TEST_HISTORY} 190 191 Run Keyword If '${exist}' == '${False}' 192 ... Create File ${TEST_HISTORY} 193 194 Rpvars TEST_HISTORY 195 196 ${cur_time}= Get Current Time Stamp 197 198 Append To File ${TEST_HISTORY} 199 ... ${cur_time}:${SUITE_NAME}:${TEST_NAME}:${TEST_STATUS}${\n} 200 201 202Log FFDC Get Requests 203 [Documentation] Create file in current FFDC log directory. 204 ... Do openbmc get request and write to 205 ... corresponding file name. 206 ... JSON pretty print for logging to file. 207 [Arguments] ${key_index} 208 209 @{cmd_list}= Get ffdc get request ${key_index} 210 :FOR ${cmd} IN @{cmd_list} 211 \ ${logpath}= Catenate SEPARATOR= ${LOG_PREFIX} ${cmd[0]}.txt 212 \ ${resp}= OpenBMC Get Request ${cmd[1]} quiet=${1} 213 \ ${status}= Run Keyword and Return Status 214 ... Should Be Equal As Strings ${resp.status_code} ${HTTP_OK} 215 \ Run Keyword If '${status}' == '${False}' Continue For Loop 216 \ ${jsondata}= to json ${resp.content} pretty_print=True 217 \ Write Data To File ${\n}${jsondata}${\n} ${logpath} 218 219 220BMC FFDC Get Requests 221 [Documentation] Get the command list and iterate 222 Open Connection And Log In 223 @{entries}= Get ffdc get request index 224 :FOR ${index} IN @{entries} 225 \ Log FFDC Get Requests ${index} 226 227 228Log OS ALL DISTROS FFDC 229 [Documentation] Create file in current FFDC log directory. 230 ... Executes OS command and write to 231 ... corresponding file name. 232 [Arguments] ${key_index} 233 234 @{cmd_list}= get ffdc os all distros call ${key_index} 235 :FOR ${cmd} IN @{cmd_list} 236 \ ${logpath}= Catenate SEPARATOR= ${LOG_PREFIX} ${cmd[0]}.txt 237 \ Execute Command and Write FFDC ${cmd[0]} ${cmd[1]} ${logpath} 238 239 240Log OS SPECIFIC DISTRO FFDC 241 [Documentation] Create file in current FFDC log directory. 242 ... Executes OS command and write to 243 ... corresponding file name. 244 [Arguments] ${key_index} ${linux_distro} 245 246 @{cmd_list}= get ffdc os distro call ${key_index} ${linux_distro} 247 :FOR ${cmd} IN @{cmd_list} 248 \ ${logpath}= Catenate SEPARATOR= ${LOG_PREFIX} ${cmd[0]}.txt 249 \ Execute Command and Write FFDC ${cmd[0]} ${cmd[1]} ${logpath} 250 251 252 253OS FFDC Files 254 [Documentation] Get the command list and iterate 255 [Arguments] ${OS_HOST}=${OS_HOST} ${OS_USERNAME}=${OS_USERNAME} 256 ... ${OS_PASSWORD}=${OS_PASSWORD} 257 258 Return From Keyword If '${OS_HOST}' == '${EMPTY}' 259 ... No OS Host Provided 260 261 # If can't ping, return 262 ${rc}= Run Keyword and Return Status Ping Host ${OS_HOST} 263 Return From Keyword If '${rc}' == '${False}' 264 ... Could not ping OS 265 266 Open Connection And Log In host=${OS_HOST} username=${OS_USERNAME} 267 ... password=${OS_PASSWORD} 268 269 ${output} ${stderr} ${rc}= Execute Command uptime return_stderr=True 270 ... return_rc=True 271 272 # If the return code returned by "Execute Command" is non-zero, return 273 Return From Keyword If '${rc}' != '${0}' 274 ... Could not connect to OS 275 276 @{entries}= Get ffdc os all distros index 277 :FOR ${index} IN @{entries} 278 \ Log OS ALL DISTROS FFDC ${index} 279 280 ${linux_distro}= Execute Command 281 ... . /etc/os-release; echo $ID 282 ... return_stdout=True return_stderr=False return_rc=False 283 284 Return From Keyword If 285 ... '${linux_distro}' == '${EMPTY}' or '${linux_distro}' == 'None' 286 ... Could not determine Linux Distribution 287 288 @{entries}= Get ffdc os distro index ${linux_distro} 289 :FOR ${index} IN @{entries} 290 \ Log OS SPECIFIC DISTRO FFDC ${index} ${linux_distro} 291 292 293############################################################################## 294SCP Coredump Files 295 [Documentation] Copy core dump file from BMC to local system. 296 # Check if core dump exist in the /tmp 297 Open Connection And Log In 298 ${core_files}= Execute Command ls /tmp/core_* 299 @{core_list} = Split String ${core_files} 300 # Copy the core files 301 Open Connection for SCP 302 :FOR ${index} IN @{core_list} 303 \ scp.Get File ${index} ${LOG_PREFIX}${index.lstrip("/tmp/")} 304 # Remove the file from remote to avoid re-copying on next FFDC call 305 \ Execute Command On BMC rm ${index} 306 307 308############################################################################## 309Collect eSEL Log 310 [Documentation] Collect eSEL log from logging entry and convert eSEL data 311 ... to elog formated string text file. 312 ${resp}= OpenBMC Get Request ${BMC_LOGGING_ENTRY}/enumerate quiet=${1} 313 ${status}= Run Keyword And Return Status 314 ... Should Be Equal As Strings ${resp.status_code} ${HTTP_OK} 315 Return From Keyword If '${status}' == '${False}' 316 317 ${content}= To Json ${resp.content} 318 # Grab the list of entries from logging/entry/ 319 # The data shown below is the result of the "Get Dictionary Keys". 320 # Example: 321 # /xyz/openbmc_project/logging/entry/1 322 # /xyz/openbmc_project/logging/entry/2 323 ${esel_list}= Get Dictionary Keys ${content['data']} 324 325 ${logpath}= Catenate SEPARATOR= ${LOG_PREFIX} esel 326 Create File ${logpath} 327 # Fetch data from /xyz/openbmc_project/logging/entry/1/attr/AdditionalData 328 # "ESEL=00 00 df 00 00 00 00 20 00 04 12 35 6f aa 00 00 " 329 # Sample eSEL entry: 330 # "/xyz/openbmc_project/logging/entry/1": { 331 # "Timestamp": 1487744317025, 332 # "AdditionalData": [ 333 # "ESEL=00 00 df 00 00 00 00 20 00 04 12 35 6f aa 00 00 " 334 # ], 335 # "Message": "org.open_power.Error.Host.Event.Event", 336 # "Id": 1, 337 # "Severity": "xyz.openbmc_project.Logging.Entry.Level.Emergency" 338 # } 339 340 :FOR ${entry_path} IN @{esel_list} 341 \ ${esel_data}= Read Attribute ${entry_path} AdditionalData quiet=${1} 342 \ ${length}= Get Length ${esel_data} 343 # Skip writting to file if eSEL AdditionalData is empty 344 \ Continue For Loop If ${length} == ${0} 345 \ Write Data To File "${esel_data[0]}" ${logpath} 346 \ Write Data To File ${\n} ${logpath} 347 348 ${out}= Run which eSEL.pl 349 ${status}= Run Keyword And Return Status 350 ... Should Contain ${out} eSEL.pl 351 Return From Keyword If '${status}' == '${False}' 352 353 Convert eSEL To Elog Format ${logpath} 354 355 356############################################################################## 357Convert eSEL To Elog Format 358 [Documentation] Execute parser tool on the eSEL data file to generate 359 ... formatted error log. 360 [Arguments] ${esel_file_path} 361 # Desription of arguments: 362 # esel_file_path Absolute path of the eSEL data (e.g. 363 # /tmp/w55.170404.154820.esel). 364 365 # Note: The only way to get eSEL.pl to put the output in a particular 366 # directory is to cd to that directory. 367 ${cmd_buf}= Catenate cd $(dirname ${esel_file_path}) ; eSEL.pl -l 368 ... ${esel_file_path} -p decode_obmc_data 369 Run ${cmd_buf} 370 371############################################################################## 372