1#!/usr/bin/env python 2 3r""" 4This module is the python counterpart to obmc_boot_test. 5""" 6 7import os 8import imp 9import time 10import glob 11import random 12import re 13import cPickle as pickle 14import socket 15 16from robot.utils import DotDict 17from robot.libraries.BuiltIn import BuiltIn 18 19from boot_data import * 20import gen_print as gp 21import gen_robot_print as grp 22import gen_robot_plug_in as grpi 23import gen_robot_valid as grv 24import gen_misc as gm 25import gen_cmd as gc 26import gen_robot_keyword as grk 27import state as st 28import var_stack as vs 29 30base_path = os.path.dirname(os.path.dirname( 31 imp.find_module("gen_robot_print")[1])) +\ 32 os.sep 33sys.path.append(base_path + "extended/") 34import run_keyword as rk 35 36# Setting master_pid correctly influences the behavior of plug-ins like 37# DB_Logging 38program_pid = os.getpid() 39master_pid = os.environ.get('AUTOBOOT_MASTER_PID', program_pid) 40 41# Set up boot data structures. 42boot_table = create_boot_table() 43valid_boot_types = create_valid_boot_list(boot_table) 44 45boot_lists = read_boot_lists() 46last_ten = [] 47 48state = st.return_default_state() 49cp_setup_called = 0 50next_boot = "" 51base_tool_dir_path = os.path.normpath(os.environ.get( 52 'AUTOBOOT_BASE_TOOL_DIR_PATH', "/tmp")) + os.sep 53 54ffdc_dir_path = os.path.normpath(os.environ.get('FFDC_DIR_PATH', '')) + os.sep 55boot_success = 0 56status_dir_path = os.environ.get('STATUS_DIR_PATH', "") 57if status_dir_path != "": 58 status_dir_path = os.path.normpath(status_dir_path) + os.sep 59default_power_on = "REST Power On" 60default_power_off = "REST Power Off" 61boot_count = 0 62 63LOG_LEVEL = BuiltIn().get_variable_value("${LOG_LEVEL}") 64ffdc_prefix = "" 65boot_start_time = "" 66boot_end_time = "" 67save_stack = vs.var_stack('save_stack') 68main_func_parm_list = ['boot_stack', 'stack_mode', 'quiet'] 69 70 71############################################################################### 72def process_host(host, 73 host_var_name=""): 74 75 r""" 76 Process a host by getting the associated host name and IP address and 77 setting them in global variables. 78 79 If the caller does not pass the host_var_name, this function will try to 80 figure out the name of the variable used by the caller for the host parm. 81 Callers are advised to explicitly specify the host_var_name when calling 82 with an exec command. In such cases, the get_arg_name cannot figure out 83 the host variable name. 84 85 This function will then create similar global variable names by 86 removing "_host" and appending "_host_name" or "_ip" to the host variable 87 name. 88 89 Example: 90 91 If a call is made like this: 92 process_host(openbmc_host) 93 94 Global variables openbmc_host_name and openbmc_ip will be set. 95 96 Description of argument(s): 97 host A host name or IP. The name of the variable used should 98 have a suffix of "_host". 99 host_var_name The name of the variable being used as the host parm. 100 """ 101 102 if host_var_name == "": 103 host_var_name = gp.get_arg_name(0, 1, stack_frame_ix=2) 104 105 host_name_var_name = re.sub("host", "host_name", host_var_name) 106 ip_var_name = re.sub("host", "ip", host_var_name) 107 cmd_buf = "global " + host_name_var_name + ", " + ip_var_name + " ; " +\ 108 host_name_var_name + ", " + ip_var_name + " = gm.get_host_name_ip('" +\ 109 host + "')" 110 exec(cmd_buf) 111 112############################################################################### 113 114 115############################################################################### 116def process_pgm_parms(): 117 118 r""" 119 Process the program parameters by assigning them all to corresponding 120 globals. Also, set some global values that depend on program parameters. 121 """ 122 123 # Program parameter processing. 124 # Assign all program parms to python variables which are global to this 125 # module. 126 127 global parm_list 128 parm_list = BuiltIn().get_variable_value("${parm_list}") 129 # The following subset of parms should be processed as integers. 130 int_list = ['max_num_tests', 'boot_pass', 'boot_fail', 'ffdc_only', 131 'boot_fail_threshold', 'quiet', 'test_mode', 'debug'] 132 for parm in parm_list: 133 if parm in int_list: 134 sub_cmd = "int(BuiltIn().get_variable_value(\"${" + parm +\ 135 "}\", \"0\"))" 136 else: 137 sub_cmd = "BuiltIn().get_variable_value(\"${" + parm + "}\")" 138 cmd_buf = "global " + parm + " ; " + parm + " = " + sub_cmd 139 gp.dpissuing(cmd_buf) 140 exec(cmd_buf) 141 if re.match(r".*_host$", parm): 142 cmd_buf = "process_host(" + parm + ", '" + parm + "')" 143 exec(cmd_buf) 144 if re.match(r".*_password$", parm): 145 # Register the value of any parm whose name ends in _password. 146 # This will cause the print functions to replace passwords with 147 # asterisks in the output. 148 cmd_buf = "gp.register_passwords(" + parm + ")" 149 exec(cmd_buf) 150 151 global ffdc_dir_path_style 152 global boot_list 153 global boot_stack 154 global boot_results_file_path 155 global boot_results 156 global ffdc_list_file_path 157 global ffdc_report_list_path 158 global ffdc_summary_list_path 159 160 if ffdc_dir_path_style == "": 161 ffdc_dir_path_style = int(os.environ.get('FFDC_DIR_PATH_STYLE', '0')) 162 163 # Convert these program parms to lists for easier processing.. 164 boot_list = filter(None, boot_list.split(":")) 165 boot_stack = filter(None, boot_stack.split(":")) 166 167 boot_results_file_path = "/tmp/" + openbmc_nickname + ":pid_" +\ 168 str(master_pid) + ":boot_results" 169 170 if os.path.isfile(boot_results_file_path): 171 # We've been called before in this run so we'll load the saved 172 # boot_results object. 173 boot_results = pickle.load(open(boot_results_file_path, 'rb')) 174 else: 175 boot_results = boot_results(boot_table, boot_pass, boot_fail) 176 177 ffdc_list_file_path = base_tool_dir_path + openbmc_nickname +\ 178 "/FFDC_FILE_LIST" 179 ffdc_report_list_path = base_tool_dir_path + openbmc_nickname +\ 180 "/FFDC_REPORT_FILE_LIST" 181 182 ffdc_summary_list_path = base_tool_dir_path + openbmc_nickname +\ 183 "/FFDC_SUMMARY_FILE_LIST" 184 185############################################################################### 186 187 188############################################################################### 189def initial_plug_in_setup(): 190 191 r""" 192 Initialize all plug-in environment variables which do not change for the 193 duration of the program. 194 195 """ 196 197 global LOG_LEVEL 198 BuiltIn().set_log_level("NONE") 199 200 BuiltIn().set_global_variable("${master_pid}", master_pid) 201 BuiltIn().set_global_variable("${FFDC_DIR_PATH}", ffdc_dir_path) 202 BuiltIn().set_global_variable("${STATUS_DIR_PATH}", status_dir_path) 203 BuiltIn().set_global_variable("${BASE_TOOL_DIR_PATH}", base_tool_dir_path) 204 BuiltIn().set_global_variable("${FFDC_LIST_FILE_PATH}", 205 ffdc_list_file_path) 206 BuiltIn().set_global_variable("${FFDC_REPORT_LIST_PATH}", 207 ffdc_report_list_path) 208 BuiltIn().set_global_variable("${FFDC_SUMMARY_LIST_PATH}", 209 ffdc_summary_list_path) 210 211 BuiltIn().set_global_variable("${FFDC_DIR_PATH_STYLE}", 212 ffdc_dir_path_style) 213 BuiltIn().set_global_variable("${FFDC_CHECK}", 214 ffdc_check) 215 216 # For each program parameter, set the corresponding AUTOBOOT_ environment 217 # variable value. Also, set an AUTOBOOT_ environment variable for every 218 # element in additional_values. 219 additional_values = ["program_pid", "master_pid", "ffdc_dir_path", 220 "status_dir_path", "base_tool_dir_path", 221 "ffdc_list_file_path", "ffdc_report_list_path", 222 "ffdc_summary_list_path"] 223 224 plug_in_vars = parm_list + additional_values 225 226 for var_name in plug_in_vars: 227 var_value = BuiltIn().get_variable_value("${" + var_name + "}") 228 var_name = var_name.upper() 229 if var_value is None: 230 var_value = "" 231 os.environ["AUTOBOOT_" + var_name] = str(var_value) 232 233 BuiltIn().set_log_level(LOG_LEVEL) 234 235 # Make sure the ffdc list directory exists. 236 ffdc_list_dir_path = os.path.dirname(ffdc_list_file_path) + os.sep 237 if not os.path.exists(ffdc_list_dir_path): 238 os.makedirs(ffdc_list_dir_path) 239 240############################################################################### 241 242 243############################################################################### 244def plug_in_setup(): 245 246 r""" 247 Initialize all changing plug-in environment variables for use by the 248 plug-in programs. 249 """ 250 251 global LOG_LEVEL 252 global test_really_running 253 254 BuiltIn().set_log_level("NONE") 255 256 boot_pass, boot_fail = boot_results.return_total_pass_fail() 257 if boot_pass > 1: 258 test_really_running = 1 259 else: 260 test_really_running = 0 261 262 BuiltIn().set_global_variable("${test_really_running}", 263 test_really_running) 264 BuiltIn().set_global_variable("${boot_type_desc}", next_boot) 265 BuiltIn().set_global_variable("${boot_pass}", boot_pass) 266 BuiltIn().set_global_variable("${boot_fail}", boot_fail) 267 BuiltIn().set_global_variable("${boot_success}", boot_success) 268 BuiltIn().set_global_variable("${ffdc_prefix}", ffdc_prefix) 269 BuiltIn().set_global_variable("${boot_start_time}", boot_start_time) 270 BuiltIn().set_global_variable("${boot_end_time}", boot_end_time) 271 272 # For each program parameter, set the corresponding AUTOBOOT_ environment 273 # variable value. Also, set an AUTOBOOT_ environment variable for every 274 # element in additional_values. 275 additional_values = ["boot_type_desc", "boot_success", "boot_pass", 276 "boot_fail", "test_really_running", "ffdc_prefix", 277 "boot_start_time", "boot_end_time"] 278 279 plug_in_vars = additional_values 280 281 for var_name in plug_in_vars: 282 var_value = BuiltIn().get_variable_value("${" + var_name + "}") 283 var_name = var_name.upper() 284 if var_value is None: 285 var_value = "" 286 os.environ["AUTOBOOT_" + var_name] = str(var_value) 287 288 if debug: 289 shell_rc, out_buf = \ 290 gc.cmd_fnc_u("printenv | egrep AUTOBOOT_ | sort -u") 291 292 BuiltIn().set_log_level(LOG_LEVEL) 293 294############################################################################### 295 296 297############################################################################### 298def pre_boot_plug_in_setup(): 299 300 # Clear the ffdc_list_file_path file. Plug-ins may now write to it. 301 try: 302 os.remove(ffdc_list_file_path) 303 except OSError: 304 pass 305 306 # Clear the ffdc_report_list_path file. Plug-ins may now write to it. 307 try: 308 os.remove(ffdc_report_list_path) 309 except OSError: 310 pass 311 312 # Clear the ffdc_summary_list_path file. Plug-ins may now write to it. 313 try: 314 os.remove(ffdc_summary_list_path) 315 except OSError: 316 pass 317 318 global ffdc_prefix 319 320 seconds = time.time() 321 loc_time = time.localtime(seconds) 322 time_string = time.strftime("%y%m%d.%H%M%S.", loc_time) 323 324 ffdc_prefix = openbmc_nickname + "." + time_string 325 326############################################################################### 327 328 329############################################################################### 330def setup(): 331 332 r""" 333 Do general program setup tasks. 334 """ 335 336 global cp_setup_called 337 338 gp.qprintn() 339 340 robot_pgm_dir_path = os.path.dirname(__file__) + os.sep 341 repo_bin_path = robot_pgm_dir_path.replace("/lib/", "/bin/") 342 # If we can't find process_plug_in_packages.py, ssh_pw or 343 # validate_plug_ins.py, then we don't have our repo bin in PATH. 344 shell_rc, out_buf = gc.cmd_fnc_u("which process_plug_in_packages.py" + 345 " ssh_pw validate_plug_ins.py", quiet=1, 346 print_output=0, show_err=0) 347 if shell_rc != 0: 348 os.environ['PATH'] = repo_bin_path + ":" + os.environ.get('PATH', "") 349 # Likewise, our repo lib subdir needs to be in sys.path and PYTHONPATH. 350 if robot_pgm_dir_path not in sys.path: 351 sys.path.append(robot_pgm_dir_path) 352 PYTHONPATH = os.environ.get("PYTHONPATH", "") 353 if PYTHONPATH == "": 354 os.environ['PYTHONPATH'] = robot_pgm_dir_path 355 else: 356 os.environ['PYTHONPATH'] = robot_pgm_dir_path + ":" + PYTHONPATH 357 358 validate_parms() 359 360 grp.rqprint_pgm_header() 361 362 grk.run_key("Set BMC Power Policy RESTORE_LAST_STATE") 363 364 initial_plug_in_setup() 365 366 plug_in_setup() 367 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages( 368 call_point='setup') 369 if rc != 0: 370 error_message = "Plug-in setup failed.\n" 371 grp.rprint_error_report(error_message) 372 BuiltIn().fail(error_message) 373 # Setting cp_setup_called lets our Teardown know that it needs to call 374 # the cleanup plug-in call point. 375 cp_setup_called = 1 376 377 # Keyword "FFDC" will fail if TEST_MESSAGE is not set. 378 BuiltIn().set_global_variable("${TEST_MESSAGE}", "${EMPTY}") 379 # FFDC_LOG_PATH is used by "FFDC" keyword. 380 BuiltIn().set_global_variable("${FFDC_LOG_PATH}", ffdc_dir_path) 381 382 # Also printed by FFDC. 383 global host_name 384 global host_ip 385 host = socket.gethostname() 386 host_name, host_ip = gm.get_host_name_ip(host) 387 388 gp.dprint_var(boot_table, 1) 389 gp.dprint_var(boot_lists) 390 391############################################################################### 392 393 394############################################################################### 395def validate_parms(): 396 397 r""" 398 Validate all program parameters. 399 """ 400 401 process_pgm_parms() 402 403 gp.qprintn() 404 405 global openbmc_model 406 grv.rvalid_value("openbmc_host") 407 grv.rvalid_value("openbmc_username") 408 grv.rvalid_value("openbmc_password") 409 if os_host != "": 410 grv.rvalid_value("os_username") 411 grv.rvalid_value("os_password") 412 413 if pdu_host != "": 414 grv.rvalid_value("pdu_username") 415 grv.rvalid_value("pdu_password") 416 grv.rvalid_integer("pdu_slot_no") 417 if openbmc_serial_host != "": 418 grv.rvalid_integer("openbmc_serial_port") 419 if openbmc_model == "": 420 status, ret_values =\ 421 grk.run_key_u("Get BMC System Model") 422 openbmc_model = ret_values 423 BuiltIn().set_global_variable("${openbmc_model}", openbmc_model) 424 grv.rvalid_value("openbmc_model") 425 grv.rvalid_integer("max_num_tests") 426 grv.rvalid_integer("boot_pass") 427 grv.rvalid_integer("boot_fail") 428 429 plug_in_packages_list = grpi.rvalidate_plug_ins(plug_in_dir_paths) 430 BuiltIn().set_global_variable("${plug_in_packages_list}", 431 plug_in_packages_list) 432 433 grv.rvalid_value("stack_mode", valid_values=['normal', 'skip']) 434 if len(boot_list) == 0 and len(boot_stack) == 0 and not ffdc_only: 435 error_message = "You must provide either a value for either the" +\ 436 " boot_list or the boot_stack parm.\n" 437 BuiltIn().fail(gp.sprint_error(error_message)) 438 439 valid_boot_list(boot_list, valid_boot_types) 440 valid_boot_list(boot_stack, valid_boot_types) 441 442 selected_PDU_boots = list(set(boot_list + boot_stack) & 443 set(boot_lists['PDU_reboot'])) 444 445 if len(selected_PDU_boots) > 0 and pdu_host == "": 446 error_message = "You have selected the following boots which" +\ 447 " require a PDU host but no value for pdu_host:\n" 448 error_message += gp.sprint_var(selected_PDU_boots) 449 error_message += gp.sprint_var(pdu_host, 2) 450 BuiltIn().fail(gp.sprint_error(error_message)) 451 452 return 453 454############################################################################### 455 456 457############################################################################### 458def my_get_state(): 459 460 r""" 461 Get the system state plus a little bit of wrapping. 462 """ 463 464 global state 465 466 req_states = ['epoch_seconds'] + st.default_req_states 467 468 gp.qprint_timen("Getting system state.") 469 if test_mode: 470 state['epoch_seconds'] = int(time.time()) 471 else: 472 state = st.get_state(req_states=req_states, quiet=quiet) 473 gp.qprint_var(state) 474 475############################################################################### 476 477 478############################################################################### 479def select_boot(): 480 481 r""" 482 Select a boot test to be run based on our current state and return the 483 chosen boot type. 484 485 Description of arguments: 486 state The state of the machine. 487 """ 488 489 global boot_stack 490 491 gp.qprint_timen("Selecting a boot test.") 492 493 my_get_state() 494 495 stack_popped = 0 496 if len(boot_stack) > 0: 497 stack_popped = 1 498 gp.qprint_dashes() 499 gp.qprint_var(boot_stack) 500 gp.qprint_dashes() 501 skip_boot_printed = 0 502 while len(boot_stack) > 0: 503 boot_candidate = boot_stack.pop() 504 if stack_mode == 'normal': 505 break 506 else: 507 if st.compare_states(state, boot_table[boot_candidate]['end']): 508 if not skip_boot_printed: 509 gp.qprint_var(stack_mode) 510 gp.qprintn() 511 gp.qprint_timen("Skipping the following boot tests" + 512 " which are unnecessary since their" + 513 " required end states match the" + 514 " current machine state:") 515 skip_boot_printed = 1 516 gp.qprint_var(boot_candidate) 517 boot_candidate = "" 518 if boot_candidate == "": 519 gp.qprint_dashes() 520 gp.qprint_var(boot_stack) 521 gp.qprint_dashes() 522 return boot_candidate 523 if st.compare_states(state, boot_table[boot_candidate]['start']): 524 gp.qprint_timen("The machine state is valid for a '" + 525 boot_candidate + "' boot test.") 526 gp.qprint_dashes() 527 gp.qprint_var(boot_stack) 528 gp.qprint_dashes() 529 return boot_candidate 530 else: 531 gp.qprint_timen("The machine state does not match the required" + 532 " starting state for a '" + boot_candidate + 533 "' boot test:") 534 gp.qprint_varx("boot_table[" + boot_candidate + "][start]", 535 boot_table[boot_candidate]['start'], 1) 536 boot_stack.append(boot_candidate) 537 popped_boot = boot_candidate 538 539 # Loop through your list selecting a boot_candidates 540 boot_candidates = [] 541 for boot_candidate in boot_list: 542 if st.compare_states(state, boot_table[boot_candidate]['start']): 543 if stack_popped: 544 if st.compare_states(boot_table[boot_candidate]['end'], 545 boot_table[popped_boot]['start']): 546 boot_candidates.append(boot_candidate) 547 else: 548 boot_candidates.append(boot_candidate) 549 550 if len(boot_candidates) == 0: 551 gp.qprint_timen("The user's boot list contained no boot tests" + 552 " which are valid for the current machine state.") 553 boot_candidate = default_power_on 554 if not st.compare_states(state, boot_table[default_power_on]['start']): 555 boot_candidate = default_power_off 556 boot_candidates.append(boot_candidate) 557 gp.qprint_timen("Using default '" + boot_candidate + 558 "' boot type to transition to valid state.") 559 560 gp.dprint_var(boot_candidates) 561 562 # Randomly select a boot from the candidate list. 563 boot = random.choice(boot_candidates) 564 565 return boot 566 567############################################################################### 568 569 570############################################################################### 571def print_last_boots(): 572 573 r""" 574 Print the last ten boots done with their time stamps. 575 """ 576 577 # indent 0, 90 chars wide, linefeed, char is "=" 578 gp.qprint_dashes(0, 90) 579 gp.qprintn("Last 10 boots:\n") 580 581 for boot_entry in last_ten: 582 grp.rqprint(boot_entry) 583 gp.qprint_dashes(0, 90) 584 585############################################################################### 586 587 588############################################################################### 589def print_defect_report(): 590 591 r""" 592 Print a defect report. 593 """ 594 595 # Making deliberate choice to NOT run plug_in_setup(). We don't want 596 # ffdc_prefix updated. 597 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages( 598 call_point='ffdc_report', stop_on_plug_in_failure=0) 599 600 # At some point I'd like to have the 'Call FFDC Methods' return a list 601 # of files it has collected. In that case, the following "ls" command 602 # would no longer be needed. For now, however, glob shows the files 603 # named in FFDC_LIST_FILE_PATH so I will refrain from printing those 604 # out (so we don't see duplicates in the list). 605 606 # Get additional header data which may have been created by ffdc plug-ins. 607 # Also, delete the individual header files to cleanup. 608 cmd_buf = "file_list=$(cat " + ffdc_report_list_path + " 2>/dev/null)" +\ 609 " ; [ ! -z \"${file_list}\" ] && cat ${file_list}" +\ 610 " 2>/dev/null ; rm -rf ${file_list} 2>/dev/null || :" 611 shell_rc, more_header_info = gc.cmd_fnc_u(cmd_buf, print_output=0, 612 show_err=0) 613 614 # Get additional header data which may have been created by ffdc plug-ins. 615 # Also, delete the individual header files to cleanup. 616 cmd_buf = "file_list=$(cat " + ffdc_summary_list_path + " 2>/dev/null)" +\ 617 " ; [ ! -z \"${file_list}\" ] && cat ${file_list}" +\ 618 " 2>/dev/null ; rm -rf ${file_list} 2>/dev/null || :" 619 shell_rc, ffdc_summary_info = gc.cmd_fnc_u(cmd_buf, print_output=0, 620 show_err=0) 621 622 LOG_PREFIX = BuiltIn().get_variable_value("${LOG_PREFIX}") 623 624 output = '\n'.join(sorted(glob.glob(LOG_PREFIX + '*'))) 625 try: 626 ffdc_list = open(ffdc_list_file_path, 'r') 627 except IOError: 628 ffdc_list = "" 629 630 # Open ffdc_file_list for writing. We will write a complete list of 631 # FFDC files to it for possible use by plug-ins like cp_stop_check. 632 ffdc_list_file = open(ffdc_list_file_path, 'w') 633 634 gp.qprintn() 635 # indent=0, width=90, linefeed=1, char="=" 636 gp.qprint_dashes(0, 90, 1, "=") 637 gp.qprintn("Copy this data to the defect:\n") 638 639 if len(more_header_info) > 0: 640 gp.qprintn(more_header_info) 641 gp.qpvars(host_name, host_ip, openbmc_nickname, openbmc_host, 642 openbmc_host_name, openbmc_ip, openbmc_username, 643 openbmc_password, os_host, os_host_name, os_ip, os_username, 644 os_password, pdu_host, pdu_host_name, pdu_ip, pdu_username, 645 pdu_password, pdu_slot_no, openbmc_serial_host, 646 openbmc_serial_host_name, openbmc_serial_ip, openbmc_serial_port) 647 648 gp.qprintn() 649 650 print_last_boots() 651 gp.qprintn() 652 gp.qprint_var(state) 653 654 gp.qprintn() 655 gp.qprintn("FFDC data files:") 656 if status_file_path != "": 657 gp.qprintn(status_file_path) 658 ffdc_list_file.write(status_file_path + "\n") 659 660 gp.qprintn(output) 661 # gp.qprintn(ffdc_list) 662 gp.qprintn() 663 664 if len(ffdc_summary_info) > 0: 665 gp.qprintn(ffdc_summary_info) 666 667 gp.qprint_dashes(0, 90, 1, "=") 668 669 ffdc_list_file.write(output + "\n") 670 ffdc_list_file.close() 671 672############################################################################### 673 674 675############################################################################### 676def my_ffdc(): 677 678 r""" 679 Collect FFDC data. 680 """ 681 682 global state 683 684 plug_in_setup() 685 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages( 686 call_point='ffdc', stop_on_plug_in_failure=0) 687 688 AUTOBOOT_FFDC_PREFIX = os.environ['AUTOBOOT_FFDC_PREFIX'] 689 status, ret_values = grk.run_key_u("FFDC ffdc_prefix=" + 690 AUTOBOOT_FFDC_PREFIX + 691 " ffdc_function_list=" + 692 ffdc_function_list, ignore=1) 693 if status != 'PASS': 694 gp.qprint_error("Call to ffdc failed.\n") 695 696 my_get_state() 697 698 print_defect_report() 699 700############################################################################### 701 702 703############################################################################### 704def print_test_start_message(boot_keyword): 705 706 r""" 707 Print a message indicating what boot test is about to run. 708 709 Description of arguments: 710 boot_keyword The name of the boot which is to be run 711 (e.g. "BMC Power On"). 712 """ 713 714 global last_ten 715 global boot_start_time 716 717 doing_msg = gp.sprint_timen("Doing \"" + boot_keyword + "\".") 718 719 # Set boot_start_time for use by plug-ins. 720 boot_start_time = doing_msg[1:33] 721 gp.qprint_var(boot_start_time) 722 723 gp.qprint(doing_msg) 724 725 last_ten.append(doing_msg) 726 727 if len(last_ten) > 10: 728 del last_ten[0] 729 730############################################################################### 731 732 733############################################################################### 734def run_boot(boot): 735 736 r""" 737 Run the specified boot. 738 739 Description of arguments: 740 boot The name of the boot test to be performed. 741 """ 742 743 global state 744 745 print_test_start_message(boot) 746 747 plug_in_setup() 748 rc, shell_rc, failed_plug_in_name = \ 749 grpi.rprocess_plug_in_packages(call_point="pre_boot") 750 if rc != 0: 751 error_message = "Plug-in failed with non-zero return code.\n" +\ 752 gp.sprint_var(rc, 1) 753 BuiltIn().fail(gp.sprint_error(error_message)) 754 755 if test_mode: 756 # In test mode, we'll pretend the boot worked by assigning its 757 # required end state to the default state value. 758 state = st.strip_anchor_state(boot_table[boot]['end']) 759 else: 760 # Assertion: We trust that the state data was made fresh by the 761 # caller. 762 763 gp.qprintn() 764 765 if boot_table[boot]['method_type'] == "keyword": 766 rk.my_run_keywords(boot_table[boot].get('lib_file_path', ''), 767 boot_table[boot]['method'], 768 quiet=quiet) 769 770 if boot_table[boot]['bmc_reboot']: 771 st.wait_for_comm_cycle(int(state['epoch_seconds'])) 772 plug_in_setup() 773 rc, shell_rc, failed_plug_in_name = \ 774 grpi.rprocess_plug_in_packages(call_point="post_reboot") 775 if rc != 0: 776 error_message = "Plug-in failed with non-zero return code.\n" 777 error_message += gp.sprint_var(rc, 1) 778 BuiltIn().fail(gp.sprint_error(error_message)) 779 else: 780 match_state = st.anchor_state(state) 781 del match_state['epoch_seconds'] 782 # Wait for the state to change in any way. 783 st.wait_state(match_state, wait_time=state_change_timeout, 784 interval="10 seconds", invert=1) 785 786 gp.qprintn() 787 if boot_table[boot]['end']['chassis'] == "Off": 788 boot_timeout = power_off_timeout 789 else: 790 boot_timeout = power_on_timeout 791 st.wait_state(boot_table[boot]['end'], wait_time=boot_timeout, 792 interval="10 seconds") 793 794 plug_in_setup() 795 rc, shell_rc, failed_plug_in_name = \ 796 grpi.rprocess_plug_in_packages(call_point="post_boot") 797 if rc != 0: 798 error_message = "Plug-in failed with non-zero return code.\n" +\ 799 gp.sprint_var(rc, 1) 800 BuiltIn().fail(gp.sprint_error(error_message)) 801 802############################################################################### 803 804 805############################################################################### 806def test_loop_body(): 807 808 r""" 809 The main loop body for the loop in main_py. 810 811 Description of arguments: 812 boot_count The iteration number (starts at 1). 813 """ 814 815 global boot_count 816 global state 817 global next_boot 818 global boot_success 819 global boot_end_time 820 821 gp.qprintn() 822 823 next_boot = select_boot() 824 if next_boot == "": 825 return True 826 827 boot_count += 1 828 gp.qprint_timen("Starting boot " + str(boot_count) + ".") 829 830 pre_boot_plug_in_setup() 831 832 cmd_buf = ["run_boot", next_boot] 833 boot_status, msg = BuiltIn().run_keyword_and_ignore_error(*cmd_buf) 834 if boot_status == "FAIL": 835 gp.qprint(msg) 836 837 gp.qprintn() 838 if boot_status == "PASS": 839 boot_success = 1 840 completion_msg = gp.sprint_timen("BOOT_SUCCESS: \"" + next_boot + 841 "\" succeeded.") 842 else: 843 boot_success = 0 844 completion_msg = gp.sprint_timen("BOOT_FAILED: \"" + next_boot + 845 "\" failed.") 846 847 # Set boot_end_time for use by plug-ins. 848 boot_end_time = completion_msg[1:33] 849 gp.qprint_var(boot_end_time) 850 851 gp.qprint(completion_msg) 852 853 boot_results.update(next_boot, boot_status) 854 855 plug_in_setup() 856 # NOTE: A post_test_case call point failure is NOT counted as a boot 857 # failure. 858 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages( 859 call_point='post_test_case', stop_on_plug_in_failure=0) 860 861 plug_in_setup() 862 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages( 863 call_point='ffdc_check', shell_rc=0x00000200, 864 stop_on_plug_in_failure=1, stop_on_non_zero_rc=1) 865 if boot_status != "PASS" or ffdc_check == "All" or shell_rc == 0x00000200: 866 status, ret_values = grk.run_key_u("my_ffdc", ignore=1) 867 if status != 'PASS': 868 gp.qprint_error("Call to my_ffdc failed.\n") 869 870 # We need to purge error logs between boots or they build up. 871 grk.run_key("Delete Error logs", ignore=1) 872 873 boot_results.print_report() 874 gp.qprint_timen("Finished boot " + str(boot_count) + ".") 875 876 plug_in_setup() 877 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages( 878 call_point='stop_check') 879 if rc != 0: 880 error_message = "Stopping as requested by user.\n" 881 grp.rprint_error_report(error_message) 882 BuiltIn().fail(error_message) 883 884 # This should help prevent ConnectionErrors. 885 grk.run_key_u("Close All Connections") 886 887 return True 888 889############################################################################### 890 891 892############################################################################### 893def obmc_boot_test_teardown(): 894 895 r""" 896 Clean up after the Main keyword. 897 """ 898 899 if cp_setup_called: 900 plug_in_setup() 901 rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages( 902 call_point='cleanup', stop_on_plug_in_failure=0) 903 904 if 'boot_results_file_path' in globals(): 905 # Save boot_results object to a file in case it is needed again. 906 gp.qprint_timen("Saving boot_results to the following path.") 907 gp.qprint_var(boot_results_file_path) 908 pickle.dump(boot_results, open(boot_results_file_path, 'wb'), 909 pickle.HIGHEST_PROTOCOL) 910 911 global save_stack 912 # Restore any global values saved on the save_stack. 913 for parm_name in main_func_parm_list: 914 # Get the parm_value if it was saved on the stack. 915 try: 916 parm_value = save_stack.pop(parm_name) 917 except: 918 # If it was not saved, no further action is required. 919 continue 920 921 # Restore the saved value. 922 cmd_buf = "BuiltIn().set_global_variable(\"${" + parm_name +\ 923 "}\", parm_value)" 924 gp.dpissuing(cmd_buf) 925 exec(cmd_buf) 926 927 gp.dprintn(save_stack.sprint_obj()) 928 929############################################################################### 930 931 932############################################################################### 933def test_teardown(): 934 935 r""" 936 Clean up after this test case. 937 """ 938 939 gp.qprintn() 940 cmd_buf = ["Print Error", 941 "A keyword timeout occurred ending this program.\n"] 942 BuiltIn().run_keyword_if_timeout_occurred(*cmd_buf) 943 944 grp.rqprint_pgm_footer() 945 946############################################################################### 947 948 949############################################################################### 950def obmc_boot_test_py(loc_boot_stack=None, 951 loc_stack_mode=None, 952 loc_quiet=None): 953 954 r""" 955 Do main program processing. 956 """ 957 958 global save_stack 959 960 # Process function parms. 961 for parm_name in main_func_parm_list: 962 # Get parm's value. 963 cmd_buf = "parm_value = loc_" + parm_name 964 exec(cmd_buf) 965 gp.dpvar(parm_name) 966 gp.dpvar(parm_value) 967 968 if parm_value is None: 969 # Parm was not specified by the calling function so set it to its 970 # corresponding global value. 971 cmd_buf = "loc_" + parm_name + " = BuiltIn().get_variable_value" +\ 972 "(\"${" + parm_name + "}\")" 973 gp.dpissuing(cmd_buf) 974 exec(cmd_buf) 975 else: 976 # Save the global value on a stack. 977 cmd_buf = "save_stack.push(BuiltIn().get_variable_value(\"${" +\ 978 parm_name + "}\"), \"" + parm_name + "\")" 979 gp.dpissuing(cmd_buf) 980 exec(cmd_buf) 981 982 # Set the global value to the passed value. 983 cmd_buf = "BuiltIn().set_global_variable(\"${" + parm_name +\ 984 "}\", loc_" + parm_name + ")" 985 gp.dpissuing(cmd_buf) 986 exec(cmd_buf) 987 988 gp.dprintn(save_stack.sprint_obj()) 989 990 setup() 991 992 if ffdc_only: 993 gp.qprint_timen("Caller requested ffdc_only.") 994 pre_boot_plug_in_setup() 995 grk.run_key_u("my_ffdc") 996 return 997 998 # Process caller's boot_stack. 999 while (len(boot_stack) > 0): 1000 test_loop_body() 1001 1002 gp.qprint_timen("Finished processing stack.") 1003 1004 # Process caller's boot_list. 1005 if len(boot_list) > 0: 1006 for ix in range(1, max_num_tests + 1): 1007 test_loop_body() 1008 1009 gp.qprint_timen("Completed all requested boot tests.") 1010 1011 boot_pass, boot_fail = boot_results.return_total_pass_fail() 1012 if boot_fail > boot_fail_threshold: 1013 error_message = "Boot failures exceed the boot failure" +\ 1014 " threshold:\n" +\ 1015 gp.sprint_var(boot_fail) +\ 1016 gp.sprint_var(boot_fail_threshold) 1017 BuiltIn().fail(gp.sprint_error(error_message)) 1018 1019############################################################################### 1020