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
13f566fb1fSMichael Walshimport signal
14d54bbc22SGeorge Keishingtry:
150b93fbf8SMichael Walsh    import cPickle as pickle
16d54bbc22SGeorge Keishingexcept ImportError:
17d54bbc22SGeorge Keishing    import pickle
18dc80d67dSMichael Walshimport socket
190b93fbf8SMichael Walsh
200b93fbf8SMichael Walshfrom robot.utils import DotDict
210b93fbf8SMichael Walshfrom robot.libraries.BuiltIn import BuiltIn
220b93fbf8SMichael Walsh
236741f740SMichael Walshfrom boot_data import *
24c9116811SMichael Walshimport gen_print as gp
2555302295SMichael Walshimport gen_robot_plug_in as grpi
26f75d4354SMichael Walshimport gen_arg as ga
2744cef258SMichael Walshimport gen_valid as gv
286741f740SMichael Walshimport gen_misc as gm
296741f740SMichael Walshimport gen_cmd as gc
30b5839d00SMichael Walshimport gen_robot_keyword as grk
3155302295SMichael Walshimport state as st
32ff340006SMichael Walshimport var_stack as vs
33c9bd2e87SMichael Walshimport gen_plug_in_utils as gpu
340bbd860fSMichael Walsh
350b93fbf8SMichael Walshbase_path = os.path.dirname(os.path.dirname(
360b93fbf8SMichael Walsh                            imp.find_module("gen_robot_print")[1])) +\
370b93fbf8SMichael Walsh    os.sep
380b93fbf8SMichael Walshsys.path.append(base_path + "extended/")
390b93fbf8SMichael Walshimport run_keyword as rk
400bbd860fSMichael Walsh
41e1e26448SMichael Walsh# Setting master_pid correctly influences the behavior of plug-ins like
42e1e26448SMichael Walsh# DB_Logging
43e1e26448SMichael Walshprogram_pid = os.getpid()
44e1e26448SMichael Walshmaster_pid = os.environ.get('AUTOBOOT_MASTER_PID', program_pid)
45004ad3c9SJoy Onyerikwupgm_name = re.sub('\\.py$', '', os.path.basename(__file__))
46e1e26448SMichael Walsh
47b5839d00SMichael Walsh# Set up boot data structures.
48986d8aeeSMichael Walshos_host = BuiltIn().get_variable_value("${OS_HOST}", default="")
490b93fbf8SMichael Walsh
506741f740SMichael Walshboot_lists = read_boot_lists()
51986d8aeeSMichael Walsh
52986d8aeeSMichael Walsh# The maximum number of entries that can be in the boot_history global variable.
53815b1d5bSMichael Walshmax_boot_history = 10
54986d8aeeSMichael Walshboot_history = []
556741f740SMichael Walsh
567dc885b6SMichael Walshstate = st.return_state_constant('default_state')
576741f740SMichael Walshcp_setup_called = 0
586741f740SMichael Walshnext_boot = ""
596741f740SMichael Walshbase_tool_dir_path = os.path.normpath(os.environ.get(
606741f740SMichael Walsh    'AUTOBOOT_BASE_TOOL_DIR_PATH', "/tmp")) + os.sep
61b5839d00SMichael Walsh
626741f740SMichael Walshffdc_dir_path = os.path.normpath(os.environ.get('FFDC_DIR_PATH', '')) + os.sep
636741f740SMichael Walshboot_success = 0
646741f740SMichael Walshstatus_dir_path = os.environ.get('STATUS_DIR_PATH', "")
656741f740SMichael Walshif status_dir_path != "":
666741f740SMichael Walsh    status_dir_path = os.path.normpath(status_dir_path) + os.sep
67e58df1c8SMichael Walshredfish_supported = BuiltIn().get_variable_value("${REDFISH_SUPPORTED}", default=False)
68e58df1c8SMichael Walshif redfish_supported:
69e58df1c8SMichael Walsh    default_power_on = "Redfish Power On"
70e58df1c8SMichael Walsh    default_power_off = "Redfish Power Off"
71409ad35aSMichael Walsh    delete_errlogs_cmd = "Delete Error Logs"
72409ad35aSMichael Walsh    # TODO: delete_errlogs_cmd="Redfish Purge Event Log"
73e58df1c8SMichael Walshelse:
740b93fbf8SMichael Walsh    default_power_on = "REST Power On"
750b93fbf8SMichael Walsh    default_power_off = "REST Power Off"
76409ad35aSMichael Walsh    delete_errlogs_cmd = "Delete Error Logs"
776741f740SMichael Walshboot_count = 0
780bbd860fSMichael Walsh
7985678948SMichael WalshLOG_LEVEL = BuiltIn().get_variable_value("${LOG_LEVEL}")
80986d8aeeSMichael WalshAUTOBOOT_FFDC_PREFIX = os.environ.get('AUTOBOOT_FFDC_PREFIX', '')
81986d8aeeSMichael Walshffdc_prefix = AUTOBOOT_FFDC_PREFIX
82325eb548SSunil Mboot_start_time = ""
83325eb548SSunil Mboot_end_time = ""
84ff340006SMichael Walshsave_stack = vs.var_stack('save_stack')
85ff340006SMichael Walshmain_func_parm_list = ['boot_stack', 'stack_mode', 'quiet']
8685678948SMichael Walsh
8785678948SMichael Walsh
8889de14a4SMichael Walshdef dump_ffdc_rc():
8989de14a4SMichael Walsh    r"""
9089de14a4SMichael Walsh    Return the constant dump ffdc test return code value.
9189de14a4SMichael Walsh
9289de14a4SMichael Walsh    When a plug-in call point program returns this value, it indicates that
9389de14a4SMichael Walsh    this program should collect FFDC.
9489de14a4SMichael Walsh    """
9589de14a4SMichael Walsh
9689de14a4SMichael Walsh    return 0x00000200
9789de14a4SMichael Walsh
9889de14a4SMichael Walsh
9989de14a4SMichael Walshdef stop_test_rc():
10089de14a4SMichael Walsh    r"""
10189de14a4SMichael Walsh    Return the constant stop test return code value.
10289de14a4SMichael Walsh
10389de14a4SMichael Walsh    When a plug-in call point program returns this value, it indicates that
10489de14a4SMichael Walsh    this program should stop running.
10589de14a4SMichael Walsh    """
10689de14a4SMichael Walsh
10789de14a4SMichael Walsh    return 0x00000200
10889de14a4SMichael Walsh
10989de14a4SMichael Walsh
1100ad0f7f8SMichael Walshdef process_host(host,
1110ad0f7f8SMichael Walsh                 host_var_name=""):
1120ad0f7f8SMichael Walsh    r"""
1130ad0f7f8SMichael Walsh    Process a host by getting the associated host name and IP address and
1140ad0f7f8SMichael Walsh    setting them in global variables.
1150ad0f7f8SMichael Walsh
1160ad0f7f8SMichael Walsh    If the caller does not pass the host_var_name, this function will try to
1170ad0f7f8SMichael Walsh    figure out the name of the variable used by the caller for the host parm.
1180ad0f7f8SMichael Walsh    Callers are advised to explicitly specify the host_var_name when calling
1190ad0f7f8SMichael Walsh    with an exec command.  In such cases, the get_arg_name cannot figure out
1200ad0f7f8SMichael Walsh    the host variable name.
1210ad0f7f8SMichael Walsh
1220ad0f7f8SMichael Walsh    This function will then create similar global variable names by
1230ad0f7f8SMichael Walsh    removing "_host" and appending "_host_name" or "_ip" to the host variable
1240ad0f7f8SMichael Walsh    name.
1250ad0f7f8SMichael Walsh
1260ad0f7f8SMichael Walsh    Example:
1270ad0f7f8SMichael Walsh
1280ad0f7f8SMichael Walsh    If a call is made like this:
1290ad0f7f8SMichael Walsh    process_host(openbmc_host)
1300ad0f7f8SMichael Walsh
1310ad0f7f8SMichael Walsh    Global variables openbmc_host_name and openbmc_ip will be set.
1320ad0f7f8SMichael Walsh
1330ad0f7f8SMichael Walsh    Description of argument(s):
1340ad0f7f8SMichael Walsh    host           A host name or IP.  The name of the variable used should
1350ad0f7f8SMichael Walsh                   have a suffix of "_host".
1360ad0f7f8SMichael Walsh    host_var_name  The name of the variable being used as the host parm.
1370ad0f7f8SMichael Walsh    """
1380ad0f7f8SMichael Walsh
1390ad0f7f8SMichael Walsh    if host_var_name == "":
1400ad0f7f8SMichael Walsh        host_var_name = gp.get_arg_name(0, 1, stack_frame_ix=2)
1410ad0f7f8SMichael Walsh
1420ad0f7f8SMichael Walsh    host_name_var_name = re.sub("host", "host_name", host_var_name)
1430ad0f7f8SMichael Walsh    ip_var_name = re.sub("host", "ip", host_var_name)
1440ad0f7f8SMichael Walsh    cmd_buf = "global " + host_name_var_name + ", " + ip_var_name + " ; " +\
1450ad0f7f8SMichael Walsh        host_name_var_name + ", " + ip_var_name + " = gm.get_host_name_ip('" +\
1460ad0f7f8SMichael Walsh        host + "')"
1470ad0f7f8SMichael Walsh    exec(cmd_buf)
1480ad0f7f8SMichael Walsh
1490ad0f7f8SMichael Walsh
150b5839d00SMichael Walshdef process_pgm_parms():
151b5839d00SMichael Walsh    r"""
152b5839d00SMichael Walsh    Process the program parameters by assigning them all to corresponding
153b5839d00SMichael Walsh    globals.  Also, set some global values that depend on program parameters.
154b5839d00SMichael Walsh    """
155b5839d00SMichael Walsh
156b5839d00SMichael Walsh    # Program parameter processing.
157b5839d00SMichael Walsh    # Assign all program parms to python variables which are global to this
158b5839d00SMichael Walsh    # module.
159b5839d00SMichael Walsh
160b5839d00SMichael Walsh    global parm_list
161b5839d00SMichael Walsh    parm_list = BuiltIn().get_variable_value("${parm_list}")
162b5839d00SMichael Walsh    # The following subset of parms should be processed as integers.
163b5839d00SMichael Walsh    int_list = ['max_num_tests', 'boot_pass', 'boot_fail', 'ffdc_only',
16489de14a4SMichael Walsh                'boot_fail_threshold', 'delete_errlogs',
165986d8aeeSMichael Walsh                'call_post_stack_plug', 'do_pre_boot_plug_in_setup', 'quiet',
166986d8aeeSMichael Walsh                'test_mode', 'debug']
167b5839d00SMichael Walsh    for parm in parm_list:
168b5839d00SMichael Walsh        if parm in int_list:
169b5839d00SMichael Walsh            sub_cmd = "int(BuiltIn().get_variable_value(\"${" + parm +\
170b5839d00SMichael Walsh                      "}\", \"0\"))"
171b5839d00SMichael Walsh        else:
172b5839d00SMichael Walsh            sub_cmd = "BuiltIn().get_variable_value(\"${" + parm + "}\")"
173b5839d00SMichael Walsh        cmd_buf = "global " + parm + " ; " + parm + " = " + sub_cmd
174ff340006SMichael Walsh        gp.dpissuing(cmd_buf)
175b5839d00SMichael Walsh        exec(cmd_buf)
1760ad0f7f8SMichael Walsh        if re.match(r".*_host$", parm):
1770ad0f7f8SMichael Walsh            cmd_buf = "process_host(" + parm + ", '" + parm + "')"
1780ad0f7f8SMichael Walsh            exec(cmd_buf)
1790ad0f7f8SMichael Walsh        if re.match(r".*_password$", parm):
1800ad0f7f8SMichael Walsh            # Register the value of any parm whose name ends in _password.
1810ad0f7f8SMichael Walsh            # This will cause the print functions to replace passwords with
1820ad0f7f8SMichael Walsh            # asterisks in the output.
1830ad0f7f8SMichael Walsh            cmd_buf = "gp.register_passwords(" + parm + ")"
1840ad0f7f8SMichael Walsh            exec(cmd_buf)
185b5839d00SMichael Walsh
186b5839d00SMichael Walsh    global ffdc_dir_path_style
187b5839d00SMichael Walsh    global boot_list
188b5839d00SMichael Walsh    global boot_stack
189b5839d00SMichael Walsh    global boot_results_file_path
190b5839d00SMichael Walsh    global boot_results
191986d8aeeSMichael Walsh    global boot_history
192b5839d00SMichael Walsh    global ffdc_list_file_path
193e0cf8d70SMichael Walsh    global ffdc_report_list_path
194600876daSMichael Walsh    global ffdc_summary_list_path
195a3e7b222SMichael Walsh    global boot_table
196a3e7b222SMichael Walsh    global valid_boot_types
197b5839d00SMichael Walsh
198b5839d00SMichael Walsh    if ffdc_dir_path_style == "":
199b5839d00SMichael Walsh        ffdc_dir_path_style = int(os.environ.get('FFDC_DIR_PATH_STYLE', '0'))
200b5839d00SMichael Walsh
201b5839d00SMichael Walsh    # Convert these program parms to lists for easier processing..
20236efbc04SGeorge Keishing    boot_list = list(filter(None, boot_list.split(":")))
20336efbc04SGeorge Keishing    boot_stack = list(filter(None, boot_stack.split(":")))
204b5839d00SMichael Walsh
205a3e7b222SMichael Walsh    boot_table = create_boot_table(boot_table_path, os_host=os_host)
206a3e7b222SMichael Walsh    valid_boot_types = create_valid_boot_list(boot_table)
207a3e7b222SMichael Walsh
208903e0b20SMichael Walsh    cleanup_boot_results_file()
209903e0b20SMichael Walsh    boot_results_file_path = create_boot_results_file_path(pgm_name,
210903e0b20SMichael Walsh                                                           openbmc_nickname,
211903e0b20SMichael Walsh                                                           master_pid)
212b5839d00SMichael Walsh
213b5839d00SMichael Walsh    if os.path.isfile(boot_results_file_path):
214b5839d00SMichael Walsh        # We've been called before in this run so we'll load the saved
215986d8aeeSMichael Walsh        # boot_results and boot_history objects.
216986d8aeeSMichael Walsh        boot_results, boot_history =\
2176c64574bSMichael Walsh            pickle.load(open(boot_results_file_path, 'rb'))
218b5839d00SMichael Walsh    else:
219b5839d00SMichael Walsh        boot_results = boot_results(boot_table, boot_pass, boot_fail)
220b5839d00SMichael Walsh
221b5839d00SMichael Walsh    ffdc_list_file_path = base_tool_dir_path + openbmc_nickname +\
222b5839d00SMichael Walsh        "/FFDC_FILE_LIST"
223e0cf8d70SMichael Walsh    ffdc_report_list_path = base_tool_dir_path + openbmc_nickname +\
224e0cf8d70SMichael Walsh        "/FFDC_REPORT_FILE_LIST"
225b5839d00SMichael Walsh
226600876daSMichael Walsh    ffdc_summary_list_path = base_tool_dir_path + openbmc_nickname +\
227600876daSMichael Walsh        "/FFDC_SUMMARY_FILE_LIST"
228600876daSMichael Walsh
229b5839d00SMichael Walsh
23085678948SMichael Walshdef initial_plug_in_setup():
23185678948SMichael Walsh    r"""
23285678948SMichael Walsh    Initialize all plug-in environment variables which do not change for the
23385678948SMichael Walsh    duration of the program.
23485678948SMichael Walsh
23585678948SMichael Walsh    """
23685678948SMichael Walsh
23785678948SMichael Walsh    global LOG_LEVEL
23885678948SMichael Walsh    BuiltIn().set_log_level("NONE")
23985678948SMichael Walsh
24085678948SMichael Walsh    BuiltIn().set_global_variable("${master_pid}", master_pid)
24185678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_DIR_PATH}", ffdc_dir_path)
24285678948SMichael Walsh    BuiltIn().set_global_variable("${STATUS_DIR_PATH}", status_dir_path)
24385678948SMichael Walsh    BuiltIn().set_global_variable("${BASE_TOOL_DIR_PATH}", base_tool_dir_path)
24485678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_LIST_FILE_PATH}",
24585678948SMichael Walsh                                  ffdc_list_file_path)
246e0cf8d70SMichael Walsh    BuiltIn().set_global_variable("${FFDC_REPORT_LIST_PATH}",
247e0cf8d70SMichael Walsh                                  ffdc_report_list_path)
248600876daSMichael Walsh    BuiltIn().set_global_variable("${FFDC_SUMMARY_LIST_PATH}",
249600876daSMichael Walsh                                  ffdc_summary_list_path)
25085678948SMichael Walsh
25185678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_DIR_PATH_STYLE}",
25285678948SMichael Walsh                                  ffdc_dir_path_style)
25385678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_CHECK}",
25485678948SMichael Walsh                                  ffdc_check)
25585678948SMichael Walsh
25685678948SMichael Walsh    # For each program parameter, set the corresponding AUTOBOOT_ environment
25785678948SMichael Walsh    # variable value.  Also, set an AUTOBOOT_ environment variable for every
25885678948SMichael Walsh    # element in additional_values.
25985678948SMichael Walsh    additional_values = ["program_pid", "master_pid", "ffdc_dir_path",
26085678948SMichael Walsh                         "status_dir_path", "base_tool_dir_path",
261600876daSMichael Walsh                         "ffdc_list_file_path", "ffdc_report_list_path",
2620a3bdb4cSMichael Walsh                         "ffdc_summary_list_path", "execdir"]
26385678948SMichael Walsh
26485678948SMichael Walsh    plug_in_vars = parm_list + additional_values
26585678948SMichael Walsh
26685678948SMichael Walsh    for var_name in plug_in_vars:
26785678948SMichael Walsh        var_value = BuiltIn().get_variable_value("${" + var_name + "}")
26885678948SMichael Walsh        var_name = var_name.upper()
26985678948SMichael Walsh        if var_value is None:
27085678948SMichael Walsh            var_value = ""
27185678948SMichael Walsh        os.environ["AUTOBOOT_" + var_name] = str(var_value)
27285678948SMichael Walsh
27385678948SMichael Walsh    BuiltIn().set_log_level(LOG_LEVEL)
27485678948SMichael Walsh
27568a61162SMichael Walsh    # Make sure the ffdc list directory exists.
27668a61162SMichael Walsh    ffdc_list_dir_path = os.path.dirname(ffdc_list_file_path) + os.sep
27768a61162SMichael Walsh    if not os.path.exists(ffdc_list_dir_path):
27868a61162SMichael Walsh        os.makedirs(ffdc_list_dir_path)
27985678948SMichael Walsh
28085678948SMichael Walsh
2810bbd860fSMichael Walshdef plug_in_setup():
2820bbd860fSMichael Walsh    r"""
28385678948SMichael Walsh    Initialize all changing plug-in environment variables for use by the
28485678948SMichael Walsh    plug-in programs.
2850bbd860fSMichael Walsh    """
2860bbd860fSMichael Walsh
28785678948SMichael Walsh    global LOG_LEVEL
28885678948SMichael Walsh    global test_really_running
28985678948SMichael Walsh
29085678948SMichael Walsh    BuiltIn().set_log_level("NONE")
29185678948SMichael Walsh
2926741f740SMichael Walsh    boot_pass, boot_fail = boot_results.return_total_pass_fail()
2930bbd860fSMichael Walsh    if boot_pass > 1:
2940bbd860fSMichael Walsh        test_really_running = 1
2950bbd860fSMichael Walsh    else:
2960bbd860fSMichael Walsh        test_really_running = 0
2970bbd860fSMichael Walsh
2986741f740SMichael Walsh    BuiltIn().set_global_variable("${test_really_running}",
2996741f740SMichael Walsh                                  test_really_running)
3006741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_type_desc}", next_boot)
3016741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_pass}", boot_pass)
3026741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_fail}", boot_fail)
3036741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_success}", boot_success)
3046741f740SMichael Walsh    BuiltIn().set_global_variable("${ffdc_prefix}", ffdc_prefix)
305325eb548SSunil M    BuiltIn().set_global_variable("${boot_start_time}", boot_start_time)
306325eb548SSunil M    BuiltIn().set_global_variable("${boot_end_time}", boot_end_time)
3074c9a6453SMichael Walsh
3080bbd860fSMichael Walsh    # For each program parameter, set the corresponding AUTOBOOT_ environment
3090bbd860fSMichael Walsh    # variable value.  Also, set an AUTOBOOT_ environment variable for every
3100bbd860fSMichael Walsh    # element in additional_values.
3110bbd860fSMichael Walsh    additional_values = ["boot_type_desc", "boot_success", "boot_pass",
312325eb548SSunil M                         "boot_fail", "test_really_running", "ffdc_prefix",
313325eb548SSunil M                         "boot_start_time", "boot_end_time"]
3140bbd860fSMichael Walsh
31585678948SMichael Walsh    plug_in_vars = additional_values
3160bbd860fSMichael Walsh
3170bbd860fSMichael Walsh    for var_name in plug_in_vars:
3180bbd860fSMichael Walsh        var_value = BuiltIn().get_variable_value("${" + var_name + "}")
3190bbd860fSMichael Walsh        var_name = var_name.upper()
3200bbd860fSMichael Walsh        if var_value is None:
3210bbd860fSMichael Walsh            var_value = ""
3226741f740SMichael Walsh        os.environ["AUTOBOOT_" + var_name] = str(var_value)
3230bbd860fSMichael Walsh
3240bbd860fSMichael Walsh    if debug:
3256741f740SMichael Walsh        shell_rc, out_buf = \
3266741f740SMichael Walsh            gc.cmd_fnc_u("printenv | egrep AUTOBOOT_ | sort -u")
3270bbd860fSMichael Walsh
32885678948SMichael Walsh    BuiltIn().set_log_level(LOG_LEVEL)
32985678948SMichael Walsh
3300bbd860fSMichael Walsh
331e0cf8d70SMichael Walshdef pre_boot_plug_in_setup():
332e0cf8d70SMichael Walsh
333e0cf8d70SMichael Walsh    # Clear the ffdc_list_file_path file.  Plug-ins may now write to it.
334e0cf8d70SMichael Walsh    try:
335e0cf8d70SMichael Walsh        os.remove(ffdc_list_file_path)
336e0cf8d70SMichael Walsh    except OSError:
337e0cf8d70SMichael Walsh        pass
338e0cf8d70SMichael Walsh
339e0cf8d70SMichael Walsh    # Clear the ffdc_report_list_path file.  Plug-ins may now write to it.
340e0cf8d70SMichael Walsh    try:
341e0cf8d70SMichael Walsh        os.remove(ffdc_report_list_path)
342e0cf8d70SMichael Walsh    except OSError:
343e0cf8d70SMichael Walsh        pass
344e0cf8d70SMichael Walsh
345600876daSMichael Walsh    # Clear the ffdc_summary_list_path file.  Plug-ins may now write to it.
346600876daSMichael Walsh    try:
347600876daSMichael Walsh        os.remove(ffdc_summary_list_path)
348600876daSMichael Walsh    except OSError:
349600876daSMichael Walsh        pass
350600876daSMichael Walsh
351e1974b96SMichael Walsh    global ffdc_prefix
352e1974b96SMichael Walsh
353e1974b96SMichael Walsh    seconds = time.time()
354e1974b96SMichael Walsh    loc_time = time.localtime(seconds)
355e1974b96SMichael Walsh    time_string = time.strftime("%y%m%d.%H%M%S.", loc_time)
356e1974b96SMichael Walsh
357e1974b96SMichael Walsh    ffdc_prefix = openbmc_nickname + "." + time_string
358e1974b96SMichael Walsh
359e0cf8d70SMichael Walsh
360f566fb1fSMichael Walshdef default_sigusr1(signal_number=0,
361f566fb1fSMichael Walsh                    frame=None):
362f566fb1fSMichael Walsh    r"""
363f566fb1fSMichael Walsh    Handle SIGUSR1 by doing nothing.
364f566fb1fSMichael Walsh
365f566fb1fSMichael Walsh    This function assists in debugging SIGUSR1 processing by printing messages
366f566fb1fSMichael Walsh    to stdout and to the log.html file.
367f566fb1fSMichael Walsh
368f566fb1fSMichael Walsh    Description of argument(s):
369f566fb1fSMichael Walsh    signal_number  The signal number (should always be 10 for SIGUSR1).
370f566fb1fSMichael Walsh    frame          The frame data.
371f566fb1fSMichael Walsh    """
372f566fb1fSMichael Walsh
37380dddde9SMichael Walsh    gp.qprintn()
37480dddde9SMichael Walsh    gp.qprint_executing()
375f566fb1fSMichael Walsh    gp.lprint_executing()
376f566fb1fSMichael Walsh
377f566fb1fSMichael Walsh
378f566fb1fSMichael Walshdef set_default_siguser1():
379f566fb1fSMichael Walsh    r"""
380f566fb1fSMichael Walsh    Set the default_sigusr1 function to be the SIGUSR1 handler.
381f566fb1fSMichael Walsh    """
382f566fb1fSMichael Walsh
38380dddde9SMichael Walsh    gp.qprintn()
38480dddde9SMichael Walsh    gp.qprint_executing()
385f566fb1fSMichael Walsh    gp.lprint_executing()
386f566fb1fSMichael Walsh    signal.signal(signal.SIGUSR1, default_sigusr1)
387f566fb1fSMichael Walsh
388f566fb1fSMichael Walsh
3896741f740SMichael Walshdef setup():
3900bbd860fSMichael Walsh    r"""
3916741f740SMichael Walsh    Do general program setup tasks.
3920bbd860fSMichael Walsh    """
3930bbd860fSMichael Walsh
3946741f740SMichael Walsh    global cp_setup_called
39581816748SMichael Walsh    global transitional_boot_selected
3960bbd860fSMichael Walsh
397b5839d00SMichael Walsh    gp.qprintn()
398b5839d00SMichael Walsh
399f566fb1fSMichael Walsh    set_default_siguser1()
40081816748SMichael Walsh    transitional_boot_selected = False
40181816748SMichael Walsh
40283f4bc77SMichael Walsh    robot_pgm_dir_path = os.path.dirname(__file__) + os.sep
40383f4bc77SMichael Walsh    repo_bin_path = robot_pgm_dir_path.replace("/lib/", "/bin/")
404d061c043SMichael Walsh    # If we can't find process_plug_in_packages.py, ssh_pw or
405d061c043SMichael Walsh    # validate_plug_ins.py, then we don't have our repo bin in PATH.
406004ad3c9SJoy Onyerikwu    shell_rc, out_buf = gc.cmd_fnc_u("which process_plug_in_packages.py"
407004ad3c9SJoy Onyerikwu                                     + " ssh_pw validate_plug_ins.py", quiet=1,
408d061c043SMichael Walsh                                     print_output=0, show_err=0)
409b5839d00SMichael Walsh    if shell_rc != 0:
41083f4bc77SMichael Walsh        os.environ['PATH'] = repo_bin_path + ":" + os.environ.get('PATH', "")
41183f4bc77SMichael Walsh    # Likewise, our repo lib subdir needs to be in sys.path and PYTHONPATH.
41283f4bc77SMichael Walsh    if robot_pgm_dir_path not in sys.path:
41383f4bc77SMichael Walsh        sys.path.append(robot_pgm_dir_path)
41483f4bc77SMichael Walsh        PYTHONPATH = os.environ.get("PYTHONPATH", "")
41583f4bc77SMichael Walsh        if PYTHONPATH == "":
41683f4bc77SMichael Walsh            os.environ['PYTHONPATH'] = robot_pgm_dir_path
41783f4bc77SMichael Walsh        else:
41883f4bc77SMichael Walsh            os.environ['PYTHONPATH'] = robot_pgm_dir_path + ":" + PYTHONPATH
4196741f740SMichael Walsh
4206741f740SMichael Walsh    validate_parms()
4216741f740SMichael Walsh
422c108e429SMichael Walsh    gp.qprint_pgm_header()
4236741f740SMichael Walsh
424efc3ff2bSGeorge Keishing    grk.run_key("Set BMC Power Policy  ALWAYS_POWER_OFF")
42511cfc8c0SMichael Walsh
42685678948SMichael Walsh    initial_plug_in_setup()
42785678948SMichael Walsh
4286741f740SMichael Walsh    plug_in_setup()
4296741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
4306741f740SMichael Walsh        call_point='setup')
4316741f740SMichael Walsh    if rc != 0:
4326741f740SMichael Walsh        error_message = "Plug-in setup failed.\n"
433c108e429SMichael Walsh        gp.print_error_report(error_message)
4346741f740SMichael Walsh        BuiltIn().fail(error_message)
4356741f740SMichael Walsh    # Setting cp_setup_called lets our Teardown know that it needs to call
4366741f740SMichael Walsh    # the cleanup plug-in call point.
4376741f740SMichael Walsh    cp_setup_called = 1
4386741f740SMichael Walsh
4396741f740SMichael Walsh    # Keyword "FFDC" will fail if TEST_MESSAGE is not set.
4406741f740SMichael Walsh    BuiltIn().set_global_variable("${TEST_MESSAGE}", "${EMPTY}")
44185678948SMichael Walsh    # FFDC_LOG_PATH is used by "FFDC" keyword.
44285678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_LOG_PATH}", ffdc_dir_path)
4436741f740SMichael Walsh
444dc80d67dSMichael Walsh    # Also printed by FFDC.
445dc80d67dSMichael Walsh    global host_name
446dc80d67dSMichael Walsh    global host_ip
447dc80d67dSMichael Walsh    host = socket.gethostname()
448dc80d67dSMichael Walsh    host_name, host_ip = gm.get_host_name_ip(host)
449dc80d67dSMichael Walsh
450986d8aeeSMichael Walsh    gp.dprint_var(boot_table)
451b5839d00SMichael Walsh    gp.dprint_var(boot_lists)
4520bbd860fSMichael Walsh
4530bbd860fSMichael Walsh
4546741f740SMichael Walshdef validate_parms():
4550bbd860fSMichael Walsh    r"""
4566741f740SMichael Walsh    Validate all program parameters.
4570bbd860fSMichael Walsh    """
4580bbd860fSMichael Walsh
459b5839d00SMichael Walsh    process_pgm_parms()
4600bbd860fSMichael Walsh
461b5839d00SMichael Walsh    gp.qprintn()
462b5839d00SMichael Walsh
463b5839d00SMichael Walsh    global openbmc_model
464*f5ce38c3SMichael Walsh    if openbmc_model == "":
465*f5ce38c3SMichael Walsh        status, ret_values =\
466*f5ce38c3SMichael Walsh            grk.run_key_u("Get BMC System Model")
467*f5ce38c3SMichael Walsh        openbmc_model = ret_values
468*f5ce38c3SMichael Walsh        BuiltIn().set_global_variable("${openbmc_model}", openbmc_model)
469*f5ce38c3SMichael Walsh    gv.set_exit_on_error(True)
47044cef258SMichael Walsh    gv.valid_value(openbmc_host)
47144cef258SMichael Walsh    gv.valid_value(openbmc_username)
47244cef258SMichael Walsh    gv.valid_value(openbmc_password)
47344cef258SMichael Walsh    gv.valid_value(rest_username)
47444cef258SMichael Walsh    gv.valid_value(rest_password)
47544cef258SMichael Walsh    gv.valid_value(ipmi_username)
47644cef258SMichael Walsh    gv.valid_value(ipmi_password)
4776741f740SMichael Walsh    if os_host != "":
47844cef258SMichael Walsh        gv.valid_value(os_username)
47944cef258SMichael Walsh        gv.valid_value(os_password)
4806741f740SMichael Walsh    if pdu_host != "":
48144cef258SMichael Walsh        gv.valid_value(pdu_username)
48244cef258SMichael Walsh        gv.valid_value(pdu_password)
48344cef258SMichael Walsh        gv.valid_integer(pdu_slot_no)
4846741f740SMichael Walsh    if openbmc_serial_host != "":
48544cef258SMichael Walsh        gv.valid_integer(openbmc_serial_port)
48644cef258SMichael Walsh    gv.valid_value(openbmc_model)
48744cef258SMichael Walsh    gv.valid_integer(max_num_tests)
48844cef258SMichael Walsh    gv.valid_integer(boot_pass)
48944cef258SMichael Walsh    gv.valid_integer(boot_fail)
4906741f740SMichael Walsh    plug_in_packages_list = grpi.rvalidate_plug_ins(plug_in_dir_paths)
4916741f740SMichael Walsh    BuiltIn().set_global_variable("${plug_in_packages_list}",
4926741f740SMichael Walsh                                  plug_in_packages_list)
49344cef258SMichael Walsh    gv.valid_value(stack_mode, valid_values=['normal', 'skip'])
494*f5ce38c3SMichael Walsh    gv.set_exit_on_error(False)
495a20da401SMichael Walsh    if len(boot_list) == 0 and len(boot_stack) == 0 and not ffdc_only:
4966741f740SMichael Walsh        error_message = "You must provide either a value for either the" +\
4976741f740SMichael Walsh            " boot_list or the boot_stack parm.\n"
4986741f740SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
4996741f740SMichael Walsh    valid_boot_list(boot_list, valid_boot_types)
5006741f740SMichael Walsh    valid_boot_list(boot_stack, valid_boot_types)
501004ad3c9SJoy Onyerikwu    selected_PDU_boots = list(set(boot_list + boot_stack)
502004ad3c9SJoy Onyerikwu                              & set(boot_lists['PDU_reboot']))
50311cfc8c0SMichael Walsh    if len(selected_PDU_boots) > 0 and pdu_host == "":
50411cfc8c0SMichael Walsh        error_message = "You have selected the following boots which" +\
50511cfc8c0SMichael Walsh                        " require a PDU host but no value for pdu_host:\n"
50611cfc8c0SMichael Walsh        error_message += gp.sprint_var(selected_PDU_boots)
507986d8aeeSMichael Walsh        error_message += gp.sprint_var(pdu_host, fmt=gp.blank())
50811cfc8c0SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
50911cfc8c0SMichael Walsh
5106741f740SMichael Walsh    return
5110bbd860fSMichael Walsh
5120bbd860fSMichael Walsh
5136741f740SMichael Walshdef my_get_state():
5140bbd860fSMichael Walsh    r"""
5156741f740SMichael Walsh    Get the system state plus a little bit of wrapping.
5160bbd860fSMichael Walsh    """
5170bbd860fSMichael Walsh
5186741f740SMichael Walsh    global state
5196741f740SMichael Walsh
5206741f740SMichael Walsh    req_states = ['epoch_seconds'] + st.default_req_states
5216741f740SMichael Walsh
522b5839d00SMichael Walsh    gp.qprint_timen("Getting system state.")
5236741f740SMichael Walsh    if test_mode:
5246741f740SMichael Walsh        state['epoch_seconds'] = int(time.time())
5256741f740SMichael Walsh    else:
526b5839d00SMichael Walsh        state = st.get_state(req_states=req_states, quiet=quiet)
527b5839d00SMichael Walsh    gp.qprint_var(state)
528341c21ebSMichael Walsh
529341c21ebSMichael Walsh
53045ca6e4cSMichael Walshdef valid_state():
53145ca6e4cSMichael Walsh    r"""
53245ca6e4cSMichael Walsh    Verify that our state dictionary contains no blank values.  If we don't get
53345ca6e4cSMichael Walsh    valid state data, we cannot continue to work.
53445ca6e4cSMichael Walsh    """
53545ca6e4cSMichael Walsh
53645ca6e4cSMichael Walsh    if st.compare_states(state, st.invalid_state_match, 'or'):
53745ca6e4cSMichael Walsh        error_message = "The state dictionary contains blank fields which" +\
53845ca6e4cSMichael Walsh            " is illegal.\n" + gp.sprint_var(state)
53945ca6e4cSMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
54045ca6e4cSMichael Walsh
54145ca6e4cSMichael Walsh
5426741f740SMichael Walshdef select_boot():
543341c21ebSMichael Walsh    r"""
544341c21ebSMichael Walsh    Select a boot test to be run based on our current state and return the
545341c21ebSMichael Walsh    chosen boot type.
546341c21ebSMichael Walsh
547341c21ebSMichael Walsh    Description of arguments:
5486741f740SMichael Walsh    state  The state of the machine.
549341c21ebSMichael Walsh    """
550341c21ebSMichael Walsh
55181816748SMichael Walsh    global transitional_boot_selected
55230dadae2SMichael Walsh    global boot_stack
55330dadae2SMichael Walsh
554b5839d00SMichael Walsh    gp.qprint_timen("Selecting a boot test.")
5556741f740SMichael Walsh
55681816748SMichael Walsh    if transitional_boot_selected and not boot_success:
55781816748SMichael Walsh        prior_boot = next_boot
55881816748SMichael Walsh        boot_candidate = boot_stack.pop()
559004ad3c9SJoy Onyerikwu        gp.qprint_timen("The prior '" + next_boot + "' was chosen to"
560004ad3c9SJoy Onyerikwu                        + " transition to a valid state for '" + boot_candidate
561004ad3c9SJoy Onyerikwu                        + "' which was at the top of the boot_stack.  Since"
562004ad3c9SJoy Onyerikwu                        + " the '" + next_boot + "' failed, the '"
563004ad3c9SJoy Onyerikwu                        + boot_candidate + "' has been removed from the stack"
564004ad3c9SJoy Onyerikwu                        + " to avoid and endless failure loop.")
56581816748SMichael Walsh        if len(boot_stack) == 0:
56681816748SMichael Walsh            return ""
56781816748SMichael Walsh
5686741f740SMichael Walsh    my_get_state()
56945ca6e4cSMichael Walsh    valid_state()
5706741f740SMichael Walsh
57181816748SMichael Walsh    transitional_boot_selected = False
5726741f740SMichael Walsh    stack_popped = 0
5736741f740SMichael Walsh    if len(boot_stack) > 0:
5746741f740SMichael Walsh        stack_popped = 1
575b5839d00SMichael Walsh        gp.qprint_dashes()
576b5839d00SMichael Walsh        gp.qprint_var(boot_stack)
577b5839d00SMichael Walsh        gp.qprint_dashes()
578b5839d00SMichael Walsh        skip_boot_printed = 0
579b5839d00SMichael Walsh        while len(boot_stack) > 0:
5806741f740SMichael Walsh            boot_candidate = boot_stack.pop()
581b5839d00SMichael Walsh            if stack_mode == 'normal':
582b5839d00SMichael Walsh                break
583b5839d00SMichael Walsh            else:
584b5839d00SMichael Walsh                if st.compare_states(state, boot_table[boot_candidate]['end']):
585b5839d00SMichael Walsh                    if not skip_boot_printed:
586ff340006SMichael Walsh                        gp.qprint_var(stack_mode)
587ff340006SMichael Walsh                        gp.qprintn()
588004ad3c9SJoy Onyerikwu                        gp.qprint_timen("Skipping the following boot tests"
589004ad3c9SJoy Onyerikwu                                        + " which are unnecessary since their"
590004ad3c9SJoy Onyerikwu                                        + " required end states match the"
591004ad3c9SJoy Onyerikwu                                        + " current machine state:")
592b5839d00SMichael Walsh                        skip_boot_printed = 1
593ff340006SMichael Walsh                    gp.qprint_var(boot_candidate)
594b5839d00SMichael Walsh                    boot_candidate = ""
595b5839d00SMichael Walsh        if boot_candidate == "":
596b5839d00SMichael Walsh            gp.qprint_dashes()
597b5839d00SMichael Walsh            gp.qprint_var(boot_stack)
598b5839d00SMichael Walsh            gp.qprint_dashes()
599b5839d00SMichael Walsh            return boot_candidate
6006741f740SMichael Walsh        if st.compare_states(state, boot_table[boot_candidate]['start']):
601004ad3c9SJoy Onyerikwu            gp.qprint_timen("The machine state is valid for a '"
602004ad3c9SJoy Onyerikwu                            + boot_candidate + "' boot test.")
603b5839d00SMichael Walsh            gp.qprint_dashes()
604b5839d00SMichael Walsh            gp.qprint_var(boot_stack)
605b5839d00SMichael Walsh            gp.qprint_dashes()
6066741f740SMichael Walsh            return boot_candidate
607341c21ebSMichael Walsh        else:
608004ad3c9SJoy Onyerikwu            gp.qprint_timen("The machine state does not match the required"
609004ad3c9SJoy Onyerikwu                            + " starting state for a '" + boot_candidate
610004ad3c9SJoy Onyerikwu                            + "' boot test:")
611986d8aeeSMichael Walsh            gp.qprint_varx("boot_table_start_entry",
612986d8aeeSMichael Walsh                           boot_table[boot_candidate]['start'])
6136741f740SMichael Walsh            boot_stack.append(boot_candidate)
61481816748SMichael Walsh            transitional_boot_selected = True
6156741f740SMichael Walsh            popped_boot = boot_candidate
6166741f740SMichael Walsh
6176741f740SMichael Walsh    # Loop through your list selecting a boot_candidates
6186741f740SMichael Walsh    boot_candidates = []
6196741f740SMichael Walsh    for boot_candidate in boot_list:
6206741f740SMichael Walsh        if st.compare_states(state, boot_table[boot_candidate]['start']):
6216741f740SMichael Walsh            if stack_popped:
6226741f740SMichael Walsh                if st.compare_states(boot_table[boot_candidate]['end'],
6236741f740SMichael Walsh                                     boot_table[popped_boot]['start']):
6246741f740SMichael Walsh                    boot_candidates.append(boot_candidate)
625341c21ebSMichael Walsh            else:
6266741f740SMichael Walsh                boot_candidates.append(boot_candidate)
6276741f740SMichael Walsh
6286741f740SMichael Walsh    if len(boot_candidates) == 0:
629004ad3c9SJoy Onyerikwu        gp.qprint_timen("The user's boot list contained no boot tests"
630004ad3c9SJoy Onyerikwu                        + " which are valid for the current machine state.")
6316741f740SMichael Walsh        boot_candidate = default_power_on
6326741f740SMichael Walsh        if not st.compare_states(state, boot_table[default_power_on]['start']):
6336741f740SMichael Walsh            boot_candidate = default_power_off
6346741f740SMichael Walsh        boot_candidates.append(boot_candidate)
635004ad3c9SJoy Onyerikwu        gp.qprint_timen("Using default '" + boot_candidate
636004ad3c9SJoy Onyerikwu                        + "' boot type to transition to valid state.")
6376741f740SMichael Walsh
638b5839d00SMichael Walsh    gp.dprint_var(boot_candidates)
6396741f740SMichael Walsh
6406741f740SMichael Walsh    # Randomly select a boot from the candidate list.
6416741f740SMichael Walsh    boot = random.choice(boot_candidates)
642341c21ebSMichael Walsh
643341c21ebSMichael Walsh    return boot
6440bbd860fSMichael Walsh
64555302295SMichael Walsh
646b2e53ecdSMichael Walshdef print_defect_report(ffdc_file_list):
647341c21ebSMichael Walsh    r"""
648341c21ebSMichael Walsh    Print a defect report.
649b2e53ecdSMichael Walsh
650b2e53ecdSMichael Walsh    Description of argument(s):
651b2e53ecdSMichael Walsh    ffdc_file_list  A list of files which were collected by our ffdc functions.
652341c21ebSMichael Walsh    """
653341c21ebSMichael Walsh
654600876daSMichael Walsh    # Making deliberate choice to NOT run plug_in_setup().  We don't want
655600876daSMichael Walsh    # ffdc_prefix updated.
656600876daSMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
657600876daSMichael Walsh        call_point='ffdc_report', stop_on_plug_in_failure=0)
658600876daSMichael Walsh
659e0cf8d70SMichael Walsh    # Get additional header data which may have been created by ffdc plug-ins.
660e0cf8d70SMichael Walsh    # Also, delete the individual header files to cleanup.
661e0cf8d70SMichael Walsh    cmd_buf = "file_list=$(cat " + ffdc_report_list_path + " 2>/dev/null)" +\
662e0cf8d70SMichael Walsh              " ; [ ! -z \"${file_list}\" ] && cat ${file_list}" +\
663e0cf8d70SMichael Walsh              " 2>/dev/null ; rm -rf ${file_list} 2>/dev/null || :"
664e0cf8d70SMichael Walsh    shell_rc, more_header_info = gc.cmd_fnc_u(cmd_buf, print_output=0,
665e0cf8d70SMichael Walsh                                              show_err=0)
666e0cf8d70SMichael Walsh
667b2e53ecdSMichael Walsh    # Get additional summary data which may have been created by ffdc plug-ins.
668600876daSMichael Walsh    # Also, delete the individual header files to cleanup.
669600876daSMichael Walsh    cmd_buf = "file_list=$(cat " + ffdc_summary_list_path + " 2>/dev/null)" +\
670600876daSMichael Walsh              " ; [ ! -z \"${file_list}\" ] && cat ${file_list}" +\
671600876daSMichael Walsh              " 2>/dev/null ; rm -rf ${file_list} 2>/dev/null || :"
672600876daSMichael Walsh    shell_rc, ffdc_summary_info = gc.cmd_fnc_u(cmd_buf, print_output=0,
673600876daSMichael Walsh                                               show_err=0)
674600876daSMichael Walsh
675b2e53ecdSMichael Walsh    # ffdc_list_file_path contains a list of any ffdc files created by plug-
676b2e53ecdSMichael Walsh    # ins, etc.  Read that data into a list.
677341c21ebSMichael Walsh    try:
678b2e53ecdSMichael Walsh        plug_in_ffdc_list = \
679b2e53ecdSMichael Walsh            open(ffdc_list_file_path, 'r').read().rstrip("\n").split("\n")
68036efbc04SGeorge Keishing        plug_in_ffdc_list = list(filter(None, plug_in_ffdc_list))
681341c21ebSMichael Walsh    except IOError:
682b2e53ecdSMichael Walsh        plug_in_ffdc_list = []
683b2e53ecdSMichael Walsh
684b2e53ecdSMichael Walsh    # Combine the files from plug_in_ffdc_list with the ffdc_file_list passed
685b2e53ecdSMichael Walsh    # in.  Eliminate duplicates and sort the list.
686004ad3c9SJoy Onyerikwu    ffdc_file_list = sorted(set(ffdc_file_list + plug_in_ffdc_list))
687b2e53ecdSMichael Walsh
688b2e53ecdSMichael Walsh    if status_file_path != "":
689b2e53ecdSMichael Walsh        ffdc_file_list.insert(0, status_file_path)
690b2e53ecdSMichael Walsh
691b2e53ecdSMichael Walsh    # Convert the list to a printable list.
692b2e53ecdSMichael Walsh    printable_ffdc_file_list = "\n".join(ffdc_file_list)
693341c21ebSMichael Walsh
69468a61162SMichael Walsh    # Open ffdc_file_list for writing.  We will write a complete list of
69568a61162SMichael Walsh    # FFDC files to it for possible use by plug-ins like cp_stop_check.
69668a61162SMichael Walsh    ffdc_list_file = open(ffdc_list_file_path, 'w')
697b2e53ecdSMichael Walsh    ffdc_list_file.write(printable_ffdc_file_list + "\n")
698b2e53ecdSMichael Walsh    ffdc_list_file.close()
699b2e53ecdSMichael Walsh
700b2e53ecdSMichael Walsh    indent = 0
701b2e53ecdSMichael Walsh    width = 90
702b2e53ecdSMichael Walsh    linefeed = 1
703b2e53ecdSMichael Walsh    char = "="
70468a61162SMichael Walsh
70568a61162SMichael Walsh    gp.qprintn()
706b2e53ecdSMichael Walsh    gp.qprint_dashes(indent, width, linefeed, char)
70768a61162SMichael Walsh    gp.qprintn("Copy this data to the defect:\n")
70868a61162SMichael Walsh
709e0cf8d70SMichael Walsh    if len(more_header_info) > 0:
710ff340006SMichael Walsh        gp.qprintn(more_header_info)
711dc80d67dSMichael Walsh    gp.qpvars(host_name, host_ip, openbmc_nickname, openbmc_host,
712dc80d67dSMichael Walsh              openbmc_host_name, openbmc_ip, openbmc_username,
7130a3bdb4cSMichael Walsh              openbmc_password, rest_username, rest_password, ipmi_username,
7140a3bdb4cSMichael Walsh              ipmi_password, os_host, os_host_name, os_ip, os_username,
715dc80d67dSMichael Walsh              os_password, pdu_host, pdu_host_name, pdu_ip, pdu_username,
716dc80d67dSMichael Walsh              pdu_password, pdu_slot_no, openbmc_serial_host,
717dc80d67dSMichael Walsh              openbmc_serial_host_name, openbmc_serial_ip, openbmc_serial_port)
71868a61162SMichael Walsh
71968a61162SMichael Walsh    gp.qprintn()
720986d8aeeSMichael Walsh    print_boot_history(boot_history)
72168a61162SMichael Walsh    gp.qprintn()
72268a61162SMichael Walsh    gp.qprint_var(state)
723b5839d00SMichael Walsh    gp.qprintn()
724b5839d00SMichael Walsh    gp.qprintn("FFDC data files:")
725b2e53ecdSMichael Walsh    gp.qprintn(printable_ffdc_file_list)
726b5839d00SMichael Walsh    gp.qprintn()
727341c21ebSMichael Walsh
728600876daSMichael Walsh    if len(ffdc_summary_info) > 0:
729ff340006SMichael Walsh        gp.qprintn(ffdc_summary_info)
730600876daSMichael Walsh
731b2e53ecdSMichael Walsh    gp.qprint_dashes(indent, width, linefeed, char)
73268a61162SMichael Walsh
7336741f740SMichael Walsh
7346741f740SMichael Walshdef my_ffdc():
7356741f740SMichael Walsh    r"""
7366741f740SMichael Walsh    Collect FFDC data.
7376741f740SMichael Walsh    """
7386741f740SMichael Walsh
7396741f740SMichael Walsh    global state
7406741f740SMichael Walsh
7416741f740SMichael Walsh    plug_in_setup()
7426741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
743600876daSMichael Walsh        call_point='ffdc', stop_on_plug_in_failure=0)
7446741f740SMichael Walsh
7456741f740SMichael Walsh    AUTOBOOT_FFDC_PREFIX = os.environ['AUTOBOOT_FFDC_PREFIX']
746004ad3c9SJoy Onyerikwu    status, ffdc_file_list = grk.run_key_u("FFDC  ffdc_prefix="
747004ad3c9SJoy Onyerikwu                                           + AUTOBOOT_FFDC_PREFIX
748004ad3c9SJoy Onyerikwu                                           + "  ffdc_function_list="
749004ad3c9SJoy Onyerikwu                                           + ffdc_function_list, ignore=1)
75083f4bc77SMichael Walsh    if status != 'PASS':
751ff340006SMichael Walsh        gp.qprint_error("Call to ffdc failed.\n")
752c9bd2e87SMichael Walsh        if type(ffdc_file_list) is not list:
753c9bd2e87SMichael Walsh            ffdc_file_list = []
754c9bd2e87SMichael Walsh        # Leave a record for caller that "soft" errors occurred.
755c9bd2e87SMichael Walsh        soft_errors = 1
756c9bd2e87SMichael Walsh        gpu.save_plug_in_value(soft_errors, pgm_name)
7576741f740SMichael Walsh
7586741f740SMichael Walsh    my_get_state()
7596741f740SMichael Walsh
760b2e53ecdSMichael Walsh    print_defect_report(ffdc_file_list)
7616741f740SMichael Walsh
7626741f740SMichael Walsh
7636741f740SMichael Walshdef print_test_start_message(boot_keyword):
7646741f740SMichael Walsh    r"""
7656741f740SMichael Walsh    Print a message indicating what boot test is about to run.
7666741f740SMichael Walsh
7676741f740SMichael Walsh    Description of arguments:
7686741f740SMichael Walsh    boot_keyword  The name of the boot which is to be run
7696741f740SMichael Walsh                  (e.g. "BMC Power On").
7706741f740SMichael Walsh    """
7716741f740SMichael Walsh
772986d8aeeSMichael Walsh    global boot_history
773325eb548SSunil M    global boot_start_time
7746741f740SMichael Walsh
7756741f740SMichael Walsh    doing_msg = gp.sprint_timen("Doing \"" + boot_keyword + "\".")
776325eb548SSunil M
777325eb548SSunil M    # Set boot_start_time for use by plug-ins.
778325eb548SSunil M    boot_start_time = doing_msg[1:33]
779325eb548SSunil M    gp.qprint_var(boot_start_time)
780325eb548SSunil M
781b5839d00SMichael Walsh    gp.qprint(doing_msg)
7826741f740SMichael Walsh
783986d8aeeSMichael Walsh    update_boot_history(boot_history, doing_msg, max_boot_history)
7846741f740SMichael Walsh
7856741f740SMichael Walsh
786f566fb1fSMichael Walshdef stop_boot_test(signal_number=0,
787f566fb1fSMichael Walsh                   frame=None):
788f566fb1fSMichael Walsh    r"""
789f566fb1fSMichael Walsh    Handle SIGUSR1 by aborting the boot test that is running.
790f566fb1fSMichael Walsh
791f566fb1fSMichael Walsh    Description of argument(s):
792f566fb1fSMichael Walsh    signal_number  The signal number (should always be 10 for SIGUSR1).
793f566fb1fSMichael Walsh    frame          The frame data.
794f566fb1fSMichael Walsh    """
795f566fb1fSMichael Walsh
79680dddde9SMichael Walsh    gp.qprintn()
79780dddde9SMichael Walsh    gp.qprint_executing()
798f566fb1fSMichael Walsh    gp.lprint_executing()
799f566fb1fSMichael Walsh
800f566fb1fSMichael Walsh    # Restore original sigusr1 handler.
801f566fb1fSMichael Walsh    set_default_siguser1()
802f566fb1fSMichael Walsh
803f566fb1fSMichael Walsh    message = "The caller has asked that the boot test be stopped and marked"
804f566fb1fSMichael Walsh    message += " as a failure."
805f566fb1fSMichael Walsh
806f566fb1fSMichael Walsh    function_stack = gm.get_function_stack()
807f566fb1fSMichael Walsh    if "wait_state" in function_stack:
808c44aa538SMichael Walsh        st.set_exit_wait_early_message(message)
809f566fb1fSMichael Walsh    else:
810f566fb1fSMichael Walsh        BuiltIn().fail(gp.sprint_error(message))
811f566fb1fSMichael Walsh
812f566fb1fSMichael Walsh
8136741f740SMichael Walshdef run_boot(boot):
8146741f740SMichael Walsh    r"""
8156741f740SMichael Walsh    Run the specified boot.
8166741f740SMichael Walsh
8176741f740SMichael Walsh    Description of arguments:
8186741f740SMichael Walsh    boot  The name of the boot test to be performed.
8196741f740SMichael Walsh    """
8206741f740SMichael Walsh
8216741f740SMichael Walsh    global state
8226741f740SMichael Walsh
823f566fb1fSMichael Walsh    signal.signal(signal.SIGUSR1, stop_boot_test)
824f566fb1fSMichael Walsh    gp.qprint_timen("stop_boot_test is armed.")
825f566fb1fSMichael Walsh
8266741f740SMichael Walsh    print_test_start_message(boot)
8276741f740SMichael Walsh
8286741f740SMichael Walsh    plug_in_setup()
8296741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = \
8306741f740SMichael Walsh        grpi.rprocess_plug_in_packages(call_point="pre_boot")
8316741f740SMichael Walsh    if rc != 0:
8326741f740SMichael Walsh        error_message = "Plug-in failed with non-zero return code.\n" +\
833986d8aeeSMichael Walsh            gp.sprint_var(rc, fmt=gp.hexa())
834f566fb1fSMichael Walsh        set_default_siguser1()
8356741f740SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
8366741f740SMichael Walsh
8376741f740SMichael Walsh    if test_mode:
8386741f740SMichael Walsh        # In test mode, we'll pretend the boot worked by assigning its
8396741f740SMichael Walsh        # required end state to the default state value.
84030dadae2SMichael Walsh        state = st.strip_anchor_state(boot_table[boot]['end'])
8416741f740SMichael Walsh    else:
8426741f740SMichael Walsh        # Assertion:  We trust that the state data was made fresh by the
8436741f740SMichael Walsh        # caller.
8446741f740SMichael Walsh
845b5839d00SMichael Walsh        gp.qprintn()
8466741f740SMichael Walsh
8476741f740SMichael Walsh        if boot_table[boot]['method_type'] == "keyword":
8480b93fbf8SMichael Walsh            rk.my_run_keywords(boot_table[boot].get('lib_file_path', ''),
849b5839d00SMichael Walsh                               boot_table[boot]['method'],
850b5839d00SMichael Walsh                               quiet=quiet)
8516741f740SMichael Walsh
8526741f740SMichael Walsh        if boot_table[boot]['bmc_reboot']:
8536741f740SMichael Walsh            st.wait_for_comm_cycle(int(state['epoch_seconds']))
85430dadae2SMichael Walsh            plug_in_setup()
85530dadae2SMichael Walsh            rc, shell_rc, failed_plug_in_name = \
85630dadae2SMichael Walsh                grpi.rprocess_plug_in_packages(call_point="post_reboot")
85730dadae2SMichael Walsh            if rc != 0:
8580b93fbf8SMichael Walsh                error_message = "Plug-in failed with non-zero return code.\n"
859986d8aeeSMichael Walsh                error_message += gp.sprint_var(rc, fmt=gp.hexa())
860f566fb1fSMichael Walsh                set_default_siguser1()
86130dadae2SMichael Walsh                BuiltIn().fail(gp.sprint_error(error_message))
8626741f740SMichael Walsh        else:
8636741f740SMichael Walsh            match_state = st.anchor_state(state)
8646741f740SMichael Walsh            del match_state['epoch_seconds']
8656741f740SMichael Walsh            # Wait for the state to change in any way.
8666741f740SMichael Walsh            st.wait_state(match_state, wait_time=state_change_timeout,
867600876daSMichael Walsh                          interval="10 seconds", invert=1)
8686741f740SMichael Walsh
869b5839d00SMichael Walsh        gp.qprintn()
8706741f740SMichael Walsh        if boot_table[boot]['end']['chassis'] == "Off":
8716741f740SMichael Walsh            boot_timeout = power_off_timeout
8726741f740SMichael Walsh        else:
8736741f740SMichael Walsh            boot_timeout = power_on_timeout
8746741f740SMichael Walsh        st.wait_state(boot_table[boot]['end'], wait_time=boot_timeout,
875600876daSMichael Walsh                      interval="10 seconds")
8766741f740SMichael Walsh
8776741f740SMichael Walsh    plug_in_setup()
8786741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = \
8796741f740SMichael Walsh        grpi.rprocess_plug_in_packages(call_point="post_boot")
8806741f740SMichael Walsh    if rc != 0:
8816741f740SMichael Walsh        error_message = "Plug-in failed with non-zero return code.\n" +\
882986d8aeeSMichael Walsh            gp.sprint_var(rc, fmt=gp.hexa())
883f566fb1fSMichael Walsh        set_default_siguser1()
8846741f740SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
8856741f740SMichael Walsh
886f566fb1fSMichael Walsh    # Restore original sigusr1 handler.
887f566fb1fSMichael Walsh    set_default_siguser1()
888f566fb1fSMichael Walsh
8896741f740SMichael Walsh
8906741f740SMichael Walshdef test_loop_body():
8916741f740SMichael Walsh    r"""
8926741f740SMichael Walsh    The main loop body for the loop in main_py.
8936741f740SMichael Walsh
8946741f740SMichael Walsh    Description of arguments:
8956741f740SMichael Walsh    boot_count  The iteration number (starts at 1).
8966741f740SMichael Walsh    """
8976741f740SMichael Walsh
8986741f740SMichael Walsh    global boot_count
8996741f740SMichael Walsh    global state
9006741f740SMichael Walsh    global next_boot
9016741f740SMichael Walsh    global boot_success
902325eb548SSunil M    global boot_end_time
9036741f740SMichael Walsh
904b5839d00SMichael Walsh    gp.qprintn()
9056741f740SMichael Walsh
9066741f740SMichael Walsh    next_boot = select_boot()
907b5839d00SMichael Walsh    if next_boot == "":
908b5839d00SMichael Walsh        return True
9096741f740SMichael Walsh
910b5839d00SMichael Walsh    boot_count += 1
911b5839d00SMichael Walsh    gp.qprint_timen("Starting boot " + str(boot_count) + ".")
9126741f740SMichael Walsh
913e0cf8d70SMichael Walsh    pre_boot_plug_in_setup()
9146741f740SMichael Walsh
9156741f740SMichael Walsh    cmd_buf = ["run_boot", next_boot]
9166741f740SMichael Walsh    boot_status, msg = BuiltIn().run_keyword_and_ignore_error(*cmd_buf)
9176741f740SMichael Walsh    if boot_status == "FAIL":
918b5839d00SMichael Walsh        gp.qprint(msg)
9196741f740SMichael Walsh
920b5839d00SMichael Walsh    gp.qprintn()
9216741f740SMichael Walsh    if boot_status == "PASS":
9226741f740SMichael Walsh        boot_success = 1
923004ad3c9SJoy Onyerikwu        completion_msg = gp.sprint_timen("BOOT_SUCCESS: \"" + next_boot
924004ad3c9SJoy Onyerikwu                                         + "\" succeeded.")
9256741f740SMichael Walsh    else:
9266741f740SMichael Walsh        boot_success = 0
927004ad3c9SJoy Onyerikwu        completion_msg = gp.sprint_timen("BOOT_FAILED: \"" + next_boot
928004ad3c9SJoy Onyerikwu                                         + "\" failed.")
929325eb548SSunil M
930325eb548SSunil M    # Set boot_end_time for use by plug-ins.
931325eb548SSunil M    boot_end_time = completion_msg[1:33]
932325eb548SSunil M    gp.qprint_var(boot_end_time)
933325eb548SSunil M
934325eb548SSunil M    gp.qprint(completion_msg)
9356741f740SMichael Walsh
9366741f740SMichael Walsh    boot_results.update(next_boot, boot_status)
9376741f740SMichael Walsh
9386741f740SMichael Walsh    plug_in_setup()
9396741f740SMichael Walsh    # NOTE: A post_test_case call point failure is NOT counted as a boot
9406741f740SMichael Walsh    # failure.
9416741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
942600876daSMichael Walsh        call_point='post_test_case', stop_on_plug_in_failure=0)
9436741f740SMichael Walsh
9446741f740SMichael Walsh    plug_in_setup()
9456741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
94689de14a4SMichael Walsh        call_point='ffdc_check', shell_rc=dump_ffdc_rc(),
9476741f740SMichael Walsh        stop_on_plug_in_failure=1, stop_on_non_zero_rc=1)
94812059e26SMichael Walsh    if ffdc_check == "All" or\
94989de14a4SMichael Walsh       shell_rc == dump_ffdc_rc():
95083f4bc77SMichael Walsh        status, ret_values = grk.run_key_u("my_ffdc", ignore=1)
95183f4bc77SMichael Walsh        if status != 'PASS':
952ff340006SMichael Walsh            gp.qprint_error("Call to my_ffdc failed.\n")
953c9bd2e87SMichael Walsh            # Leave a record for caller that "soft" errors occurred.
954c9bd2e87SMichael Walsh            soft_errors = 1
955c9bd2e87SMichael Walsh            gpu.save_plug_in_value(soft_errors, pgm_name)
9566741f740SMichael Walsh
957aabef1e3SMichael Walsh    if delete_errlogs:
958d139f286SMichael Walsh        # We need to purge error logs between boots or they build up.
959409ad35aSMichael Walsh        grk.run_key(delete_errlogs_cmd, ignore=1)
960d139f286SMichael Walsh
961952f9b09SMichael Walsh    boot_results.print_report()
962b5839d00SMichael Walsh    gp.qprint_timen("Finished boot " + str(boot_count) + ".")
963952f9b09SMichael Walsh
9646741f740SMichael Walsh    plug_in_setup()
9656741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
96689de14a4SMichael Walsh        call_point='stop_check', shell_rc=stop_test_rc(),
96789de14a4SMichael Walsh        stop_on_non_zero_rc=1)
96889de14a4SMichael Walsh    if shell_rc == stop_test_rc():
9693ba8ecdcSMichael Walsh        message = "Stopping as requested by user.\n"
97080dddde9SMichael Walsh        gp.qprint_time(message)
9713ba8ecdcSMichael Walsh        BuiltIn().fail(message)
9726741f740SMichael Walsh
973d139f286SMichael Walsh    # This should help prevent ConnectionErrors.
9740960b384SMichael Walsh    grk.run_key_u("Close All Connections")
975d139f286SMichael Walsh
9766741f740SMichael Walsh    return True
9776741f740SMichael Walsh
9786741f740SMichael Walsh
97983f4bc77SMichael Walshdef obmc_boot_test_teardown():
9806741f740SMichael Walsh    r"""
981f75d4354SMichael Walsh    Clean up after the main keyword.
9826741f740SMichael Walsh    """
983f75d4354SMichael Walsh    gp.qprint_executing()
984f75d4354SMichael Walsh
985f75d4354SMichael Walsh    if ga.psutil_imported:
986f75d4354SMichael Walsh        ga.terminate_descendants()
9876741f740SMichael Walsh
9886741f740SMichael Walsh    if cp_setup_called:
9896741f740SMichael Walsh        plug_in_setup()
9906741f740SMichael Walsh        rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
991600876daSMichael Walsh            call_point='cleanup', stop_on_plug_in_failure=0)
9926741f740SMichael Walsh
993600876daSMichael Walsh    if 'boot_results_file_path' in globals():
994986d8aeeSMichael Walsh        # Save boot_results and boot_history objects to a file in case they are
9956c64574bSMichael Walsh        # needed again.
996b5839d00SMichael Walsh        gp.qprint_timen("Saving boot_results to the following path.")
997b5839d00SMichael Walsh        gp.qprint_var(boot_results_file_path)
998986d8aeeSMichael Walsh        pickle.dump((boot_results, boot_history),
9996c64574bSMichael Walsh                    open(boot_results_file_path, 'wb'),
10000b93fbf8SMichael Walsh                    pickle.HIGHEST_PROTOCOL)
10010b93fbf8SMichael Walsh
1002ff340006SMichael Walsh    global save_stack
1003ff340006SMichael Walsh    # Restore any global values saved on the save_stack.
1004ff340006SMichael Walsh    for parm_name in main_func_parm_list:
1005ff340006SMichael Walsh        # Get the parm_value if it was saved on the stack.
1006ff340006SMichael Walsh        try:
1007ff340006SMichael Walsh            parm_value = save_stack.pop(parm_name)
1008004ad3c9SJoy Onyerikwu        except BaseException:
1009ff340006SMichael Walsh            # If it was not saved, no further action is required.
1010ff340006SMichael Walsh            continue
1011ff340006SMichael Walsh
1012ff340006SMichael Walsh        # Restore the saved value.
1013ff340006SMichael Walsh        cmd_buf = "BuiltIn().set_global_variable(\"${" + parm_name +\
1014ff340006SMichael Walsh            "}\", parm_value)"
1015ff340006SMichael Walsh        gp.dpissuing(cmd_buf)
1016ff340006SMichael Walsh        exec(cmd_buf)
1017ff340006SMichael Walsh
1018ff340006SMichael Walsh    gp.dprintn(save_stack.sprint_obj())
1019ff340006SMichael Walsh
10206741f740SMichael Walsh
1021c9116811SMichael Walshdef test_teardown():
1022c9116811SMichael Walsh    r"""
1023c9116811SMichael Walsh    Clean up after this test case.
1024c9116811SMichael Walsh    """
1025c9116811SMichael Walsh
1026c9116811SMichael Walsh    gp.qprintn()
1027f75d4354SMichael Walsh    gp.qprint_executing()
1028f75d4354SMichael Walsh
1029f75d4354SMichael Walsh    if ga.psutil_imported:
1030f75d4354SMichael Walsh        ga.terminate_descendants()
1031f75d4354SMichael Walsh
1032c9116811SMichael Walsh    cmd_buf = ["Print Error",
1033c9116811SMichael Walsh               "A keyword timeout occurred ending this program.\n"]
1034c9116811SMichael Walsh    BuiltIn().run_keyword_if_timeout_occurred(*cmd_buf)
1035c9116811SMichael Walsh
1036c108e429SMichael Walsh    gp.qprint_pgm_footer()
1037b5839d00SMichael Walsh
1038c9116811SMichael Walsh
103989de14a4SMichael Walshdef post_stack():
104089de14a4SMichael Walsh    r"""
104189de14a4SMichael Walsh    Process post_stack plug-in programs.
104289de14a4SMichael Walsh    """
104389de14a4SMichael Walsh
104489de14a4SMichael Walsh    if not call_post_stack_plug:
104589de14a4SMichael Walsh        # The caller does not wish to have post_stack plug-in processing done.
104689de14a4SMichael Walsh        return
104789de14a4SMichael Walsh
104889de14a4SMichael Walsh    global boot_success
104989de14a4SMichael Walsh
105089de14a4SMichael Walsh    # NOTE: A post_stack call-point failure is NOT counted as a boot failure.
105189de14a4SMichael Walsh    pre_boot_plug_in_setup()
105289de14a4SMichael Walsh    # For the purposes of the following plug-ins, mark the "boot" as a success.
105389de14a4SMichael Walsh    boot_success = 1
105489de14a4SMichael Walsh    plug_in_setup()
1055815b1d5bSMichael Walsh    rc, shell_rc, failed_plug_in_name, history =\
1056815b1d5bSMichael Walsh        grpi.rprocess_plug_in_packages(call_point='post_stack',
1057815b1d5bSMichael Walsh                                       stop_on_plug_in_failure=0,
1058815b1d5bSMichael Walsh                                       return_history=True)
1059986d8aeeSMichael Walsh    for doing_msg in history:
1060986d8aeeSMichael Walsh        update_boot_history(boot_history, doing_msg, max_boot_history)
1061815b1d5bSMichael Walsh    if rc != 0:
1062815b1d5bSMichael Walsh        boot_success = 0
106389de14a4SMichael Walsh
106489de14a4SMichael Walsh    plug_in_setup()
1065815b1d5bSMichael Walsh    rc, shell_rc, failed_plug_in_name =\
1066815b1d5bSMichael Walsh        grpi.rprocess_plug_in_packages(call_point='ffdc_check',
1067815b1d5bSMichael Walsh                                       shell_rc=dump_ffdc_rc(),
1068815b1d5bSMichael Walsh                                       stop_on_plug_in_failure=1,
1069815b1d5bSMichael Walsh                                       stop_on_non_zero_rc=1)
1070815b1d5bSMichael Walsh    if shell_rc == dump_ffdc_rc():
107189de14a4SMichael Walsh        status, ret_values = grk.run_key_u("my_ffdc", ignore=1)
107289de14a4SMichael Walsh        if status != 'PASS':
107389de14a4SMichael Walsh            gp.qprint_error("Call to my_ffdc failed.\n")
1074c9bd2e87SMichael Walsh            # Leave a record for caller that "soft" errors occurred.
1075c9bd2e87SMichael Walsh            soft_errors = 1
1076c9bd2e87SMichael Walsh            gpu.save_plug_in_value(soft_errors, pgm_name)
107789de14a4SMichael Walsh
107889de14a4SMichael Walsh    plug_in_setup()
107989de14a4SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
108089de14a4SMichael Walsh        call_point='stop_check', shell_rc=stop_test_rc(),
108189de14a4SMichael Walsh        stop_on_non_zero_rc=1)
108289de14a4SMichael Walsh    if shell_rc == stop_test_rc():
108389de14a4SMichael Walsh        message = "Stopping as requested by user.\n"
108480dddde9SMichael Walsh        gp.qprint_time(message)
108589de14a4SMichael Walsh        BuiltIn().fail(message)
108689de14a4SMichael Walsh
108789de14a4SMichael Walsh
1088ff340006SMichael Walshdef obmc_boot_test_py(loc_boot_stack=None,
1089ff340006SMichael Walsh                      loc_stack_mode=None,
1090ff340006SMichael Walsh                      loc_quiet=None):
10916741f740SMichael Walsh    r"""
10926741f740SMichael Walsh    Do main program processing.
10936741f740SMichael Walsh    """
10946741f740SMichael Walsh
1095ff340006SMichael Walsh    global save_stack
1096ff340006SMichael Walsh
1097f75d4354SMichael Walsh    ga.set_term_options(term_requests={'pgm_names': ['process_plug_in_packages.py']})
1098f75d4354SMichael Walsh
109936efbc04SGeorge Keishing    gp.dprintn()
1100ff340006SMichael Walsh    # Process function parms.
1101ff340006SMichael Walsh    for parm_name in main_func_parm_list:
1102ff340006SMichael Walsh        # Get parm's value.
110336efbc04SGeorge Keishing        parm_value = eval("loc_" + parm_name)
110436efbc04SGeorge Keishing        gp.dpvars(parm_name, parm_value)
1105ff340006SMichael Walsh
110636efbc04SGeorge Keishing        if parm_value is not None:
1107ff340006SMichael Walsh            # Save the global value on a stack.
1108ff340006SMichael Walsh            cmd_buf = "save_stack.push(BuiltIn().get_variable_value(\"${" +\
1109ff340006SMichael Walsh                parm_name + "}\"), \"" + parm_name + "\")"
1110ff340006SMichael Walsh            gp.dpissuing(cmd_buf)
1111ff340006SMichael Walsh            exec(cmd_buf)
1112ff340006SMichael Walsh
1113ff340006SMichael Walsh            # Set the global value to the passed value.
1114ff340006SMichael Walsh            cmd_buf = "BuiltIn().set_global_variable(\"${" + parm_name +\
1115ff340006SMichael Walsh                "}\", loc_" + parm_name + ")"
1116ff340006SMichael Walsh            gp.dpissuing(cmd_buf)
1117ff340006SMichael Walsh            exec(cmd_buf)
1118ff340006SMichael Walsh
1119ff340006SMichael Walsh    gp.dprintn(save_stack.sprint_obj())
1120b5839d00SMichael Walsh
11216741f740SMichael Walsh    setup()
11226741f740SMichael Walsh
1123cd9fbfd7SMichael Walsh    init_boot_pass, init_boot_fail = boot_results.return_total_pass_fail()
1124cd9fbfd7SMichael Walsh
1125a20da401SMichael Walsh    if ffdc_only:
1126a20da401SMichael Walsh        gp.qprint_timen("Caller requested ffdc_only.")
1127986d8aeeSMichael Walsh        if do_pre_boot_plug_in_setup:
1128e0cf8d70SMichael Walsh            pre_boot_plug_in_setup()
112983f4bc77SMichael Walsh        grk.run_key_u("my_ffdc")
1130764d2f83SMichael Walsh        return
1131a20da401SMichael Walsh
1132409ad35aSMichael Walsh    if delete_errlogs:
1133409ad35aSMichael Walsh        # Delete errlogs prior to doing any boot tests.
1134409ad35aSMichael Walsh        grk.run_key(delete_errlogs_cmd, ignore=1)
1135409ad35aSMichael Walsh
11366741f740SMichael Walsh    # Process caller's boot_stack.
11376741f740SMichael Walsh    while (len(boot_stack) > 0):
11386741f740SMichael Walsh        test_loop_body()
11396741f740SMichael Walsh
1140b5839d00SMichael Walsh    gp.qprint_timen("Finished processing stack.")
114130dadae2SMichael Walsh
114289de14a4SMichael Walsh    post_stack()
114389de14a4SMichael Walsh
11446741f740SMichael Walsh    # Process caller's boot_list.
11456741f740SMichael Walsh    if len(boot_list) > 0:
11466741f740SMichael Walsh        for ix in range(1, max_num_tests + 1):
11476741f740SMichael Walsh            test_loop_body()
11486741f740SMichael Walsh
1149b5839d00SMichael Walsh    gp.qprint_timen("Completed all requested boot tests.")
1150b5839d00SMichael Walsh
1151b5839d00SMichael Walsh    boot_pass, boot_fail = boot_results.return_total_pass_fail()
1152cd9fbfd7SMichael Walsh    new_fail = boot_fail - init_boot_fail
1153cd9fbfd7SMichael Walsh    if new_fail > boot_fail_threshold:
1154b5839d00SMichael Walsh        error_message = "Boot failures exceed the boot failure" +\
1155b5839d00SMichael Walsh                        " threshold:\n" +\
1156cd9fbfd7SMichael Walsh                        gp.sprint_var(new_fail) +\
1157b5839d00SMichael Walsh                        gp.sprint_var(boot_fail_threshold)
1158b5839d00SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
1159