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