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
14*dc80d67dSMichael 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
280bbd860fSMichael Walsh
290b93fbf8SMichael Walshbase_path = os.path.dirname(os.path.dirname(
300b93fbf8SMichael Walsh                            imp.find_module("gen_robot_print")[1])) +\
310b93fbf8SMichael Walsh    os.sep
320b93fbf8SMichael Walshsys.path.append(base_path + "extended/")
330b93fbf8SMichael Walshimport run_keyword as rk
340bbd860fSMichael Walsh
35e1e26448SMichael Walsh# Setting master_pid correctly influences the behavior of plug-ins like
36e1e26448SMichael Walsh# DB_Logging
37e1e26448SMichael Walshprogram_pid = os.getpid()
38e1e26448SMichael Walshmaster_pid = os.environ.get('AUTOBOOT_MASTER_PID', program_pid)
39e1e26448SMichael Walsh
40b5839d00SMichael Walsh# Set up boot data structures.
41b5839d00SMichael Walshboot_table = create_boot_table()
42b5839d00SMichael Walshvalid_boot_types = create_valid_boot_list(boot_table)
430b93fbf8SMichael Walsh
446741f740SMichael Walshboot_lists = read_boot_lists()
456741f740SMichael Walshlast_ten = []
466741f740SMichael Walsh
476741f740SMichael Walshstate = st.return_default_state()
486741f740SMichael Walshcp_setup_called = 0
496741f740SMichael Walshnext_boot = ""
506741f740SMichael Walshbase_tool_dir_path = os.path.normpath(os.environ.get(
516741f740SMichael Walsh    'AUTOBOOT_BASE_TOOL_DIR_PATH', "/tmp")) + os.sep
52b5839d00SMichael Walsh
536741f740SMichael Walshffdc_dir_path = os.path.normpath(os.environ.get('FFDC_DIR_PATH', '')) + os.sep
546741f740SMichael Walshboot_success = 0
556741f740SMichael Walshstatus_dir_path = os.environ.get('STATUS_DIR_PATH', "")
566741f740SMichael Walshif status_dir_path != "":
576741f740SMichael Walsh    status_dir_path = os.path.normpath(status_dir_path) + os.sep
580b93fbf8SMichael Walshdefault_power_on = "REST Power On"
590b93fbf8SMichael Walshdefault_power_off = "REST Power Off"
606741f740SMichael Walshboot_count = 0
610bbd860fSMichael Walsh
6285678948SMichael WalshLOG_LEVEL = BuiltIn().get_variable_value("${LOG_LEVEL}")
6385678948SMichael Walsh
6485678948SMichael Walsh
6585678948SMichael Walsh###############################################################################
660ad0f7f8SMichael Walshdef process_host(host,
670ad0f7f8SMichael Walsh                 host_var_name=""):
680ad0f7f8SMichael Walsh
690ad0f7f8SMichael Walsh    r"""
700ad0f7f8SMichael Walsh    Process a host by getting the associated host name and IP address and
710ad0f7f8SMichael Walsh    setting them in global variables.
720ad0f7f8SMichael Walsh
730ad0f7f8SMichael Walsh    If the caller does not pass the host_var_name, this function will try to
740ad0f7f8SMichael Walsh    figure out the name of the variable used by the caller for the host parm.
750ad0f7f8SMichael Walsh    Callers are advised to explicitly specify the host_var_name when calling
760ad0f7f8SMichael Walsh    with an exec command.  In such cases, the get_arg_name cannot figure out
770ad0f7f8SMichael Walsh    the host variable name.
780ad0f7f8SMichael Walsh
790ad0f7f8SMichael Walsh    This function will then create similar global variable names by
800ad0f7f8SMichael Walsh    removing "_host" and appending "_host_name" or "_ip" to the host variable
810ad0f7f8SMichael Walsh    name.
820ad0f7f8SMichael Walsh
830ad0f7f8SMichael Walsh    Example:
840ad0f7f8SMichael Walsh
850ad0f7f8SMichael Walsh    If a call is made like this:
860ad0f7f8SMichael Walsh    process_host(openbmc_host)
870ad0f7f8SMichael Walsh
880ad0f7f8SMichael Walsh    Global variables openbmc_host_name and openbmc_ip will be set.
890ad0f7f8SMichael Walsh
900ad0f7f8SMichael Walsh    Description of argument(s):
910ad0f7f8SMichael Walsh    host           A host name or IP.  The name of the variable used should
920ad0f7f8SMichael Walsh                   have a suffix of "_host".
930ad0f7f8SMichael Walsh    host_var_name  The name of the variable being used as the host parm.
940ad0f7f8SMichael Walsh    """
950ad0f7f8SMichael Walsh
960ad0f7f8SMichael Walsh    if host_var_name == "":
970ad0f7f8SMichael Walsh        host_var_name = gp.get_arg_name(0, 1, stack_frame_ix=2)
980ad0f7f8SMichael Walsh
990ad0f7f8SMichael Walsh    host_name_var_name = re.sub("host", "host_name", host_var_name)
1000ad0f7f8SMichael Walsh    ip_var_name = re.sub("host", "ip", host_var_name)
1010ad0f7f8SMichael Walsh    cmd_buf = "global " + host_name_var_name + ", " + ip_var_name + " ; " +\
1020ad0f7f8SMichael Walsh        host_name_var_name + ", " + ip_var_name + " = gm.get_host_name_ip('" +\
1030ad0f7f8SMichael Walsh        host + "')"
1040ad0f7f8SMichael Walsh    exec(cmd_buf)
1050ad0f7f8SMichael Walsh
1060ad0f7f8SMichael Walsh###############################################################################
1070ad0f7f8SMichael Walsh
1080ad0f7f8SMichael Walsh
1090ad0f7f8SMichael Walsh###############################################################################
110b5839d00SMichael Walshdef process_pgm_parms():
111b5839d00SMichael Walsh
112b5839d00SMichael Walsh    r"""
113b5839d00SMichael Walsh    Process the program parameters by assigning them all to corresponding
114b5839d00SMichael Walsh    globals.  Also, set some global values that depend on program parameters.
115b5839d00SMichael Walsh    """
116b5839d00SMichael Walsh
117b5839d00SMichael Walsh    # Program parameter processing.
118b5839d00SMichael Walsh    # Assign all program parms to python variables which are global to this
119b5839d00SMichael Walsh    # module.
120b5839d00SMichael Walsh
121b5839d00SMichael Walsh    global parm_list
122b5839d00SMichael Walsh    parm_list = BuiltIn().get_variable_value("${parm_list}")
123b5839d00SMichael Walsh    # The following subset of parms should be processed as integers.
124b5839d00SMichael Walsh    int_list = ['max_num_tests', 'boot_pass', 'boot_fail', 'ffdc_only',
125b5839d00SMichael Walsh                'boot_fail_threshold', 'quiet', 'test_mode', 'debug']
126b5839d00SMichael Walsh    for parm in parm_list:
127b5839d00SMichael Walsh        if parm in int_list:
128b5839d00SMichael Walsh            sub_cmd = "int(BuiltIn().get_variable_value(\"${" + parm +\
129b5839d00SMichael Walsh                      "}\", \"0\"))"
130b5839d00SMichael Walsh        else:
131b5839d00SMichael Walsh            sub_cmd = "BuiltIn().get_variable_value(\"${" + parm + "}\")"
132b5839d00SMichael Walsh        cmd_buf = "global " + parm + " ; " + parm + " = " + sub_cmd
133b5839d00SMichael Walsh        exec(cmd_buf)
1340ad0f7f8SMichael Walsh        if re.match(r".*_host$", parm):
1350ad0f7f8SMichael Walsh            cmd_buf = "process_host(" + parm + ", '" + parm + "')"
1360ad0f7f8SMichael Walsh            exec(cmd_buf)
1370ad0f7f8SMichael Walsh        if re.match(r".*_password$", parm):
1380ad0f7f8SMichael Walsh            # Register the value of any parm whose name ends in _password.
1390ad0f7f8SMichael Walsh            # This will cause the print functions to replace passwords with
1400ad0f7f8SMichael Walsh            # asterisks in the output.
1410ad0f7f8SMichael Walsh            cmd_buf = "gp.register_passwords(" + parm + ")"
1420ad0f7f8SMichael Walsh            exec(cmd_buf)
143b5839d00SMichael Walsh
144b5839d00SMichael Walsh    global ffdc_dir_path_style
145b5839d00SMichael Walsh    global boot_list
146b5839d00SMichael Walsh    global boot_stack
147b5839d00SMichael Walsh    global boot_results_file_path
148b5839d00SMichael Walsh    global boot_results
149b5839d00SMichael Walsh    global ffdc_list_file_path
150b5839d00SMichael Walsh
151b5839d00SMichael Walsh    if ffdc_dir_path_style == "":
152b5839d00SMichael Walsh        ffdc_dir_path_style = int(os.environ.get('FFDC_DIR_PATH_STYLE', '0'))
153b5839d00SMichael Walsh
154b5839d00SMichael Walsh    # Convert these program parms to lists for easier processing..
155b5839d00SMichael Walsh    boot_list = filter(None, boot_list.split(":"))
156b5839d00SMichael Walsh    boot_stack = filter(None, boot_stack.split(":"))
157b5839d00SMichael Walsh
158b5839d00SMichael Walsh    boot_results_file_path = "/tmp/" + openbmc_nickname + ":pid_" +\
159b5839d00SMichael Walsh                             str(master_pid) + ":boot_results"
160b5839d00SMichael Walsh
161b5839d00SMichael Walsh    if os.path.isfile(boot_results_file_path):
162b5839d00SMichael Walsh        # We've been called before in this run so we'll load the saved
163b5839d00SMichael Walsh        # boot_results object.
164b5839d00SMichael Walsh        boot_results = pickle.load(open(boot_results_file_path, 'rb'))
165b5839d00SMichael Walsh    else:
166b5839d00SMichael Walsh        boot_results = boot_results(boot_table, boot_pass, boot_fail)
167b5839d00SMichael Walsh
168b5839d00SMichael Walsh    ffdc_list_file_path = base_tool_dir_path + openbmc_nickname +\
169b5839d00SMichael Walsh        "/FFDC_FILE_LIST"
170b5839d00SMichael Walsh
171b5839d00SMichael Walsh###############################################################################
172b5839d00SMichael Walsh
173b5839d00SMichael Walsh
174b5839d00SMichael Walsh###############################################################################
17585678948SMichael Walshdef initial_plug_in_setup():
17685678948SMichael Walsh
17785678948SMichael Walsh    r"""
17885678948SMichael Walsh    Initialize all plug-in environment variables which do not change for the
17985678948SMichael Walsh    duration of the program.
18085678948SMichael Walsh
18185678948SMichael Walsh    """
18285678948SMichael Walsh
18385678948SMichael Walsh    global LOG_LEVEL
18485678948SMichael Walsh    BuiltIn().set_log_level("NONE")
18585678948SMichael Walsh
18685678948SMichael Walsh    BuiltIn().set_global_variable("${master_pid}", master_pid)
18785678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_DIR_PATH}", ffdc_dir_path)
18885678948SMichael Walsh    BuiltIn().set_global_variable("${STATUS_DIR_PATH}", status_dir_path)
18985678948SMichael Walsh    BuiltIn().set_global_variable("${BASE_TOOL_DIR_PATH}", base_tool_dir_path)
19085678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_LIST_FILE_PATH}",
19185678948SMichael Walsh                                  ffdc_list_file_path)
19285678948SMichael Walsh
19385678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_DIR_PATH_STYLE}",
19485678948SMichael Walsh                                  ffdc_dir_path_style)
19585678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_CHECK}",
19685678948SMichael Walsh                                  ffdc_check)
19785678948SMichael Walsh
19885678948SMichael Walsh    # For each program parameter, set the corresponding AUTOBOOT_ environment
19985678948SMichael Walsh    # variable value.  Also, set an AUTOBOOT_ environment variable for every
20085678948SMichael Walsh    # element in additional_values.
20185678948SMichael Walsh    additional_values = ["program_pid", "master_pid", "ffdc_dir_path",
20285678948SMichael Walsh                         "status_dir_path", "base_tool_dir_path",
20385678948SMichael Walsh                         "ffdc_list_file_path"]
20485678948SMichael Walsh
20585678948SMichael Walsh    plug_in_vars = parm_list + additional_values
20685678948SMichael Walsh
20785678948SMichael Walsh    for var_name in plug_in_vars:
20885678948SMichael Walsh        var_value = BuiltIn().get_variable_value("${" + var_name + "}")
20985678948SMichael Walsh        var_name = var_name.upper()
21085678948SMichael Walsh        if var_value is None:
21185678948SMichael Walsh            var_value = ""
21285678948SMichael Walsh        os.environ["AUTOBOOT_" + var_name] = str(var_value)
21385678948SMichael Walsh
21485678948SMichael Walsh    BuiltIn().set_log_level(LOG_LEVEL)
21585678948SMichael Walsh
21668a61162SMichael Walsh    # Make sure the ffdc list directory exists.
21768a61162SMichael Walsh    ffdc_list_dir_path = os.path.dirname(ffdc_list_file_path) + os.sep
21868a61162SMichael Walsh    if not os.path.exists(ffdc_list_dir_path):
21968a61162SMichael Walsh        os.makedirs(ffdc_list_dir_path)
22085678948SMichael Walsh
22185678948SMichael Walsh###############################################################################
22285678948SMichael Walsh
2230bbd860fSMichael Walsh
2240bbd860fSMichael Walsh###############################################################################
2250bbd860fSMichael Walshdef plug_in_setup():
2260bbd860fSMichael Walsh
2270bbd860fSMichael Walsh    r"""
22885678948SMichael Walsh    Initialize all changing plug-in environment variables for use by the
22985678948SMichael Walsh    plug-in programs.
2300bbd860fSMichael Walsh    """
2310bbd860fSMichael Walsh
23285678948SMichael Walsh    global LOG_LEVEL
23385678948SMichael Walsh    global test_really_running
23485678948SMichael Walsh
23585678948SMichael Walsh    BuiltIn().set_log_level("NONE")
23685678948SMichael Walsh
2376741f740SMichael Walsh    boot_pass, boot_fail = boot_results.return_total_pass_fail()
2380bbd860fSMichael Walsh    if boot_pass > 1:
2390bbd860fSMichael Walsh        test_really_running = 1
2400bbd860fSMichael Walsh    else:
2410bbd860fSMichael Walsh        test_really_running = 0
2420bbd860fSMichael Walsh
2430bbd860fSMichael Walsh    seconds = time.time()
2440bbd860fSMichael Walsh    loc_time = time.localtime(seconds)
2450bbd860fSMichael Walsh    time_string = time.strftime("%y%m%d.%H%M%S.", loc_time)
2460bbd860fSMichael Walsh
2476741f740SMichael Walsh    ffdc_prefix = openbmc_nickname + "." + time_string
2480bbd860fSMichael Walsh
2496741f740SMichael Walsh    BuiltIn().set_global_variable("${test_really_running}",
2506741f740SMichael Walsh                                  test_really_running)
2516741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_type_desc}", next_boot)
2526741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_pass}", boot_pass)
2536741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_fail}", boot_fail)
2546741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_success}", boot_success)
2556741f740SMichael Walsh    BuiltIn().set_global_variable("${ffdc_prefix}", ffdc_prefix)
2564c9a6453SMichael Walsh
2570bbd860fSMichael Walsh    # For each program parameter, set the corresponding AUTOBOOT_ environment
2580bbd860fSMichael Walsh    # variable value.  Also, set an AUTOBOOT_ environment variable for every
2590bbd860fSMichael Walsh    # element in additional_values.
2600bbd860fSMichael Walsh    additional_values = ["boot_type_desc", "boot_success", "boot_pass",
26185678948SMichael Walsh                         "boot_fail", "test_really_running", "ffdc_prefix"]
2620bbd860fSMichael Walsh
26385678948SMichael Walsh    plug_in_vars = additional_values
2640bbd860fSMichael Walsh
2650bbd860fSMichael Walsh    for var_name in plug_in_vars:
2660bbd860fSMichael Walsh        var_value = BuiltIn().get_variable_value("${" + var_name + "}")
2670bbd860fSMichael Walsh        var_name = var_name.upper()
2680bbd860fSMichael Walsh        if var_value is None:
2690bbd860fSMichael Walsh            var_value = ""
2706741f740SMichael Walsh        os.environ["AUTOBOOT_" + var_name] = str(var_value)
2710bbd860fSMichael Walsh
2720bbd860fSMichael Walsh    if debug:
2736741f740SMichael Walsh        shell_rc, out_buf = \
2746741f740SMichael Walsh            gc.cmd_fnc_u("printenv | egrep AUTOBOOT_ | sort -u")
2750bbd860fSMichael Walsh
27685678948SMichael Walsh    BuiltIn().set_log_level(LOG_LEVEL)
27785678948SMichael Walsh
2780bbd860fSMichael Walsh###############################################################################
2790bbd860fSMichael Walsh
2800bbd860fSMichael Walsh
2810bbd860fSMichael Walsh###############################################################################
2826741f740SMichael Walshdef setup():
2830bbd860fSMichael Walsh
2840bbd860fSMichael Walsh    r"""
2856741f740SMichael Walsh    Do general program setup tasks.
2860bbd860fSMichael Walsh    """
2870bbd860fSMichael Walsh
2886741f740SMichael Walsh    global cp_setup_called
2890bbd860fSMichael Walsh
290b5839d00SMichael Walsh    gp.qprintn()
291b5839d00SMichael Walsh
29283f4bc77SMichael Walsh    robot_pgm_dir_path = os.path.dirname(__file__) + os.sep
29383f4bc77SMichael Walsh    repo_bin_path = robot_pgm_dir_path.replace("/lib/", "/bin/")
29483f4bc77SMichael Walsh    # If we can't find ssh_pw, then we don't have our repo bin in PATH.
295b5839d00SMichael Walsh    shell_rc, out_buf = gc.cmd_fnc_u("which ssh_pw", quiet=1, print_output=0,
296b5839d00SMichael Walsh                                     show_err=0)
297b5839d00SMichael Walsh    if shell_rc != 0:
29883f4bc77SMichael Walsh        os.environ['PATH'] = repo_bin_path + ":" + os.environ.get('PATH', "")
29983f4bc77SMichael Walsh    # Likewise, our repo lib subdir needs to be in sys.path and PYTHONPATH.
30083f4bc77SMichael Walsh    if robot_pgm_dir_path not in sys.path:
30183f4bc77SMichael Walsh        sys.path.append(robot_pgm_dir_path)
30283f4bc77SMichael Walsh        PYTHONPATH = os.environ.get("PYTHONPATH", "")
30383f4bc77SMichael Walsh        if PYTHONPATH == "":
30483f4bc77SMichael Walsh            os.environ['PYTHONPATH'] = robot_pgm_dir_path
30583f4bc77SMichael Walsh        else:
30683f4bc77SMichael Walsh            os.environ['PYTHONPATH'] = robot_pgm_dir_path + ":" + PYTHONPATH
3076741f740SMichael Walsh
3086741f740SMichael Walsh    validate_parms()
3096741f740SMichael Walsh
3106741f740SMichael Walsh    grp.rqprint_pgm_header()
3116741f740SMichael Walsh
312b5839d00SMichael Walsh    grk.run_key("Set BMC Power Policy  RESTORE_LAST_STATE")
31311cfc8c0SMichael Walsh
31485678948SMichael Walsh    initial_plug_in_setup()
31585678948SMichael Walsh
3166741f740SMichael Walsh    plug_in_setup()
3176741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
3186741f740SMichael Walsh        call_point='setup')
3196741f740SMichael Walsh    if rc != 0:
3206741f740SMichael Walsh        error_message = "Plug-in setup failed.\n"
3216741f740SMichael Walsh        grp.rprint_error_report(error_message)
3226741f740SMichael Walsh        BuiltIn().fail(error_message)
3236741f740SMichael Walsh    # Setting cp_setup_called lets our Teardown know that it needs to call
3246741f740SMichael Walsh    # the cleanup plug-in call point.
3256741f740SMichael Walsh    cp_setup_called = 1
3266741f740SMichael Walsh
3276741f740SMichael Walsh    # Keyword "FFDC" will fail if TEST_MESSAGE is not set.
3286741f740SMichael Walsh    BuiltIn().set_global_variable("${TEST_MESSAGE}", "${EMPTY}")
32985678948SMichael Walsh    # FFDC_LOG_PATH is used by "FFDC" keyword.
33085678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_LOG_PATH}", ffdc_dir_path)
3316741f740SMichael Walsh
332*dc80d67dSMichael Walsh    # Also printed by FFDC.
333*dc80d67dSMichael Walsh    global host_name
334*dc80d67dSMichael Walsh    global host_ip
335*dc80d67dSMichael Walsh    host = socket.gethostname()
336*dc80d67dSMichael Walsh    host_name, host_ip = gm.get_host_name_ip(host)
337*dc80d67dSMichael Walsh
338b5839d00SMichael Walsh    gp.dprint_var(boot_table, 1)
339b5839d00SMichael Walsh    gp.dprint_var(boot_lists)
3400bbd860fSMichael Walsh
3410bbd860fSMichael Walsh###############################################################################
3420bbd860fSMichael Walsh
3430bbd860fSMichael Walsh
3440bbd860fSMichael Walsh###############################################################################
3456741f740SMichael Walshdef validate_parms():
3460bbd860fSMichael Walsh
3470bbd860fSMichael Walsh    r"""
3486741f740SMichael Walsh    Validate all program parameters.
3490bbd860fSMichael Walsh    """
3500bbd860fSMichael Walsh
351b5839d00SMichael Walsh    process_pgm_parms()
3520bbd860fSMichael Walsh
353b5839d00SMichael Walsh    gp.qprintn()
354b5839d00SMichael Walsh
355b5839d00SMichael Walsh    global openbmc_model
3566741f740SMichael Walsh    grv.rvalid_value("openbmc_host")
3576741f740SMichael Walsh    grv.rvalid_value("openbmc_username")
3586741f740SMichael Walsh    grv.rvalid_value("openbmc_password")
3596741f740SMichael Walsh    if os_host != "":
3606741f740SMichael Walsh        grv.rvalid_value("os_username")
3616741f740SMichael Walsh        grv.rvalid_value("os_password")
3620bbd860fSMichael Walsh
3636741f740SMichael Walsh    if pdu_host != "":
3646741f740SMichael Walsh        grv.rvalid_value("pdu_username")
3656741f740SMichael Walsh        grv.rvalid_value("pdu_password")
3666741f740SMichael Walsh        grv.rvalid_integer("pdu_slot_no")
3676741f740SMichael Walsh    if openbmc_serial_host != "":
3686741f740SMichael Walsh        grv.rvalid_integer("openbmc_serial_port")
369b5839d00SMichael Walsh    if openbmc_model == "":
370b5839d00SMichael Walsh        status, ret_values =\
371b5839d00SMichael Walsh            grk.run_key_u("Get BMC System Model")
372b5839d00SMichael Walsh        openbmc_model = ret_values
373b5839d00SMichael Walsh        BuiltIn().set_global_variable("${openbmc_model}", openbmc_model)
3746741f740SMichael Walsh    grv.rvalid_value("openbmc_model")
375b5839d00SMichael Walsh    grv.rvalid_integer("max_num_tests")
3766741f740SMichael Walsh    grv.rvalid_integer("boot_pass")
3776741f740SMichael Walsh    grv.rvalid_integer("boot_fail")
3786741f740SMichael Walsh
3796741f740SMichael Walsh    plug_in_packages_list = grpi.rvalidate_plug_ins(plug_in_dir_paths)
3806741f740SMichael Walsh    BuiltIn().set_global_variable("${plug_in_packages_list}",
3816741f740SMichael Walsh                                  plug_in_packages_list)
3826741f740SMichael Walsh
383b5839d00SMichael Walsh    grv.rvalid_value("stack_mode", valid_values=['normal', 'skip'])
384a20da401SMichael Walsh    if len(boot_list) == 0 and len(boot_stack) == 0 and not ffdc_only:
3856741f740SMichael Walsh        error_message = "You must provide either a value for either the" +\
3866741f740SMichael Walsh            " boot_list or the boot_stack parm.\n"
3876741f740SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
3886741f740SMichael Walsh
3896741f740SMichael Walsh    valid_boot_list(boot_list, valid_boot_types)
3906741f740SMichael Walsh    valid_boot_list(boot_stack, valid_boot_types)
3916741f740SMichael Walsh
39211cfc8c0SMichael Walsh    selected_PDU_boots = list(set(boot_list + boot_stack) &
39311cfc8c0SMichael Walsh                              set(boot_lists['PDU_reboot']))
39411cfc8c0SMichael Walsh
39511cfc8c0SMichael Walsh    if len(selected_PDU_boots) > 0 and pdu_host == "":
39611cfc8c0SMichael Walsh        error_message = "You have selected the following boots which" +\
39711cfc8c0SMichael Walsh                        " require a PDU host but no value for pdu_host:\n"
39811cfc8c0SMichael Walsh        error_message += gp.sprint_var(selected_PDU_boots)
39911cfc8c0SMichael Walsh        error_message += gp.sprint_var(pdu_host, 2)
40011cfc8c0SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
40111cfc8c0SMichael Walsh
4026741f740SMichael Walsh    return
4030bbd860fSMichael Walsh
4040bbd860fSMichael Walsh###############################################################################
4050bbd860fSMichael Walsh
4060bbd860fSMichael Walsh
4070bbd860fSMichael Walsh###############################################################################
4086741f740SMichael Walshdef my_get_state():
4090bbd860fSMichael Walsh
4100bbd860fSMichael Walsh    r"""
4116741f740SMichael Walsh    Get the system state plus a little bit of wrapping.
4120bbd860fSMichael Walsh    """
4130bbd860fSMichael Walsh
4146741f740SMichael Walsh    global state
4156741f740SMichael Walsh
4166741f740SMichael Walsh    req_states = ['epoch_seconds'] + st.default_req_states
4176741f740SMichael Walsh
418b5839d00SMichael Walsh    gp.qprint_timen("Getting system state.")
4196741f740SMichael Walsh    if test_mode:
4206741f740SMichael Walsh        state['epoch_seconds'] = int(time.time())
4216741f740SMichael Walsh    else:
422b5839d00SMichael Walsh        state = st.get_state(req_states=req_states, quiet=quiet)
423b5839d00SMichael Walsh    gp.qprint_var(state)
424341c21ebSMichael Walsh
425341c21ebSMichael Walsh###############################################################################
426341c21ebSMichael Walsh
427341c21ebSMichael Walsh
428341c21ebSMichael Walsh###############################################################################
4296741f740SMichael Walshdef select_boot():
430341c21ebSMichael Walsh
431341c21ebSMichael Walsh    r"""
432341c21ebSMichael Walsh    Select a boot test to be run based on our current state and return the
433341c21ebSMichael Walsh    chosen boot type.
434341c21ebSMichael Walsh
435341c21ebSMichael Walsh    Description of arguments:
4366741f740SMichael Walsh    state  The state of the machine.
437341c21ebSMichael Walsh    """
438341c21ebSMichael Walsh
43930dadae2SMichael Walsh    global boot_stack
44030dadae2SMichael Walsh
441b5839d00SMichael Walsh    gp.qprint_timen("Selecting a boot test.")
4426741f740SMichael Walsh
4436741f740SMichael Walsh    my_get_state()
4446741f740SMichael Walsh
4456741f740SMichael Walsh    stack_popped = 0
4466741f740SMichael Walsh    if len(boot_stack) > 0:
4476741f740SMichael Walsh        stack_popped = 1
448b5839d00SMichael Walsh        gp.qprint_dashes()
449b5839d00SMichael Walsh        gp.qprint_var(boot_stack)
450b5839d00SMichael Walsh        gp.qprint_dashes()
451b5839d00SMichael Walsh        skip_boot_printed = 0
452b5839d00SMichael Walsh        while len(boot_stack) > 0:
4536741f740SMichael Walsh            boot_candidate = boot_stack.pop()
454b5839d00SMichael Walsh            if stack_mode == 'normal':
455b5839d00SMichael Walsh                break
456b5839d00SMichael Walsh            else:
457b5839d00SMichael Walsh                if st.compare_states(state, boot_table[boot_candidate]['end']):
458b5839d00SMichael Walsh                    if not skip_boot_printed:
459b5839d00SMichael Walsh                        gp.print_var(stack_mode)
460b5839d00SMichael Walsh                        gp.printn()
461b5839d00SMichael Walsh                        gp.print_timen("Skipping the following boot tests" +
462b5839d00SMichael Walsh                                       " which are unnecessary since their" +
463b5839d00SMichael Walsh                                       " required end states match the" +
464b5839d00SMichael Walsh                                       " current machine state:")
465b5839d00SMichael Walsh                        skip_boot_printed = 1
466b5839d00SMichael Walsh                    gp.print_var(boot_candidate)
467b5839d00SMichael Walsh                    boot_candidate = ""
468b5839d00SMichael Walsh        if boot_candidate == "":
469b5839d00SMichael Walsh            gp.qprint_dashes()
470b5839d00SMichael Walsh            gp.qprint_var(boot_stack)
471b5839d00SMichael Walsh            gp.qprint_dashes()
472b5839d00SMichael Walsh            return boot_candidate
4736741f740SMichael Walsh        if st.compare_states(state, boot_table[boot_candidate]['start']):
474b5839d00SMichael Walsh            gp.qprint_timen("The machine state is valid for a '" +
4756741f740SMichael Walsh                            boot_candidate + "' boot test.")
476b5839d00SMichael Walsh            gp.qprint_dashes()
477b5839d00SMichael Walsh            gp.qprint_var(boot_stack)
478b5839d00SMichael Walsh            gp.qprint_dashes()
4796741f740SMichael Walsh            return boot_candidate
480341c21ebSMichael Walsh        else:
481b5839d00SMichael Walsh            gp.qprint_timen("The machine state does not match the required" +
482b5839d00SMichael Walsh                            " starting state for a '" + boot_candidate +
483b5839d00SMichael Walsh                            "' boot test:")
484b5839d00SMichael Walsh            gp.print_varx("boot_table[" + boot_candidate + "][start]",
485b5839d00SMichael Walsh                          boot_table[boot_candidate]['start'], 1)
4866741f740SMichael Walsh            boot_stack.append(boot_candidate)
4876741f740SMichael Walsh            popped_boot = boot_candidate
4886741f740SMichael Walsh
4896741f740SMichael Walsh    # Loop through your list selecting a boot_candidates
4906741f740SMichael Walsh    boot_candidates = []
4916741f740SMichael Walsh    for boot_candidate in boot_list:
4926741f740SMichael Walsh        if st.compare_states(state, boot_table[boot_candidate]['start']):
4936741f740SMichael Walsh            if stack_popped:
4946741f740SMichael Walsh                if st.compare_states(boot_table[boot_candidate]['end'],
4956741f740SMichael Walsh                   boot_table[popped_boot]['start']):
4966741f740SMichael Walsh                    boot_candidates.append(boot_candidate)
497341c21ebSMichael Walsh            else:
4986741f740SMichael Walsh                boot_candidates.append(boot_candidate)
4996741f740SMichael Walsh
5006741f740SMichael Walsh    if len(boot_candidates) == 0:
501b5839d00SMichael Walsh        gp.qprint_timen("The user's boot list contained no boot tests" +
5026741f740SMichael Walsh                        " which are valid for the current machine state.")
5036741f740SMichael Walsh        boot_candidate = default_power_on
5046741f740SMichael Walsh        if not st.compare_states(state, boot_table[default_power_on]['start']):
5056741f740SMichael Walsh            boot_candidate = default_power_off
5066741f740SMichael Walsh        boot_candidates.append(boot_candidate)
507b5839d00SMichael Walsh        gp.qprint_timen("Using default '" + boot_candidate +
508b5839d00SMichael Walsh                        "' boot type to transition to valid state.")
5096741f740SMichael Walsh
510b5839d00SMichael Walsh    gp.dprint_var(boot_candidates)
5116741f740SMichael Walsh
5126741f740SMichael Walsh    # Randomly select a boot from the candidate list.
5136741f740SMichael Walsh    boot = random.choice(boot_candidates)
514341c21ebSMichael Walsh
515341c21ebSMichael Walsh    return boot
5160bbd860fSMichael Walsh
5170bbd860fSMichael Walsh###############################################################################
51855302295SMichael Walsh
51955302295SMichael Walsh
52055302295SMichael Walsh###############################################################################
521341c21ebSMichael Walshdef print_last_boots():
522341c21ebSMichael Walsh
523341c21ebSMichael Walsh    r"""
524341c21ebSMichael Walsh    Print the last ten boots done with their time stamps.
525341c21ebSMichael Walsh    """
526341c21ebSMichael Walsh
527341c21ebSMichael Walsh    # indent 0, 90 chars wide, linefeed, char is "="
528b5839d00SMichael Walsh    gp.qprint_dashes(0, 90)
529b5839d00SMichael Walsh    gp.qprintn("Last 10 boots:\n")
530341c21ebSMichael Walsh
531341c21ebSMichael Walsh    for boot_entry in last_ten:
532341c21ebSMichael Walsh        grp.rqprint(boot_entry)
533b5839d00SMichael Walsh    gp.qprint_dashes(0, 90)
534341c21ebSMichael Walsh
535341c21ebSMichael Walsh###############################################################################
536341c21ebSMichael Walsh
537341c21ebSMichael Walsh
538341c21ebSMichael Walsh###############################################################################
539341c21ebSMichael Walshdef print_defect_report():
540341c21ebSMichael Walsh
541341c21ebSMichael Walsh    r"""
542341c21ebSMichael Walsh    Print a defect report.
543341c21ebSMichael Walsh    """
544341c21ebSMichael Walsh
545341c21ebSMichael Walsh    # At some point I'd like to have the 'Call FFDC Methods' return a list
546341c21ebSMichael Walsh    # of files it has collected.  In that case, the following "ls" command
547341c21ebSMichael Walsh    # would no longer be needed.  For now, however, glob shows the files
548341c21ebSMichael Walsh    # named in FFDC_LIST_FILE_PATH so I will refrain from printing those
549341c21ebSMichael Walsh    # out (so we don't see duplicates in the list).
550341c21ebSMichael Walsh
551341c21ebSMichael Walsh    LOG_PREFIX = BuiltIn().get_variable_value("${LOG_PREFIX}")
552341c21ebSMichael Walsh
553341c21ebSMichael Walsh    output = '\n'.join(glob.glob(LOG_PREFIX + '*'))
554341c21ebSMichael Walsh    try:
5556741f740SMichael Walsh        ffdc_list = open(ffdc_list_file_path, 'r')
556341c21ebSMichael Walsh    except IOError:
557341c21ebSMichael Walsh        ffdc_list = ""
558341c21ebSMichael Walsh
55968a61162SMichael Walsh    # Open ffdc_file_list for writing.  We will write a complete list of
56068a61162SMichael Walsh    # FFDC files to it for possible use by plug-ins like cp_stop_check.
56168a61162SMichael Walsh    ffdc_list_file = open(ffdc_list_file_path, 'w')
56268a61162SMichael Walsh
56368a61162SMichael Walsh    gp.qprintn()
56468a61162SMichael Walsh    # indent=0, width=90, linefeed=1, char="="
56568a61162SMichael Walsh    gp.qprint_dashes(0, 90, 1, "=")
56668a61162SMichael Walsh    gp.qprintn("Copy this data to the defect:\n")
56768a61162SMichael Walsh
568*dc80d67dSMichael Walsh    gp.qpvars(host_name, host_ip, openbmc_nickname, openbmc_host,
569*dc80d67dSMichael Walsh              openbmc_host_name, openbmc_ip, openbmc_username,
570*dc80d67dSMichael Walsh              openbmc_password, os_host, os_host_name, os_ip, os_username,
571*dc80d67dSMichael Walsh              os_password, pdu_host, pdu_host_name, pdu_ip, pdu_username,
572*dc80d67dSMichael Walsh              pdu_password, pdu_slot_no, openbmc_serial_host,
573*dc80d67dSMichael Walsh              openbmc_serial_host_name, openbmc_serial_ip, openbmc_serial_port)
57468a61162SMichael Walsh
57568a61162SMichael Walsh    gp.qprintn()
57668a61162SMichael Walsh
57768a61162SMichael Walsh    print_last_boots()
57868a61162SMichael Walsh    gp.qprintn()
57968a61162SMichael Walsh    gp.qprint_var(state)
58068a61162SMichael Walsh
581b5839d00SMichael Walsh    gp.qprintn()
582b5839d00SMichael Walsh    gp.qprintn("FFDC data files:")
583341c21ebSMichael Walsh    if status_file_path != "":
584b5839d00SMichael Walsh        gp.qprintn(status_file_path)
58568a61162SMichael Walsh        ffdc_list_file.write(status_file_path + "\n")
586341c21ebSMichael Walsh
587b5839d00SMichael Walsh    gp.qprintn(output)
588b5839d00SMichael Walsh    # gp.qprintn(ffdc_list)
589b5839d00SMichael Walsh    gp.qprintn()
590341c21ebSMichael Walsh
591b5839d00SMichael Walsh    gp.qprint_dashes(0, 90, 1, "=")
592341c21ebSMichael Walsh
59368a61162SMichael Walsh    ffdc_list_file.write(output + "\n")
59468a61162SMichael Walsh    ffdc_list_file.close()
59568a61162SMichael Walsh
596341c21ebSMichael Walsh###############################################################################
5976741f740SMichael Walsh
5986741f740SMichael Walsh
5996741f740SMichael Walsh###############################################################################
6006741f740SMichael Walshdef my_ffdc():
6016741f740SMichael Walsh
6026741f740SMichael Walsh    r"""
6036741f740SMichael Walsh    Collect FFDC data.
6046741f740SMichael Walsh    """
6056741f740SMichael Walsh
6066741f740SMichael Walsh    global state
6076741f740SMichael Walsh
6086741f740SMichael Walsh    plug_in_setup()
6096741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
6106741f740SMichael Walsh        call_point='ffdc', stop_on_plug_in_failure=1)
6116741f740SMichael Walsh
6126741f740SMichael Walsh    AUTOBOOT_FFDC_PREFIX = os.environ['AUTOBOOT_FFDC_PREFIX']
61383f4bc77SMichael Walsh    status, ret_values = grk.run_key_u("FFDC  ffdc_prefix=" +
61483f4bc77SMichael Walsh                                       AUTOBOOT_FFDC_PREFIX +
61583f4bc77SMichael Walsh                                       "  ffdc_function_list=" +
61683f4bc77SMichael Walsh                                       ffdc_function_list, ignore=1)
61783f4bc77SMichael Walsh    if status != 'PASS':
6183328caffSMichael Walsh        gp.print_error("Call to ffdc failed.\n")
6196741f740SMichael Walsh
6206741f740SMichael Walsh    my_get_state()
6216741f740SMichael Walsh
6226741f740SMichael Walsh    print_defect_report()
6236741f740SMichael Walsh
6246741f740SMichael Walsh###############################################################################
6256741f740SMichael Walsh
6266741f740SMichael Walsh
6276741f740SMichael Walsh###############################################################################
6286741f740SMichael Walshdef print_test_start_message(boot_keyword):
6296741f740SMichael Walsh
6306741f740SMichael Walsh    r"""
6316741f740SMichael Walsh    Print a message indicating what boot test is about to run.
6326741f740SMichael Walsh
6336741f740SMichael Walsh    Description of arguments:
6346741f740SMichael Walsh    boot_keyword  The name of the boot which is to be run
6356741f740SMichael Walsh                  (e.g. "BMC Power On").
6366741f740SMichael Walsh    """
6376741f740SMichael Walsh
6386741f740SMichael Walsh    global last_ten
6396741f740SMichael Walsh
6406741f740SMichael Walsh    doing_msg = gp.sprint_timen("Doing \"" + boot_keyword + "\".")
641b5839d00SMichael Walsh    gp.qprint(doing_msg)
6426741f740SMichael Walsh
6436741f740SMichael Walsh    last_ten.append(doing_msg)
6446741f740SMichael Walsh
6456741f740SMichael Walsh    if len(last_ten) > 10:
6466741f740SMichael Walsh        del last_ten[0]
6476741f740SMichael Walsh
6486741f740SMichael Walsh###############################################################################
6496741f740SMichael Walsh
6506741f740SMichael Walsh
6516741f740SMichael Walsh###############################################################################
6526741f740SMichael Walshdef run_boot(boot):
6536741f740SMichael Walsh
6546741f740SMichael Walsh    r"""
6556741f740SMichael Walsh    Run the specified boot.
6566741f740SMichael Walsh
6576741f740SMichael Walsh    Description of arguments:
6586741f740SMichael Walsh    boot  The name of the boot test to be performed.
6596741f740SMichael Walsh    """
6606741f740SMichael Walsh
6616741f740SMichael Walsh    global state
6626741f740SMichael Walsh
6636741f740SMichael Walsh    print_test_start_message(boot)
6646741f740SMichael Walsh
6656741f740SMichael Walsh    plug_in_setup()
6666741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = \
6676741f740SMichael Walsh        grpi.rprocess_plug_in_packages(call_point="pre_boot")
6686741f740SMichael Walsh    if rc != 0:
6696741f740SMichael Walsh        error_message = "Plug-in failed with non-zero return code.\n" +\
6706741f740SMichael Walsh            gp.sprint_var(rc, 1)
6716741f740SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
6726741f740SMichael Walsh
6736741f740SMichael Walsh    if test_mode:
6746741f740SMichael Walsh        # In test mode, we'll pretend the boot worked by assigning its
6756741f740SMichael Walsh        # required end state to the default state value.
67630dadae2SMichael Walsh        state = st.strip_anchor_state(boot_table[boot]['end'])
6776741f740SMichael Walsh    else:
6786741f740SMichael Walsh        # Assertion:  We trust that the state data was made fresh by the
6796741f740SMichael Walsh        # caller.
6806741f740SMichael Walsh
681b5839d00SMichael Walsh        gp.qprintn()
6826741f740SMichael Walsh
6836741f740SMichael Walsh        if boot_table[boot]['method_type'] == "keyword":
6840b93fbf8SMichael Walsh            rk.my_run_keywords(boot_table[boot].get('lib_file_path', ''),
685b5839d00SMichael Walsh                               boot_table[boot]['method'],
686b5839d00SMichael Walsh                               quiet=quiet)
6876741f740SMichael Walsh
6886741f740SMichael Walsh        if boot_table[boot]['bmc_reboot']:
6896741f740SMichael Walsh            st.wait_for_comm_cycle(int(state['epoch_seconds']))
69030dadae2SMichael Walsh            plug_in_setup()
69130dadae2SMichael Walsh            rc, shell_rc, failed_plug_in_name = \
69230dadae2SMichael Walsh                grpi.rprocess_plug_in_packages(call_point="post_reboot")
69330dadae2SMichael Walsh            if rc != 0:
6940b93fbf8SMichael Walsh                error_message = "Plug-in failed with non-zero return code.\n"
6950b93fbf8SMichael Walsh                error_message += gp.sprint_var(rc, 1)
69630dadae2SMichael Walsh                BuiltIn().fail(gp.sprint_error(error_message))
6976741f740SMichael Walsh        else:
6986741f740SMichael Walsh            match_state = st.anchor_state(state)
6996741f740SMichael Walsh            del match_state['epoch_seconds']
7006741f740SMichael Walsh            # Wait for the state to change in any way.
7016741f740SMichael Walsh            st.wait_state(match_state, wait_time=state_change_timeout,
7026741f740SMichael Walsh                          interval="3 seconds", invert=1)
7036741f740SMichael Walsh
704b5839d00SMichael Walsh        gp.qprintn()
7056741f740SMichael Walsh        if boot_table[boot]['end']['chassis'] == "Off":
7066741f740SMichael Walsh            boot_timeout = power_off_timeout
7076741f740SMichael Walsh        else:
7086741f740SMichael Walsh            boot_timeout = power_on_timeout
7096741f740SMichael Walsh        st.wait_state(boot_table[boot]['end'], wait_time=boot_timeout,
7106741f740SMichael Walsh                      interval="3 seconds")
7116741f740SMichael Walsh
7126741f740SMichael Walsh    plug_in_setup()
7136741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = \
7146741f740SMichael Walsh        grpi.rprocess_plug_in_packages(call_point="post_boot")
7156741f740SMichael Walsh    if rc != 0:
7166741f740SMichael Walsh        error_message = "Plug-in failed with non-zero return code.\n" +\
7176741f740SMichael Walsh            gp.sprint_var(rc, 1)
7186741f740SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
7196741f740SMichael Walsh
7206741f740SMichael Walsh###############################################################################
7216741f740SMichael Walsh
7226741f740SMichael Walsh
7236741f740SMichael Walsh###############################################################################
7246741f740SMichael Walshdef test_loop_body():
7256741f740SMichael Walsh
7266741f740SMichael Walsh    r"""
7276741f740SMichael Walsh    The main loop body for the loop in main_py.
7286741f740SMichael Walsh
7296741f740SMichael Walsh    Description of arguments:
7306741f740SMichael Walsh    boot_count  The iteration number (starts at 1).
7316741f740SMichael Walsh    """
7326741f740SMichael Walsh
7336741f740SMichael Walsh    global boot_count
7346741f740SMichael Walsh    global state
7356741f740SMichael Walsh    global next_boot
7366741f740SMichael Walsh    global boot_success
7376741f740SMichael Walsh
738b5839d00SMichael Walsh    gp.qprintn()
7396741f740SMichael Walsh
7406741f740SMichael Walsh    next_boot = select_boot()
741b5839d00SMichael Walsh    if next_boot == "":
742b5839d00SMichael Walsh        return True
7436741f740SMichael Walsh
744b5839d00SMichael Walsh    boot_count += 1
745b5839d00SMichael Walsh    gp.qprint_timen("Starting boot " + str(boot_count) + ".")
7466741f740SMichael Walsh
7476741f740SMichael Walsh    # Clear the ffdc_list_file_path file.  Plug-ins may now write to it.
7486741f740SMichael Walsh    try:
7496741f740SMichael Walsh        os.remove(ffdc_list_file_path)
7506741f740SMichael Walsh    except OSError:
7516741f740SMichael Walsh        pass
7526741f740SMichael Walsh
7536741f740SMichael Walsh    cmd_buf = ["run_boot", next_boot]
7546741f740SMichael Walsh    boot_status, msg = BuiltIn().run_keyword_and_ignore_error(*cmd_buf)
7556741f740SMichael Walsh    if boot_status == "FAIL":
756b5839d00SMichael Walsh        gp.qprint(msg)
7576741f740SMichael Walsh
758b5839d00SMichael Walsh    gp.qprintn()
7596741f740SMichael Walsh    if boot_status == "PASS":
7606741f740SMichael Walsh        boot_success = 1
761b5839d00SMichael Walsh        gp.qprint_timen("BOOT_SUCCESS: \"" + next_boot + "\" succeeded.")
7626741f740SMichael Walsh    else:
7636741f740SMichael Walsh        boot_success = 0
764b5839d00SMichael Walsh        gp.qprint_timen("BOOT_FAILED: \"" + next_boot + "\" failed.")
7656741f740SMichael Walsh
7666741f740SMichael Walsh    boot_results.update(next_boot, boot_status)
7676741f740SMichael Walsh
7686741f740SMichael Walsh    plug_in_setup()
7696741f740SMichael Walsh    # NOTE: A post_test_case call point failure is NOT counted as a boot
7706741f740SMichael Walsh    # failure.
7716741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
7726741f740SMichael Walsh        call_point='post_test_case', stop_on_plug_in_failure=1)
7736741f740SMichael Walsh
7746741f740SMichael Walsh    plug_in_setup()
7756741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
7766741f740SMichael Walsh        call_point='ffdc_check', shell_rc=0x00000200,
7776741f740SMichael Walsh        stop_on_plug_in_failure=1, stop_on_non_zero_rc=1)
7786741f740SMichael Walsh    if boot_status != "PASS" or ffdc_check == "All" or shell_rc == 0x00000200:
77983f4bc77SMichael Walsh        status, ret_values = grk.run_key_u("my_ffdc", ignore=1)
78083f4bc77SMichael Walsh        if status != 'PASS':
7813328caffSMichael Walsh            gp.print_error("Call to my_ffdc failed.\n")
7826741f740SMichael Walsh
783d139f286SMichael Walsh    # We need to purge error logs between boots or they build up.
784b5839d00SMichael Walsh    grk.run_key("Delete Error logs", ignore=1)
785d139f286SMichael Walsh
786952f9b09SMichael Walsh    boot_results.print_report()
787b5839d00SMichael Walsh    gp.qprint_timen("Finished boot " + str(boot_count) + ".")
788952f9b09SMichael Walsh
7896741f740SMichael Walsh    plug_in_setup()
7906741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
7916741f740SMichael Walsh        call_point='stop_check')
7926741f740SMichael Walsh    if rc != 0:
7936741f740SMichael Walsh        error_message = "Stopping as requested by user.\n"
7946741f740SMichael Walsh        grp.rprint_error_report(error_message)
7956741f740SMichael Walsh        BuiltIn().fail(error_message)
7966741f740SMichael Walsh
797d139f286SMichael Walsh    # This should help prevent ConnectionErrors.
798b5839d00SMichael Walsh    grk.run_key_u("Delete All Sessions")
799d139f286SMichael Walsh
8006741f740SMichael Walsh    return True
8016741f740SMichael Walsh
8026741f740SMichael Walsh###############################################################################
8036741f740SMichael Walsh
8046741f740SMichael Walsh
8056741f740SMichael Walsh###############################################################################
80683f4bc77SMichael Walshdef obmc_boot_test_teardown():
8076741f740SMichael Walsh
8086741f740SMichael Walsh    r"""
809c9116811SMichael Walsh    Clean up after the Main keyword.
8106741f740SMichael Walsh    """
8116741f740SMichael Walsh
8126741f740SMichael Walsh    if cp_setup_called:
8136741f740SMichael Walsh        plug_in_setup()
8146741f740SMichael Walsh        rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
8156741f740SMichael Walsh            call_point='cleanup', stop_on_plug_in_failure=1)
8166741f740SMichael Walsh
8170b93fbf8SMichael Walsh    # Save boot_results object to a file in case it is needed again.
818b5839d00SMichael Walsh    gp.qprint_timen("Saving boot_results to the following path.")
819b5839d00SMichael Walsh    gp.qprint_var(boot_results_file_path)
8200b93fbf8SMichael Walsh    pickle.dump(boot_results, open(boot_results_file_path, 'wb'),
8210b93fbf8SMichael Walsh                pickle.HIGHEST_PROTOCOL)
8220b93fbf8SMichael Walsh
8236741f740SMichael Walsh###############################################################################
8246741f740SMichael Walsh
8256741f740SMichael Walsh
8266741f740SMichael Walsh###############################################################################
827c9116811SMichael Walshdef test_teardown():
828c9116811SMichael Walsh
829c9116811SMichael Walsh    r"""
830c9116811SMichael Walsh    Clean up after this test case.
831c9116811SMichael Walsh    """
832c9116811SMichael Walsh
833c9116811SMichael Walsh    gp.qprintn()
834c9116811SMichael Walsh    cmd_buf = ["Print Error",
835c9116811SMichael Walsh               "A keyword timeout occurred ending this program.\n"]
836c9116811SMichael Walsh    BuiltIn().run_keyword_if_timeout_occurred(*cmd_buf)
837c9116811SMichael Walsh
838b5839d00SMichael Walsh    grp.rqprint_pgm_footer()
839b5839d00SMichael Walsh
840c9116811SMichael Walsh###############################################################################
841c9116811SMichael Walsh
842c9116811SMichael Walsh
843c9116811SMichael Walsh###############################################################################
84483f4bc77SMichael Walshdef obmc_boot_test_py(alt_boot_stack=None):
8456741f740SMichael Walsh
8466741f740SMichael Walsh    r"""
8476741f740SMichael Walsh    Do main program processing.
8486741f740SMichael Walsh    """
8496741f740SMichael Walsh
850b5839d00SMichael Walsh    if alt_boot_stack is not None:
851b5839d00SMichael Walsh        BuiltIn().set_global_variable("${boot_stack}", alt_boot_stack)
852b5839d00SMichael Walsh
8536741f740SMichael Walsh    setup()
8546741f740SMichael Walsh
855a20da401SMichael Walsh    if ffdc_only:
856a20da401SMichael Walsh        gp.qprint_timen("Caller requested ffdc_only.")
85783f4bc77SMichael Walsh        grk.run_key_u("my_ffdc")
858764d2f83SMichael Walsh        return
859a20da401SMichael Walsh
8606741f740SMichael Walsh    # Process caller's boot_stack.
8616741f740SMichael Walsh    while (len(boot_stack) > 0):
8626741f740SMichael Walsh        test_loop_body()
8636741f740SMichael Walsh
864b5839d00SMichael Walsh    gp.qprint_timen("Finished processing stack.")
86530dadae2SMichael Walsh
8666741f740SMichael Walsh    # Process caller's boot_list.
8676741f740SMichael Walsh    if len(boot_list) > 0:
8686741f740SMichael Walsh        for ix in range(1, max_num_tests + 1):
8696741f740SMichael Walsh            test_loop_body()
8706741f740SMichael Walsh
871b5839d00SMichael Walsh    gp.qprint_timen("Completed all requested boot tests.")
872b5839d00SMichael Walsh
873b5839d00SMichael Walsh    boot_pass, boot_fail = boot_results.return_total_pass_fail()
874b5839d00SMichael Walsh    if boot_fail > boot_fail_threshold:
875b5839d00SMichael Walsh        error_message = "Boot failures exceed the boot failure" +\
876b5839d00SMichael Walsh                        " threshold:\n" +\
877b5839d00SMichael Walsh                        gp.sprint_var(boot_fail) +\
878b5839d00SMichael Walsh                        gp.sprint_var(boot_fail_threshold)
879b5839d00SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
8806741f740SMichael Walsh
8816741f740SMichael Walsh###############################################################################
882