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
13d54bbc22SGeorge Keishingtry:
140b93fbf8SMichael Walsh    import cPickle as pickle
15d54bbc22SGeorge Keishingexcept ImportError:
16d54bbc22SGeorge Keishing    import pickle
17dc80d67dSMichael Walshimport socket
180b93fbf8SMichael Walsh
190b93fbf8SMichael Walshfrom robot.utils import DotDict
200b93fbf8SMichael Walshfrom robot.libraries.BuiltIn import BuiltIn
210b93fbf8SMichael Walsh
226741f740SMichael Walshfrom boot_data import *
23c9116811SMichael Walshimport gen_print as gp
240bbd860fSMichael Walshimport gen_robot_print as grp
2555302295SMichael Walshimport gen_robot_plug_in as grpi
266741f740SMichael Walshimport gen_robot_valid as grv
276741f740SMichael Walshimport gen_misc as gm
286741f740SMichael Walshimport gen_cmd as gc
29b5839d00SMichael Walshimport gen_robot_keyword as grk
3055302295SMichael Walshimport state as st
31ff340006SMichael Walshimport var_stack as vs
320bbd860fSMichael Walsh
330b93fbf8SMichael Walshbase_path = os.path.dirname(os.path.dirname(
340b93fbf8SMichael Walsh                            imp.find_module("gen_robot_print")[1])) +\
350b93fbf8SMichael Walsh    os.sep
360b93fbf8SMichael Walshsys.path.append(base_path + "extended/")
370b93fbf8SMichael Walshimport run_keyword as rk
380bbd860fSMichael Walsh
39e1e26448SMichael Walsh# Setting master_pid correctly influences the behavior of plug-ins like
40e1e26448SMichael Walsh# DB_Logging
41e1e26448SMichael Walshprogram_pid = os.getpid()
42e1e26448SMichael Walshmaster_pid = os.environ.get('AUTOBOOT_MASTER_PID', program_pid)
43004ad3c9SJoy Onyerikwupgm_name = re.sub('\\.py$', '', os.path.basename(__file__))
44e1e26448SMichael Walsh
45b5839d00SMichael Walsh# Set up boot data structures.
46b5839d00SMichael Walshboot_table = create_boot_table()
47b5839d00SMichael Walshvalid_boot_types = create_valid_boot_list(boot_table)
480b93fbf8SMichael Walsh
496741f740SMichael Walshboot_lists = read_boot_lists()
506741f740SMichael Walshlast_ten = []
516741f740SMichael Walsh
527dc885b6SMichael Walshstate = st.return_state_constant('default_state')
536741f740SMichael Walshcp_setup_called = 0
546741f740SMichael Walshnext_boot = ""
556741f740SMichael Walshbase_tool_dir_path = os.path.normpath(os.environ.get(
566741f740SMichael Walsh    'AUTOBOOT_BASE_TOOL_DIR_PATH', "/tmp")) + os.sep
57b5839d00SMichael Walsh
586741f740SMichael Walshffdc_dir_path = os.path.normpath(os.environ.get('FFDC_DIR_PATH', '')) + os.sep
596741f740SMichael Walshboot_success = 0
606741f740SMichael Walshstatus_dir_path = os.environ.get('STATUS_DIR_PATH', "")
616741f740SMichael Walshif status_dir_path != "":
626741f740SMichael Walsh    status_dir_path = os.path.normpath(status_dir_path) + os.sep
630b93fbf8SMichael Walshdefault_power_on = "REST Power On"
640b93fbf8SMichael Walshdefault_power_off = "REST Power Off"
656741f740SMichael Walshboot_count = 0
660bbd860fSMichael Walsh
6785678948SMichael WalshLOG_LEVEL = BuiltIn().get_variable_value("${LOG_LEVEL}")
68e1974b96SMichael Walshffdc_prefix = ""
69325eb548SSunil Mboot_start_time = ""
70325eb548SSunil Mboot_end_time = ""
71ff340006SMichael Walshsave_stack = vs.var_stack('save_stack')
72ff340006SMichael Walshmain_func_parm_list = ['boot_stack', 'stack_mode', 'quiet']
7385678948SMichael Walsh
7485678948SMichael Walsh
750ad0f7f8SMichael Walshdef process_host(host,
760ad0f7f8SMichael Walsh                 host_var_name=""):
770ad0f7f8SMichael Walsh    r"""
780ad0f7f8SMichael Walsh    Process a host by getting the associated host name and IP address and
790ad0f7f8SMichael Walsh    setting them in global variables.
800ad0f7f8SMichael Walsh
810ad0f7f8SMichael Walsh    If the caller does not pass the host_var_name, this function will try to
820ad0f7f8SMichael Walsh    figure out the name of the variable used by the caller for the host parm.
830ad0f7f8SMichael Walsh    Callers are advised to explicitly specify the host_var_name when calling
840ad0f7f8SMichael Walsh    with an exec command.  In such cases, the get_arg_name cannot figure out
850ad0f7f8SMichael Walsh    the host variable name.
860ad0f7f8SMichael Walsh
870ad0f7f8SMichael Walsh    This function will then create similar global variable names by
880ad0f7f8SMichael Walsh    removing "_host" and appending "_host_name" or "_ip" to the host variable
890ad0f7f8SMichael Walsh    name.
900ad0f7f8SMichael Walsh
910ad0f7f8SMichael Walsh    Example:
920ad0f7f8SMichael Walsh
930ad0f7f8SMichael Walsh    If a call is made like this:
940ad0f7f8SMichael Walsh    process_host(openbmc_host)
950ad0f7f8SMichael Walsh
960ad0f7f8SMichael Walsh    Global variables openbmc_host_name and openbmc_ip will be set.
970ad0f7f8SMichael Walsh
980ad0f7f8SMichael Walsh    Description of argument(s):
990ad0f7f8SMichael Walsh    host           A host name or IP.  The name of the variable used should
1000ad0f7f8SMichael Walsh                   have a suffix of "_host".
1010ad0f7f8SMichael Walsh    host_var_name  The name of the variable being used as the host parm.
1020ad0f7f8SMichael Walsh    """
1030ad0f7f8SMichael Walsh
1040ad0f7f8SMichael Walsh    if host_var_name == "":
1050ad0f7f8SMichael Walsh        host_var_name = gp.get_arg_name(0, 1, stack_frame_ix=2)
1060ad0f7f8SMichael Walsh
1070ad0f7f8SMichael Walsh    host_name_var_name = re.sub("host", "host_name", host_var_name)
1080ad0f7f8SMichael Walsh    ip_var_name = re.sub("host", "ip", host_var_name)
1090ad0f7f8SMichael Walsh    cmd_buf = "global " + host_name_var_name + ", " + ip_var_name + " ; " +\
1100ad0f7f8SMichael Walsh        host_name_var_name + ", " + ip_var_name + " = gm.get_host_name_ip('" +\
1110ad0f7f8SMichael Walsh        host + "')"
1120ad0f7f8SMichael Walsh    exec(cmd_buf)
1130ad0f7f8SMichael Walsh
1140ad0f7f8SMichael Walsh
115b5839d00SMichael Walshdef process_pgm_parms():
116b5839d00SMichael Walsh    r"""
117b5839d00SMichael Walsh    Process the program parameters by assigning them all to corresponding
118b5839d00SMichael Walsh    globals.  Also, set some global values that depend on program parameters.
119b5839d00SMichael Walsh    """
120b5839d00SMichael Walsh
121b5839d00SMichael Walsh    # Program parameter processing.
122b5839d00SMichael Walsh    # Assign all program parms to python variables which are global to this
123b5839d00SMichael Walsh    # module.
124b5839d00SMichael Walsh
125b5839d00SMichael Walsh    global parm_list
126b5839d00SMichael Walsh    parm_list = BuiltIn().get_variable_value("${parm_list}")
127b5839d00SMichael Walsh    # The following subset of parms should be processed as integers.
128b5839d00SMichael Walsh    int_list = ['max_num_tests', 'boot_pass', 'boot_fail', 'ffdc_only',
129aabef1e3SMichael Walsh                'boot_fail_threshold', 'delete_errlogs', 'quiet', 'test_mode',
130aabef1e3SMichael Walsh                'debug']
131b5839d00SMichael Walsh    for parm in parm_list:
132b5839d00SMichael Walsh        if parm in int_list:
133b5839d00SMichael Walsh            sub_cmd = "int(BuiltIn().get_variable_value(\"${" + parm +\
134b5839d00SMichael Walsh                      "}\", \"0\"))"
135b5839d00SMichael Walsh        else:
136b5839d00SMichael Walsh            sub_cmd = "BuiltIn().get_variable_value(\"${" + parm + "}\")"
137b5839d00SMichael Walsh        cmd_buf = "global " + parm + " ; " + parm + " = " + sub_cmd
138ff340006SMichael Walsh        gp.dpissuing(cmd_buf)
139b5839d00SMichael Walsh        exec(cmd_buf)
1400ad0f7f8SMichael Walsh        if re.match(r".*_host$", parm):
1410ad0f7f8SMichael Walsh            cmd_buf = "process_host(" + parm + ", '" + parm + "')"
1420ad0f7f8SMichael Walsh            exec(cmd_buf)
1430ad0f7f8SMichael Walsh        if re.match(r".*_password$", parm):
1440ad0f7f8SMichael Walsh            # Register the value of any parm whose name ends in _password.
1450ad0f7f8SMichael Walsh            # This will cause the print functions to replace passwords with
1460ad0f7f8SMichael Walsh            # asterisks in the output.
1470ad0f7f8SMichael Walsh            cmd_buf = "gp.register_passwords(" + parm + ")"
1480ad0f7f8SMichael Walsh            exec(cmd_buf)
149b5839d00SMichael Walsh
150b5839d00SMichael Walsh    global ffdc_dir_path_style
151b5839d00SMichael Walsh    global boot_list
152b5839d00SMichael Walsh    global boot_stack
153b5839d00SMichael Walsh    global boot_results_file_path
154b5839d00SMichael Walsh    global boot_results
155*6c64574bSMichael Walsh    global last_ten
156b5839d00SMichael Walsh    global ffdc_list_file_path
157e0cf8d70SMichael Walsh    global ffdc_report_list_path
158600876daSMichael Walsh    global ffdc_summary_list_path
159b5839d00SMichael Walsh
160b5839d00SMichael Walsh    if ffdc_dir_path_style == "":
161b5839d00SMichael Walsh        ffdc_dir_path_style = int(os.environ.get('FFDC_DIR_PATH_STYLE', '0'))
162b5839d00SMichael Walsh
163b5839d00SMichael Walsh    # Convert these program parms to lists for easier processing..
164b5839d00SMichael Walsh    boot_list = filter(None, boot_list.split(":"))
165b5839d00SMichael Walsh    boot_stack = filter(None, boot_stack.split(":"))
166b5839d00SMichael Walsh
167903e0b20SMichael Walsh    cleanup_boot_results_file()
168903e0b20SMichael Walsh    boot_results_file_path = create_boot_results_file_path(pgm_name,
169903e0b20SMichael Walsh                                                           openbmc_nickname,
170903e0b20SMichael Walsh                                                           master_pid)
171b5839d00SMichael Walsh
172b5839d00SMichael Walsh    if os.path.isfile(boot_results_file_path):
173b5839d00SMichael Walsh        # We've been called before in this run so we'll load the saved
174*6c64574bSMichael Walsh        # boot_results and last_ten objects.
175*6c64574bSMichael Walsh        boot_results, last_ten =\
176*6c64574bSMichael Walsh            pickle.load(open(boot_results_file_path, 'rb'))
177b5839d00SMichael Walsh    else:
178b5839d00SMichael Walsh        boot_results = boot_results(boot_table, boot_pass, boot_fail)
179b5839d00SMichael Walsh
180b5839d00SMichael Walsh    ffdc_list_file_path = base_tool_dir_path + openbmc_nickname +\
181b5839d00SMichael Walsh        "/FFDC_FILE_LIST"
182e0cf8d70SMichael Walsh    ffdc_report_list_path = base_tool_dir_path + openbmc_nickname +\
183e0cf8d70SMichael Walsh        "/FFDC_REPORT_FILE_LIST"
184b5839d00SMichael Walsh
185600876daSMichael Walsh    ffdc_summary_list_path = base_tool_dir_path + openbmc_nickname +\
186600876daSMichael Walsh        "/FFDC_SUMMARY_FILE_LIST"
187600876daSMichael Walsh
188b5839d00SMichael Walsh
18985678948SMichael Walshdef initial_plug_in_setup():
19085678948SMichael Walsh    r"""
19185678948SMichael Walsh    Initialize all plug-in environment variables which do not change for the
19285678948SMichael Walsh    duration of the program.
19385678948SMichael Walsh
19485678948SMichael Walsh    """
19585678948SMichael Walsh
19685678948SMichael Walsh    global LOG_LEVEL
19785678948SMichael Walsh    BuiltIn().set_log_level("NONE")
19885678948SMichael Walsh
19985678948SMichael Walsh    BuiltIn().set_global_variable("${master_pid}", master_pid)
20085678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_DIR_PATH}", ffdc_dir_path)
20185678948SMichael Walsh    BuiltIn().set_global_variable("${STATUS_DIR_PATH}", status_dir_path)
20285678948SMichael Walsh    BuiltIn().set_global_variable("${BASE_TOOL_DIR_PATH}", base_tool_dir_path)
20385678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_LIST_FILE_PATH}",
20485678948SMichael Walsh                                  ffdc_list_file_path)
205e0cf8d70SMichael Walsh    BuiltIn().set_global_variable("${FFDC_REPORT_LIST_PATH}",
206e0cf8d70SMichael Walsh                                  ffdc_report_list_path)
207600876daSMichael Walsh    BuiltIn().set_global_variable("${FFDC_SUMMARY_LIST_PATH}",
208600876daSMichael Walsh                                  ffdc_summary_list_path)
20985678948SMichael Walsh
21085678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_DIR_PATH_STYLE}",
21185678948SMichael Walsh                                  ffdc_dir_path_style)
21285678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_CHECK}",
21385678948SMichael Walsh                                  ffdc_check)
21485678948SMichael Walsh
21585678948SMichael Walsh    # For each program parameter, set the corresponding AUTOBOOT_ environment
21685678948SMichael Walsh    # variable value.  Also, set an AUTOBOOT_ environment variable for every
21785678948SMichael Walsh    # element in additional_values.
21885678948SMichael Walsh    additional_values = ["program_pid", "master_pid", "ffdc_dir_path",
21985678948SMichael Walsh                         "status_dir_path", "base_tool_dir_path",
220600876daSMichael Walsh                         "ffdc_list_file_path", "ffdc_report_list_path",
221600876daSMichael Walsh                         "ffdc_summary_list_path"]
22285678948SMichael Walsh
22385678948SMichael Walsh    plug_in_vars = parm_list + additional_values
22485678948SMichael Walsh
22585678948SMichael Walsh    for var_name in plug_in_vars:
22685678948SMichael Walsh        var_value = BuiltIn().get_variable_value("${" + var_name + "}")
22785678948SMichael Walsh        var_name = var_name.upper()
22885678948SMichael Walsh        if var_value is None:
22985678948SMichael Walsh            var_value = ""
23085678948SMichael Walsh        os.environ["AUTOBOOT_" + var_name] = str(var_value)
23185678948SMichael Walsh
23285678948SMichael Walsh    BuiltIn().set_log_level(LOG_LEVEL)
23385678948SMichael Walsh
23468a61162SMichael Walsh    # Make sure the ffdc list directory exists.
23568a61162SMichael Walsh    ffdc_list_dir_path = os.path.dirname(ffdc_list_file_path) + os.sep
23668a61162SMichael Walsh    if not os.path.exists(ffdc_list_dir_path):
23768a61162SMichael Walsh        os.makedirs(ffdc_list_dir_path)
23885678948SMichael Walsh
23985678948SMichael Walsh
2400bbd860fSMichael Walshdef plug_in_setup():
2410bbd860fSMichael Walsh    r"""
24285678948SMichael Walsh    Initialize all changing plug-in environment variables for use by the
24385678948SMichael Walsh    plug-in programs.
2440bbd860fSMichael Walsh    """
2450bbd860fSMichael Walsh
24685678948SMichael Walsh    global LOG_LEVEL
24785678948SMichael Walsh    global test_really_running
24885678948SMichael Walsh
24985678948SMichael Walsh    BuiltIn().set_log_level("NONE")
25085678948SMichael Walsh
2516741f740SMichael Walsh    boot_pass, boot_fail = boot_results.return_total_pass_fail()
2520bbd860fSMichael Walsh    if boot_pass > 1:
2530bbd860fSMichael Walsh        test_really_running = 1
2540bbd860fSMichael Walsh    else:
2550bbd860fSMichael Walsh        test_really_running = 0
2560bbd860fSMichael Walsh
2576741f740SMichael Walsh    BuiltIn().set_global_variable("${test_really_running}",
2586741f740SMichael Walsh                                  test_really_running)
2596741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_type_desc}", next_boot)
2606741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_pass}", boot_pass)
2616741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_fail}", boot_fail)
2626741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_success}", boot_success)
2636741f740SMichael Walsh    BuiltIn().set_global_variable("${ffdc_prefix}", ffdc_prefix)
264325eb548SSunil M    BuiltIn().set_global_variable("${boot_start_time}", boot_start_time)
265325eb548SSunil M    BuiltIn().set_global_variable("${boot_end_time}", boot_end_time)
2664c9a6453SMichael Walsh
2670bbd860fSMichael Walsh    # For each program parameter, set the corresponding AUTOBOOT_ environment
2680bbd860fSMichael Walsh    # variable value.  Also, set an AUTOBOOT_ environment variable for every
2690bbd860fSMichael Walsh    # element in additional_values.
2700bbd860fSMichael Walsh    additional_values = ["boot_type_desc", "boot_success", "boot_pass",
271325eb548SSunil M                         "boot_fail", "test_really_running", "ffdc_prefix",
272325eb548SSunil M                         "boot_start_time", "boot_end_time"]
2730bbd860fSMichael Walsh
27485678948SMichael Walsh    plug_in_vars = additional_values
2750bbd860fSMichael Walsh
2760bbd860fSMichael Walsh    for var_name in plug_in_vars:
2770bbd860fSMichael Walsh        var_value = BuiltIn().get_variable_value("${" + var_name + "}")
2780bbd860fSMichael Walsh        var_name = var_name.upper()
2790bbd860fSMichael Walsh        if var_value is None:
2800bbd860fSMichael Walsh            var_value = ""
2816741f740SMichael Walsh        os.environ["AUTOBOOT_" + var_name] = str(var_value)
2820bbd860fSMichael Walsh
2830bbd860fSMichael Walsh    if debug:
2846741f740SMichael Walsh        shell_rc, out_buf = \
2856741f740SMichael Walsh            gc.cmd_fnc_u("printenv | egrep AUTOBOOT_ | sort -u")
2860bbd860fSMichael Walsh
28785678948SMichael Walsh    BuiltIn().set_log_level(LOG_LEVEL)
28885678948SMichael Walsh
2890bbd860fSMichael Walsh
290e0cf8d70SMichael Walshdef pre_boot_plug_in_setup():
291e0cf8d70SMichael Walsh
292e0cf8d70SMichael Walsh    # Clear the ffdc_list_file_path file.  Plug-ins may now write to it.
293e0cf8d70SMichael Walsh    try:
294e0cf8d70SMichael Walsh        os.remove(ffdc_list_file_path)
295e0cf8d70SMichael Walsh    except OSError:
296e0cf8d70SMichael Walsh        pass
297e0cf8d70SMichael Walsh
298e0cf8d70SMichael Walsh    # Clear the ffdc_report_list_path file.  Plug-ins may now write to it.
299e0cf8d70SMichael Walsh    try:
300e0cf8d70SMichael Walsh        os.remove(ffdc_report_list_path)
301e0cf8d70SMichael Walsh    except OSError:
302e0cf8d70SMichael Walsh        pass
303e0cf8d70SMichael Walsh
304600876daSMichael Walsh    # Clear the ffdc_summary_list_path file.  Plug-ins may now write to it.
305600876daSMichael Walsh    try:
306600876daSMichael Walsh        os.remove(ffdc_summary_list_path)
307600876daSMichael Walsh    except OSError:
308600876daSMichael Walsh        pass
309600876daSMichael Walsh
310e1974b96SMichael Walsh    global ffdc_prefix
311e1974b96SMichael Walsh
312e1974b96SMichael Walsh    seconds = time.time()
313e1974b96SMichael Walsh    loc_time = time.localtime(seconds)
314e1974b96SMichael Walsh    time_string = time.strftime("%y%m%d.%H%M%S.", loc_time)
315e1974b96SMichael Walsh
316e1974b96SMichael Walsh    ffdc_prefix = openbmc_nickname + "." + time_string
317e1974b96SMichael Walsh
318e0cf8d70SMichael Walsh
3196741f740SMichael Walshdef setup():
3200bbd860fSMichael Walsh    r"""
3216741f740SMichael Walsh    Do general program setup tasks.
3220bbd860fSMichael Walsh    """
3230bbd860fSMichael Walsh
3246741f740SMichael Walsh    global cp_setup_called
32581816748SMichael Walsh    global transitional_boot_selected
3260bbd860fSMichael Walsh
327b5839d00SMichael Walsh    gp.qprintn()
328b5839d00SMichael Walsh
32981816748SMichael Walsh    transitional_boot_selected = False
33081816748SMichael Walsh
33183f4bc77SMichael Walsh    robot_pgm_dir_path = os.path.dirname(__file__) + os.sep
33283f4bc77SMichael Walsh    repo_bin_path = robot_pgm_dir_path.replace("/lib/", "/bin/")
333d061c043SMichael Walsh    # If we can't find process_plug_in_packages.py, ssh_pw or
334d061c043SMichael Walsh    # validate_plug_ins.py, then we don't have our repo bin in PATH.
335004ad3c9SJoy Onyerikwu    shell_rc, out_buf = gc.cmd_fnc_u("which process_plug_in_packages.py"
336004ad3c9SJoy Onyerikwu                                     + " ssh_pw validate_plug_ins.py", quiet=1,
337d061c043SMichael Walsh                                     print_output=0, show_err=0)
338b5839d00SMichael Walsh    if shell_rc != 0:
33983f4bc77SMichael Walsh        os.environ['PATH'] = repo_bin_path + ":" + os.environ.get('PATH', "")
34083f4bc77SMichael Walsh    # Likewise, our repo lib subdir needs to be in sys.path and PYTHONPATH.
34183f4bc77SMichael Walsh    if robot_pgm_dir_path not in sys.path:
34283f4bc77SMichael Walsh        sys.path.append(robot_pgm_dir_path)
34383f4bc77SMichael Walsh        PYTHONPATH = os.environ.get("PYTHONPATH", "")
34483f4bc77SMichael Walsh        if PYTHONPATH == "":
34583f4bc77SMichael Walsh            os.environ['PYTHONPATH'] = robot_pgm_dir_path
34683f4bc77SMichael Walsh        else:
34783f4bc77SMichael Walsh            os.environ['PYTHONPATH'] = robot_pgm_dir_path + ":" + PYTHONPATH
3486741f740SMichael Walsh
3496741f740SMichael Walsh    validate_parms()
3506741f740SMichael Walsh
3516741f740SMichael Walsh    grp.rqprint_pgm_header()
3526741f740SMichael Walsh
353efc3ff2bSGeorge Keishing    grk.run_key("Set BMC Power Policy  ALWAYS_POWER_OFF")
35411cfc8c0SMichael Walsh
35585678948SMichael Walsh    initial_plug_in_setup()
35685678948SMichael Walsh
3576741f740SMichael Walsh    plug_in_setup()
3586741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
3596741f740SMichael Walsh        call_point='setup')
3606741f740SMichael Walsh    if rc != 0:
3616741f740SMichael Walsh        error_message = "Plug-in setup failed.\n"
3626741f740SMichael Walsh        grp.rprint_error_report(error_message)
3636741f740SMichael Walsh        BuiltIn().fail(error_message)
3646741f740SMichael Walsh    # Setting cp_setup_called lets our Teardown know that it needs to call
3656741f740SMichael Walsh    # the cleanup plug-in call point.
3666741f740SMichael Walsh    cp_setup_called = 1
3676741f740SMichael Walsh
3686741f740SMichael Walsh    # Keyword "FFDC" will fail if TEST_MESSAGE is not set.
3696741f740SMichael Walsh    BuiltIn().set_global_variable("${TEST_MESSAGE}", "${EMPTY}")
37085678948SMichael Walsh    # FFDC_LOG_PATH is used by "FFDC" keyword.
37185678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_LOG_PATH}", ffdc_dir_path)
3726741f740SMichael Walsh
373dc80d67dSMichael Walsh    # Also printed by FFDC.
374dc80d67dSMichael Walsh    global host_name
375dc80d67dSMichael Walsh    global host_ip
376dc80d67dSMichael Walsh    host = socket.gethostname()
377dc80d67dSMichael Walsh    host_name, host_ip = gm.get_host_name_ip(host)
378dc80d67dSMichael Walsh
379b5839d00SMichael Walsh    gp.dprint_var(boot_table, 1)
380b5839d00SMichael Walsh    gp.dprint_var(boot_lists)
3810bbd860fSMichael Walsh
3820bbd860fSMichael Walsh
3836741f740SMichael Walshdef validate_parms():
3840bbd860fSMichael Walsh    r"""
3856741f740SMichael Walsh    Validate all program parameters.
3860bbd860fSMichael Walsh    """
3870bbd860fSMichael Walsh
388b5839d00SMichael Walsh    process_pgm_parms()
3890bbd860fSMichael Walsh
390b5839d00SMichael Walsh    gp.qprintn()
391b5839d00SMichael Walsh
392b5839d00SMichael Walsh    global openbmc_model
3936741f740SMichael Walsh    grv.rvalid_value("openbmc_host")
3946741f740SMichael Walsh    grv.rvalid_value("openbmc_username")
3956741f740SMichael Walsh    grv.rvalid_value("openbmc_password")
3966741f740SMichael Walsh    if os_host != "":
3976741f740SMichael Walsh        grv.rvalid_value("os_username")
3986741f740SMichael Walsh        grv.rvalid_value("os_password")
3990bbd860fSMichael Walsh
4006741f740SMichael Walsh    if pdu_host != "":
4016741f740SMichael Walsh        grv.rvalid_value("pdu_username")
4026741f740SMichael Walsh        grv.rvalid_value("pdu_password")
4036741f740SMichael Walsh        grv.rvalid_integer("pdu_slot_no")
4046741f740SMichael Walsh    if openbmc_serial_host != "":
4056741f740SMichael Walsh        grv.rvalid_integer("openbmc_serial_port")
406b5839d00SMichael Walsh    if openbmc_model == "":
407b5839d00SMichael Walsh        status, ret_values =\
408b5839d00SMichael Walsh            grk.run_key_u("Get BMC System Model")
409b5839d00SMichael Walsh        openbmc_model = ret_values
410b5839d00SMichael Walsh        BuiltIn().set_global_variable("${openbmc_model}", openbmc_model)
4116741f740SMichael Walsh    grv.rvalid_value("openbmc_model")
412b5839d00SMichael Walsh    grv.rvalid_integer("max_num_tests")
4136741f740SMichael Walsh    grv.rvalid_integer("boot_pass")
4146741f740SMichael Walsh    grv.rvalid_integer("boot_fail")
4156741f740SMichael Walsh
4166741f740SMichael Walsh    plug_in_packages_list = grpi.rvalidate_plug_ins(plug_in_dir_paths)
4176741f740SMichael Walsh    BuiltIn().set_global_variable("${plug_in_packages_list}",
4186741f740SMichael Walsh                                  plug_in_packages_list)
4196741f740SMichael Walsh
420b5839d00SMichael Walsh    grv.rvalid_value("stack_mode", valid_values=['normal', 'skip'])
421a20da401SMichael Walsh    if len(boot_list) == 0 and len(boot_stack) == 0 and not ffdc_only:
4226741f740SMichael Walsh        error_message = "You must provide either a value for either the" +\
4236741f740SMichael Walsh            " boot_list or the boot_stack parm.\n"
4246741f740SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
4256741f740SMichael Walsh
4266741f740SMichael Walsh    valid_boot_list(boot_list, valid_boot_types)
4276741f740SMichael Walsh    valid_boot_list(boot_stack, valid_boot_types)
4286741f740SMichael Walsh
429004ad3c9SJoy Onyerikwu    selected_PDU_boots = list(set(boot_list + boot_stack)
430004ad3c9SJoy Onyerikwu                              & set(boot_lists['PDU_reboot']))
43111cfc8c0SMichael Walsh
43211cfc8c0SMichael Walsh    if len(selected_PDU_boots) > 0 and pdu_host == "":
43311cfc8c0SMichael Walsh        error_message = "You have selected the following boots which" +\
43411cfc8c0SMichael Walsh                        " require a PDU host but no value for pdu_host:\n"
43511cfc8c0SMichael Walsh        error_message += gp.sprint_var(selected_PDU_boots)
43611cfc8c0SMichael Walsh        error_message += gp.sprint_var(pdu_host, 2)
43711cfc8c0SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
43811cfc8c0SMichael Walsh
4396741f740SMichael Walsh    return
4400bbd860fSMichael Walsh
4410bbd860fSMichael Walsh
4426741f740SMichael Walshdef my_get_state():
4430bbd860fSMichael Walsh    r"""
4446741f740SMichael Walsh    Get the system state plus a little bit of wrapping.
4450bbd860fSMichael Walsh    """
4460bbd860fSMichael Walsh
4476741f740SMichael Walsh    global state
4486741f740SMichael Walsh
4496741f740SMichael Walsh    req_states = ['epoch_seconds'] + st.default_req_states
4506741f740SMichael Walsh
451b5839d00SMichael Walsh    gp.qprint_timen("Getting system state.")
4526741f740SMichael Walsh    if test_mode:
4536741f740SMichael Walsh        state['epoch_seconds'] = int(time.time())
4546741f740SMichael Walsh    else:
455b5839d00SMichael Walsh        state = st.get_state(req_states=req_states, quiet=quiet)
456b5839d00SMichael Walsh    gp.qprint_var(state)
457341c21ebSMichael Walsh
458341c21ebSMichael Walsh
45945ca6e4cSMichael Walshdef valid_state():
46045ca6e4cSMichael Walsh    r"""
46145ca6e4cSMichael Walsh    Verify that our state dictionary contains no blank values.  If we don't get
46245ca6e4cSMichael Walsh    valid state data, we cannot continue to work.
46345ca6e4cSMichael Walsh    """
46445ca6e4cSMichael Walsh
46545ca6e4cSMichael Walsh    if st.compare_states(state, st.invalid_state_match, 'or'):
46645ca6e4cSMichael Walsh        error_message = "The state dictionary contains blank fields which" +\
46745ca6e4cSMichael Walsh            " is illegal.\n" + gp.sprint_var(state)
46845ca6e4cSMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
46945ca6e4cSMichael Walsh
47045ca6e4cSMichael Walsh
4716741f740SMichael Walshdef select_boot():
472341c21ebSMichael Walsh    r"""
473341c21ebSMichael Walsh    Select a boot test to be run based on our current state and return the
474341c21ebSMichael Walsh    chosen boot type.
475341c21ebSMichael Walsh
476341c21ebSMichael Walsh    Description of arguments:
4776741f740SMichael Walsh    state  The state of the machine.
478341c21ebSMichael Walsh    """
479341c21ebSMichael Walsh
48081816748SMichael Walsh    global transitional_boot_selected
48130dadae2SMichael Walsh    global boot_stack
48230dadae2SMichael Walsh
483b5839d00SMichael Walsh    gp.qprint_timen("Selecting a boot test.")
4846741f740SMichael Walsh
48581816748SMichael Walsh    if transitional_boot_selected and not boot_success:
48681816748SMichael Walsh        prior_boot = next_boot
48781816748SMichael Walsh        boot_candidate = boot_stack.pop()
488004ad3c9SJoy Onyerikwu        gp.qprint_timen("The prior '" + next_boot + "' was chosen to"
489004ad3c9SJoy Onyerikwu                        + " transition to a valid state for '" + boot_candidate
490004ad3c9SJoy Onyerikwu                        + "' which was at the top of the boot_stack.  Since"
491004ad3c9SJoy Onyerikwu                        + " the '" + next_boot + "' failed, the '"
492004ad3c9SJoy Onyerikwu                        + boot_candidate + "' has been removed from the stack"
493004ad3c9SJoy Onyerikwu                        + " to avoid and endless failure loop.")
49481816748SMichael Walsh        if len(boot_stack) == 0:
49581816748SMichael Walsh            return ""
49681816748SMichael Walsh
4976741f740SMichael Walsh    my_get_state()
49845ca6e4cSMichael Walsh    valid_state()
4996741f740SMichael Walsh
50081816748SMichael Walsh    transitional_boot_selected = False
5016741f740SMichael Walsh    stack_popped = 0
5026741f740SMichael Walsh    if len(boot_stack) > 0:
5036741f740SMichael Walsh        stack_popped = 1
504b5839d00SMichael Walsh        gp.qprint_dashes()
505b5839d00SMichael Walsh        gp.qprint_var(boot_stack)
506b5839d00SMichael Walsh        gp.qprint_dashes()
507b5839d00SMichael Walsh        skip_boot_printed = 0
508b5839d00SMichael Walsh        while len(boot_stack) > 0:
5096741f740SMichael Walsh            boot_candidate = boot_stack.pop()
510b5839d00SMichael Walsh            if stack_mode == 'normal':
511b5839d00SMichael Walsh                break
512b5839d00SMichael Walsh            else:
513b5839d00SMichael Walsh                if st.compare_states(state, boot_table[boot_candidate]['end']):
514b5839d00SMichael Walsh                    if not skip_boot_printed:
515ff340006SMichael Walsh                        gp.qprint_var(stack_mode)
516ff340006SMichael Walsh                        gp.qprintn()
517004ad3c9SJoy Onyerikwu                        gp.qprint_timen("Skipping the following boot tests"
518004ad3c9SJoy Onyerikwu                                        + " which are unnecessary since their"
519004ad3c9SJoy Onyerikwu                                        + " required end states match the"
520004ad3c9SJoy Onyerikwu                                        + " current machine state:")
521b5839d00SMichael Walsh                        skip_boot_printed = 1
522ff340006SMichael Walsh                    gp.qprint_var(boot_candidate)
523b5839d00SMichael Walsh                    boot_candidate = ""
524b5839d00SMichael Walsh        if boot_candidate == "":
525b5839d00SMichael Walsh            gp.qprint_dashes()
526b5839d00SMichael Walsh            gp.qprint_var(boot_stack)
527b5839d00SMichael Walsh            gp.qprint_dashes()
528b5839d00SMichael Walsh            return boot_candidate
5296741f740SMichael Walsh        if st.compare_states(state, boot_table[boot_candidate]['start']):
530004ad3c9SJoy Onyerikwu            gp.qprint_timen("The machine state is valid for a '"
531004ad3c9SJoy Onyerikwu                            + boot_candidate + "' boot test.")
532b5839d00SMichael Walsh            gp.qprint_dashes()
533b5839d00SMichael Walsh            gp.qprint_var(boot_stack)
534b5839d00SMichael Walsh            gp.qprint_dashes()
5356741f740SMichael Walsh            return boot_candidate
536341c21ebSMichael Walsh        else:
537004ad3c9SJoy Onyerikwu            gp.qprint_timen("The machine state does not match the required"
538004ad3c9SJoy Onyerikwu                            + " starting state for a '" + boot_candidate
539004ad3c9SJoy Onyerikwu                            + "' boot test:")
540ff340006SMichael Walsh            gp.qprint_varx("boot_table[" + boot_candidate + "][start]",
541b5839d00SMichael Walsh                           boot_table[boot_candidate]['start'], 1)
5426741f740SMichael Walsh            boot_stack.append(boot_candidate)
54381816748SMichael Walsh            transitional_boot_selected = True
5446741f740SMichael Walsh            popped_boot = boot_candidate
5456741f740SMichael Walsh
5466741f740SMichael Walsh    # Loop through your list selecting a boot_candidates
5476741f740SMichael Walsh    boot_candidates = []
5486741f740SMichael Walsh    for boot_candidate in boot_list:
5496741f740SMichael Walsh        if st.compare_states(state, boot_table[boot_candidate]['start']):
5506741f740SMichael Walsh            if stack_popped:
5516741f740SMichael Walsh                if st.compare_states(boot_table[boot_candidate]['end'],
5526741f740SMichael Walsh                                     boot_table[popped_boot]['start']):
5536741f740SMichael Walsh                    boot_candidates.append(boot_candidate)
554341c21ebSMichael Walsh            else:
5556741f740SMichael Walsh                boot_candidates.append(boot_candidate)
5566741f740SMichael Walsh
5576741f740SMichael Walsh    if len(boot_candidates) == 0:
558004ad3c9SJoy Onyerikwu        gp.qprint_timen("The user's boot list contained no boot tests"
559004ad3c9SJoy Onyerikwu                        + " which are valid for the current machine state.")
5606741f740SMichael Walsh        boot_candidate = default_power_on
5616741f740SMichael Walsh        if not st.compare_states(state, boot_table[default_power_on]['start']):
5626741f740SMichael Walsh            boot_candidate = default_power_off
5636741f740SMichael Walsh        boot_candidates.append(boot_candidate)
564004ad3c9SJoy Onyerikwu        gp.qprint_timen("Using default '" + boot_candidate
565004ad3c9SJoy Onyerikwu                        + "' boot type to transition to valid state.")
5666741f740SMichael Walsh
567b5839d00SMichael Walsh    gp.dprint_var(boot_candidates)
5686741f740SMichael Walsh
5696741f740SMichael Walsh    # Randomly select a boot from the candidate list.
5706741f740SMichael Walsh    boot = random.choice(boot_candidates)
571341c21ebSMichael Walsh
572341c21ebSMichael Walsh    return boot
5730bbd860fSMichael Walsh
57455302295SMichael Walsh
575341c21ebSMichael Walshdef print_last_boots():
576341c21ebSMichael Walsh    r"""
577341c21ebSMichael Walsh    Print the last ten boots done with their time stamps.
578341c21ebSMichael Walsh    """
579341c21ebSMichael Walsh
580341c21ebSMichael Walsh    # indent 0, 90 chars wide, linefeed, char is "="
581b5839d00SMichael Walsh    gp.qprint_dashes(0, 90)
582b5839d00SMichael Walsh    gp.qprintn("Last 10 boots:\n")
583341c21ebSMichael Walsh
584341c21ebSMichael Walsh    for boot_entry in last_ten:
585341c21ebSMichael Walsh        grp.rqprint(boot_entry)
586b5839d00SMichael Walsh    gp.qprint_dashes(0, 90)
587341c21ebSMichael Walsh
588341c21ebSMichael Walsh
589b2e53ecdSMichael Walshdef print_defect_report(ffdc_file_list):
590341c21ebSMichael Walsh    r"""
591341c21ebSMichael Walsh    Print a defect report.
592b2e53ecdSMichael Walsh
593b2e53ecdSMichael Walsh    Description of argument(s):
594b2e53ecdSMichael Walsh    ffdc_file_list  A list of files which were collected by our ffdc functions.
595341c21ebSMichael Walsh    """
596341c21ebSMichael Walsh
597600876daSMichael Walsh    # Making deliberate choice to NOT run plug_in_setup().  We don't want
598600876daSMichael Walsh    # ffdc_prefix updated.
599600876daSMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
600600876daSMichael Walsh        call_point='ffdc_report', stop_on_plug_in_failure=0)
601600876daSMichael Walsh
602e0cf8d70SMichael Walsh    # Get additional header data which may have been created by ffdc plug-ins.
603e0cf8d70SMichael Walsh    # Also, delete the individual header files to cleanup.
604e0cf8d70SMichael Walsh    cmd_buf = "file_list=$(cat " + ffdc_report_list_path + " 2>/dev/null)" +\
605e0cf8d70SMichael Walsh              " ; [ ! -z \"${file_list}\" ] && cat ${file_list}" +\
606e0cf8d70SMichael Walsh              " 2>/dev/null ; rm -rf ${file_list} 2>/dev/null || :"
607e0cf8d70SMichael Walsh    shell_rc, more_header_info = gc.cmd_fnc_u(cmd_buf, print_output=0,
608e0cf8d70SMichael Walsh                                              show_err=0)
609e0cf8d70SMichael Walsh
610b2e53ecdSMichael Walsh    # Get additional summary data which may have been created by ffdc plug-ins.
611600876daSMichael Walsh    # Also, delete the individual header files to cleanup.
612600876daSMichael Walsh    cmd_buf = "file_list=$(cat " + ffdc_summary_list_path + " 2>/dev/null)" +\
613600876daSMichael Walsh              " ; [ ! -z \"${file_list}\" ] && cat ${file_list}" +\
614600876daSMichael Walsh              " 2>/dev/null ; rm -rf ${file_list} 2>/dev/null || :"
615600876daSMichael Walsh    shell_rc, ffdc_summary_info = gc.cmd_fnc_u(cmd_buf, print_output=0,
616600876daSMichael Walsh                                               show_err=0)
617600876daSMichael Walsh
618b2e53ecdSMichael Walsh    # ffdc_list_file_path contains a list of any ffdc files created by plug-
619b2e53ecdSMichael Walsh    # ins, etc.  Read that data into a list.
620341c21ebSMichael Walsh    try:
621b2e53ecdSMichael Walsh        plug_in_ffdc_list = \
622b2e53ecdSMichael Walsh            open(ffdc_list_file_path, 'r').read().rstrip("\n").split("\n")
623b2e53ecdSMichael Walsh        plug_in_ffdc_list = filter(None, plug_in_ffdc_list)
624341c21ebSMichael Walsh    except IOError:
625b2e53ecdSMichael Walsh        plug_in_ffdc_list = []
626b2e53ecdSMichael Walsh
627b2e53ecdSMichael Walsh    # Combine the files from plug_in_ffdc_list with the ffdc_file_list passed
628b2e53ecdSMichael Walsh    # in.  Eliminate duplicates and sort the list.
629004ad3c9SJoy Onyerikwu    ffdc_file_list = sorted(set(ffdc_file_list + plug_in_ffdc_list))
630b2e53ecdSMichael Walsh
631b2e53ecdSMichael Walsh    if status_file_path != "":
632b2e53ecdSMichael Walsh        ffdc_file_list.insert(0, status_file_path)
633b2e53ecdSMichael Walsh
634b2e53ecdSMichael Walsh    # Convert the list to a printable list.
635b2e53ecdSMichael Walsh    printable_ffdc_file_list = "\n".join(ffdc_file_list)
636341c21ebSMichael Walsh
63768a61162SMichael Walsh    # Open ffdc_file_list for writing.  We will write a complete list of
63868a61162SMichael Walsh    # FFDC files to it for possible use by plug-ins like cp_stop_check.
63968a61162SMichael Walsh    ffdc_list_file = open(ffdc_list_file_path, 'w')
640b2e53ecdSMichael Walsh    ffdc_list_file.write(printable_ffdc_file_list + "\n")
641b2e53ecdSMichael Walsh    ffdc_list_file.close()
642b2e53ecdSMichael Walsh
643b2e53ecdSMichael Walsh    indent = 0
644b2e53ecdSMichael Walsh    width = 90
645b2e53ecdSMichael Walsh    linefeed = 1
646b2e53ecdSMichael Walsh    char = "="
64768a61162SMichael Walsh
64868a61162SMichael Walsh    gp.qprintn()
649b2e53ecdSMichael Walsh    gp.qprint_dashes(indent, width, linefeed, char)
65068a61162SMichael Walsh    gp.qprintn("Copy this data to the defect:\n")
65168a61162SMichael Walsh
652e0cf8d70SMichael Walsh    if len(more_header_info) > 0:
653ff340006SMichael Walsh        gp.qprintn(more_header_info)
654dc80d67dSMichael Walsh    gp.qpvars(host_name, host_ip, openbmc_nickname, openbmc_host,
655dc80d67dSMichael Walsh              openbmc_host_name, openbmc_ip, openbmc_username,
656dc80d67dSMichael Walsh              openbmc_password, os_host, os_host_name, os_ip, os_username,
657dc80d67dSMichael Walsh              os_password, pdu_host, pdu_host_name, pdu_ip, pdu_username,
658dc80d67dSMichael Walsh              pdu_password, pdu_slot_no, openbmc_serial_host,
659dc80d67dSMichael Walsh              openbmc_serial_host_name, openbmc_serial_ip, openbmc_serial_port)
66068a61162SMichael Walsh
66168a61162SMichael Walsh    gp.qprintn()
66268a61162SMichael Walsh    print_last_boots()
66368a61162SMichael Walsh    gp.qprintn()
66468a61162SMichael Walsh    gp.qprint_var(state)
665b5839d00SMichael Walsh    gp.qprintn()
666b5839d00SMichael Walsh    gp.qprintn("FFDC data files:")
667b2e53ecdSMichael Walsh    gp.qprintn(printable_ffdc_file_list)
668b5839d00SMichael Walsh    gp.qprintn()
669341c21ebSMichael Walsh
670600876daSMichael Walsh    if len(ffdc_summary_info) > 0:
671ff340006SMichael Walsh        gp.qprintn(ffdc_summary_info)
672600876daSMichael Walsh
673b2e53ecdSMichael Walsh    gp.qprint_dashes(indent, width, linefeed, char)
67468a61162SMichael Walsh
6756741f740SMichael Walsh
6766741f740SMichael Walshdef my_ffdc():
6776741f740SMichael Walsh    r"""
6786741f740SMichael Walsh    Collect FFDC data.
6796741f740SMichael Walsh    """
6806741f740SMichael Walsh
6816741f740SMichael Walsh    global state
6826741f740SMichael Walsh
6836741f740SMichael Walsh    plug_in_setup()
6846741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
685600876daSMichael Walsh        call_point='ffdc', stop_on_plug_in_failure=0)
6866741f740SMichael Walsh
6876741f740SMichael Walsh    AUTOBOOT_FFDC_PREFIX = os.environ['AUTOBOOT_FFDC_PREFIX']
688004ad3c9SJoy Onyerikwu    status, ffdc_file_list = grk.run_key_u("FFDC  ffdc_prefix="
689004ad3c9SJoy Onyerikwu                                           + AUTOBOOT_FFDC_PREFIX
690004ad3c9SJoy Onyerikwu                                           + "  ffdc_function_list="
691004ad3c9SJoy Onyerikwu                                           + ffdc_function_list, ignore=1)
69283f4bc77SMichael Walsh    if status != 'PASS':
693ff340006SMichael Walsh        gp.qprint_error("Call to ffdc failed.\n")
6946741f740SMichael Walsh
6956741f740SMichael Walsh    my_get_state()
6966741f740SMichael Walsh
697b2e53ecdSMichael Walsh    print_defect_report(ffdc_file_list)
6986741f740SMichael Walsh
6996741f740SMichael Walsh
7006741f740SMichael Walshdef print_test_start_message(boot_keyword):
7016741f740SMichael Walsh    r"""
7026741f740SMichael Walsh    Print a message indicating what boot test is about to run.
7036741f740SMichael Walsh
7046741f740SMichael Walsh    Description of arguments:
7056741f740SMichael Walsh    boot_keyword  The name of the boot which is to be run
7066741f740SMichael Walsh                  (e.g. "BMC Power On").
7076741f740SMichael Walsh    """
7086741f740SMichael Walsh
7096741f740SMichael Walsh    global last_ten
710325eb548SSunil M    global boot_start_time
7116741f740SMichael Walsh
7126741f740SMichael Walsh    doing_msg = gp.sprint_timen("Doing \"" + boot_keyword + "\".")
713325eb548SSunil M
714325eb548SSunil M    # Set boot_start_time for use by plug-ins.
715325eb548SSunil M    boot_start_time = doing_msg[1:33]
716325eb548SSunil M    gp.qprint_var(boot_start_time)
717325eb548SSunil M
718b5839d00SMichael Walsh    gp.qprint(doing_msg)
7196741f740SMichael Walsh
7206741f740SMichael Walsh    last_ten.append(doing_msg)
7216741f740SMichael Walsh
7226741f740SMichael Walsh    if len(last_ten) > 10:
7236741f740SMichael Walsh        del last_ten[0]
7246741f740SMichael Walsh
7256741f740SMichael Walsh
7266741f740SMichael Walshdef run_boot(boot):
7276741f740SMichael Walsh    r"""
7286741f740SMichael Walsh    Run the specified boot.
7296741f740SMichael Walsh
7306741f740SMichael Walsh    Description of arguments:
7316741f740SMichael Walsh    boot  The name of the boot test to be performed.
7326741f740SMichael Walsh    """
7336741f740SMichael Walsh
7346741f740SMichael Walsh    global state
7356741f740SMichael Walsh
7366741f740SMichael Walsh    print_test_start_message(boot)
7376741f740SMichael Walsh
7386741f740SMichael Walsh    plug_in_setup()
7396741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = \
7406741f740SMichael Walsh        grpi.rprocess_plug_in_packages(call_point="pre_boot")
7416741f740SMichael Walsh    if rc != 0:
7426741f740SMichael Walsh        error_message = "Plug-in failed with non-zero return code.\n" +\
7436741f740SMichael Walsh            gp.sprint_var(rc, 1)
7446741f740SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
7456741f740SMichael Walsh
7466741f740SMichael Walsh    if test_mode:
7476741f740SMichael Walsh        # In test mode, we'll pretend the boot worked by assigning its
7486741f740SMichael Walsh        # required end state to the default state value.
74930dadae2SMichael Walsh        state = st.strip_anchor_state(boot_table[boot]['end'])
7506741f740SMichael Walsh    else:
7516741f740SMichael Walsh        # Assertion:  We trust that the state data was made fresh by the
7526741f740SMichael Walsh        # caller.
7536741f740SMichael Walsh
754b5839d00SMichael Walsh        gp.qprintn()
7556741f740SMichael Walsh
7566741f740SMichael Walsh        if boot_table[boot]['method_type'] == "keyword":
7570b93fbf8SMichael Walsh            rk.my_run_keywords(boot_table[boot].get('lib_file_path', ''),
758b5839d00SMichael Walsh                               boot_table[boot]['method'],
759b5839d00SMichael Walsh                               quiet=quiet)
7606741f740SMichael Walsh
7616741f740SMichael Walsh        if boot_table[boot]['bmc_reboot']:
7626741f740SMichael Walsh            st.wait_for_comm_cycle(int(state['epoch_seconds']))
76330dadae2SMichael Walsh            plug_in_setup()
76430dadae2SMichael Walsh            rc, shell_rc, failed_plug_in_name = \
76530dadae2SMichael Walsh                grpi.rprocess_plug_in_packages(call_point="post_reboot")
76630dadae2SMichael Walsh            if rc != 0:
7670b93fbf8SMichael Walsh                error_message = "Plug-in failed with non-zero return code.\n"
7680b93fbf8SMichael Walsh                error_message += gp.sprint_var(rc, 1)
76930dadae2SMichael Walsh                BuiltIn().fail(gp.sprint_error(error_message))
7706741f740SMichael Walsh        else:
7716741f740SMichael Walsh            match_state = st.anchor_state(state)
7726741f740SMichael Walsh            del match_state['epoch_seconds']
7736741f740SMichael Walsh            # Wait for the state to change in any way.
7746741f740SMichael Walsh            st.wait_state(match_state, wait_time=state_change_timeout,
775600876daSMichael Walsh                          interval="10 seconds", invert=1)
7766741f740SMichael Walsh
777b5839d00SMichael Walsh        gp.qprintn()
7786741f740SMichael Walsh        if boot_table[boot]['end']['chassis'] == "Off":
7796741f740SMichael Walsh            boot_timeout = power_off_timeout
7806741f740SMichael Walsh        else:
7816741f740SMichael Walsh            boot_timeout = power_on_timeout
7826741f740SMichael Walsh        st.wait_state(boot_table[boot]['end'], wait_time=boot_timeout,
783600876daSMichael Walsh                      interval="10 seconds")
7846741f740SMichael Walsh
7856741f740SMichael Walsh    plug_in_setup()
7866741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = \
7876741f740SMichael Walsh        grpi.rprocess_plug_in_packages(call_point="post_boot")
7886741f740SMichael Walsh    if rc != 0:
7896741f740SMichael Walsh        error_message = "Plug-in failed with non-zero return code.\n" +\
7906741f740SMichael Walsh            gp.sprint_var(rc, 1)
7916741f740SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
7926741f740SMichael Walsh
7936741f740SMichael Walsh
7946741f740SMichael Walshdef test_loop_body():
7956741f740SMichael Walsh    r"""
7966741f740SMichael Walsh    The main loop body for the loop in main_py.
7976741f740SMichael Walsh
7986741f740SMichael Walsh    Description of arguments:
7996741f740SMichael Walsh    boot_count  The iteration number (starts at 1).
8006741f740SMichael Walsh    """
8016741f740SMichael Walsh
8026741f740SMichael Walsh    global boot_count
8036741f740SMichael Walsh    global state
8046741f740SMichael Walsh    global next_boot
8056741f740SMichael Walsh    global boot_success
806325eb548SSunil M    global boot_end_time
8076741f740SMichael Walsh
808b5839d00SMichael Walsh    gp.qprintn()
8096741f740SMichael Walsh
8106741f740SMichael Walsh    next_boot = select_boot()
811b5839d00SMichael Walsh    if next_boot == "":
812b5839d00SMichael Walsh        return True
8136741f740SMichael Walsh
814b5839d00SMichael Walsh    boot_count += 1
815b5839d00SMichael Walsh    gp.qprint_timen("Starting boot " + str(boot_count) + ".")
8166741f740SMichael Walsh
817e0cf8d70SMichael Walsh    pre_boot_plug_in_setup()
8186741f740SMichael Walsh
8196741f740SMichael Walsh    cmd_buf = ["run_boot", next_boot]
8206741f740SMichael Walsh    boot_status, msg = BuiltIn().run_keyword_and_ignore_error(*cmd_buf)
8216741f740SMichael Walsh    if boot_status == "FAIL":
822b5839d00SMichael Walsh        gp.qprint(msg)
8236741f740SMichael Walsh
824b5839d00SMichael Walsh    gp.qprintn()
8256741f740SMichael Walsh    if boot_status == "PASS":
8266741f740SMichael Walsh        boot_success = 1
827004ad3c9SJoy Onyerikwu        completion_msg = gp.sprint_timen("BOOT_SUCCESS: \"" + next_boot
828004ad3c9SJoy Onyerikwu                                         + "\" succeeded.")
8296741f740SMichael Walsh    else:
8306741f740SMichael Walsh        boot_success = 0
831004ad3c9SJoy Onyerikwu        completion_msg = gp.sprint_timen("BOOT_FAILED: \"" + next_boot
832004ad3c9SJoy Onyerikwu                                         + "\" failed.")
833325eb548SSunil M
834325eb548SSunil M    # Set boot_end_time for use by plug-ins.
835325eb548SSunil M    boot_end_time = completion_msg[1:33]
836325eb548SSunil M    gp.qprint_var(boot_end_time)
837325eb548SSunil M
838325eb548SSunil M    gp.qprint(completion_msg)
8396741f740SMichael Walsh
8406741f740SMichael Walsh    boot_results.update(next_boot, boot_status)
8416741f740SMichael Walsh
8426741f740SMichael Walsh    plug_in_setup()
8436741f740SMichael Walsh    # NOTE: A post_test_case call point failure is NOT counted as a boot
8446741f740SMichael Walsh    # failure.
8456741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
846600876daSMichael Walsh        call_point='post_test_case', stop_on_plug_in_failure=0)
8476741f740SMichael Walsh
8486741f740SMichael Walsh    plug_in_setup()
8496741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
8506741f740SMichael Walsh        call_point='ffdc_check', shell_rc=0x00000200,
8516741f740SMichael Walsh        stop_on_plug_in_failure=1, stop_on_non_zero_rc=1)
8526741f740SMichael Walsh    if boot_status != "PASS" or ffdc_check == "All" or shell_rc == 0x00000200:
85383f4bc77SMichael Walsh        status, ret_values = grk.run_key_u("my_ffdc", ignore=1)
85483f4bc77SMichael Walsh        if status != 'PASS':
855ff340006SMichael Walsh            gp.qprint_error("Call to my_ffdc failed.\n")
8566741f740SMichael Walsh
857aabef1e3SMichael Walsh    if delete_errlogs:
858d139f286SMichael Walsh        # We need to purge error logs between boots or they build up.
859b5839d00SMichael Walsh        grk.run_key("Delete Error logs", ignore=1)
860d139f286SMichael Walsh
861952f9b09SMichael Walsh    boot_results.print_report()
862b5839d00SMichael Walsh    gp.qprint_timen("Finished boot " + str(boot_count) + ".")
863952f9b09SMichael Walsh
8646741f740SMichael Walsh    plug_in_setup()
8656741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
8663ba8ecdcSMichael Walsh        call_point='stop_check', shell_rc=0x00000200, stop_on_non_zero_rc=1)
8673ba8ecdcSMichael Walsh    if shell_rc == 0x00000200:
8683ba8ecdcSMichael Walsh        message = "Stopping as requested by user.\n"
8693ba8ecdcSMichael Walsh        gp.print_time(message)
8703ba8ecdcSMichael Walsh        BuiltIn().fail(message)
8716741f740SMichael Walsh
872d139f286SMichael Walsh    # This should help prevent ConnectionErrors.
8730960b384SMichael Walsh    grk.run_key_u("Close All Connections")
874d139f286SMichael Walsh
8756741f740SMichael Walsh    return True
8766741f740SMichael Walsh
8776741f740SMichael Walsh
87883f4bc77SMichael Walshdef obmc_boot_test_teardown():
8796741f740SMichael Walsh    r"""
880c9116811SMichael Walsh    Clean up after the Main keyword.
8816741f740SMichael Walsh    """
8826741f740SMichael Walsh
8836741f740SMichael Walsh    if cp_setup_called:
8846741f740SMichael Walsh        plug_in_setup()
8856741f740SMichael Walsh        rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
886600876daSMichael Walsh            call_point='cleanup', stop_on_plug_in_failure=0)
8876741f740SMichael Walsh
888600876daSMichael Walsh    if 'boot_results_file_path' in globals():
889*6c64574bSMichael Walsh        # Save boot_results and last_ten objects to a file in case they are
890*6c64574bSMichael Walsh        # needed again.
891b5839d00SMichael Walsh        gp.qprint_timen("Saving boot_results to the following path.")
892b5839d00SMichael Walsh        gp.qprint_var(boot_results_file_path)
893*6c64574bSMichael Walsh        pickle.dump((boot_results, last_ten),
894*6c64574bSMichael Walsh                    open(boot_results_file_path, 'wb'),
8950b93fbf8SMichael Walsh                    pickle.HIGHEST_PROTOCOL)
8960b93fbf8SMichael Walsh
897ff340006SMichael Walsh    global save_stack
898ff340006SMichael Walsh    # Restore any global values saved on the save_stack.
899ff340006SMichael Walsh    for parm_name in main_func_parm_list:
900ff340006SMichael Walsh        # Get the parm_value if it was saved on the stack.
901ff340006SMichael Walsh        try:
902ff340006SMichael Walsh            parm_value = save_stack.pop(parm_name)
903004ad3c9SJoy Onyerikwu        except BaseException:
904ff340006SMichael Walsh            # If it was not saved, no further action is required.
905ff340006SMichael Walsh            continue
906ff340006SMichael Walsh
907ff340006SMichael Walsh        # Restore the saved value.
908ff340006SMichael Walsh        cmd_buf = "BuiltIn().set_global_variable(\"${" + parm_name +\
909ff340006SMichael Walsh            "}\", parm_value)"
910ff340006SMichael Walsh        gp.dpissuing(cmd_buf)
911ff340006SMichael Walsh        exec(cmd_buf)
912ff340006SMichael Walsh
913ff340006SMichael Walsh    gp.dprintn(save_stack.sprint_obj())
914ff340006SMichael Walsh
9156741f740SMichael Walsh
916c9116811SMichael Walshdef test_teardown():
917c9116811SMichael Walsh    r"""
918c9116811SMichael Walsh    Clean up after this test case.
919c9116811SMichael Walsh    """
920c9116811SMichael Walsh
921c9116811SMichael Walsh    gp.qprintn()
922c9116811SMichael Walsh    cmd_buf = ["Print Error",
923c9116811SMichael Walsh               "A keyword timeout occurred ending this program.\n"]
924c9116811SMichael Walsh    BuiltIn().run_keyword_if_timeout_occurred(*cmd_buf)
925c9116811SMichael Walsh
926b5839d00SMichael Walsh    grp.rqprint_pgm_footer()
927b5839d00SMichael Walsh
928c9116811SMichael Walsh
929ff340006SMichael Walshdef obmc_boot_test_py(loc_boot_stack=None,
930ff340006SMichael Walsh                      loc_stack_mode=None,
931ff340006SMichael Walsh                      loc_quiet=None):
9326741f740SMichael Walsh    r"""
9336741f740SMichael Walsh    Do main program processing.
9346741f740SMichael Walsh    """
9356741f740SMichael Walsh
936ff340006SMichael Walsh    global save_stack
937ff340006SMichael Walsh
938ff340006SMichael Walsh    # Process function parms.
939ff340006SMichael Walsh    for parm_name in main_func_parm_list:
940ff340006SMichael Walsh        # Get parm's value.
941ff340006SMichael Walsh        cmd_buf = "parm_value = loc_" + parm_name
942ff340006SMichael Walsh        exec(cmd_buf)
943ff340006SMichael Walsh        gp.dpvar(parm_name)
944ff340006SMichael Walsh        gp.dpvar(parm_value)
945ff340006SMichael Walsh
946ff340006SMichael Walsh        if parm_value is None:
947ff340006SMichael Walsh            # Parm was not specified by the calling function so set it to its
948ff340006SMichael Walsh            # corresponding global value.
949ff340006SMichael Walsh            cmd_buf = "loc_" + parm_name + " = BuiltIn().get_variable_value" +\
950ff340006SMichael Walsh                "(\"${" + parm_name + "}\")"
951ff340006SMichael Walsh            gp.dpissuing(cmd_buf)
952ff340006SMichael Walsh            exec(cmd_buf)
953ff340006SMichael Walsh        else:
954ff340006SMichael Walsh            # Save the global value on a stack.
955ff340006SMichael Walsh            cmd_buf = "save_stack.push(BuiltIn().get_variable_value(\"${" +\
956ff340006SMichael Walsh                parm_name + "}\"), \"" + parm_name + "\")"
957ff340006SMichael Walsh            gp.dpissuing(cmd_buf)
958ff340006SMichael Walsh            exec(cmd_buf)
959ff340006SMichael Walsh
960ff340006SMichael Walsh            # Set the global value to the passed value.
961ff340006SMichael Walsh            cmd_buf = "BuiltIn().set_global_variable(\"${" + parm_name +\
962ff340006SMichael Walsh                "}\", loc_" + parm_name + ")"
963ff340006SMichael Walsh            gp.dpissuing(cmd_buf)
964ff340006SMichael Walsh            exec(cmd_buf)
965ff340006SMichael Walsh
966ff340006SMichael Walsh    gp.dprintn(save_stack.sprint_obj())
967b5839d00SMichael Walsh
9686741f740SMichael Walsh    setup()
9696741f740SMichael Walsh
970cd9fbfd7SMichael Walsh    init_boot_pass, init_boot_fail = boot_results.return_total_pass_fail()
971cd9fbfd7SMichael Walsh
972a20da401SMichael Walsh    if ffdc_only:
973a20da401SMichael Walsh        gp.qprint_timen("Caller requested ffdc_only.")
974e0cf8d70SMichael Walsh        pre_boot_plug_in_setup()
97583f4bc77SMichael Walsh        grk.run_key_u("my_ffdc")
976764d2f83SMichael Walsh        return
977a20da401SMichael Walsh
9786741f740SMichael Walsh    # Process caller's boot_stack.
9796741f740SMichael Walsh    while (len(boot_stack) > 0):
9806741f740SMichael Walsh        test_loop_body()
9816741f740SMichael Walsh
982b5839d00SMichael Walsh    gp.qprint_timen("Finished processing stack.")
98330dadae2SMichael Walsh
9846741f740SMichael Walsh    # Process caller's boot_list.
9856741f740SMichael Walsh    if len(boot_list) > 0:
9866741f740SMichael Walsh        for ix in range(1, max_num_tests + 1):
9876741f740SMichael Walsh            test_loop_body()
9886741f740SMichael Walsh
989b5839d00SMichael Walsh    gp.qprint_timen("Completed all requested boot tests.")
990b5839d00SMichael Walsh
991b5839d00SMichael Walsh    boot_pass, boot_fail = boot_results.return_total_pass_fail()
992cd9fbfd7SMichael Walsh    new_fail = boot_fail - init_boot_fail
993cd9fbfd7SMichael Walsh    if new_fail > boot_fail_threshold:
994b5839d00SMichael Walsh        error_message = "Boot failures exceed the boot failure" +\
995b5839d00SMichael Walsh                        " threshold:\n" +\
996cd9fbfd7SMichael Walsh                        gp.sprint_var(new_fail) +\
997b5839d00SMichael Walsh                        gp.sprint_var(boot_fail_threshold)
998b5839d00SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
999