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_print.py 13Library gen_robot_keyword.py 14 15*** Keywords *** 16 17################################################################ 18# Method : Call FFDC Methods # 19# Execute the user define keywords from the FFDC List # 20# Unlike any other keywords this will call into the # 21# list of keywords defined in the FFDC list at one go # 22################################################################ 23 24Call FFDC Methods 25 [Documentation] Call into FFDC Keyword index list. 26 [Arguments] ${ffdc_function_list}=${EMPTY} 27 28 # Description of argument(s): 29 # ffdc_function_list A colon-delimited list naming the kinds of FFDC that 30 # is to be collected 31 # (e.g. "FFDC Generic Report:BMC Specific Files"). 32 # Acceptable values can be found in the description 33 # field of FFDC_METHOD_CALL in 34 # lib/openbmc_ffdc_list.py. Those values can be 35 # obtained via a call to 'Get FFDC Method Desc' (also 36 # from lib/openbmc_ffdc_list.py). 37 38 @{entries}= Get FFDC Method Index 39 :FOR ${index} IN @{entries} 40 \ Method Call Keyword List ${index} ${ffdc_function_list} 41 Run Key U SSHLibrary.Close All Connections 42 43Method Call Keyword List 44 [Documentation] Iterate the list through keyword index. 45 [Arguments] ${index} ${ffdc_function_list}=${EMPTY} 46 47 # Description of argument(s): 48 # index The index into the FFDC_METHOD_CALL dictionary (e.g. 49 # 'BMC LOGS'). 50 # ffdc_function_list See ffdc_function_list description in 51 # "Call FFDC Methods" (above). 52 53 @{method_list}= Get ffdc method call ${index} 54 55 # If function list is empty assign default (i.e. a list of all allowable 56 # values). In either case, convert ffdc_function_list from a string to 57 # a list. 58 @{ffdc_function_list}= 59 ... Run Keyword If '${ffdc_function_list}' == '${EMPTY}' 60 ... Get FFDC Method Desc ${index} 61 ... ELSE 62 ... Split String ${ffdc_function_list} separator=: 63 64 :FOR ${method} IN @{method_list} 65 \ Execute Keyword Method ${method[0]} ${method[1]} 66 ... @{ffdc_function_list} 67 68Execute Keyword Method 69 [Documentation] Call into BMC method keywords. Don't let one 70 ... failure skip the remaining. Get whatever data 71 ... it could gather at worse case scenario. 72 [Arguments] ${description} ${keyword_name} @{ffdc_function_list} 73 74 # Description of argument(s): 75 # description The description of the FFDC to be collected. This 76 # would be any value returned by 77 # 'Get FFDC Method Desc' (e.g. "FFDC Generic Report"). 78 # keyword_name The name of the keyword to call to collect the FFDC 79 # data (again, see FFDC_METHOD_CALL). 80 # ffdc_function_list See ffdc_function_list description in 81 # "Call FFDC Methods" (above). The only difference is 82 # in this case, it should be a list rather than a 83 # colon-delimited value. 84 85 ${status} ${ret_values}= Run Keyword And Ignore Error 86 ... List Should Contain Value ${ffdc_function_list} ${description} 87 Run Keyword If '${status}' != 'PASS' Return from Keyword 88 89 Run Key ${keyword_name} ignore=1 90 91################################################################ 92# Method : BMC FFDC Manifest # 93# Execute command on BMC and write to ffdc_report.txt # 94################################################################ 95 96BMC FFDC Manifest 97 [Documentation] Get the commands index for the FFDC_BMC_CMD, 98 ... login to BMC and execute commands. 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 ... ${target}=BMC 123 124 Run Keyword If '${logpath}' == '${FFDC_FILE_PATH}' 125 ... Write Cmd Output to FFDC File ${key_index} ${cmd} 126 127 ${cmd_buf}= Catenate ${target} Execute Command \ ${cmd} \ ignore_err=${1} 128 ${status} ${ret_values}= Run Key ${cmd_buf} ignore=${1} 129 130 ${stdout}= Set Variable @{ret_values}[0] 131 ${stderr}= Set Variable @{ret_values}[1] 132 133 # Write stdout on success and stderr/stdout to the file on failure. 134 Run Keyword If $stderr == '${EMPTY}' 135 ... Write Data To File ${stdout}${\n} ${logpath} 136 ... ELSE Write Data To File 137 ... ERROR output:${\n}${stderr}${\n}Output:${\n}${stdout}${\n} 138 ... ${logpath} 139 140 141################################################################ 142# Method : BMC FFDC Files # 143# Execute command on BMC and write to individual file # 144# based on the file name pre-defined in the list # 145################################################################ 146 147BMC FFDC Files 148 [Documentation] Get the command list and iterate 149 @{entries}= Get ffdc file index 150 :FOR ${index} IN @{entries} 151 \ Create File and Write Data ${index} 152 153 154Create File and Write Data 155 [Documentation] Create files to current FFDC log directory, 156 ... executes command and write to corresponding 157 ... file name in the current FFDC directory. 158 [Arguments] ${key_index} 159 160 @{cmd_list}= Get ffdc bmc file ${key_index} 161 :FOR ${cmd} IN @{cmd_list} 162 \ ${logpath}= Catenate SEPARATOR= ${LOG_PREFIX} ${cmd[0]}.txt 163 \ Execute Command and Write FFDC ${cmd[0]} ${cmd[1]} ${logpath} 164 165 166 167################################################################ 168# Method : Log Test Case Status # 169# Creates test result history footprint for reference # 170################################################################ 171 172Log Test Case Status 173 [Documentation] Test case execution result history. 174 ... Create once and append to this file 175 ... logs/test_history.txt 176 ... Format Date:Test suite:Test case:Status 177 ... 20160909214053719992:Test Warmreset:Test WarmReset via REST:FAIL 178 179 ${FFDC_DIR_PATH_STYLE}= Get Variable Value ${FFDC_DIR_PATH_STYLE} 180 ... ${EMPTY} 181 ${FFDC_DIR_PATH}= Get Variable Value ${FFDC_DIR_PATH} ${EMPTY} 182 183 Run Keyword If '${FFDC_DIR_PATH}' == '${EMPTY}' Set FFDC Defaults 184 185 Run Keyword If '${FFDC_DIR_PATH_STYLE}' == '${1}' Run Keywords 186 ... Set Global Variable ${FFDC_LOG_PATH} ${FFDC_DIR_PATH} AND 187 ... Set Global Variable ${TEST_HISTORY} ${FFDC_DIR_PATH}test_history.txt 188 189 Create Directory ${FFDC_LOG_PATH} 190 191 ${exist}= Run Keyword and Return Status 192 ... OperatingSystem.File Should Exist ${TEST_HISTORY} 193 194 Run Keyword If '${exist}' == '${False}' 195 ... Create File ${TEST_HISTORY} 196 197 Rpvars TEST_HISTORY 198 199 ${cur_time}= Get Current Time Stamp 200 201 Append To File ${TEST_HISTORY} 202 ... ${cur_time}:${SUITE_NAME}:${TEST_NAME}:${TEST_STATUS}${\n} 203 204 205Log FFDC Get Requests 206 [Documentation] Create file in current FFDC log directory. 207 ... Do openbmc get request and write to 208 ... corresponding file name. 209 ... JSON pretty print for logging to file. 210 [Arguments] ${key_index} 211 212 @{cmd_list}= Get ffdc get request ${key_index} 213 :FOR ${cmd} IN @{cmd_list} 214 \ ${logpath}= Catenate SEPARATOR= ${LOG_PREFIX} ${cmd[0]}.txt 215 \ ${resp}= OpenBMC Get Request ${cmd[1]} quiet=${1} 216 \ ${status}= Run Keyword and Return Status 217 ... Should Be Equal As Strings ${resp.status_code} ${HTTP_OK} 218 \ Run Keyword If '${status}' == '${False}' Continue For Loop 219 \ ${jsondata}= to json ${resp.content} pretty_print=True 220 \ Write Data To File ${\n}${jsondata}${\n} ${logpath} 221 222 223BMC FFDC Get Requests 224 [Documentation] Get the command list and iterate 225 @{entries}= Get ffdc get request index 226 :FOR ${index} IN @{entries} 227 \ Log FFDC Get Requests ${index} 228 229 230Log OS ALL DISTROS FFDC 231 [Documentation] Create file in current FFDC log directory. 232 ... Executes OS command and write to 233 ... corresponding file name. 234 [Arguments] ${key_index} 235 236 @{cmd_list}= get ffdc os all distros call ${key_index} 237 :FOR ${cmd} IN @{cmd_list} 238 \ ${logpath}= Catenate SEPARATOR= ${LOG_PREFIX} ${cmd[0]}.txt 239 \ Execute Command and Write FFDC ${cmd[0]} ${cmd[1]} ${logpath} 240 \ ... target=OS 241 242 243Log OS SPECIFIC DISTRO FFDC 244 [Documentation] Create file in current FFDC log directory. 245 ... Executes OS command and write to 246 ... corresponding file name. 247 [Arguments] ${key_index} ${linux_distro} 248 249 @{cmd_list}= get ffdc os distro call ${key_index} ${linux_distro} 250 :FOR ${cmd} IN @{cmd_list} 251 \ ${logpath}= Catenate SEPARATOR= ${LOG_PREFIX} ${cmd[0]}.txt 252 \ Execute Command and Write FFDC ${cmd[0]} ${cmd[1]} ${logpath} 253 \ ... target=OS 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 ${stdout} ${stderr} ${rc}= OS Execute Command uptime ignore_err=${1} 271 Return From Keyword If '${rc}' != '${0}' Could not connect to OS. 272 273 ${stdout} ${stderr} ${rc}= OS Execute Command 274 ... . /etc/os-release; echo $ID ignore_err=${0} 275 Set Global Variable ${linux_distro} ${stdout} 276 277 Rpvars linux_distro 278 279 @{entries}= Get ffdc os all distros index 280 :FOR ${index} IN @{entries} 281 \ Log OS ALL DISTROS FFDC ${index} 282 283 Return From Keyword If 284 ... '${linux_distro}' == '${EMPTY}' or '${linux_distro}' == 'None' 285 ... Could not determine Linux Distribution. 286 287 @{entries}= Get ffdc os distro index ${linux_distro} 288 :FOR ${index} IN @{entries} 289 \ Log OS SPECIFIC DISTRO FFDC ${index} ${linux_distro} 290 291 292############################################################################## 293SCP Coredump Files 294 [Documentation] Copy core dump file from BMC to local system. 295 296 # Check if core dump exist in the /tmp 297 ${core_files} ${stderr} ${rc}= BMC Execute Command ls /tmp/core_* 298 @{core_list} = Split String ${core_files} 299 # Copy the core files 300 Run Key U Open Connection for SCP 301 :FOR ${index} IN @{core_list} 302 \ scp.Get File ${index} ${LOG_PREFIX}${index.lstrip("/tmp/")} 303 # Remove the file from remote to avoid re-copying on next FFDC call 304 \ BMC Execute Command rm ${index} 305 # I can't find a way to do this: scp.Close Connection 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 # Skip reading attribute if entry URI is a callout. 342 # Example: /xyz/openbmc_project/logging/entry/1/callout 343 \ Continue For Loop If '${entry_path.rsplit('/', 1)[1]}' == 'callout' 344 \ ${esel_data}= Read Attribute ${entry_path} AdditionalData quiet=${1} 345 \ ${length}= Get Length ${esel_data} 346 # Skip writting to file if eSEL AdditionalData is empty 347 \ Continue For Loop If ${length} == ${0} 348 \ ${index}= Get Esel Index ${esel_data} 349 \ Write Data To File "${esel_data[${index}]}" ${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