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 8Resource list_utils.robot 9Library SSHLibrary 10Library OperatingSystem 11Library Collections 12Library String 13Library gen_print.py 14Library gen_cmd.py 15Library gen_robot_keyword.py 16Library dump_utils.py 17Library logging_utils.py 18 19*** Keywords *** 20 21# Method : Call FFDC Methods # 22# Execute the user define keywords from the FFDC List # 23# Unlike any other keywords this will call into the # 24# list of keywords defined in the FFDC list at one go # 25 26Call FFDC Methods 27 [Documentation] Call into FFDC Keyword index list. 28 [Arguments] ${ffdc_function_list}=${EMPTY} 29 30 # Description of argument(s): 31 # ffdc_function_list A colon-delimited list naming the kinds of FFDC that 32 # are to be collected 33 # (e.g. "FFDC Generic Report:BMC Specific Files"). 34 # Acceptable values can be found in the description 35 # field of FFDC_METHOD_CALL in 36 # lib/openbmc_ffdc_list.py. Those values can be 37 # obtained via a call to 'Get FFDC Method Desc' (also 38 # from lib/openbmc_ffdc_list.py). 39 40 @{entries}= Get FFDC Method Index 41 # Example entries: 42 # entries: 43 # entries[0]: BMC LOGS 44 45 @{ffdc_file_list}= Create List 46 :FOR ${index} IN @{entries} 47 \ ${ffdc_file_sub_list}= Method Call Keyword List ${index} 48 ... ${ffdc_function_list} 49 \ ${ffdc_file_list}= Smart Combine Lists ${ffdc_file_list} 50 ... ${ffdc_file_sub_list} 51 52 Run Key U SSHLibrary.Close All Connections 53 54 [Return] ${ffdc_file_list} 55 56Method Call Keyword List 57 [Documentation] Process FFDC request and return a list of generated files. 58 [Arguments] ${index} ${ffdc_function_list}=${EMPTY} 59 60 # Description of argument(s): 61 # index The index into the FFDC_METHOD_CALL dictionary (e.g. 62 # 'BMC LOGS'). 63 # ffdc_function_list See ffdc_function_list description in 64 # "Call FFDC Methods" (above). 65 66 @{method_list}= Get FFDC Method Call ${index} 67 # Example method_list: 68 # method_list: 69 # method_list[0]: 70 # method_list[0][0]: FFDC Generic Report 71 # method_list[0][1]: BMC FFDC Manifest 72 # method_list[1]: 73 # method_list[1][0]: Get Request FFDC 74 # method_list[1][1]: BMC FFDC Get Requests 75 # (etc.) 76 77 # If function list is empty assign default (i.e. a list of all allowable 78 # values). In either case, convert ffdc_function_list from a string to 79 # a list. 80 @{ffdc_function_list}= 81 ... Run Keyword If '${ffdc_function_list}' == '${EMPTY}' 82 ... Get FFDC Method Desc ${index} 83 ... ELSE 84 ... Split String ${ffdc_function_list} separator=: 85 86 @{ffdc_file_list}= Create List 87 :FOR ${method} IN @{method_list} 88 \ ${ffdc_file_sub_list}= Execute Keyword Method ${method[0]} 89 ... ${method[1]} @{ffdc_function_list} 90 \ ${ffdc_file_list}= Smart Combine Lists ${ffdc_file_list} 91 ... ${ffdc_file_sub_list} 92 93 [Return] ${ffdc_file_list} 94 95 96Execute Keyword Method 97 [Documentation] Call into BMC method keywords. Don't let one 98 ... failure skip the remaining. Get whatever data 99 ... it could gather at worse case scenario. 100 [Arguments] ${description} ${keyword_name} @{ffdc_function_list} 101 102 # Description of argument(s): 103 # description The description of the FFDC to be collected. This 104 # would be any value returned by 105 # 'Get FFDC Method Desc' (e.g. "FFDC Generic Report"). 106 # keyword_name The name of the keyword to call to collect the FFDC 107 # data (again, see FFDC_METHOD_CALL). 108 # ffdc_function_list See ffdc_function_list description in 109 # "Call FFDC Methods" (above). The only difference is 110 # in this case, it should be a list rather than a 111 # colon-delimited value. 112 113 @{ffdc_file_list}= Create List 114 115 ${index}= Get Index From List ${ffdc_function_list} ${description} 116 Run Keyword If '${index}' == '${-1}' Return from Keyword 117 ... ${ffdc_file_list} 118 119 ${status} ${ffdc_file_list}= Run Key ${keyword_name} ignore=1 120 [Return] ${ffdc_file_list} 121 122# Method : BMC FFDC Manifest # 123# Execute command on BMC and write to ffdc_report.txt # 124 125BMC FFDC Manifest 126 [Documentation] Run the ssh commands from FFDC_BMC_CMD and return a list 127 ... of generated files. 128 129 @{ffdc_file_list}= Create List ${FFDC_FILE_PATH} 130 @{entries}= Get FFDC Cmd Index 131 :FOR ${index} IN @{entries} 132 \ Iterate BMC Command List Pairs ${index} 133 134 [Return] ${ffdc_file_list} 135 136 137Iterate BMC Command List Pairs 138 [Documentation] Feed in key pair list from dictionary to execute 139 [Arguments] ${key_index} 140 141 @{cmd_list}= Get ffdc bmc cmd ${key_index} 142 Set Suite Variable ${ENTRY_INDEX} ${key_index} 143 :FOR ${cmd} IN @{cmd_list} 144 \ Execute Command and Write FFDC ${cmd[0]} ${cmd[1]} 145 146 147Execute Command and Write FFDC 148 [Documentation] Run a command on the BMC or OS, write the output to the 149 ... specified file and return a list of generated files. 150 [Arguments] ${key_index} ${cmd} ${logpath}=${FFDC_FILE_PATH} 151 ... ${target}=BMC 152 153 Run Keyword If '${logpath}' == '${FFDC_FILE_PATH}' 154 ... Write Cmd Output to FFDC File ${key_index} ${cmd} 155 156 @{ffdc_file_list}= Create List ${log_path} 157 158 ${cmd_buf}= Catenate ${target} Execute Command \ ${cmd} \ ignore_err=${1} 159 ${status} ${ret_values}= Run Key ${cmd_buf} ignore=${1} 160 161 ${stdout}= Set Variable @{ret_values}[0] 162 ${stderr}= Set Variable @{ret_values}[1] 163 164 # Write stdout on success and stderr/stdout to the file on failure. 165 Run Keyword If $stderr == '${EMPTY}' 166 ... Write Data To File ${stdout}${\n} ${logpath} 167 ... ELSE Write Data To File 168 ... ERROR output:${\n}${stderr}${\n}Output:${\n}${stdout}${\n} 169 ... ${logpath} 170 171 [Return] ${ffdc_file_list} 172 173 174# Method : BMC FFDC Files # 175# Execute command on BMC and write to individual file # 176# based on the file name pre-defined in the list # 177 178BMC FFDC Files 179 [Documentation] Run the commands from FFDC_BMC_FILE and return a list of 180 ... generated files. 181 182 @{entries}= Get FFDC File Index 183 # Example of entries: 184 # entries: 185 # entries[0]: BMC FILES 186 187 @{ffdc_file_list}= Create List 188 :FOR ${index} IN @{entries} 189 \ ${ffdc_file_sub_list}= Create File and Write Data ${index} 190 \ ${ffdc_file_list}= Smart Combine Lists ${ffdc_file_list} 191 ... ${ffdc_file_sub_list} 192 193 [Return] ${ffdc_file_list} 194 195 196Create File and Write Data 197 [Documentation] Run commands from FFDC_BMC_FILE to create FFDC files and 198 ... return a list of generated files. 199 [Arguments] ${key_index} 200 201 # Description of argument(s): 202 # key_index The index into the FFDC_BMC_FILE dictionary. 203 204 @{ffdc_file_list}= Create List 205 @{cmd_list}= Get FFDC BMC File ${key_index} 206 :FOR ${cmd} IN @{cmd_list} 207 \ ${logpath}= Catenate SEPARATOR= ${LOG_PREFIX} ${cmd[0]}.txt 208 \ ${ffdc_file_sub_list}= Execute Command and Write FFDC ${cmd[0]} 209 ... ${cmd[1]} ${logpath} 210 \ ${ffdc_file_list}= Smart Combine Lists ${ffdc_file_list} 211 ... ${ffdc_file_sub_list} 212 213 [Return] ${ffdc_file_list} 214 215 216# Method : Log Test Case Status # 217# Creates test result history footprint for reference # 218 219Log Test Case Status 220 [Documentation] Test case execution result history. 221 ... Create once and append to this file 222 ... logs/test_history.txt 223 ... Format Date:Test suite:Test case:Status 224 ... 20160909214053719992:Test Warmreset:Test WarmReset via REST:FAIL 225 226 ${FFDC_DIR_PATH_STYLE}= Get Variable Value ${FFDC_DIR_PATH_STYLE} 227 ... ${EMPTY} 228 ${FFDC_DIR_PATH}= Get Variable Value ${FFDC_DIR_PATH} ${EMPTY} 229 230 Run Keyword If '${FFDC_DIR_PATH}' == '${EMPTY}' Set FFDC Defaults 231 232 Run Keyword If '${FFDC_DIR_PATH_STYLE}' == '${1}' Run Keywords 233 ... Set Global Variable ${FFDC_LOG_PATH} ${FFDC_DIR_PATH} AND 234 ... Set Global Variable ${TEST_HISTORY} ${FFDC_DIR_PATH}test_history.txt 235 236 Create Directory ${FFDC_LOG_PATH} 237 238 ${exist}= Run Keyword and Return Status 239 ... OperatingSystem.File Should Exist ${TEST_HISTORY} 240 241 Run Keyword If '${exist}' == '${False}' 242 ... Create File ${TEST_HISTORY} 243 244 Rpvars TEST_HISTORY 245 246 ${cur_time}= Get Current Time Stamp 247 248 Append To File ${TEST_HISTORY} 249 ... ${cur_time}:${SUITE_NAME}:${TEST_NAME}:${TEST_STATUS}${\n} 250 251 252Log FFDC Get Requests 253 [Documentation] Run the get requests associated with the key and return a 254 ... list of generated files. 255 [Arguments] ${key_index} 256 257 # Note: Output will be in JSON pretty_print format. 258 259 # Description of argument(s): 260 # key_index The key to the FFDC_GET_REQUEST dictionary that contains the 261 # get requests that are to be run. 262 263 @{ffdc_file_list}= Create List 264 @{cmd_list}= Get FFDC Get Request ${key_index} 265 :FOR ${cmd} IN @{cmd_list} 266 \ ${logpath}= Catenate SEPARATOR= ${LOG_PREFIX} ${cmd[0]}.txt 267 \ ${resp}= OpenBMC Get Request ${cmd[1]} quiet=${1} 268 \ ${status}= Run Keyword and Return Status 269 ... Should Be Equal As Strings ${resp.status_code} ${HTTP_OK} 270 \ Run Keyword If '${status}' == '${False}' Continue For Loop 271 \ ${jsondata}= to json ${resp.content} pretty_print=True 272 \ Write Data To File ${\n}${jsondata}${\n} ${logpath} 273 \ Append To List ${ffdc_file_list} ${logpath} 274 275 [Return] ${ffdc_file_list} 276 277BMC FFDC Get Requests 278 [Documentation] Iterate over get request list and return a list of 279 ... generated files. 280 281 @{ffdc_file_list}= Create List 282 283 @{entries}= Get ffdc get request index 284 # Example of entries: 285 # entries: 286 # entries[0]: GET REQUESTS 287 :FOR ${index} IN @{entries} 288 \ ${ffdc_file_sub_list}= Log FFDC Get Requests ${index} 289 \ ${ffdc_file_list}= Smart Combine Lists ${ffdc_file_list} 290 ... ${ffdc_file_sub_list} 291 292 [Return] ${ffdc_file_list} 293 294Log OS All distros FFDC 295 [Documentation] Run commands from FFDC_OS_ALL_DISTROS_FILE to create FFDC 296 ... files and return a list of generated files. 297 [Arguments] ${key_index} 298 299 # Description of argument(s): 300 # key_index The index into the FFDC_OS_ALL_DISTROS_FILE dictionary. 301 302 @{ffdc_file_list}= Create List 303 304 @{cmd_list}= Get FFDC OS All Distros Call ${key_index} 305 :FOR ${cmd} IN @{cmd_list} 306 \ ${logpath}= Catenate SEPARATOR= ${LOG_PREFIX} ${cmd[0]}.txt 307 \ ${ffdc_file_sub_list}= Execute Command and Write FFDC ${cmd[0]} 308 ... ${cmd[1]} ${logpath} target=OS 309 \ ${ffdc_file_list}= Smart Combine Lists ${ffdc_file_list} 310 ... ${ffdc_file_sub_list} 311 312 [Return] ${ffdc_file_list} 313 314 315Log OS SPECIFIC DISTRO FFDC 316 [Documentation] Run commands from the FFDC_OS_<distro>_FILE to create FFDC 317 ... files and return a list of generated files. 318 [Arguments] ${key_index} ${linux_distro} 319 320 # Description of argument(s): 321 # key_index The index into the FFDC_OS_<distro>_FILE dictionary. 322 # linux_distro Your OS's linux distro (e.g. "UBUNTU", "RHEL", etc). 323 324 @{ffdc_file_list}= Create List 325 326 @{cmd_list}= Get FFDC OS Distro Call ${key_index} ${linux_distro} 327 :FOR ${cmd} IN @{cmd_list} 328 \ ${logpath}= Catenate SEPARATOR= ${LOG_PREFIX} ${cmd[0]}.txt 329 \ ${ffdc_file_sub_list}= Execute Command and Write FFDC ${cmd[0]} 330 ... ${cmd[1]} ${logpath} target=OS 331 \ ${ffdc_file_list}= Smart Combine Lists ${ffdc_file_list} 332 ... ${ffdc_file_sub_list} 333 334 [Return] ${ffdc_file_list} 335 336 337OS FFDC Files 338 [Documentation] Run the commands from FFDC_OS_ALL_DISTROS_FILE to create 339 ... FFDC files and return a list of generated files. 340 [Arguments] ${OS_HOST}=${OS_HOST} ${OS_USERNAME}=${OS_USERNAME} 341 ... ${OS_PASSWORD}=${OS_PASSWORD} 342 343 @{ffdc_file_list}= Create List 344 345 Run Keyword If '${OS_HOST}' == '${EMPTY}' Run Keywords 346 ... Print Timen No OS Host provided so no OS FFDC will be done. AND 347 ... Return From Keyword ${ffdc_file_list} 348 349 ${match_state}= Create Dictionary os_ping=^1$ os_login=^1$ 350 ... os_run_cmd=^1$ 351 ${status} ${ret_values}= Run Keyword and Ignore Error Check State 352 ... ${match_state} quiet=0 353 354 Run Keyword If '${status}' == 'FAIL' Run Keywords 355 ... Print Timen The OS is not communicating so no OS FFDC will be done.\n 356 ... AND 357 ... Return From Keyword ${ffdc_file_list} 358 359 ${stdout} ${stderr} ${rc}= OS Execute Command 360 ... . /etc/os-release; echo $ID ignore_err=${0} 361 Set Global Variable ${linux_distro} ${stdout} 362 363 Rpvars linux_distro 364 365 @{entries}= Get FFDC OS All Distros Index 366 :FOR ${index} IN @{entries} 367 \ ${ffdc_file_sub_list}= Log OS All distros FFDC ${index} 368 \ ${ffdc_file_list}= Smart Combine Lists ${ffdc_file_list} 369 ... ${ffdc_file_sub_list} 370 371 Return From Keyword If 372 ... '${linux_distro}' == '${EMPTY}' or '${linux_distro}' == 'None' 373 ... ${ffdc_file_list} 374 375 @{entries}= Get ffdc os distro index ${linux_distro} 376 :FOR ${index} IN @{entries} 377 \ ${ffdc_file_sub_list}= Log OS SPECIFIC DISTRO FFDC ${index} 378 ... ${linux_distro} 379 \ ${ffdc_file_list}= Smart Combine Lists ${ffdc_file_list} 380 ... ${ffdc_file_sub_list} 381 382 [Return] ${ffdc_file_list} 383 384 385System Inventory Files 386 [Documentation] Copy systest os_inventory files and return a list of 387 ... generated files.. 388 # The os_inventory files are the result of running 389 # systest/htx_hardbootme_test. If these files exist 390 # they are copied to the FFDC directory. 391 # Global variable ffdc_dir_path is the path name of the 392 # directory they are copied to. 393 394 @{ffdc_file_list}= Create List 395 396 ${globex}= Set Variable os_inventory_*.json 397 398 @{file_list}= OperatingSystem.List Files In Directory . ${globex} 399 400 Copy Files ${globex} ${ffdc_dir_path} 401 402 : FOR ${file_name} IN @{file_list} 403 \ Append To List ${ffdc_file_list} ${ffdc_dir_path}${file_name} 404 405 Run Keyword and Ignore Error Remove Files ${globex} 406 407 [Return] ${ffdc_file_list} 408 409 410SCP Coredump Files 411 [Documentation] Copy core dump files from BMC to local system and return a 412 ... list of generated file names. 413 414 @{ffdc_file_list}= Create List 415 416 # Check if core dump exist in the /tmp 417 ${core_files} ${stderr} ${rc}= BMC Execute Command ls /tmp/core_* 418 ... ignore_err=${1} 419 Run Keyword If '${rc}' != '${0}' Return From Keyword ${ffdc_file_list} 420 421 @{core_list}= Split String ${core_files} 422 # Copy the core files 423 Run Key U Open Connection for SCP 424 :FOR ${index} IN @{core_list} 425 \ ${ffdc_file_path}= Catenate ${LOG_PREFIX}${index.lstrip("/tmp/")} 426 \ ${status}= Run Keyword and Return Status 427 ... scp.Get File ${index} ${ffdc_file_path} 428 \ Run Keyword If '${status}' == '${False}' Continue For Loop 429 \ Append To List ${ffdc_file_list} ${ffdc_file_path} 430 # Remove the file from remote to avoid re-copying on next FFDC call 431 \ BMC Execute Command rm ${index} ignore_err=${1} 432 # I can't find a way to do this: scp.Close Connection 433 434 [Return] ${ffdc_file_list} 435 436SCP Dump Files 437 [Documentation] Copy all dump files from BMC to local system. 438 439 # Check if dumps exist 440 ${ffdc_file_list}= Scp Dumps ${FFDC_DIR_PATH} ${FFDC_PREFIX} 441 442 [Return] ${ffdc_file_list} 443 444Collect Dump Log 445 [Documentation] Collect dumps from dump entry. 446 [Arguments] ${log_prefix_path}=${LOG_PREFIX} 447 448 ${data}= Read Properties ${DUMP_ENTRY_URI}/enumerate quiet=${1} 449 450 # Grab the list of entries from dump/entry/ 451 # The data shown below is the result of the "Get Dictionary Keys". 452 # Example: 453 # /xyz/openbmc_project/dump/entry/1 454 # /xyz/openbmc_project/dump/entry/2 455 456 ${dump_list}= Get Dictionary Keys ${data} 457 458 459Collect eSEL Log 460 [Documentation] Create raw and formatted eSEL files. 461 [Arguments] ${log_prefix_path}=${LOG_PREFIX} 462 463 # NOTE: If no eSEL.pl program can be located, then no formatted eSEL file 464 # will be generated. 465 466 # Description of argument(s): 467 # log_prefix_path The path prefix to be used in creating 468 # eSEL file path names. For example, if 469 # log_prefix_path is 470 # "/tmp/user1/dummy.181001.120000.", then 471 # this keyword will create 472 # /tmp/user1/dummy.181001.120000.esel (raw) 473 # and 474 # /tmp/user1/dummy.181001.120000.esel.txt 475 # (formatted). 476 477 @{ffdc_file_list}= Create List 478 479 ${esels}= Get Esels 480 ${num_esels}= Evaluate len(${esels}) 481 Rprint Vars num_esels 482 Return From Keyword If ${num_esels} == ${0} ${ffdc_file_list} 483 484 ${logpath}= Catenate SEPARATOR= ${log_prefix_path} esel 485 Create File ${logpath} 486 487 :FOR ${esel} IN @{esels} 488 \ Write Data To File "${esel}"${\n} ${logpath} 489 490 Append To List ${ffdc_file_list} ${logpath} 491 492 ${rc} ${output}= Shell Cmd which eSEL.pl show_err=0 493 Return From Keyword If ${rc} != ${0} ${ffdc_file_list} 494 495 Convert eSEL To Elog Format ${logpath} 496 Append To List ${ffdc_file_list} ${logpath}.txt 497 498 [Return] ${ffdc_file_list} 499 500 501Convert eSEL To Elog Format 502 [Documentation] Execute parser tool on the eSEL data file to generate 503 ... formatted error log. 504 [Arguments] ${esel_file_path} 505 # Description of argument(s): 506 # esel_file_path The path to the file containg raw eSEL 507 # data (e.g. 508 # "/tmp/user1/dummy.181001.120000.esel"). 509 510 # Note: The only way to get eSEL.pl to put the output in a particular 511 # directory is to cd to that directory. 512 ${cmd_buf}= Catenate cd $(dirname ${esel_file_path}) ; eSEL.pl -l 513 ... ${esel_file_path} -p decode_obmc_data 514 Qprint Issuing ${cmd_buf} 515 Run ${cmd_buf} 516 # The .binary file, which is generated by eSEL.pl, is of no use to us. 517 Remove File ${esel_file_path}.binary 518