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 # To build IP address in searchable form eg: dummy\.domain\.com 158 ${OPENBMC_HOST_REGEX}= Run echo ${OPENBMC_HOST} | sed 's/\(\.\)/\\\1/g' 159 @{cmd_list}= Get ffdc bmc file ${key_index} 160 :FOR ${cmd} IN @{cmd_list} 161 \ ${logpath}= Catenate SEPARATOR= ${LOG_PREFIX} ${cmd[0]}.txt 162 \ Execute Command and Write FFDC ${cmd[0]} ${cmd[1]} ${logpath} 163 # Rename OPENBMC_HOST IP address from given file to DUMMYIP 164 \ Run sed -i 's/'${OPENBMC_HOST_REGEX}'/DUMMYIP/g' ${logpath} 165 166 167 168################################################################ 169# Method : Log Test Case Status # 170# Creates test result history footprint for reference # 171################################################################ 172 173Log Test Case Status 174 [Documentation] Test case execution result history. 175 ... Create once and append to this file 176 ... logs/test_history.txt 177 ... Format Date:Test suite:Test case:Status 178 ... 20160909214053719992:Test Warmreset:Test WarmReset via REST:FAIL 179 180 ${FFDC_DIR_PATH_STYLE}= Get Variable Value ${FFDC_DIR_PATH_STYLE} 181 ... ${EMPTY} 182 ${FFDC_DIR_PATH}= Get Variable Value ${FFDC_DIR_PATH} ${EMPTY} 183 184 Run Keyword If '${FFDC_DIR_PATH}' == '${EMPTY}' Set FFDC Defaults 185 186 Run Keyword If '${FFDC_DIR_PATH_STYLE}' == '${1}' Run Keywords 187 ... Set Global Variable ${FFDC_LOG_PATH} ${FFDC_DIR_PATH} AND 188 ... Set Global Variable ${TEST_HISTORY} ${FFDC_DIR_PATH}test_history.txt 189 190 Create Directory ${FFDC_LOG_PATH} 191 192 ${exist}= Run Keyword and Return Status 193 ... OperatingSystem.File Should Exist ${TEST_HISTORY} 194 195 Run Keyword If '${exist}' == '${False}' 196 ... Create File ${TEST_HISTORY} 197 198 Rpvars TEST_HISTORY 199 200 ${cur_time}= Get Current Time Stamp 201 202 Append To File ${TEST_HISTORY} 203 ... ${cur_time}:${SUITE_NAME}:${TEST_NAME}:${TEST_STATUS}${\n} 204 205 206Log FFDC Get Requests 207 [Documentation] Create file in current FFDC log directory. 208 ... Do openbmc get request and write to 209 ... corresponding file name. 210 ... JSON pretty print for logging to file. 211 [Arguments] ${key_index} 212 213 @{cmd_list}= Get ffdc get request ${key_index} 214 :FOR ${cmd} IN @{cmd_list} 215 \ ${logpath}= Catenate SEPARATOR= ${LOG_PREFIX} ${cmd[0]}.txt 216 \ ${resp}= OpenBMC Get Request ${cmd[1]} quiet=${1} 217 \ ${status}= Run Keyword and Return Status 218 ... Should Be Equal As Strings ${resp.status_code} ${HTTP_OK} 219 \ Run Keyword If '${status}' == '${False}' Continue For Loop 220 \ ${jsondata}= to json ${resp.content} pretty_print=True 221 \ Write Data To File ${\n}${jsondata}${\n} ${logpath} 222 223 224BMC FFDC Get Requests 225 [Documentation] Get the command list and iterate 226 Open Connection And Log In 227 @{entries}= Get ffdc get request index 228 :FOR ${index} IN @{entries} 229 \ Log FFDC Get Requests ${index} 230 231 232Log OS ALL DISTROS FFDC 233 [Documentation] Create file in current FFDC log directory. 234 ... Executes OS command and write to 235 ... corresponding file name. 236 [Arguments] ${key_index} 237 238 @{cmd_list}= get ffdc os all distros call ${key_index} 239 :FOR ${cmd} IN @{cmd_list} 240 \ ${logpath}= Catenate SEPARATOR= ${LOG_PREFIX} ${cmd[0]}.txt 241 \ Execute Command and Write FFDC ${cmd[0]} ${cmd[1]} ${logpath} 242 243 244Log OS SPECIFIC DISTRO FFDC 245 [Documentation] Create file in current FFDC log directory. 246 ... Executes OS command and write to 247 ... corresponding file name. 248 [Arguments] ${key_index} ${linux_distro} 249 250 @{cmd_list}= get ffdc os distro call ${key_index} ${linux_distro} 251 :FOR ${cmd} IN @{cmd_list} 252 \ ${logpath}= Catenate SEPARATOR= ${LOG_PREFIX} ${cmd[0]}.txt 253 \ Execute Command and Write FFDC ${cmd[0]} ${cmd[1]} ${logpath} 254 255 256 257OS FFDC Files 258 [Documentation] Get the command list and iterate 259 [Arguments] ${OS_HOST}=${OS_HOST} ${OS_USERNAME}=${OS_USERNAME} 260 ... ${OS_PASSWORD}=${OS_PASSWORD} 261 262 Return From Keyword If '${OS_HOST}' == '${EMPTY}' 263 ... No OS Host Provided 264 265 # If can't ping, return 266 ${rc}= Run Keyword and Return Status Ping Host ${OS_HOST} 267 Return From Keyword If '${rc}' == '${False}' 268 ... Could not ping OS 269 270 Open Connection And Log In host=${OS_HOST} username=${OS_USERNAME} 271 ... password=${OS_PASSWORD} 272 273 ${output} ${stderr} ${rc}= Execute Command uptime return_stderr=True 274 ... return_rc=True 275 276 # If the return code returned by "Execute Command" is non-zero, return 277 Return From Keyword If '${rc}' != '${0}' 278 ... Could not connect to OS 279 280 @{entries}= Get ffdc os all distros index 281 :FOR ${index} IN @{entries} 282 \ Log OS ALL DISTROS FFDC ${index} 283 284 ${linux_distro}= Execute Command 285 ... . /etc/os-release; echo $ID 286 ... return_stdout=True return_stderr=False return_rc=False 287 288 Return From Keyword If 289 ... '${linux_distro}' == '${EMPTY}' or '${linux_distro}' == 'None' 290 ... Could not determine Linux Distribution 291 292 @{entries}= Get ffdc os distro index ${linux_distro} 293 :FOR ${index} IN @{entries} 294 \ Log OS SPECIFIC DISTRO FFDC ${index} ${linux_distro} 295 296 297############################################################################## 298SCP Coredump Files 299 [Documentation] Copy core dump file from BMC to local system. 300 # Check if core dump exist in the /tmp 301 Open Connection And Log In 302 ${core_files}= Execute Command ls /tmp/core_* 303 @{core_list} = Split String ${core_files} 304 # Copy the core files 305 Open Connection for SCP 306 :FOR ${index} IN @{core_list} 307 \ scp.Get File ${index} ${LOG_PREFIX}${index.lstrip("/tmp/")} 308 # Remove the file from remote to avoid re-copying on next FFDC call 309 \ Execute Command On BMC rm ${index} 310 311 312############################################################################## 313Collect eSEL Log 314 [Documentation] Collect eSEL log from logging entry and convert eSEL data 315 ... to elog formated string text file. 316 ${resp}= OpenBMC Get Request ${BMC_LOGGING_ENTRY}/enumerate quiet=${1} 317 ${status}= Run Keyword And Return Status 318 ... Should Be Equal As Strings ${resp.status_code} ${HTTP_OK} 319 Return From Keyword If '${status}' == '${False}' 320 321 ${content}= To Json ${resp.content} 322 # Grab the list of entries from logging/entry/ 323 # The data shown below is the result of the "Get Dictionary Keys". 324 # Example: 325 # /xyz/openbmc_project/logging/entry/1 326 # /xyz/openbmc_project/logging/entry/2 327 ${esel_list}= Get Dictionary Keys ${content['data']} 328 329 ${logpath}= Catenate SEPARATOR= ${LOG_PREFIX} esel 330 Create File ${logpath} 331 # Fetch data from /xyz/openbmc_project/logging/entry/1/attr/AdditionalData 332 # "ESEL=00 00 df 00 00 00 00 20 00 04 12 35 6f aa 00 00 " 333 # Sample eSEL entry: 334 # "/xyz/openbmc_project/logging/entry/1": { 335 # "Timestamp": 1487744317025, 336 # "AdditionalData": [ 337 # "ESEL=00 00 df 00 00 00 00 20 00 04 12 35 6f aa 00 00 " 338 # ], 339 # "Message": "org.open_power.Error.Host.Event.Event", 340 # "Id": 1, 341 # "Severity": "xyz.openbmc_project.Logging.Entry.Level.Emergency" 342 # } 343 344 :FOR ${entry_path} IN @{esel_list} 345 \ ${esel_data}= Read Attribute ${entry_path} AdditionalData quiet=${1} 346 \ ${length}= Get Length ${esel_data} 347 # Skip writting to file if eSEL AdditionalData is empty 348 \ Continue For Loop If ${length} == ${0} 349 \ Write Data To File "${esel_data[0]}" ${logpath} 350 \ Write Data To File ${\n} ${logpath} 351 352 ${out}= Run which eSEL.pl 353 ${status}= Run Keyword And Return Status 354 ... Should Contain ${out} eSEL.pl 355 Return From Keyword If '${status}' == '${False}' 356 357 Convert eSEL To Elog Format ${logpath} 358 359 360############################################################################## 361Convert eSEL To Elog Format 362 [Documentation] Execute parser tool on the eSEL data file to generate 363 ... formatted error log. 364 [Arguments] ${esel_file_path} 365 # Desription of arguments: 366 # esel_file_path Absolute path of the eSEL data (e.g. 367 # /tmp/w55.170404.154820.esel). 368 369 # Note: The only way to get eSEL.pl to put the output in a particular 370 # directory is to cd to that directory. 371 ${cmd_buf}= Catenate cd $(dirname ${esel_file_path}) ; eSEL.pl -l 372 ... ${esel_file_path} -p decode_obmc_data 373 Run ${cmd_buf} 374 375############################################################################## 376