10bbd860fSMichael Walsh#!/usr/bin/env python 20bbd860fSMichael Walsh 30bbd860fSMichael Walshr""" 40bbd860fSMichael WalshThis module is the python counterpart to obmc_boot_test. 50bbd860fSMichael Walsh""" 60bbd860fSMichael Walsh 70b93fbf8SMichael Walshimport os 80b93fbf8SMichael Walshimport imp 90b93fbf8SMichael Walshimport time 100b93fbf8SMichael Walshimport glob 110b93fbf8SMichael Walshimport random 120ad0f7f8SMichael Walshimport re 130b93fbf8SMichael Walshimport cPickle as pickle 14dc80d67dSMichael Walshimport socket 150b93fbf8SMichael Walsh 160b93fbf8SMichael Walshfrom robot.utils import DotDict 170b93fbf8SMichael Walshfrom robot.libraries.BuiltIn import BuiltIn 180b93fbf8SMichael Walsh 196741f740SMichael Walshfrom boot_data import * 20c9116811SMichael Walshimport gen_print as gp 210bbd860fSMichael Walshimport gen_robot_print as grp 2255302295SMichael Walshimport gen_robot_plug_in as grpi 236741f740SMichael Walshimport gen_robot_valid as grv 246741f740SMichael Walshimport gen_misc as gm 256741f740SMichael Walshimport gen_cmd as gc 26b5839d00SMichael Walshimport gen_robot_keyword as grk 2755302295SMichael Walshimport state as st 28ff340006SMichael Walshimport var_stack as vs 290bbd860fSMichael Walsh 300b93fbf8SMichael Walshbase_path = os.path.dirname(os.path.dirname( 310b93fbf8SMichael Walsh imp.find_module("gen_robot_print")[1])) +\ 320b93fbf8SMichael Walsh os.sep 330b93fbf8SMichael Walshsys.path.append(base_path + "extended/") 340b93fbf8SMichael Walshimport run_keyword as rk 350bbd860fSMichael Walsh 36e1e26448SMichael Walsh# Setting master_pid correctly influences the behavior of plug-ins like 37e1e26448SMichael Walsh# DB_Logging 38e1e26448SMichael Walshprogram_pid = os.getpid() 39e1e26448SMichael Walshmaster_pid = os.environ.get('AUTOBOOT_MASTER_PID', program_pid) 40903e0b20SMichael Walshpgm_name = re.sub('\.py$', '', os.path.basename(__file__)) 41e1e26448SMichael Walsh 42b5839d00SMichael Walsh# Set up boot data structures. 43b5839d00SMichael Walshboot_table = create_boot_table() 44b5839d00SMichael Walshvalid_boot_types = create_valid_boot_list(boot_table) 450b93fbf8SMichael Walsh 466741f740SMichael Walshboot_lists = read_boot_lists() 476741f740SMichael Walshlast_ten = [] 486741f740SMichael Walsh 497dc885b6SMichael Walshstate = st.return_state_constant('default_state') 506741f740SMichael Walshcp_setup_called = 0 516741f740SMichael Walshnext_boot = "" 526741f740SMichael Walshbase_tool_dir_path = os.path.normpath(os.environ.get( 536741f740SMichael Walsh 'AUTOBOOT_BASE_TOOL_DIR_PATH', "/tmp")) + os.sep 54b5839d00SMichael Walsh 556741f740SMichael Walshffdc_dir_path = os.path.normpath(os.environ.get('FFDC_DIR_PATH', '')) + os.sep 566741f740SMichael Walshboot_success = 0 576741f740SMichael Walshstatus_dir_path = os.environ.get('STATUS_DIR_PATH', "") 586741f740SMichael Walshif status_dir_path != "": 596741f740SMichael Walsh status_dir_path = os.path.normpath(status_dir_path) + os.sep 600b93fbf8SMichael Walshdefault_power_on = "REST Power On" 610b93fbf8SMichael Walshdefault_power_off = "REST Power Off" 626741f740SMichael Walshboot_count = 0 630bbd860fSMichael Walsh 6485678948SMichael WalshLOG_LEVEL = BuiltIn().get_variable_value("${LOG_LEVEL}") 65e1974b96SMichael Walshffdc_prefix = "" 66325eb548SSunil Mboot_start_time = "" 67325eb548SSunil Mboot_end_time = "" 68ff340006SMichael Walshsave_stack = vs.var_stack('save_stack') 69ff340006SMichael Walshmain_func_parm_list = ['boot_stack', 'stack_mode', 'quiet'] 7085678948SMichael Walsh 7185678948SMichael Walsh 720ad0f7f8SMichael Walshdef process_host(host, 730ad0f7f8SMichael Walsh host_var_name=""): 740ad0f7f8SMichael Walsh r""" 750ad0f7f8SMichael Walsh Process a host by getting the associated host name and IP address and 760ad0f7f8SMichael Walsh setting them in global variables. 770ad0f7f8SMichael Walsh 780ad0f7f8SMichael Walsh If the caller does not pass the host_var_name, this function will try to 790ad0f7f8SMichael Walsh figure out the name of the variable used by the caller for the host parm. 800ad0f7f8SMichael Walsh Callers are advised to explicitly specify the host_var_name when calling 810ad0f7f8SMichael Walsh with an exec command. In such cases, the get_arg_name cannot figure out 820ad0f7f8SMichael Walsh the host variable name. 830ad0f7f8SMichael Walsh 840ad0f7f8SMichael Walsh This function will then create similar global variable names by 850ad0f7f8SMichael Walsh removing "_host" and appending "_host_name" or "_ip" to the host variable 860ad0f7f8SMichael Walsh name. 870ad0f7f8SMichael Walsh 880ad0f7f8SMichael Walsh Example: 890ad0f7f8SMichael Walsh 900ad0f7f8SMichael Walsh If a call is made like this: 910ad0f7f8SMichael Walsh process_host(openbmc_host) 920ad0f7f8SMichael Walsh 930ad0f7f8SMichael Walsh Global variables openbmc_host_name and openbmc_ip will be set. 940ad0f7f8SMichael Walsh 950ad0f7f8SMichael Walsh Description of argument(s): 960ad0f7f8SMichael Walsh host A host name or IP. The name of the variable used should 970ad0f7f8SMichael Walsh have a suffix of "_host". 980ad0f7f8SMichael Walsh host_var_name The name of the variable being used as the host parm. 990ad0f7f8SMichael Walsh """ 1000ad0f7f8SMichael Walsh 1010ad0f7f8SMichael Walsh if host_var_name == "": 1020ad0f7f8SMichael Walsh host_var_name = gp.get_arg_name(0, 1, stack_frame_ix=2) 1030ad0f7f8SMichael Walsh 1040ad0f7f8SMichael Walsh host_name_var_name = re.sub("host", "host_name", host_var_name) 1050ad0f7f8SMichael Walsh ip_var_name = re.sub("host", "ip", host_var_name) 1060ad0f7f8SMichael Walsh cmd_buf = "global " + host_name_var_name + ", " + ip_var_name + " ; " +\ 1070ad0f7f8SMichael Walsh host_name_var_name + ", " + ip_var_name + " = gm.get_host_name_ip('" +\ 1080ad0f7f8SMichael Walsh host + "')" 1090ad0f7f8SMichael Walsh exec(cmd_buf) 1100ad0f7f8SMichael Walsh 1110ad0f7f8SMichael Walsh 112b5839d00SMichael Walshdef process_pgm_parms(): 113b5839d00SMichael Walsh r""" 114b5839d00SMichael Walsh Process the program parameters by assigning them all to corresponding 115b5839d00SMichael Walsh globals. Also, set some global values that depend on program parameters. 116b5839d00SMichael Walsh """ 117b5839d00SMichael Walsh 118b5839d00SMichael Walsh # Program parameter processing. 119b5839d00SMichael Walsh # Assign all program parms to python variables which are global to this 120b5839d00SMichael Walsh # module. 121b5839d00SMichael Walsh 122b5839d00SMichael Walsh global parm_list 123b5839d00SMichael Walsh parm_list = BuiltIn().get_variable_value("${parm_list}") 124b5839d00SMichael Walsh # The following subset of parms should be processed as integers. 125b5839d00SMichael Walsh int_list = ['max_num_tests', 'boot_pass', 'boot_fail', 'ffdc_only', 126aabef1e3SMichael Walsh 'boot_fail_threshold', 'delete_errlogs', 'quiet', 'test_mode', 127aabef1e3SMichael Walsh 'debug'] 128b5839d00SMichael Walsh for parm in parm_list: 129b5839d00SMichael Walsh if parm in int_list: 130b5839d00SMichael Walsh sub_cmd = "int(BuiltIn().get_variable_value(\"${" + parm +\ 131b5839d00SMichael Walsh "}\", \"0\"))" 132b5839d00SMichael Walsh else: 133b5839d00SMichael Walsh sub_cmd = "BuiltIn().get_variable_value(\"${" + parm + "}\")" 134b5839d00SMichael Walsh cmd_buf = "global " + parm + " ; " + parm + " = " + sub_cmd 135ff340006SMichael Walsh gp.dpissuing(cmd_buf) 136b5839d00SMichael Walsh exec(cmd_buf) 1370ad0f7f8SMichael Walsh if re.match(r".*_host$", parm): 1380ad0f7f8SMichael Walsh cmd_buf = "process_host(" + parm + ", '" + parm + "')" 1390ad0f7f8SMichael Walsh exec(cmd_buf) 1400ad0f7f8SMichael Walsh if re.match(r".*_password$", parm): 1410ad0f7f8SMichael Walsh # Register the value of any parm whose name ends in _password. 1420ad0f7f8SMichael Walsh # This will cause the print functions to replace passwords with 1430ad0f7f8SMichael Walsh # asterisks in the output. 1440ad0f7f8SMichael Walsh cmd_buf = "gp.register_passwords(" + parm + ")" 1450ad0f7f8SMichael Walsh exec(cmd_buf) 146b5839d00SMichael Walsh 147b5839d00SMichael Walsh global ffdc_dir_path_style 148b5839d00SMichael Walsh global boot_list 149b5839d00SMichael Walsh global boot_stack 150b5839d00SMichael Walsh global boot_results_file_path 151b5839d00SMichael Walsh global boot_results 152b5839d00SMichael Walsh global ffdc_list_file_path 153e0cf8d70SMichael Walsh global ffdc_report_list_path 154600876daSMichael Walsh global ffdc_summary_list_path 155b5839d00SMichael Walsh 156b5839d00SMichael Walsh if ffdc_dir_path_style == "": 157b5839d00SMichael Walsh ffdc_dir_path_style = int(os.environ.get('FFDC_DIR_PATH_STYLE', '0')) 158b5839d00SMichael Walsh 159b5839d00SMichael Walsh # Convert these program parms to lists for easier processing.. 160b5839d00SMichael Walsh boot_list = filter(None, boot_list.split(":")) 161b5839d00SMichael Walsh boot_stack = filter(None, boot_stack.split(":")) 162b5839d00SMichael Walsh 163903e0b20SMichael Walsh cleanup_boot_results_file() 164903e0b20SMichael Walsh boot_results_file_path = create_boot_results_file_path(pgm_name, 165903e0b20SMichael Walsh openbmc_nickname, 166903e0b20SMichael Walsh master_pid) 167b5839d00SMichael Walsh 168b5839d00SMichael Walsh if os.path.isfile(boot_results_file_path): 169b5839d00SMichael Walsh # We've been called before in this run so we'll load the saved 170b5839d00SMichael Walsh # boot_results object. 171b5839d00SMichael Walsh boot_results = pickle.load(open(boot_results_file_path, 'rb')) 172b5839d00SMichael Walsh else: 173b5839d00SMichael Walsh boot_results = boot_results(boot_table, boot_pass, boot_fail) 174b5839d00SMichael Walsh 175b5839d00SMichael Walsh ffdc_list_file_path = base_tool_dir_path + openbmc_nickname +\ 176b5839d00SMichael Walsh "/FFDC_FILE_LIST" 177e0cf8d70SMichael Walsh ffdc_report_list_path = base_tool_dir_path + openbmc_nickname +\ 178e0cf8d70SMichael Walsh "/FFDC_REPORT_FILE_LIST" 179b5839d00SMichael Walsh 180600876daSMichael Walsh ffdc_summary_list_path = base_tool_dir_path + openbmc_nickname +\ 181600876daSMichael Walsh "/FFDC_SUMMARY_FILE_LIST" 182600876daSMichael Walsh 183b5839d00SMichael Walsh 18485678948SMichael Walshdef initial_plug_in_setup(): 18585678948SMichael Walsh r""" 18685678948SMichael Walsh Initialize all plug-in environment variables which do not change for the 18785678948SMichael Walsh duration of the program. 18885678948SMichael Walsh 18985678948SMichael Walsh """ 19085678948SMichael Walsh 19185678948SMichael Walsh global LOG_LEVEL 19285678948SMichael Walsh BuiltIn().set_log_level("NONE") 19385678948SMichael Walsh 19485678948SMichael Walsh BuiltIn().set_global_variable("${master_pid}", master_pid) 19585678948SMichael Walsh BuiltIn().set_global_variable("${FFDC_DIR_PATH}", ffdc_dir_path) 19685678948SMichael Walsh BuiltIn().set_global_variable("${STATUS_DIR_PATH}", status_dir_path) 19785678948SMichael Walsh BuiltIn().set_global_variable("${BASE_TOOL_DIR_PATH}", base_tool_dir_path) 19885678948SMichael Walsh BuiltIn().set_global_variable("${FFDC_LIST_FILE_PATH}", 19985678948SMichael Walsh ffdc_list_file_path) 200e0cf8d70SMichael Walsh BuiltIn().set_global_variable("${FFDC_REPORT_LIST_PATH}", 201e0cf8d70SMichael Walsh ffdc_report_list_path) 202600876daSMichael Walsh BuiltIn().set_global_variable("${FFDC_SUMMARY_LIST_PATH}", 203600876daSMichael Walsh ffdc_summary_list_path) 20485678948SMichael Walsh 20585678948SMichael Walsh BuiltIn().set_global_variable("${FFDC_DIR_PATH_STYLE}", 20685678948SMichael Walsh ffdc_dir_path_style) 20785678948SMichael Walsh BuiltIn().set_global_variable("${FFDC_CHECK}", 20885678948SMichael Walsh ffdc_check) 20985678948SMichael Walsh 21085678948SMichael Walsh # For each program parameter, set the corresponding AUTOBOOT_ environment 21185678948SMichael Walsh # variable value. Also, set an AUTOBOOT_ environment variable for every 21285678948SMichael Walsh # element in additional_values. 21385678948SMichael Walsh additional_values = ["program_pid", "master_pid", "ffdc_dir_path", 21485678948SMichael Walsh "status_dir_path", "base_tool_dir_path", 215600876daSMichael Walsh "ffdc_list_file_path", "ffdc_report_list_path", 216600876daSMichael Walsh "ffdc_summary_list_path"] 21785678948SMichael Walsh 21885678948SMichael Walsh plug_in_vars = parm_list + additional_values 21985678948SMichael Walsh 22085678948SMichael Walsh for var_name in plug_in_vars: 22185678948SMichael Walsh var_value = BuiltIn().get_variable_value("${" + var_name + "}") 22285678948SMichael Walsh var_name = var_name.upper() 22385678948SMichael Walsh if var_value is None: 22485678948SMichael Walsh var_value = "" 22585678948SMichael Walsh os.environ["AUTOBOOT_" + var_name] = str(var_value) 22685678948SMichael Walsh 22785678948SMichael Walsh BuiltIn().set_log_level(LOG_LEVEL) 22885678948SMichael Walsh 22968a61162SMichael Walsh # Make sure the ffdc list directory exists. 23068a61162SMichael Walsh ffdc_list_dir_path = os.path.dirname(ffdc_list_file_path) + os.sep 23168a61162SMichael Walsh if not os.path.exists(ffdc_list_dir_path): 23268a61162SMichael Walsh os.makedirs(ffdc_list_dir_path) 23385678948SMichael Walsh 23485678948SMichael Walsh 2350bbd860fSMichael Walshdef plug_in_setup(): 2360bbd860fSMichael Walsh r""" 23785678948SMichael Walsh Initialize all changing plug-in environment variables for use by the 23885678948SMichael Walsh plug-in programs. 2390bbd860fSMichael Walsh """ 2400bbd860fSMichael Walsh 24185678948SMichael Walsh global LOG_LEVEL 24285678948SMichael Walsh global test_really_running 24385678948SMichael Walsh 24485678948SMichael Walsh BuiltIn().set_log_level("NONE") 24585678948SMichael Walsh 2466741f740SMichael Walsh boot_pass, boot_fail = boot_results.return_total_pass_fail() 2470bbd860fSMichael Walsh if boot_pass > 1: 2480bbd860fSMichael Walsh test_really_running = 1 2490bbd860fSMichael Walsh else: 2500bbd860fSMichael Walsh test_really_running = 0 2510bbd860fSMichael Walsh 2526741f740SMichael Walsh BuiltIn().set_global_variable("${test_really_running}", 2536741f740SMichael Walsh test_really_running) 2546741f740SMichael Walsh BuiltIn().set_global_variable("${boot_type_desc}", next_boot) 2556741f740SMichael Walsh BuiltIn().set_global_variable("${boot_pass}", boot_pass) 2566741f740SMichael Walsh BuiltIn().set_global_variable("${boot_fail}", boot_fail) 2576741f740SMichael Walsh BuiltIn().set_global_variable("${boot_success}", boot_success) 2586741f740SMichael Walsh BuiltIn().set_global_variable("${ffdc_prefix}", ffdc_prefix) 259325eb548SSunil M BuiltIn().set_global_variable("${boot_start_time}", boot_start_time) 260325eb548SSunil M BuiltIn().set_global_variable("${boot_end_time}", boot_end_time) 2614c9a6453SMichael Walsh 2620bbd860fSMichael Walsh # For each program parameter, set the corresponding AUTOBOOT_ environment 2630bbd860fSMichael Walsh # variable value. Also, set an AUTOBOOT_ environment variable for every 2640bbd860fSMichael Walsh # element in additional_values. 2650bbd860fSMichael Walsh additional_values = ["boot_type_desc", "boot_success", "boot_pass", 266325eb548SSunil M "boot_fail", "test_really_running", "ffdc_prefix", 267325eb548SSunil M "boot_start_time", "boot_end_time"] 2680bbd860fSMichael Walsh 26985678948SMichael Walsh plug_in_vars = additional_values 2700bbd860fSMichael Walsh 2710bbd860fSMichael Walsh for var_name in plug_in_vars: 2720bbd860fSMichael Walsh var_value = BuiltIn().get_variable_value("${" + var_name + "}") 2730bbd860fSMichael Walsh var_name = var_name.upper() 2740bbd860fSMichael Walsh if var_value is None: 2750bbd860fSMichael Walsh var_value = "" 2766741f740SMichael Walsh os.environ["AUTOBOOT_" + var_name] = str(var_value) 2770bbd860fSMichael Walsh 2780bbd860fSMichael Walsh if debug: 2796741f740SMichael Walsh shell_rc, out_buf = \ 2806741f740SMichael Walsh gc.cmd_fnc_u("printenv | egrep AUTOBOOT_ | sort -u") 2810bbd860fSMichael Walsh 28285678948SMichael Walsh BuiltIn().set_log_level(LOG_LEVEL) 28385678948SMichael Walsh 2840bbd860fSMichael Walsh 285e0cf8d70SMichael Walshdef pre_boot_plug_in_setup(): 286e0cf8d70SMichael Walsh 287e0cf8d70SMichael Walsh # Clear the ffdc_list_file_path file. Plug-ins may now write to it. 288e0cf8d70SMichael Walsh try: 289e0cf8d70SMichael Walsh os.remove(ffdc_list_file_path) 290e0cf8d70SMichael Walsh except OSError: 291e0cf8d70SMichael Walsh pass 292e0cf8d70SMichael Walsh 293e0cf8d70SMichael Walsh # Clear the ffdc_report_list_path file. Plug-ins may now write to it. 294e0cf8d70SMichael Walsh try: 295e0cf8d70SMichael Walsh os.remove(ffdc_report_list_path) 296e0cf8d70SMichael Walsh except OSError: 297e0cf8d70SMichael Walsh pass 298e0cf8d70SMichael Walsh 299600876daSMichael Walsh # Clear the ffdc_summary_list_path file. Plug-ins may now write to it. 300600876daSMichael Walsh try: 301600876daSMichael Walsh os.remove(ffdc_summary_list_path) 302600876daSMichael Walsh except OSError: 303600876daSMichael Walsh pass 304600876daSMichael Walsh 305e1974b96SMichael Walsh global ffdc_prefix 306e1974b96SMichael Walsh 307e1974b96SMichael Walsh seconds = time.time() 308e1974b96SMichael Walsh loc_time = time.localtime(seconds) 309e1974b96SMichael Walsh time_string = time.strftime("%y%m%d.%H%M%S.", loc_time) 310e1974b96SMichael Walsh 311e1974b96SMichael Walsh ffdc_prefix = openbmc_nickname + "." + time_string 312e1974b96SMichael Walsh 313e0cf8d70SMichael Walsh 3146741f740SMichael Walshdef setup(): 3150bbd860fSMichael Walsh r""" 3166741f740SMichael Walsh Do general program setup tasks. 3170bbd860fSMichael Walsh """ 3180bbd860fSMichael Walsh 3196741f740SMichael Walsh global cp_setup_called 32081816748SMichael Walsh global transitional_boot_selected 3210bbd860fSMichael Walsh 322b5839d00SMichael Walsh gp.qprintn() 323b5839d00SMichael Walsh 32481816748SMichael Walsh transitional_boot_selected = False 32581816748SMichael Walsh 32683f4bc77SMichael Walsh robot_pgm_dir_path = os.path.dirname(__file__) + os.sep 32783f4bc77SMichael Walsh repo_bin_path = robot_pgm_dir_path.replace("/lib/", "/bin/") 328d061c043SMichael Walsh # If we can't find process_plug_in_packages.py, ssh_pw or 329d061c043SMichael Walsh # validate_plug_ins.py, then we don't have our repo bin in PATH. 330d061c043SMichael Walsh shell_rc, out_buf = gc.cmd_fnc_u("which process_plug_in_packages.py" + 331d061c043SMichael Walsh " ssh_pw validate_plug_ins.py", quiet=1, 332d061c043SMichael Walsh print_output=0, show_err=0) 333b5839d00SMichael Walsh if shell_rc != 0: 33483f4bc77SMichael Walsh os.environ['PATH'] = repo_bin_path + ":" + os.environ.get('PATH', "") 33583f4bc77SMichael Walsh # Likewise, our repo lib subdir needs to be in sys.path and PYTHONPATH. 33683f4bc77SMichael Walsh if robot_pgm_dir_path not in sys.path: 33783f4bc77SMichael Walsh sys.path.append(robot_pgm_dir_path) 33883f4bc77SMichael Walsh PYTHONPATH = os.environ.get("PYTHONPATH", "") 33983f4bc77SMichael Walsh if PYTHONPATH == "": 34083f4bc77SMichael Walsh os.environ['PYTHONPATH'] = robot_pgm_dir_path 34183f4bc77SMichael Walsh else: 34283f4bc77SMichael Walsh os.environ['PYTHONPATH'] = robot_pgm_dir_path + ":" + PYTHONPATH 3436741f740SMichael Walsh 3446741f740SMichael Walsh validate_parms() 3456741f740SMichael Walsh 3466741f740SMichael Walsh grp.rqprint_pgm_header() 3476741f740SMichael Walsh 348efc3ff2bSGeorge Keishing grk.run_key("Set BMC Power Policy ALWAYS_POWER_OFF") 34911cfc8c0SMichael Walsh 35085678948SMichael Walsh initial_plug_in_setup() 35185678948SMichael Walsh 3526741f740SMichael Walsh plug_in_setup() 3536741f740SMichael Walsh rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages( 3546741f740SMichael Walsh call_point='setup') 3556741f740SMichael Walsh if rc != 0: 3566741f740SMichael Walsh error_message = "Plug-in setup failed.\n" 3576741f740SMichael Walsh grp.rprint_error_report(error_message) 3586741f740SMichael Walsh BuiltIn().fail(error_message) 3596741f740SMichael Walsh # Setting cp_setup_called lets our Teardown know that it needs to call 3606741f740SMichael Walsh # the cleanup plug-in call point. 3616741f740SMichael Walsh cp_setup_called = 1 3626741f740SMichael Walsh 3636741f740SMichael Walsh # Keyword "FFDC" will fail if TEST_MESSAGE is not set. 3646741f740SMichael Walsh BuiltIn().set_global_variable("${TEST_MESSAGE}", "${EMPTY}") 36585678948SMichael Walsh # FFDC_LOG_PATH is used by "FFDC" keyword. 36685678948SMichael Walsh BuiltIn().set_global_variable("${FFDC_LOG_PATH}", ffdc_dir_path) 3676741f740SMichael Walsh 368dc80d67dSMichael Walsh # Also printed by FFDC. 369dc80d67dSMichael Walsh global host_name 370dc80d67dSMichael Walsh global host_ip 371dc80d67dSMichael Walsh host = socket.gethostname() 372dc80d67dSMichael Walsh host_name, host_ip = gm.get_host_name_ip(host) 373dc80d67dSMichael Walsh 374b5839d00SMichael Walsh gp.dprint_var(boot_table, 1) 375b5839d00SMichael Walsh gp.dprint_var(boot_lists) 3760bbd860fSMichael Walsh 3770bbd860fSMichael Walsh 3786741f740SMichael Walshdef validate_parms(): 3790bbd860fSMichael Walsh r""" 3806741f740SMichael Walsh Validate all program parameters. 3810bbd860fSMichael Walsh """ 3820bbd860fSMichael Walsh 383b5839d00SMichael Walsh process_pgm_parms() 3840bbd860fSMichael Walsh 385b5839d00SMichael Walsh gp.qprintn() 386b5839d00SMichael Walsh 387b5839d00SMichael Walsh global openbmc_model 3886741f740SMichael Walsh grv.rvalid_value("openbmc_host") 3896741f740SMichael Walsh grv.rvalid_value("openbmc_username") 3906741f740SMichael Walsh grv.rvalid_value("openbmc_password") 3916741f740SMichael Walsh if os_host != "": 3926741f740SMichael Walsh grv.rvalid_value("os_username") 3936741f740SMichael Walsh grv.rvalid_value("os_password") 3940bbd860fSMichael Walsh 3956741f740SMichael Walsh if pdu_host != "": 3966741f740SMichael Walsh grv.rvalid_value("pdu_username") 3976741f740SMichael Walsh grv.rvalid_value("pdu_password") 3986741f740SMichael Walsh grv.rvalid_integer("pdu_slot_no") 3996741f740SMichael Walsh if openbmc_serial_host != "": 4006741f740SMichael Walsh grv.rvalid_integer("openbmc_serial_port") 401b5839d00SMichael Walsh if openbmc_model == "": 402b5839d00SMichael Walsh status, ret_values =\ 403b5839d00SMichael Walsh grk.run_key_u("Get BMC System Model") 404b5839d00SMichael Walsh openbmc_model = ret_values 405b5839d00SMichael Walsh BuiltIn().set_global_variable("${openbmc_model}", openbmc_model) 4066741f740SMichael Walsh grv.rvalid_value("openbmc_model") 407b5839d00SMichael Walsh grv.rvalid_integer("max_num_tests") 4086741f740SMichael Walsh grv.rvalid_integer("boot_pass") 4096741f740SMichael Walsh grv.rvalid_integer("boot_fail") 4106741f740SMichael Walsh 4116741f740SMichael Walsh plug_in_packages_list = grpi.rvalidate_plug_ins(plug_in_dir_paths) 4126741f740SMichael Walsh BuiltIn().set_global_variable("${plug_in_packages_list}", 4136741f740SMichael Walsh plug_in_packages_list) 4146741f740SMichael Walsh 415b5839d00SMichael Walsh grv.rvalid_value("stack_mode", valid_values=['normal', 'skip']) 416a20da401SMichael Walsh if len(boot_list) == 0 and len(boot_stack) == 0 and not ffdc_only: 4176741f740SMichael Walsh error_message = "You must provide either a value for either the" +\ 4186741f740SMichael Walsh " boot_list or the boot_stack parm.\n" 4196741f740SMichael Walsh BuiltIn().fail(gp.sprint_error(error_message)) 4206741f740SMichael Walsh 4216741f740SMichael Walsh valid_boot_list(boot_list, valid_boot_types) 4226741f740SMichael Walsh valid_boot_list(boot_stack, valid_boot_types) 4236741f740SMichael Walsh 42411cfc8c0SMichael Walsh selected_PDU_boots = list(set(boot_list + boot_stack) & 42511cfc8c0SMichael Walsh set(boot_lists['PDU_reboot'])) 42611cfc8c0SMichael Walsh 42711cfc8c0SMichael Walsh if len(selected_PDU_boots) > 0 and pdu_host == "": 42811cfc8c0SMichael Walsh error_message = "You have selected the following boots which" +\ 42911cfc8c0SMichael Walsh " require a PDU host but no value for pdu_host:\n" 43011cfc8c0SMichael Walsh error_message += gp.sprint_var(selected_PDU_boots) 43111cfc8c0SMichael Walsh error_message += gp.sprint_var(pdu_host, 2) 43211cfc8c0SMichael Walsh BuiltIn().fail(gp.sprint_error(error_message)) 43311cfc8c0SMichael Walsh 4346741f740SMichael Walsh return 4350bbd860fSMichael Walsh 4360bbd860fSMichael Walsh 4376741f740SMichael Walshdef my_get_state(): 4380bbd860fSMichael Walsh r""" 4396741f740SMichael Walsh Get the system state plus a little bit of wrapping. 4400bbd860fSMichael Walsh """ 4410bbd860fSMichael Walsh 4426741f740SMichael Walsh global state 4436741f740SMichael Walsh 4446741f740SMichael Walsh req_states = ['epoch_seconds'] + st.default_req_states 4456741f740SMichael Walsh 446b5839d00SMichael Walsh gp.qprint_timen("Getting system state.") 4476741f740SMichael Walsh if test_mode: 4486741f740SMichael Walsh state['epoch_seconds'] = int(time.time()) 4496741f740SMichael Walsh else: 450b5839d00SMichael Walsh state = st.get_state(req_states=req_states, quiet=quiet) 451b5839d00SMichael Walsh gp.qprint_var(state) 452341c21ebSMichael Walsh 453341c21ebSMichael Walsh 45445ca6e4cSMichael Walshdef valid_state(): 45545ca6e4cSMichael Walsh r""" 45645ca6e4cSMichael Walsh Verify that our state dictionary contains no blank values. If we don't get 45745ca6e4cSMichael Walsh valid state data, we cannot continue to work. 45845ca6e4cSMichael Walsh """ 45945ca6e4cSMichael Walsh 46045ca6e4cSMichael Walsh if st.compare_states(state, st.invalid_state_match, 'or'): 46145ca6e4cSMichael Walsh error_message = "The state dictionary contains blank fields which" +\ 46245ca6e4cSMichael Walsh " is illegal.\n" + gp.sprint_var(state) 46345ca6e4cSMichael Walsh BuiltIn().fail(gp.sprint_error(error_message)) 46445ca6e4cSMichael Walsh 46545ca6e4cSMichael Walsh 4666741f740SMichael Walshdef select_boot(): 467341c21ebSMichael Walsh r""" 468341c21ebSMichael Walsh Select a boot test to be run based on our current state and return the 469341c21ebSMichael Walsh chosen boot type. 470341c21ebSMichael Walsh 471341c21ebSMichael Walsh Description of arguments: 4726741f740SMichael Walsh state The state of the machine. 473341c21ebSMichael Walsh """ 474341c21ebSMichael Walsh 47581816748SMichael Walsh global transitional_boot_selected 47630dadae2SMichael Walsh global boot_stack 47730dadae2SMichael Walsh 478b5839d00SMichael Walsh gp.qprint_timen("Selecting a boot test.") 4796741f740SMichael Walsh 48081816748SMichael Walsh if transitional_boot_selected and not boot_success: 48181816748SMichael Walsh prior_boot = next_boot 48281816748SMichael Walsh boot_candidate = boot_stack.pop() 48381816748SMichael Walsh gp.qprint_timen("The prior '" + next_boot + "' was chosen to" + 48481816748SMichael Walsh " transition to a valid state for '" + boot_candidate + 48581816748SMichael Walsh "' which was at the top of the boot_stack. Since" + 48681816748SMichael Walsh " the '" + next_boot + "' failed, the '" + 48781816748SMichael Walsh boot_candidate + "' has been removed from the stack" + 48881816748SMichael Walsh " to avoid and endless failure loop.") 48981816748SMichael Walsh if len(boot_stack) == 0: 49081816748SMichael Walsh return "" 49181816748SMichael Walsh 4926741f740SMichael Walsh my_get_state() 49345ca6e4cSMichael Walsh valid_state() 4946741f740SMichael Walsh 49581816748SMichael Walsh transitional_boot_selected = False 4966741f740SMichael Walsh stack_popped = 0 4976741f740SMichael Walsh if len(boot_stack) > 0: 4986741f740SMichael Walsh stack_popped = 1 499b5839d00SMichael Walsh gp.qprint_dashes() 500b5839d00SMichael Walsh gp.qprint_var(boot_stack) 501b5839d00SMichael Walsh gp.qprint_dashes() 502b5839d00SMichael Walsh skip_boot_printed = 0 503b5839d00SMichael Walsh while len(boot_stack) > 0: 5046741f740SMichael Walsh boot_candidate = boot_stack.pop() 505b5839d00SMichael Walsh if stack_mode == 'normal': 506b5839d00SMichael Walsh break 507b5839d00SMichael Walsh else: 508b5839d00SMichael Walsh if st.compare_states(state, boot_table[boot_candidate]['end']): 509b5839d00SMichael Walsh if not skip_boot_printed: 510ff340006SMichael Walsh gp.qprint_var(stack_mode) 511ff340006SMichael Walsh gp.qprintn() 512ff340006SMichael Walsh gp.qprint_timen("Skipping the following boot tests" + 513b5839d00SMichael Walsh " which are unnecessary since their" + 514b5839d00SMichael Walsh " required end states match the" + 515b5839d00SMichael Walsh " current machine state:") 516b5839d00SMichael Walsh skip_boot_printed = 1 517ff340006SMichael Walsh gp.qprint_var(boot_candidate) 518b5839d00SMichael Walsh boot_candidate = "" 519b5839d00SMichael Walsh if boot_candidate == "": 520b5839d00SMichael Walsh gp.qprint_dashes() 521b5839d00SMichael Walsh gp.qprint_var(boot_stack) 522b5839d00SMichael Walsh gp.qprint_dashes() 523b5839d00SMichael Walsh return boot_candidate 5246741f740SMichael Walsh if st.compare_states(state, boot_table[boot_candidate]['start']): 525b5839d00SMichael Walsh gp.qprint_timen("The machine state is valid for a '" + 5266741f740SMichael Walsh boot_candidate + "' boot test.") 527b5839d00SMichael Walsh gp.qprint_dashes() 528b5839d00SMichael Walsh gp.qprint_var(boot_stack) 529b5839d00SMichael Walsh gp.qprint_dashes() 5306741f740SMichael Walsh return boot_candidate 531341c21ebSMichael Walsh else: 532b5839d00SMichael Walsh gp.qprint_timen("The machine state does not match the required" + 533b5839d00SMichael Walsh " starting state for a '" + boot_candidate + 534b5839d00SMichael Walsh "' boot test:") 535ff340006SMichael Walsh gp.qprint_varx("boot_table[" + boot_candidate + "][start]", 536b5839d00SMichael Walsh boot_table[boot_candidate]['start'], 1) 5376741f740SMichael Walsh boot_stack.append(boot_candidate) 53881816748SMichael Walsh transitional_boot_selected = True 5396741f740SMichael Walsh popped_boot = boot_candidate 5406741f740SMichael Walsh 5416741f740SMichael Walsh # Loop through your list selecting a boot_candidates 5426741f740SMichael Walsh boot_candidates = [] 5436741f740SMichael Walsh for boot_candidate in boot_list: 5446741f740SMichael Walsh if st.compare_states(state, boot_table[boot_candidate]['start']): 5456741f740SMichael Walsh if stack_popped: 5466741f740SMichael Walsh if st.compare_states(boot_table[boot_candidate]['end'], 5476741f740SMichael Walsh boot_table[popped_boot]['start']): 5486741f740SMichael Walsh boot_candidates.append(boot_candidate) 549341c21ebSMichael Walsh else: 5506741f740SMichael Walsh boot_candidates.append(boot_candidate) 5516741f740SMichael Walsh 5526741f740SMichael Walsh if len(boot_candidates) == 0: 553b5839d00SMichael Walsh gp.qprint_timen("The user's boot list contained no boot tests" + 5546741f740SMichael Walsh " which are valid for the current machine state.") 5556741f740SMichael Walsh boot_candidate = default_power_on 5566741f740SMichael Walsh if not st.compare_states(state, boot_table[default_power_on]['start']): 5576741f740SMichael Walsh boot_candidate = default_power_off 5586741f740SMichael Walsh boot_candidates.append(boot_candidate) 559b5839d00SMichael Walsh gp.qprint_timen("Using default '" + boot_candidate + 560b5839d00SMichael Walsh "' boot type to transition to valid state.") 5616741f740SMichael Walsh 562b5839d00SMichael Walsh gp.dprint_var(boot_candidates) 5636741f740SMichael Walsh 5646741f740SMichael Walsh # Randomly select a boot from the candidate list. 5656741f740SMichael Walsh boot = random.choice(boot_candidates) 566341c21ebSMichael Walsh 567341c21ebSMichael Walsh return boot 5680bbd860fSMichael Walsh 56955302295SMichael Walsh 570341c21ebSMichael Walshdef print_last_boots(): 571341c21ebSMichael Walsh r""" 572341c21ebSMichael Walsh Print the last ten boots done with their time stamps. 573341c21ebSMichael Walsh """ 574341c21ebSMichael Walsh 575341c21ebSMichael Walsh # indent 0, 90 chars wide, linefeed, char is "=" 576b5839d00SMichael Walsh gp.qprint_dashes(0, 90) 577b5839d00SMichael Walsh gp.qprintn("Last 10 boots:\n") 578341c21ebSMichael Walsh 579341c21ebSMichael Walsh for boot_entry in last_ten: 580341c21ebSMichael Walsh grp.rqprint(boot_entry) 581b5839d00SMichael Walsh gp.qprint_dashes(0, 90) 582341c21ebSMichael Walsh 583341c21ebSMichael Walsh 584b2e53ecdSMichael Walshdef print_defect_report(ffdc_file_list): 585341c21ebSMichael Walsh r""" 586341c21ebSMichael Walsh Print a defect report. 587b2e53ecdSMichael Walsh 588b2e53ecdSMichael Walsh Description of argument(s): 589b2e53ecdSMichael Walsh ffdc_file_list A list of files which were collected by our ffdc functions. 590341c21ebSMichael Walsh """ 591341c21ebSMichael Walsh 592600876daSMichael Walsh # Making deliberate choice to NOT run plug_in_setup(). We don't want 593600876daSMichael Walsh # ffdc_prefix updated. 594600876daSMichael Walsh rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages( 595600876daSMichael Walsh call_point='ffdc_report', stop_on_plug_in_failure=0) 596600876daSMichael Walsh 597e0cf8d70SMichael Walsh # Get additional header data which may have been created by ffdc plug-ins. 598e0cf8d70SMichael Walsh # Also, delete the individual header files to cleanup. 599e0cf8d70SMichael Walsh cmd_buf = "file_list=$(cat " + ffdc_report_list_path + " 2>/dev/null)" +\ 600e0cf8d70SMichael Walsh " ; [ ! -z \"${file_list}\" ] && cat ${file_list}" +\ 601e0cf8d70SMichael Walsh " 2>/dev/null ; rm -rf ${file_list} 2>/dev/null || :" 602e0cf8d70SMichael Walsh shell_rc, more_header_info = gc.cmd_fnc_u(cmd_buf, print_output=0, 603e0cf8d70SMichael Walsh show_err=0) 604e0cf8d70SMichael Walsh 605b2e53ecdSMichael Walsh # Get additional summary data which may have been created by ffdc plug-ins. 606600876daSMichael Walsh # Also, delete the individual header files to cleanup. 607600876daSMichael Walsh cmd_buf = "file_list=$(cat " + ffdc_summary_list_path + " 2>/dev/null)" +\ 608600876daSMichael Walsh " ; [ ! -z \"${file_list}\" ] && cat ${file_list}" +\ 609600876daSMichael Walsh " 2>/dev/null ; rm -rf ${file_list} 2>/dev/null || :" 610600876daSMichael Walsh shell_rc, ffdc_summary_info = gc.cmd_fnc_u(cmd_buf, print_output=0, 611600876daSMichael Walsh show_err=0) 612600876daSMichael Walsh 613b2e53ecdSMichael Walsh # ffdc_list_file_path contains a list of any ffdc files created by plug- 614b2e53ecdSMichael Walsh # ins, etc. Read that data into a list. 615341c21ebSMichael Walsh try: 616b2e53ecdSMichael Walsh plug_in_ffdc_list = \ 617b2e53ecdSMichael Walsh open(ffdc_list_file_path, 'r').read().rstrip("\n").split("\n") 618b2e53ecdSMichael Walsh plug_in_ffdc_list = filter(None, plug_in_ffdc_list) 619341c21ebSMichael Walsh except IOError: 620b2e53ecdSMichael Walsh plug_in_ffdc_list = [] 621b2e53ecdSMichael Walsh 622b2e53ecdSMichael Walsh # Combine the files from plug_in_ffdc_list with the ffdc_file_list passed 623b2e53ecdSMichael Walsh # in. Eliminate duplicates and sort the list. 624b2e53ecdSMichael Walsh ffdc_file_list = list(set(ffdc_file_list + plug_in_ffdc_list)) 625b2e53ecdSMichael Walsh ffdc_file_list.sort() 626b2e53ecdSMichael Walsh 627b2e53ecdSMichael Walsh if status_file_path != "": 628b2e53ecdSMichael Walsh ffdc_file_list.insert(0, status_file_path) 629b2e53ecdSMichael Walsh 630b2e53ecdSMichael Walsh # Convert the list to a printable list. 631b2e53ecdSMichael Walsh printable_ffdc_file_list = "\n".join(ffdc_file_list) 632341c21ebSMichael Walsh 63368a61162SMichael Walsh # Open ffdc_file_list for writing. We will write a complete list of 63468a61162SMichael Walsh # FFDC files to it for possible use by plug-ins like cp_stop_check. 63568a61162SMichael Walsh ffdc_list_file = open(ffdc_list_file_path, 'w') 636b2e53ecdSMichael Walsh ffdc_list_file.write(printable_ffdc_file_list + "\n") 637b2e53ecdSMichael Walsh ffdc_list_file.close() 638b2e53ecdSMichael Walsh 639b2e53ecdSMichael Walsh indent = 0 640b2e53ecdSMichael Walsh width = 90 641b2e53ecdSMichael Walsh linefeed = 1 642b2e53ecdSMichael Walsh char = "=" 64368a61162SMichael Walsh 64468a61162SMichael Walsh gp.qprintn() 645b2e53ecdSMichael Walsh gp.qprint_dashes(indent, width, linefeed, char) 64668a61162SMichael Walsh gp.qprintn("Copy this data to the defect:\n") 64768a61162SMichael Walsh 648e0cf8d70SMichael Walsh if len(more_header_info) > 0: 649ff340006SMichael Walsh gp.qprintn(more_header_info) 650dc80d67dSMichael Walsh gp.qpvars(host_name, host_ip, openbmc_nickname, openbmc_host, 651dc80d67dSMichael Walsh openbmc_host_name, openbmc_ip, openbmc_username, 652dc80d67dSMichael Walsh openbmc_password, os_host, os_host_name, os_ip, os_username, 653dc80d67dSMichael Walsh os_password, pdu_host, pdu_host_name, pdu_ip, pdu_username, 654dc80d67dSMichael Walsh pdu_password, pdu_slot_no, openbmc_serial_host, 655dc80d67dSMichael Walsh openbmc_serial_host_name, openbmc_serial_ip, openbmc_serial_port) 65668a61162SMichael Walsh 65768a61162SMichael Walsh gp.qprintn() 65868a61162SMichael Walsh print_last_boots() 65968a61162SMichael Walsh gp.qprintn() 66068a61162SMichael Walsh gp.qprint_var(state) 661b5839d00SMichael Walsh gp.qprintn() 662b5839d00SMichael Walsh gp.qprintn("FFDC data files:") 663b2e53ecdSMichael Walsh gp.qprintn(printable_ffdc_file_list) 664b5839d00SMichael Walsh gp.qprintn() 665341c21ebSMichael Walsh 666600876daSMichael Walsh if len(ffdc_summary_info) > 0: 667ff340006SMichael Walsh gp.qprintn(ffdc_summary_info) 668600876daSMichael Walsh 669b2e53ecdSMichael Walsh gp.qprint_dashes(indent, width, linefeed, char) 67068a61162SMichael Walsh 6716741f740SMichael Walsh 6726741f740SMichael Walshdef my_ffdc(): 6736741f740SMichael Walsh r""" 6746741f740SMichael Walsh Collect FFDC data. 6756741f740SMichael Walsh """ 6766741f740SMichael Walsh 6776741f740SMichael Walsh global state 6786741f740SMichael Walsh 6796741f740SMichael Walsh plug_in_setup() 6806741f740SMichael Walsh rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages( 681600876daSMichael Walsh call_point='ffdc', stop_on_plug_in_failure=0) 6826741f740SMichael Walsh 6836741f740SMichael Walsh AUTOBOOT_FFDC_PREFIX = os.environ['AUTOBOOT_FFDC_PREFIX'] 684b2e53ecdSMichael Walsh status, ffdc_file_list = grk.run_key_u("FFDC ffdc_prefix=" + 68583f4bc77SMichael Walsh AUTOBOOT_FFDC_PREFIX + 68683f4bc77SMichael Walsh " ffdc_function_list=" + 68783f4bc77SMichael Walsh ffdc_function_list, ignore=1) 68883f4bc77SMichael Walsh if status != 'PASS': 689ff340006SMichael Walsh gp.qprint_error("Call to ffdc failed.\n") 6906741f740SMichael Walsh 6916741f740SMichael Walsh my_get_state() 6926741f740SMichael Walsh 693b2e53ecdSMichael Walsh print_defect_report(ffdc_file_list) 6946741f740SMichael Walsh 6956741f740SMichael Walsh 6966741f740SMichael Walshdef print_test_start_message(boot_keyword): 6976741f740SMichael Walsh r""" 6986741f740SMichael Walsh Print a message indicating what boot test is about to run. 6996741f740SMichael Walsh 7006741f740SMichael Walsh Description of arguments: 7016741f740SMichael Walsh boot_keyword The name of the boot which is to be run 7026741f740SMichael Walsh (e.g. "BMC Power On"). 7036741f740SMichael Walsh """ 7046741f740SMichael Walsh 7056741f740SMichael Walsh global last_ten 706325eb548SSunil M global boot_start_time 7076741f740SMichael Walsh 7086741f740SMichael Walsh doing_msg = gp.sprint_timen("Doing \"" + boot_keyword + "\".") 709325eb548SSunil M 710325eb548SSunil M # Set boot_start_time for use by plug-ins. 711325eb548SSunil M boot_start_time = doing_msg[1:33] 712325eb548SSunil M gp.qprint_var(boot_start_time) 713325eb548SSunil M 714b5839d00SMichael Walsh gp.qprint(doing_msg) 7156741f740SMichael Walsh 7166741f740SMichael Walsh last_ten.append(doing_msg) 7176741f740SMichael Walsh 7186741f740SMichael Walsh if len(last_ten) > 10: 7196741f740SMichael Walsh del last_ten[0] 7206741f740SMichael Walsh 7216741f740SMichael Walsh 7226741f740SMichael Walshdef run_boot(boot): 7236741f740SMichael Walsh r""" 7246741f740SMichael Walsh Run the specified boot. 7256741f740SMichael Walsh 7266741f740SMichael Walsh Description of arguments: 7276741f740SMichael Walsh boot The name of the boot test to be performed. 7286741f740SMichael Walsh """ 7296741f740SMichael Walsh 7306741f740SMichael Walsh global state 7316741f740SMichael Walsh 7326741f740SMichael Walsh print_test_start_message(boot) 7336741f740SMichael Walsh 7346741f740SMichael Walsh plug_in_setup() 7356741f740SMichael Walsh rc, shell_rc, failed_plug_in_name = \ 7366741f740SMichael Walsh grpi.rprocess_plug_in_packages(call_point="pre_boot") 7376741f740SMichael Walsh if rc != 0: 7386741f740SMichael Walsh error_message = "Plug-in failed with non-zero return code.\n" +\ 7396741f740SMichael Walsh gp.sprint_var(rc, 1) 7406741f740SMichael Walsh BuiltIn().fail(gp.sprint_error(error_message)) 7416741f740SMichael Walsh 7426741f740SMichael Walsh if test_mode: 7436741f740SMichael Walsh # In test mode, we'll pretend the boot worked by assigning its 7446741f740SMichael Walsh # required end state to the default state value. 74530dadae2SMichael Walsh state = st.strip_anchor_state(boot_table[boot]['end']) 7466741f740SMichael Walsh else: 7476741f740SMichael Walsh # Assertion: We trust that the state data was made fresh by the 7486741f740SMichael Walsh # caller. 7496741f740SMichael Walsh 750b5839d00SMichael Walsh gp.qprintn() 7516741f740SMichael Walsh 7526741f740SMichael Walsh if boot_table[boot]['method_type'] == "keyword": 7530b93fbf8SMichael Walsh rk.my_run_keywords(boot_table[boot].get('lib_file_path', ''), 754b5839d00SMichael Walsh boot_table[boot]['method'], 755b5839d00SMichael Walsh quiet=quiet) 7566741f740SMichael Walsh 7576741f740SMichael Walsh if boot_table[boot]['bmc_reboot']: 7586741f740SMichael Walsh st.wait_for_comm_cycle(int(state['epoch_seconds'])) 75930dadae2SMichael Walsh plug_in_setup() 76030dadae2SMichael Walsh rc, shell_rc, failed_plug_in_name = \ 76130dadae2SMichael Walsh grpi.rprocess_plug_in_packages(call_point="post_reboot") 76230dadae2SMichael Walsh if rc != 0: 7630b93fbf8SMichael Walsh error_message = "Plug-in failed with non-zero return code.\n" 7640b93fbf8SMichael Walsh error_message += gp.sprint_var(rc, 1) 76530dadae2SMichael Walsh BuiltIn().fail(gp.sprint_error(error_message)) 7666741f740SMichael Walsh else: 7676741f740SMichael Walsh match_state = st.anchor_state(state) 7686741f740SMichael Walsh del match_state['epoch_seconds'] 7696741f740SMichael Walsh # Wait for the state to change in any way. 7706741f740SMichael Walsh st.wait_state(match_state, wait_time=state_change_timeout, 771600876daSMichael Walsh interval="10 seconds", invert=1) 7726741f740SMichael Walsh 773b5839d00SMichael Walsh gp.qprintn() 7746741f740SMichael Walsh if boot_table[boot]['end']['chassis'] == "Off": 7756741f740SMichael Walsh boot_timeout = power_off_timeout 7766741f740SMichael Walsh else: 7776741f740SMichael Walsh boot_timeout = power_on_timeout 7786741f740SMichael Walsh st.wait_state(boot_table[boot]['end'], wait_time=boot_timeout, 779600876daSMichael Walsh interval="10 seconds") 7806741f740SMichael Walsh 7816741f740SMichael Walsh plug_in_setup() 7826741f740SMichael Walsh rc, shell_rc, failed_plug_in_name = \ 7836741f740SMichael Walsh grpi.rprocess_plug_in_packages(call_point="post_boot") 7846741f740SMichael Walsh if rc != 0: 7856741f740SMichael Walsh error_message = "Plug-in failed with non-zero return code.\n" +\ 7866741f740SMichael Walsh gp.sprint_var(rc, 1) 7876741f740SMichael Walsh BuiltIn().fail(gp.sprint_error(error_message)) 7886741f740SMichael Walsh 7896741f740SMichael Walsh 7906741f740SMichael Walshdef test_loop_body(): 7916741f740SMichael Walsh r""" 7926741f740SMichael Walsh The main loop body for the loop in main_py. 7936741f740SMichael Walsh 7946741f740SMichael Walsh Description of arguments: 7956741f740SMichael Walsh boot_count The iteration number (starts at 1). 7966741f740SMichael Walsh """ 7976741f740SMichael Walsh 7986741f740SMichael Walsh global boot_count 7996741f740SMichael Walsh global state 8006741f740SMichael Walsh global next_boot 8016741f740SMichael Walsh global boot_success 802325eb548SSunil M global boot_end_time 8036741f740SMichael Walsh 804b5839d00SMichael Walsh gp.qprintn() 8056741f740SMichael Walsh 8066741f740SMichael Walsh next_boot = select_boot() 807b5839d00SMichael Walsh if next_boot == "": 808b5839d00SMichael Walsh return True 8096741f740SMichael Walsh 810b5839d00SMichael Walsh boot_count += 1 811b5839d00SMichael Walsh gp.qprint_timen("Starting boot " + str(boot_count) + ".") 8126741f740SMichael Walsh 813e0cf8d70SMichael Walsh pre_boot_plug_in_setup() 8146741f740SMichael Walsh 8156741f740SMichael Walsh cmd_buf = ["run_boot", next_boot] 8166741f740SMichael Walsh boot_status, msg = BuiltIn().run_keyword_and_ignore_error(*cmd_buf) 8176741f740SMichael Walsh if boot_status == "FAIL": 818b5839d00SMichael Walsh gp.qprint(msg) 8196741f740SMichael Walsh 820b5839d00SMichael Walsh gp.qprintn() 8216741f740SMichael Walsh if boot_status == "PASS": 8226741f740SMichael Walsh boot_success = 1 823ff340006SMichael Walsh completion_msg = gp.sprint_timen("BOOT_SUCCESS: \"" + next_boot + 824325eb548SSunil M "\" succeeded.") 8256741f740SMichael Walsh else: 8266741f740SMichael Walsh boot_success = 0 827ff340006SMichael Walsh completion_msg = gp.sprint_timen("BOOT_FAILED: \"" + next_boot + 828325eb548SSunil M "\" failed.") 829325eb548SSunil M 830325eb548SSunil M # Set boot_end_time for use by plug-ins. 831325eb548SSunil M boot_end_time = completion_msg[1:33] 832325eb548SSunil M gp.qprint_var(boot_end_time) 833325eb548SSunil M 834325eb548SSunil M gp.qprint(completion_msg) 8356741f740SMichael Walsh 8366741f740SMichael Walsh boot_results.update(next_boot, boot_status) 8376741f740SMichael Walsh 8386741f740SMichael Walsh plug_in_setup() 8396741f740SMichael Walsh # NOTE: A post_test_case call point failure is NOT counted as a boot 8406741f740SMichael Walsh # failure. 8416741f740SMichael Walsh rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages( 842600876daSMichael Walsh call_point='post_test_case', stop_on_plug_in_failure=0) 8436741f740SMichael Walsh 8446741f740SMichael Walsh plug_in_setup() 8456741f740SMichael Walsh rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages( 8466741f740SMichael Walsh call_point='ffdc_check', shell_rc=0x00000200, 8476741f740SMichael Walsh stop_on_plug_in_failure=1, stop_on_non_zero_rc=1) 8486741f740SMichael Walsh if boot_status != "PASS" or ffdc_check == "All" or shell_rc == 0x00000200: 84983f4bc77SMichael Walsh status, ret_values = grk.run_key_u("my_ffdc", ignore=1) 85083f4bc77SMichael Walsh if status != 'PASS': 851ff340006SMichael Walsh gp.qprint_error("Call to my_ffdc failed.\n") 8526741f740SMichael Walsh 853aabef1e3SMichael Walsh if delete_errlogs: 854d139f286SMichael Walsh # We need to purge error logs between boots or they build up. 855b5839d00SMichael Walsh grk.run_key("Delete Error logs", ignore=1) 856d139f286SMichael Walsh 857952f9b09SMichael Walsh boot_results.print_report() 858b5839d00SMichael Walsh gp.qprint_timen("Finished boot " + str(boot_count) + ".") 859952f9b09SMichael Walsh 8606741f740SMichael Walsh plug_in_setup() 8616741f740SMichael Walsh rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages( 862*3ba8ecdcSMichael Walsh call_point='stop_check', shell_rc=0x00000200, stop_on_non_zero_rc=1) 863*3ba8ecdcSMichael Walsh if shell_rc == 0x00000200: 864*3ba8ecdcSMichael Walsh message = "Stopping as requested by user.\n" 865*3ba8ecdcSMichael Walsh gp.print_time(message) 866*3ba8ecdcSMichael Walsh BuiltIn().fail(message) 8676741f740SMichael Walsh 868d139f286SMichael Walsh # This should help prevent ConnectionErrors. 8690960b384SMichael Walsh grk.run_key_u("Close All Connections") 870d139f286SMichael Walsh 8716741f740SMichael Walsh return True 8726741f740SMichael Walsh 8736741f740SMichael Walsh 87483f4bc77SMichael Walshdef obmc_boot_test_teardown(): 8756741f740SMichael Walsh r""" 876c9116811SMichael Walsh Clean up after the Main keyword. 8776741f740SMichael Walsh """ 8786741f740SMichael Walsh 8796741f740SMichael Walsh if cp_setup_called: 8806741f740SMichael Walsh plug_in_setup() 8816741f740SMichael Walsh rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages( 882600876daSMichael Walsh call_point='cleanup', stop_on_plug_in_failure=0) 8836741f740SMichael Walsh 884600876daSMichael Walsh if 'boot_results_file_path' in globals(): 8850b93fbf8SMichael Walsh # Save boot_results object to a file in case it is needed again. 886b5839d00SMichael Walsh gp.qprint_timen("Saving boot_results to the following path.") 887b5839d00SMichael Walsh gp.qprint_var(boot_results_file_path) 8880b93fbf8SMichael Walsh pickle.dump(boot_results, open(boot_results_file_path, 'wb'), 8890b93fbf8SMichael Walsh pickle.HIGHEST_PROTOCOL) 8900b93fbf8SMichael Walsh 891ff340006SMichael Walsh global save_stack 892ff340006SMichael Walsh # Restore any global values saved on the save_stack. 893ff340006SMichael Walsh for parm_name in main_func_parm_list: 894ff340006SMichael Walsh # Get the parm_value if it was saved on the stack. 895ff340006SMichael Walsh try: 896ff340006SMichael Walsh parm_value = save_stack.pop(parm_name) 897ff340006SMichael Walsh except: 898ff340006SMichael Walsh # If it was not saved, no further action is required. 899ff340006SMichael Walsh continue 900ff340006SMichael Walsh 901ff340006SMichael Walsh # Restore the saved value. 902ff340006SMichael Walsh cmd_buf = "BuiltIn().set_global_variable(\"${" + parm_name +\ 903ff340006SMichael Walsh "}\", parm_value)" 904ff340006SMichael Walsh gp.dpissuing(cmd_buf) 905ff340006SMichael Walsh exec(cmd_buf) 906ff340006SMichael Walsh 907ff340006SMichael Walsh gp.dprintn(save_stack.sprint_obj()) 908ff340006SMichael Walsh 9096741f740SMichael Walsh 910c9116811SMichael Walshdef test_teardown(): 911c9116811SMichael Walsh r""" 912c9116811SMichael Walsh Clean up after this test case. 913c9116811SMichael Walsh """ 914c9116811SMichael Walsh 915c9116811SMichael Walsh gp.qprintn() 916c9116811SMichael Walsh cmd_buf = ["Print Error", 917c9116811SMichael Walsh "A keyword timeout occurred ending this program.\n"] 918c9116811SMichael Walsh BuiltIn().run_keyword_if_timeout_occurred(*cmd_buf) 919c9116811SMichael Walsh 920b5839d00SMichael Walsh grp.rqprint_pgm_footer() 921b5839d00SMichael Walsh 922c9116811SMichael Walsh 923ff340006SMichael Walshdef obmc_boot_test_py(loc_boot_stack=None, 924ff340006SMichael Walsh loc_stack_mode=None, 925ff340006SMichael Walsh loc_quiet=None): 9266741f740SMichael Walsh r""" 9276741f740SMichael Walsh Do main program processing. 9286741f740SMichael Walsh """ 9296741f740SMichael Walsh 930ff340006SMichael Walsh global save_stack 931ff340006SMichael Walsh 932ff340006SMichael Walsh # Process function parms. 933ff340006SMichael Walsh for parm_name in main_func_parm_list: 934ff340006SMichael Walsh # Get parm's value. 935ff340006SMichael Walsh cmd_buf = "parm_value = loc_" + parm_name 936ff340006SMichael Walsh exec(cmd_buf) 937ff340006SMichael Walsh gp.dpvar(parm_name) 938ff340006SMichael Walsh gp.dpvar(parm_value) 939ff340006SMichael Walsh 940ff340006SMichael Walsh if parm_value is None: 941ff340006SMichael Walsh # Parm was not specified by the calling function so set it to its 942ff340006SMichael Walsh # corresponding global value. 943ff340006SMichael Walsh cmd_buf = "loc_" + parm_name + " = BuiltIn().get_variable_value" +\ 944ff340006SMichael Walsh "(\"${" + parm_name + "}\")" 945ff340006SMichael Walsh gp.dpissuing(cmd_buf) 946ff340006SMichael Walsh exec(cmd_buf) 947ff340006SMichael Walsh else: 948ff340006SMichael Walsh # Save the global value on a stack. 949ff340006SMichael Walsh cmd_buf = "save_stack.push(BuiltIn().get_variable_value(\"${" +\ 950ff340006SMichael Walsh parm_name + "}\"), \"" + parm_name + "\")" 951ff340006SMichael Walsh gp.dpissuing(cmd_buf) 952ff340006SMichael Walsh exec(cmd_buf) 953ff340006SMichael Walsh 954ff340006SMichael Walsh # Set the global value to the passed value. 955ff340006SMichael Walsh cmd_buf = "BuiltIn().set_global_variable(\"${" + parm_name +\ 956ff340006SMichael Walsh "}\", loc_" + parm_name + ")" 957ff340006SMichael Walsh gp.dpissuing(cmd_buf) 958ff340006SMichael Walsh exec(cmd_buf) 959ff340006SMichael Walsh 960ff340006SMichael Walsh gp.dprintn(save_stack.sprint_obj()) 961b5839d00SMichael Walsh 9626741f740SMichael Walsh setup() 9636741f740SMichael Walsh 964cd9fbfd7SMichael Walsh init_boot_pass, init_boot_fail = boot_results.return_total_pass_fail() 965cd9fbfd7SMichael Walsh 966a20da401SMichael Walsh if ffdc_only: 967a20da401SMichael Walsh gp.qprint_timen("Caller requested ffdc_only.") 968e0cf8d70SMichael Walsh pre_boot_plug_in_setup() 96983f4bc77SMichael Walsh grk.run_key_u("my_ffdc") 970764d2f83SMichael Walsh return 971a20da401SMichael Walsh 9726741f740SMichael Walsh # Process caller's boot_stack. 9736741f740SMichael Walsh while (len(boot_stack) > 0): 9746741f740SMichael Walsh test_loop_body() 9756741f740SMichael Walsh 976b5839d00SMichael Walsh gp.qprint_timen("Finished processing stack.") 97730dadae2SMichael Walsh 9786741f740SMichael Walsh # Process caller's boot_list. 9796741f740SMichael Walsh if len(boot_list) > 0: 9806741f740SMichael Walsh for ix in range(1, max_num_tests + 1): 9816741f740SMichael Walsh test_loop_body() 9826741f740SMichael Walsh 983b5839d00SMichael Walsh gp.qprint_timen("Completed all requested boot tests.") 984b5839d00SMichael Walsh 985b5839d00SMichael Walsh boot_pass, boot_fail = boot_results.return_total_pass_fail() 986cd9fbfd7SMichael Walsh new_fail = boot_fail - init_boot_fail 987cd9fbfd7SMichael Walsh if new_fail > boot_fail_threshold: 988b5839d00SMichael Walsh error_message = "Boot failures exceed the boot failure" +\ 989b5839d00SMichael Walsh " threshold:\n" +\ 990cd9fbfd7SMichael Walsh gp.sprint_var(new_fail) +\ 991b5839d00SMichael Walsh gp.sprint_var(boot_fail_threshold) 992b5839d00SMichael Walsh BuiltIn().fail(gp.sprint_error(error_message)) 993