10bbd860fSMichael Walsh#!/usr/bin/env python
20bbd860fSMichael Walsh
30bbd860fSMichael Walshr"""
40bbd860fSMichael WalshThis module is the python counterpart to obmc_boot_test.
50bbd860fSMichael Walsh"""
60bbd860fSMichael Walsh
70b93fbf8SMichael Walshimport os
80b93fbf8SMichael Walshimport imp
90b93fbf8SMichael Walshimport time
100b93fbf8SMichael Walshimport glob
110b93fbf8SMichael Walshimport random
120ad0f7f8SMichael Walshimport re
130b93fbf8SMichael Walshimport cPickle as pickle
14dc80d67dSMichael Walshimport socket
150b93fbf8SMichael Walsh
160b93fbf8SMichael Walshfrom robot.utils import DotDict
170b93fbf8SMichael Walshfrom robot.libraries.BuiltIn import BuiltIn
180b93fbf8SMichael Walsh
196741f740SMichael Walshfrom boot_data import *
20c9116811SMichael Walshimport gen_print as gp
210bbd860fSMichael Walshimport gen_robot_print as grp
2255302295SMichael Walshimport gen_robot_plug_in as grpi
236741f740SMichael Walshimport gen_robot_valid as grv
246741f740SMichael Walshimport gen_misc as gm
256741f740SMichael Walshimport gen_cmd as gc
26b5839d00SMichael Walshimport gen_robot_keyword as grk
2755302295SMichael Walshimport state as st
280bbd860fSMichael Walsh
290b93fbf8SMichael Walshbase_path = os.path.dirname(os.path.dirname(
300b93fbf8SMichael Walsh                            imp.find_module("gen_robot_print")[1])) +\
310b93fbf8SMichael Walsh    os.sep
320b93fbf8SMichael Walshsys.path.append(base_path + "extended/")
330b93fbf8SMichael Walshimport run_keyword as rk
340bbd860fSMichael Walsh
35e1e26448SMichael Walsh# Setting master_pid correctly influences the behavior of plug-ins like
36e1e26448SMichael Walsh# DB_Logging
37e1e26448SMichael Walshprogram_pid = os.getpid()
38e1e26448SMichael Walshmaster_pid = os.environ.get('AUTOBOOT_MASTER_PID', program_pid)
39e1e26448SMichael Walsh
40b5839d00SMichael Walsh# Set up boot data structures.
41b5839d00SMichael Walshboot_table = create_boot_table()
42b5839d00SMichael Walshvalid_boot_types = create_valid_boot_list(boot_table)
430b93fbf8SMichael Walsh
446741f740SMichael Walshboot_lists = read_boot_lists()
456741f740SMichael Walshlast_ten = []
466741f740SMichael Walsh
476741f740SMichael Walshstate = st.return_default_state()
486741f740SMichael Walshcp_setup_called = 0
496741f740SMichael Walshnext_boot = ""
506741f740SMichael Walshbase_tool_dir_path = os.path.normpath(os.environ.get(
516741f740SMichael Walsh    'AUTOBOOT_BASE_TOOL_DIR_PATH', "/tmp")) + os.sep
52b5839d00SMichael Walsh
536741f740SMichael Walshffdc_dir_path = os.path.normpath(os.environ.get('FFDC_DIR_PATH', '')) + os.sep
546741f740SMichael Walshboot_success = 0
556741f740SMichael Walshstatus_dir_path = os.environ.get('STATUS_DIR_PATH', "")
566741f740SMichael Walshif status_dir_path != "":
576741f740SMichael Walsh    status_dir_path = os.path.normpath(status_dir_path) + os.sep
580b93fbf8SMichael Walshdefault_power_on = "REST Power On"
590b93fbf8SMichael Walshdefault_power_off = "REST Power Off"
606741f740SMichael Walshboot_count = 0
610bbd860fSMichael Walsh
6285678948SMichael WalshLOG_LEVEL = BuiltIn().get_variable_value("${LOG_LEVEL}")
63e1974b96SMichael Walshffdc_prefix = ""
64*325eb548SSunil Mboot_start_time = ""
65*325eb548SSunil Mboot_end_time = ""
6685678948SMichael Walsh
6785678948SMichael Walsh
6885678948SMichael Walsh###############################################################################
690ad0f7f8SMichael Walshdef process_host(host,
700ad0f7f8SMichael Walsh                 host_var_name=""):
710ad0f7f8SMichael Walsh
720ad0f7f8SMichael Walsh    r"""
730ad0f7f8SMichael Walsh    Process a host by getting the associated host name and IP address and
740ad0f7f8SMichael Walsh    setting them in global variables.
750ad0f7f8SMichael Walsh
760ad0f7f8SMichael Walsh    If the caller does not pass the host_var_name, this function will try to
770ad0f7f8SMichael Walsh    figure out the name of the variable used by the caller for the host parm.
780ad0f7f8SMichael Walsh    Callers are advised to explicitly specify the host_var_name when calling
790ad0f7f8SMichael Walsh    with an exec command.  In such cases, the get_arg_name cannot figure out
800ad0f7f8SMichael Walsh    the host variable name.
810ad0f7f8SMichael Walsh
820ad0f7f8SMichael Walsh    This function will then create similar global variable names by
830ad0f7f8SMichael Walsh    removing "_host" and appending "_host_name" or "_ip" to the host variable
840ad0f7f8SMichael Walsh    name.
850ad0f7f8SMichael Walsh
860ad0f7f8SMichael Walsh    Example:
870ad0f7f8SMichael Walsh
880ad0f7f8SMichael Walsh    If a call is made like this:
890ad0f7f8SMichael Walsh    process_host(openbmc_host)
900ad0f7f8SMichael Walsh
910ad0f7f8SMichael Walsh    Global variables openbmc_host_name and openbmc_ip will be set.
920ad0f7f8SMichael Walsh
930ad0f7f8SMichael Walsh    Description of argument(s):
940ad0f7f8SMichael Walsh    host           A host name or IP.  The name of the variable used should
950ad0f7f8SMichael Walsh                   have a suffix of "_host".
960ad0f7f8SMichael Walsh    host_var_name  The name of the variable being used as the host parm.
970ad0f7f8SMichael Walsh    """
980ad0f7f8SMichael Walsh
990ad0f7f8SMichael Walsh    if host_var_name == "":
1000ad0f7f8SMichael Walsh        host_var_name = gp.get_arg_name(0, 1, stack_frame_ix=2)
1010ad0f7f8SMichael Walsh
1020ad0f7f8SMichael Walsh    host_name_var_name = re.sub("host", "host_name", host_var_name)
1030ad0f7f8SMichael Walsh    ip_var_name = re.sub("host", "ip", host_var_name)
1040ad0f7f8SMichael Walsh    cmd_buf = "global " + host_name_var_name + ", " + ip_var_name + " ; " +\
1050ad0f7f8SMichael Walsh        host_name_var_name + ", " + ip_var_name + " = gm.get_host_name_ip('" +\
1060ad0f7f8SMichael Walsh        host + "')"
1070ad0f7f8SMichael Walsh    exec(cmd_buf)
1080ad0f7f8SMichael Walsh
1090ad0f7f8SMichael Walsh###############################################################################
1100ad0f7f8SMichael Walsh
1110ad0f7f8SMichael Walsh
1120ad0f7f8SMichael Walsh###############################################################################
113b5839d00SMichael Walshdef process_pgm_parms():
114b5839d00SMichael Walsh
115b5839d00SMichael Walsh    r"""
116b5839d00SMichael Walsh    Process the program parameters by assigning them all to corresponding
117b5839d00SMichael Walsh    globals.  Also, set some global values that depend on program parameters.
118b5839d00SMichael Walsh    """
119b5839d00SMichael Walsh
120b5839d00SMichael Walsh    # Program parameter processing.
121b5839d00SMichael Walsh    # Assign all program parms to python variables which are global to this
122b5839d00SMichael Walsh    # module.
123b5839d00SMichael Walsh
124b5839d00SMichael Walsh    global parm_list
125b5839d00SMichael Walsh    parm_list = BuiltIn().get_variable_value("${parm_list}")
126b5839d00SMichael Walsh    # The following subset of parms should be processed as integers.
127b5839d00SMichael Walsh    int_list = ['max_num_tests', 'boot_pass', 'boot_fail', 'ffdc_only',
128b5839d00SMichael Walsh                'boot_fail_threshold', 'quiet', 'test_mode', 'debug']
129b5839d00SMichael Walsh    for parm in parm_list:
130b5839d00SMichael Walsh        if parm in int_list:
131b5839d00SMichael Walsh            sub_cmd = "int(BuiltIn().get_variable_value(\"${" + parm +\
132b5839d00SMichael Walsh                      "}\", \"0\"))"
133b5839d00SMichael Walsh        else:
134b5839d00SMichael Walsh            sub_cmd = "BuiltIn().get_variable_value(\"${" + parm + "}\")"
135b5839d00SMichael Walsh        cmd_buf = "global " + parm + " ; " + parm + " = " + sub_cmd
136b5839d00SMichael Walsh        exec(cmd_buf)
1370ad0f7f8SMichael Walsh        if re.match(r".*_host$", parm):
1380ad0f7f8SMichael Walsh            cmd_buf = "process_host(" + parm + ", '" + parm + "')"
1390ad0f7f8SMichael Walsh            exec(cmd_buf)
1400ad0f7f8SMichael Walsh        if re.match(r".*_password$", parm):
1410ad0f7f8SMichael Walsh            # Register the value of any parm whose name ends in _password.
1420ad0f7f8SMichael Walsh            # This will cause the print functions to replace passwords with
1430ad0f7f8SMichael Walsh            # asterisks in the output.
1440ad0f7f8SMichael Walsh            cmd_buf = "gp.register_passwords(" + parm + ")"
1450ad0f7f8SMichael Walsh            exec(cmd_buf)
146b5839d00SMichael Walsh
147b5839d00SMichael Walsh    global ffdc_dir_path_style
148b5839d00SMichael Walsh    global boot_list
149b5839d00SMichael Walsh    global boot_stack
150b5839d00SMichael Walsh    global boot_results_file_path
151b5839d00SMichael Walsh    global boot_results
152b5839d00SMichael Walsh    global ffdc_list_file_path
153e0cf8d70SMichael Walsh    global ffdc_report_list_path
154600876daSMichael Walsh    global ffdc_summary_list_path
155b5839d00SMichael Walsh
156b5839d00SMichael Walsh    if ffdc_dir_path_style == "":
157b5839d00SMichael Walsh        ffdc_dir_path_style = int(os.environ.get('FFDC_DIR_PATH_STYLE', '0'))
158b5839d00SMichael Walsh
159b5839d00SMichael Walsh    # Convert these program parms to lists for easier processing..
160b5839d00SMichael Walsh    boot_list = filter(None, boot_list.split(":"))
161b5839d00SMichael Walsh    boot_stack = filter(None, boot_stack.split(":"))
162b5839d00SMichael Walsh
163b5839d00SMichael Walsh    boot_results_file_path = "/tmp/" + openbmc_nickname + ":pid_" +\
164b5839d00SMichael Walsh                             str(master_pid) + ":boot_results"
165b5839d00SMichael Walsh
166b5839d00SMichael Walsh    if os.path.isfile(boot_results_file_path):
167b5839d00SMichael Walsh        # We've been called before in this run so we'll load the saved
168b5839d00SMichael Walsh        # boot_results object.
169b5839d00SMichael Walsh        boot_results = pickle.load(open(boot_results_file_path, 'rb'))
170b5839d00SMichael Walsh    else:
171b5839d00SMichael Walsh        boot_results = boot_results(boot_table, boot_pass, boot_fail)
172b5839d00SMichael Walsh
173b5839d00SMichael Walsh    ffdc_list_file_path = base_tool_dir_path + openbmc_nickname +\
174b5839d00SMichael Walsh        "/FFDC_FILE_LIST"
175e0cf8d70SMichael Walsh    ffdc_report_list_path = base_tool_dir_path + openbmc_nickname +\
176e0cf8d70SMichael Walsh        "/FFDC_REPORT_FILE_LIST"
177b5839d00SMichael Walsh
178600876daSMichael Walsh    ffdc_summary_list_path = base_tool_dir_path + openbmc_nickname +\
179600876daSMichael Walsh        "/FFDC_SUMMARY_FILE_LIST"
180600876daSMichael Walsh
181b5839d00SMichael Walsh###############################################################################
182b5839d00SMichael Walsh
183b5839d00SMichael Walsh
184b5839d00SMichael Walsh###############################################################################
18585678948SMichael Walshdef initial_plug_in_setup():
18685678948SMichael Walsh
18785678948SMichael Walsh    r"""
18885678948SMichael Walsh    Initialize all plug-in environment variables which do not change for the
18985678948SMichael Walsh    duration of the program.
19085678948SMichael Walsh
19185678948SMichael Walsh    """
19285678948SMichael Walsh
19385678948SMichael Walsh    global LOG_LEVEL
19485678948SMichael Walsh    BuiltIn().set_log_level("NONE")
19585678948SMichael Walsh
19685678948SMichael Walsh    BuiltIn().set_global_variable("${master_pid}", master_pid)
19785678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_DIR_PATH}", ffdc_dir_path)
19885678948SMichael Walsh    BuiltIn().set_global_variable("${STATUS_DIR_PATH}", status_dir_path)
19985678948SMichael Walsh    BuiltIn().set_global_variable("${BASE_TOOL_DIR_PATH}", base_tool_dir_path)
20085678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_LIST_FILE_PATH}",
20185678948SMichael Walsh                                  ffdc_list_file_path)
202e0cf8d70SMichael Walsh    BuiltIn().set_global_variable("${FFDC_REPORT_LIST_PATH}",
203e0cf8d70SMichael Walsh                                  ffdc_report_list_path)
204600876daSMichael Walsh    BuiltIn().set_global_variable("${FFDC_SUMMARY_LIST_PATH}",
205600876daSMichael Walsh                                  ffdc_summary_list_path)
20685678948SMichael Walsh
20785678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_DIR_PATH_STYLE}",
20885678948SMichael Walsh                                  ffdc_dir_path_style)
20985678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_CHECK}",
21085678948SMichael Walsh                                  ffdc_check)
21185678948SMichael Walsh
21285678948SMichael Walsh    # For each program parameter, set the corresponding AUTOBOOT_ environment
21385678948SMichael Walsh    # variable value.  Also, set an AUTOBOOT_ environment variable for every
21485678948SMichael Walsh    # element in additional_values.
21585678948SMichael Walsh    additional_values = ["program_pid", "master_pid", "ffdc_dir_path",
21685678948SMichael Walsh                         "status_dir_path", "base_tool_dir_path",
217600876daSMichael Walsh                         "ffdc_list_file_path", "ffdc_report_list_path",
218600876daSMichael Walsh                         "ffdc_summary_list_path"]
21985678948SMichael Walsh
22085678948SMichael Walsh    plug_in_vars = parm_list + additional_values
22185678948SMichael Walsh
22285678948SMichael Walsh    for var_name in plug_in_vars:
22385678948SMichael Walsh        var_value = BuiltIn().get_variable_value("${" + var_name + "}")
22485678948SMichael Walsh        var_name = var_name.upper()
22585678948SMichael Walsh        if var_value is None:
22685678948SMichael Walsh            var_value = ""
22785678948SMichael Walsh        os.environ["AUTOBOOT_" + var_name] = str(var_value)
22885678948SMichael Walsh
22985678948SMichael Walsh    BuiltIn().set_log_level(LOG_LEVEL)
23085678948SMichael Walsh
23168a61162SMichael Walsh    # Make sure the ffdc list directory exists.
23268a61162SMichael Walsh    ffdc_list_dir_path = os.path.dirname(ffdc_list_file_path) + os.sep
23368a61162SMichael Walsh    if not os.path.exists(ffdc_list_dir_path):
23468a61162SMichael Walsh        os.makedirs(ffdc_list_dir_path)
23585678948SMichael Walsh
23685678948SMichael Walsh###############################################################################
23785678948SMichael Walsh
2380bbd860fSMichael Walsh
2390bbd860fSMichael Walsh###############################################################################
2400bbd860fSMichael Walshdef plug_in_setup():
2410bbd860fSMichael Walsh
2420bbd860fSMichael Walsh    r"""
24385678948SMichael Walsh    Initialize all changing plug-in environment variables for use by the
24485678948SMichael Walsh    plug-in programs.
2450bbd860fSMichael Walsh    """
2460bbd860fSMichael Walsh
24785678948SMichael Walsh    global LOG_LEVEL
24885678948SMichael Walsh    global test_really_running
24985678948SMichael Walsh
25085678948SMichael Walsh    BuiltIn().set_log_level("NONE")
25185678948SMichael Walsh
2526741f740SMichael Walsh    boot_pass, boot_fail = boot_results.return_total_pass_fail()
2530bbd860fSMichael Walsh    if boot_pass > 1:
2540bbd860fSMichael Walsh        test_really_running = 1
2550bbd860fSMichael Walsh    else:
2560bbd860fSMichael Walsh        test_really_running = 0
2570bbd860fSMichael Walsh
2586741f740SMichael Walsh    BuiltIn().set_global_variable("${test_really_running}",
2596741f740SMichael Walsh                                  test_really_running)
2606741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_type_desc}", next_boot)
2616741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_pass}", boot_pass)
2626741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_fail}", boot_fail)
2636741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_success}", boot_success)
2646741f740SMichael Walsh    BuiltIn().set_global_variable("${ffdc_prefix}", ffdc_prefix)
265*325eb548SSunil M    BuiltIn().set_global_variable("${boot_start_time}", boot_start_time)
266*325eb548SSunil M    BuiltIn().set_global_variable("${boot_end_time}", boot_end_time)
2674c9a6453SMichael Walsh
2680bbd860fSMichael Walsh    # For each program parameter, set the corresponding AUTOBOOT_ environment
2690bbd860fSMichael Walsh    # variable value.  Also, set an AUTOBOOT_ environment variable for every
2700bbd860fSMichael Walsh    # element in additional_values.
2710bbd860fSMichael Walsh    additional_values = ["boot_type_desc", "boot_success", "boot_pass",
272*325eb548SSunil M                         "boot_fail", "test_really_running", "ffdc_prefix",
273*325eb548SSunil M                         "boot_start_time", "boot_end_time"]
2740bbd860fSMichael Walsh
27585678948SMichael Walsh    plug_in_vars = additional_values
2760bbd860fSMichael Walsh
2770bbd860fSMichael Walsh    for var_name in plug_in_vars:
2780bbd860fSMichael Walsh        var_value = BuiltIn().get_variable_value("${" + var_name + "}")
2790bbd860fSMichael Walsh        var_name = var_name.upper()
2800bbd860fSMichael Walsh        if var_value is None:
2810bbd860fSMichael Walsh            var_value = ""
2826741f740SMichael Walsh        os.environ["AUTOBOOT_" + var_name] = str(var_value)
2830bbd860fSMichael Walsh
2840bbd860fSMichael Walsh    if debug:
2856741f740SMichael Walsh        shell_rc, out_buf = \
2866741f740SMichael Walsh            gc.cmd_fnc_u("printenv | egrep AUTOBOOT_ | sort -u")
2870bbd860fSMichael Walsh
28885678948SMichael Walsh    BuiltIn().set_log_level(LOG_LEVEL)
28985678948SMichael Walsh
2900bbd860fSMichael Walsh###############################################################################
2910bbd860fSMichael Walsh
2920bbd860fSMichael Walsh
2930bbd860fSMichael Walsh###############################################################################
294e0cf8d70SMichael Walshdef pre_boot_plug_in_setup():
295e0cf8d70SMichael Walsh
296e0cf8d70SMichael Walsh    # Clear the ffdc_list_file_path file.  Plug-ins may now write to it.
297e0cf8d70SMichael Walsh    try:
298e0cf8d70SMichael Walsh        os.remove(ffdc_list_file_path)
299e0cf8d70SMichael Walsh    except OSError:
300e0cf8d70SMichael Walsh        pass
301e0cf8d70SMichael Walsh
302e0cf8d70SMichael Walsh    # Clear the ffdc_report_list_path file.  Plug-ins may now write to it.
303e0cf8d70SMichael Walsh    try:
304e0cf8d70SMichael Walsh        os.remove(ffdc_report_list_path)
305e0cf8d70SMichael Walsh    except OSError:
306e0cf8d70SMichael Walsh        pass
307e0cf8d70SMichael Walsh
308600876daSMichael Walsh    # Clear the ffdc_summary_list_path file.  Plug-ins may now write to it.
309600876daSMichael Walsh    try:
310600876daSMichael Walsh        os.remove(ffdc_summary_list_path)
311600876daSMichael Walsh    except OSError:
312600876daSMichael Walsh        pass
313600876daSMichael Walsh
314e1974b96SMichael Walsh    global ffdc_prefix
315e1974b96SMichael Walsh
316e1974b96SMichael Walsh    seconds = time.time()
317e1974b96SMichael Walsh    loc_time = time.localtime(seconds)
318e1974b96SMichael Walsh    time_string = time.strftime("%y%m%d.%H%M%S.", loc_time)
319e1974b96SMichael Walsh
320e1974b96SMichael Walsh    ffdc_prefix = openbmc_nickname + "." + time_string
321e1974b96SMichael Walsh
322e0cf8d70SMichael Walsh###############################################################################
323e0cf8d70SMichael Walsh
324e0cf8d70SMichael Walsh
325e0cf8d70SMichael Walsh###############################################################################
3266741f740SMichael Walshdef setup():
3270bbd860fSMichael Walsh
3280bbd860fSMichael Walsh    r"""
3296741f740SMichael Walsh    Do general program setup tasks.
3300bbd860fSMichael Walsh    """
3310bbd860fSMichael Walsh
3326741f740SMichael Walsh    global cp_setup_called
3330bbd860fSMichael Walsh
334b5839d00SMichael Walsh    gp.qprintn()
335b5839d00SMichael Walsh
33683f4bc77SMichael Walsh    robot_pgm_dir_path = os.path.dirname(__file__) + os.sep
33783f4bc77SMichael Walsh    repo_bin_path = robot_pgm_dir_path.replace("/lib/", "/bin/")
338d061c043SMichael Walsh    # If we can't find process_plug_in_packages.py, ssh_pw or
339d061c043SMichael Walsh    # validate_plug_ins.py, then we don't have our repo bin in PATH.
340d061c043SMichael Walsh    shell_rc, out_buf = gc.cmd_fnc_u("which process_plug_in_packages.py" +
341d061c043SMichael Walsh                                     " ssh_pw validate_plug_ins.py", quiet=1,
342d061c043SMichael Walsh                                     print_output=0, show_err=0)
343b5839d00SMichael Walsh    if shell_rc != 0:
34483f4bc77SMichael Walsh        os.environ['PATH'] = repo_bin_path + ":" + os.environ.get('PATH', "")
34583f4bc77SMichael Walsh    # Likewise, our repo lib subdir needs to be in sys.path and PYTHONPATH.
34683f4bc77SMichael Walsh    if robot_pgm_dir_path not in sys.path:
34783f4bc77SMichael Walsh        sys.path.append(robot_pgm_dir_path)
34883f4bc77SMichael Walsh        PYTHONPATH = os.environ.get("PYTHONPATH", "")
34983f4bc77SMichael Walsh        if PYTHONPATH == "":
35083f4bc77SMichael Walsh            os.environ['PYTHONPATH'] = robot_pgm_dir_path
35183f4bc77SMichael Walsh        else:
35283f4bc77SMichael Walsh            os.environ['PYTHONPATH'] = robot_pgm_dir_path + ":" + PYTHONPATH
3536741f740SMichael Walsh
3546741f740SMichael Walsh    validate_parms()
3556741f740SMichael Walsh
3566741f740SMichael Walsh    grp.rqprint_pgm_header()
3576741f740SMichael Walsh
358fdc5ced1SMichael Walsh    grk.run_key("Set BMC Power Policy  RESTORE_LAST_STATE")
35911cfc8c0SMichael Walsh
36085678948SMichael Walsh    initial_plug_in_setup()
36185678948SMichael Walsh
3626741f740SMichael Walsh    plug_in_setup()
3636741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
3646741f740SMichael Walsh        call_point='setup')
3656741f740SMichael Walsh    if rc != 0:
3666741f740SMichael Walsh        error_message = "Plug-in setup failed.\n"
3676741f740SMichael Walsh        grp.rprint_error_report(error_message)
3686741f740SMichael Walsh        BuiltIn().fail(error_message)
3696741f740SMichael Walsh    # Setting cp_setup_called lets our Teardown know that it needs to call
3706741f740SMichael Walsh    # the cleanup plug-in call point.
3716741f740SMichael Walsh    cp_setup_called = 1
3726741f740SMichael Walsh
3736741f740SMichael Walsh    # Keyword "FFDC" will fail if TEST_MESSAGE is not set.
3746741f740SMichael Walsh    BuiltIn().set_global_variable("${TEST_MESSAGE}", "${EMPTY}")
37585678948SMichael Walsh    # FFDC_LOG_PATH is used by "FFDC" keyword.
37685678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_LOG_PATH}", ffdc_dir_path)
3776741f740SMichael Walsh
378dc80d67dSMichael Walsh    # Also printed by FFDC.
379dc80d67dSMichael Walsh    global host_name
380dc80d67dSMichael Walsh    global host_ip
381dc80d67dSMichael Walsh    host = socket.gethostname()
382dc80d67dSMichael Walsh    host_name, host_ip = gm.get_host_name_ip(host)
383dc80d67dSMichael Walsh
384b5839d00SMichael Walsh    gp.dprint_var(boot_table, 1)
385b5839d00SMichael Walsh    gp.dprint_var(boot_lists)
3860bbd860fSMichael Walsh
3870bbd860fSMichael Walsh###############################################################################
3880bbd860fSMichael Walsh
3890bbd860fSMichael Walsh
3900bbd860fSMichael Walsh###############################################################################
3916741f740SMichael Walshdef validate_parms():
3920bbd860fSMichael Walsh
3930bbd860fSMichael Walsh    r"""
3946741f740SMichael Walsh    Validate all program parameters.
3950bbd860fSMichael Walsh    """
3960bbd860fSMichael Walsh
397b5839d00SMichael Walsh    process_pgm_parms()
3980bbd860fSMichael Walsh
399b5839d00SMichael Walsh    gp.qprintn()
400b5839d00SMichael Walsh
401b5839d00SMichael Walsh    global openbmc_model
4026741f740SMichael Walsh    grv.rvalid_value("openbmc_host")
4036741f740SMichael Walsh    grv.rvalid_value("openbmc_username")
4046741f740SMichael Walsh    grv.rvalid_value("openbmc_password")
4056741f740SMichael Walsh    if os_host != "":
4066741f740SMichael Walsh        grv.rvalid_value("os_username")
4076741f740SMichael Walsh        grv.rvalid_value("os_password")
4080bbd860fSMichael Walsh
4096741f740SMichael Walsh    if pdu_host != "":
4106741f740SMichael Walsh        grv.rvalid_value("pdu_username")
4116741f740SMichael Walsh        grv.rvalid_value("pdu_password")
4126741f740SMichael Walsh        grv.rvalid_integer("pdu_slot_no")
4136741f740SMichael Walsh    if openbmc_serial_host != "":
4146741f740SMichael Walsh        grv.rvalid_integer("openbmc_serial_port")
415b5839d00SMichael Walsh    if openbmc_model == "":
416b5839d00SMichael Walsh        status, ret_values =\
417b5839d00SMichael Walsh            grk.run_key_u("Get BMC System Model")
418b5839d00SMichael Walsh        openbmc_model = ret_values
419b5839d00SMichael Walsh        BuiltIn().set_global_variable("${openbmc_model}", openbmc_model)
4206741f740SMichael Walsh    grv.rvalid_value("openbmc_model")
421b5839d00SMichael Walsh    grv.rvalid_integer("max_num_tests")
4226741f740SMichael Walsh    grv.rvalid_integer("boot_pass")
4236741f740SMichael Walsh    grv.rvalid_integer("boot_fail")
4246741f740SMichael Walsh
4256741f740SMichael Walsh    plug_in_packages_list = grpi.rvalidate_plug_ins(plug_in_dir_paths)
4266741f740SMichael Walsh    BuiltIn().set_global_variable("${plug_in_packages_list}",
4276741f740SMichael Walsh                                  plug_in_packages_list)
4286741f740SMichael Walsh
429b5839d00SMichael Walsh    grv.rvalid_value("stack_mode", valid_values=['normal', 'skip'])
430a20da401SMichael Walsh    if len(boot_list) == 0 and len(boot_stack) == 0 and not ffdc_only:
4316741f740SMichael Walsh        error_message = "You must provide either a value for either the" +\
4326741f740SMichael Walsh            " boot_list or the boot_stack parm.\n"
4336741f740SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
4346741f740SMichael Walsh
4356741f740SMichael Walsh    valid_boot_list(boot_list, valid_boot_types)
4366741f740SMichael Walsh    valid_boot_list(boot_stack, valid_boot_types)
4376741f740SMichael Walsh
43811cfc8c0SMichael Walsh    selected_PDU_boots = list(set(boot_list + boot_stack) &
43911cfc8c0SMichael Walsh                              set(boot_lists['PDU_reboot']))
44011cfc8c0SMichael Walsh
44111cfc8c0SMichael Walsh    if len(selected_PDU_boots) > 0 and pdu_host == "":
44211cfc8c0SMichael Walsh        error_message = "You have selected the following boots which" +\
44311cfc8c0SMichael Walsh                        " require a PDU host but no value for pdu_host:\n"
44411cfc8c0SMichael Walsh        error_message += gp.sprint_var(selected_PDU_boots)
44511cfc8c0SMichael Walsh        error_message += gp.sprint_var(pdu_host, 2)
44611cfc8c0SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
44711cfc8c0SMichael Walsh
4486741f740SMichael Walsh    return
4490bbd860fSMichael Walsh
4500bbd860fSMichael Walsh###############################################################################
4510bbd860fSMichael Walsh
4520bbd860fSMichael Walsh
4530bbd860fSMichael Walsh###############################################################################
4546741f740SMichael Walshdef my_get_state():
4550bbd860fSMichael Walsh
4560bbd860fSMichael Walsh    r"""
4576741f740SMichael Walsh    Get the system state plus a little bit of wrapping.
4580bbd860fSMichael Walsh    """
4590bbd860fSMichael Walsh
4606741f740SMichael Walsh    global state
4616741f740SMichael Walsh
4626741f740SMichael Walsh    req_states = ['epoch_seconds'] + st.default_req_states
4636741f740SMichael Walsh
464b5839d00SMichael Walsh    gp.qprint_timen("Getting system state.")
4656741f740SMichael Walsh    if test_mode:
4666741f740SMichael Walsh        state['epoch_seconds'] = int(time.time())
4676741f740SMichael Walsh    else:
468b5839d00SMichael Walsh        state = st.get_state(req_states=req_states, quiet=quiet)
469b5839d00SMichael Walsh    gp.qprint_var(state)
470341c21ebSMichael Walsh
471341c21ebSMichael Walsh###############################################################################
472341c21ebSMichael Walsh
473341c21ebSMichael Walsh
474341c21ebSMichael Walsh###############################################################################
4756741f740SMichael Walshdef select_boot():
476341c21ebSMichael Walsh
477341c21ebSMichael Walsh    r"""
478341c21ebSMichael Walsh    Select a boot test to be run based on our current state and return the
479341c21ebSMichael Walsh    chosen boot type.
480341c21ebSMichael Walsh
481341c21ebSMichael Walsh    Description of arguments:
4826741f740SMichael Walsh    state  The state of the machine.
483341c21ebSMichael Walsh    """
484341c21ebSMichael Walsh
48530dadae2SMichael Walsh    global boot_stack
48630dadae2SMichael Walsh
487b5839d00SMichael Walsh    gp.qprint_timen("Selecting a boot test.")
4886741f740SMichael Walsh
4896741f740SMichael Walsh    my_get_state()
4906741f740SMichael Walsh
4916741f740SMichael Walsh    stack_popped = 0
4926741f740SMichael Walsh    if len(boot_stack) > 0:
4936741f740SMichael Walsh        stack_popped = 1
494b5839d00SMichael Walsh        gp.qprint_dashes()
495b5839d00SMichael Walsh        gp.qprint_var(boot_stack)
496b5839d00SMichael Walsh        gp.qprint_dashes()
497b5839d00SMichael Walsh        skip_boot_printed = 0
498b5839d00SMichael Walsh        while len(boot_stack) > 0:
4996741f740SMichael Walsh            boot_candidate = boot_stack.pop()
500b5839d00SMichael Walsh            if stack_mode == 'normal':
501b5839d00SMichael Walsh                break
502b5839d00SMichael Walsh            else:
503b5839d00SMichael Walsh                if st.compare_states(state, boot_table[boot_candidate]['end']):
504b5839d00SMichael Walsh                    if not skip_boot_printed:
505b5839d00SMichael Walsh                        gp.print_var(stack_mode)
506b5839d00SMichael Walsh                        gp.printn()
507b5839d00SMichael Walsh                        gp.print_timen("Skipping the following boot tests" +
508b5839d00SMichael Walsh                                       " which are unnecessary since their" +
509b5839d00SMichael Walsh                                       " required end states match the" +
510b5839d00SMichael Walsh                                       " current machine state:")
511b5839d00SMichael Walsh                        skip_boot_printed = 1
512b5839d00SMichael Walsh                    gp.print_var(boot_candidate)
513b5839d00SMichael Walsh                    boot_candidate = ""
514b5839d00SMichael Walsh        if boot_candidate == "":
515b5839d00SMichael Walsh            gp.qprint_dashes()
516b5839d00SMichael Walsh            gp.qprint_var(boot_stack)
517b5839d00SMichael Walsh            gp.qprint_dashes()
518b5839d00SMichael Walsh            return boot_candidate
5196741f740SMichael Walsh        if st.compare_states(state, boot_table[boot_candidate]['start']):
520b5839d00SMichael Walsh            gp.qprint_timen("The machine state is valid for a '" +
5216741f740SMichael Walsh                            boot_candidate + "' boot test.")
522b5839d00SMichael Walsh            gp.qprint_dashes()
523b5839d00SMichael Walsh            gp.qprint_var(boot_stack)
524b5839d00SMichael Walsh            gp.qprint_dashes()
5256741f740SMichael Walsh            return boot_candidate
526341c21ebSMichael Walsh        else:
527b5839d00SMichael Walsh            gp.qprint_timen("The machine state does not match the required" +
528b5839d00SMichael Walsh                            " starting state for a '" + boot_candidate +
529b5839d00SMichael Walsh                            "' boot test:")
530b5839d00SMichael Walsh            gp.print_varx("boot_table[" + boot_candidate + "][start]",
531b5839d00SMichael Walsh                          boot_table[boot_candidate]['start'], 1)
5326741f740SMichael Walsh            boot_stack.append(boot_candidate)
5336741f740SMichael Walsh            popped_boot = boot_candidate
5346741f740SMichael Walsh
5356741f740SMichael Walsh    # Loop through your list selecting a boot_candidates
5366741f740SMichael Walsh    boot_candidates = []
5376741f740SMichael Walsh    for boot_candidate in boot_list:
5386741f740SMichael Walsh        if st.compare_states(state, boot_table[boot_candidate]['start']):
5396741f740SMichael Walsh            if stack_popped:
5406741f740SMichael Walsh                if st.compare_states(boot_table[boot_candidate]['end'],
5416741f740SMichael Walsh                   boot_table[popped_boot]['start']):
5426741f740SMichael Walsh                    boot_candidates.append(boot_candidate)
543341c21ebSMichael Walsh            else:
5446741f740SMichael Walsh                boot_candidates.append(boot_candidate)
5456741f740SMichael Walsh
5466741f740SMichael Walsh    if len(boot_candidates) == 0:
547b5839d00SMichael Walsh        gp.qprint_timen("The user's boot list contained no boot tests" +
5486741f740SMichael Walsh                        " which are valid for the current machine state.")
5496741f740SMichael Walsh        boot_candidate = default_power_on
5506741f740SMichael Walsh        if not st.compare_states(state, boot_table[default_power_on]['start']):
5516741f740SMichael Walsh            boot_candidate = default_power_off
5526741f740SMichael Walsh        boot_candidates.append(boot_candidate)
553b5839d00SMichael Walsh        gp.qprint_timen("Using default '" + boot_candidate +
554b5839d00SMichael Walsh                        "' boot type to transition to valid state.")
5556741f740SMichael Walsh
556b5839d00SMichael Walsh    gp.dprint_var(boot_candidates)
5576741f740SMichael Walsh
5586741f740SMichael Walsh    # Randomly select a boot from the candidate list.
5596741f740SMichael Walsh    boot = random.choice(boot_candidates)
560341c21ebSMichael Walsh
561341c21ebSMichael Walsh    return boot
5620bbd860fSMichael Walsh
5630bbd860fSMichael Walsh###############################################################################
56455302295SMichael Walsh
56555302295SMichael Walsh
56655302295SMichael Walsh###############################################################################
567341c21ebSMichael Walshdef print_last_boots():
568341c21ebSMichael Walsh
569341c21ebSMichael Walsh    r"""
570341c21ebSMichael Walsh    Print the last ten boots done with their time stamps.
571341c21ebSMichael Walsh    """
572341c21ebSMichael Walsh
573341c21ebSMichael Walsh    # indent 0, 90 chars wide, linefeed, char is "="
574b5839d00SMichael Walsh    gp.qprint_dashes(0, 90)
575b5839d00SMichael Walsh    gp.qprintn("Last 10 boots:\n")
576341c21ebSMichael Walsh
577341c21ebSMichael Walsh    for boot_entry in last_ten:
578341c21ebSMichael Walsh        grp.rqprint(boot_entry)
579b5839d00SMichael Walsh    gp.qprint_dashes(0, 90)
580341c21ebSMichael Walsh
581341c21ebSMichael Walsh###############################################################################
582341c21ebSMichael Walsh
583341c21ebSMichael Walsh
584341c21ebSMichael Walsh###############################################################################
585341c21ebSMichael Walshdef print_defect_report():
586341c21ebSMichael Walsh
587341c21ebSMichael Walsh    r"""
588341c21ebSMichael Walsh    Print a defect report.
589341c21ebSMichael Walsh    """
590341c21ebSMichael Walsh
591600876daSMichael Walsh    # Making deliberate choice to NOT run plug_in_setup().  We don't want
592600876daSMichael Walsh    # ffdc_prefix updated.
593600876daSMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
594600876daSMichael Walsh        call_point='ffdc_report', stop_on_plug_in_failure=0)
595600876daSMichael Walsh
596341c21ebSMichael Walsh    # At some point I'd like to have the 'Call FFDC Methods' return a list
597341c21ebSMichael Walsh    # of files it has collected.  In that case, the following "ls" command
598341c21ebSMichael Walsh    # would no longer be needed.  For now, however, glob shows the files
599341c21ebSMichael Walsh    # named in FFDC_LIST_FILE_PATH so I will refrain from printing those
600341c21ebSMichael Walsh    # out (so we don't see duplicates in the list).
601341c21ebSMichael 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
610600876daSMichael Walsh    # Get additional header 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
618341c21ebSMichael Walsh    LOG_PREFIX = BuiltIn().get_variable_value("${LOG_PREFIX}")
619341c21ebSMichael Walsh
620e0cf8d70SMichael Walsh    output = '\n'.join(sorted(glob.glob(LOG_PREFIX + '*')))
621341c21ebSMichael Walsh    try:
6226741f740SMichael Walsh        ffdc_list = open(ffdc_list_file_path, 'r')
623341c21ebSMichael Walsh    except IOError:
624341c21ebSMichael Walsh        ffdc_list = ""
625341c21ebSMichael Walsh
62668a61162SMichael Walsh    # Open ffdc_file_list for writing.  We will write a complete list of
62768a61162SMichael Walsh    # FFDC files to it for possible use by plug-ins like cp_stop_check.
62868a61162SMichael Walsh    ffdc_list_file = open(ffdc_list_file_path, 'w')
62968a61162SMichael Walsh
63068a61162SMichael Walsh    gp.qprintn()
63168a61162SMichael Walsh    # indent=0, width=90, linefeed=1, char="="
63268a61162SMichael Walsh    gp.qprint_dashes(0, 90, 1, "=")
63368a61162SMichael Walsh    gp.qprintn("Copy this data to the defect:\n")
63468a61162SMichael Walsh
635e0cf8d70SMichael Walsh    if len(more_header_info) > 0:
636e0cf8d70SMichael Walsh        gp.printn(more_header_info)
637dc80d67dSMichael Walsh    gp.qpvars(host_name, host_ip, openbmc_nickname, openbmc_host,
638dc80d67dSMichael Walsh              openbmc_host_name, openbmc_ip, openbmc_username,
639dc80d67dSMichael Walsh              openbmc_password, os_host, os_host_name, os_ip, os_username,
640dc80d67dSMichael Walsh              os_password, pdu_host, pdu_host_name, pdu_ip, pdu_username,
641dc80d67dSMichael Walsh              pdu_password, pdu_slot_no, openbmc_serial_host,
642dc80d67dSMichael Walsh              openbmc_serial_host_name, openbmc_serial_ip, openbmc_serial_port)
64368a61162SMichael Walsh
64468a61162SMichael Walsh    gp.qprintn()
64568a61162SMichael Walsh
64668a61162SMichael Walsh    print_last_boots()
64768a61162SMichael Walsh    gp.qprintn()
64868a61162SMichael Walsh    gp.qprint_var(state)
64968a61162SMichael Walsh
650b5839d00SMichael Walsh    gp.qprintn()
651b5839d00SMichael Walsh    gp.qprintn("FFDC data files:")
652341c21ebSMichael Walsh    if status_file_path != "":
653b5839d00SMichael Walsh        gp.qprintn(status_file_path)
65468a61162SMichael Walsh        ffdc_list_file.write(status_file_path + "\n")
655341c21ebSMichael Walsh
656b5839d00SMichael Walsh    gp.qprintn(output)
657b5839d00SMichael Walsh    # gp.qprintn(ffdc_list)
658b5839d00SMichael Walsh    gp.qprintn()
659341c21ebSMichael Walsh
660600876daSMichael Walsh    if len(ffdc_summary_info) > 0:
661600876daSMichael Walsh        gp.printn(ffdc_summary_info)
662600876daSMichael Walsh
663b5839d00SMichael Walsh    gp.qprint_dashes(0, 90, 1, "=")
664341c21ebSMichael Walsh
66568a61162SMichael Walsh    ffdc_list_file.write(output + "\n")
66668a61162SMichael Walsh    ffdc_list_file.close()
66768a61162SMichael Walsh
668341c21ebSMichael Walsh###############################################################################
6696741f740SMichael Walsh
6706741f740SMichael Walsh
6716741f740SMichael Walsh###############################################################################
6726741f740SMichael Walshdef my_ffdc():
6736741f740SMichael Walsh
6746741f740SMichael Walsh    r"""
6756741f740SMichael Walsh    Collect FFDC data.
6766741f740SMichael Walsh    """
6776741f740SMichael Walsh
6786741f740SMichael Walsh    global state
6796741f740SMichael Walsh
6806741f740SMichael Walsh    plug_in_setup()
6816741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
682600876daSMichael Walsh        call_point='ffdc', stop_on_plug_in_failure=0)
6836741f740SMichael Walsh
6846741f740SMichael Walsh    AUTOBOOT_FFDC_PREFIX = os.environ['AUTOBOOT_FFDC_PREFIX']
68583f4bc77SMichael Walsh    status, ret_values = grk.run_key_u("FFDC  ffdc_prefix=" +
68683f4bc77SMichael Walsh                                       AUTOBOOT_FFDC_PREFIX +
68783f4bc77SMichael Walsh                                       "  ffdc_function_list=" +
68883f4bc77SMichael Walsh                                       ffdc_function_list, ignore=1)
68983f4bc77SMichael Walsh    if status != 'PASS':
6903328caffSMichael Walsh        gp.print_error("Call to ffdc failed.\n")
6916741f740SMichael Walsh
6926741f740SMichael Walsh    my_get_state()
6936741f740SMichael Walsh
6946741f740SMichael Walsh    print_defect_report()
6956741f740SMichael Walsh
6966741f740SMichael Walsh###############################################################################
6976741f740SMichael Walsh
6986741f740SMichael Walsh
6996741f740SMichael Walsh###############################################################################
7006741f740SMichael Walshdef print_test_start_message(boot_keyword):
7016741f740SMichael Walsh
7026741f740SMichael Walsh    r"""
7036741f740SMichael Walsh    Print a message indicating what boot test is about to run.
7046741f740SMichael Walsh
7056741f740SMichael Walsh    Description of arguments:
7066741f740SMichael Walsh    boot_keyword  The name of the boot which is to be run
7076741f740SMichael Walsh                  (e.g. "BMC Power On").
7086741f740SMichael Walsh    """
7096741f740SMichael Walsh
7106741f740SMichael Walsh    global last_ten
711*325eb548SSunil M    global boot_start_time
7126741f740SMichael Walsh
7136741f740SMichael Walsh    doing_msg = gp.sprint_timen("Doing \"" + boot_keyword + "\".")
714*325eb548SSunil M
715*325eb548SSunil M    # Set boot_start_time for use by plug-ins.
716*325eb548SSunil M    boot_start_time = doing_msg[1:33]
717*325eb548SSunil M    gp.qprint_var(boot_start_time)
718*325eb548SSunil M
719b5839d00SMichael Walsh    gp.qprint(doing_msg)
7206741f740SMichael Walsh
7216741f740SMichael Walsh    last_ten.append(doing_msg)
7226741f740SMichael Walsh
7236741f740SMichael Walsh    if len(last_ten) > 10:
7246741f740SMichael Walsh        del last_ten[0]
7256741f740SMichael Walsh
7266741f740SMichael Walsh###############################################################################
7276741f740SMichael Walsh
7286741f740SMichael Walsh
7296741f740SMichael Walsh###############################################################################
7306741f740SMichael Walshdef run_boot(boot):
7316741f740SMichael Walsh
7326741f740SMichael Walsh    r"""
7336741f740SMichael Walsh    Run the specified boot.
7346741f740SMichael Walsh
7356741f740SMichael Walsh    Description of arguments:
7366741f740SMichael Walsh    boot  The name of the boot test to be performed.
7376741f740SMichael Walsh    """
7386741f740SMichael Walsh
7396741f740SMichael Walsh    global state
7406741f740SMichael Walsh
7416741f740SMichael Walsh    print_test_start_message(boot)
7426741f740SMichael Walsh
7436741f740SMichael Walsh    plug_in_setup()
7446741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = \
7456741f740SMichael Walsh        grpi.rprocess_plug_in_packages(call_point="pre_boot")
7466741f740SMichael Walsh    if rc != 0:
7476741f740SMichael Walsh        error_message = "Plug-in failed with non-zero return code.\n" +\
7486741f740SMichael Walsh            gp.sprint_var(rc, 1)
7496741f740SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
7506741f740SMichael Walsh
7516741f740SMichael Walsh    if test_mode:
7526741f740SMichael Walsh        # In test mode, we'll pretend the boot worked by assigning its
7536741f740SMichael Walsh        # required end state to the default state value.
75430dadae2SMichael Walsh        state = st.strip_anchor_state(boot_table[boot]['end'])
7556741f740SMichael Walsh    else:
7566741f740SMichael Walsh        # Assertion:  We trust that the state data was made fresh by the
7576741f740SMichael Walsh        # caller.
7586741f740SMichael Walsh
759b5839d00SMichael Walsh        gp.qprintn()
7606741f740SMichael Walsh
7616741f740SMichael Walsh        if boot_table[boot]['method_type'] == "keyword":
7620b93fbf8SMichael Walsh            rk.my_run_keywords(boot_table[boot].get('lib_file_path', ''),
763b5839d00SMichael Walsh                               boot_table[boot]['method'],
764b5839d00SMichael Walsh                               quiet=quiet)
7656741f740SMichael Walsh
7666741f740SMichael Walsh        if boot_table[boot]['bmc_reboot']:
7676741f740SMichael Walsh            st.wait_for_comm_cycle(int(state['epoch_seconds']))
76830dadae2SMichael Walsh            plug_in_setup()
76930dadae2SMichael Walsh            rc, shell_rc, failed_plug_in_name = \
77030dadae2SMichael Walsh                grpi.rprocess_plug_in_packages(call_point="post_reboot")
77130dadae2SMichael Walsh            if rc != 0:
7720b93fbf8SMichael Walsh                error_message = "Plug-in failed with non-zero return code.\n"
7730b93fbf8SMichael Walsh                error_message += gp.sprint_var(rc, 1)
77430dadae2SMichael Walsh                BuiltIn().fail(gp.sprint_error(error_message))
7756741f740SMichael Walsh        else:
7766741f740SMichael Walsh            match_state = st.anchor_state(state)
7776741f740SMichael Walsh            del match_state['epoch_seconds']
7786741f740SMichael Walsh            # Wait for the state to change in any way.
7796741f740SMichael Walsh            st.wait_state(match_state, wait_time=state_change_timeout,
780600876daSMichael Walsh                          interval="10 seconds", invert=1)
7816741f740SMichael Walsh
782b5839d00SMichael Walsh        gp.qprintn()
7836741f740SMichael Walsh        if boot_table[boot]['end']['chassis'] == "Off":
7846741f740SMichael Walsh            boot_timeout = power_off_timeout
7856741f740SMichael Walsh        else:
7866741f740SMichael Walsh            boot_timeout = power_on_timeout
7876741f740SMichael Walsh        st.wait_state(boot_table[boot]['end'], wait_time=boot_timeout,
788600876daSMichael Walsh                      interval="10 seconds")
7896741f740SMichael Walsh
7906741f740SMichael Walsh    plug_in_setup()
7916741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = \
7926741f740SMichael Walsh        grpi.rprocess_plug_in_packages(call_point="post_boot")
7936741f740SMichael Walsh    if rc != 0:
7946741f740SMichael Walsh        error_message = "Plug-in failed with non-zero return code.\n" +\
7956741f740SMichael Walsh            gp.sprint_var(rc, 1)
7966741f740SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
7976741f740SMichael Walsh
7986741f740SMichael Walsh###############################################################################
7996741f740SMichael Walsh
8006741f740SMichael Walsh
8016741f740SMichael Walsh###############################################################################
8026741f740SMichael Walshdef test_loop_body():
8036741f740SMichael Walsh
8046741f740SMichael Walsh    r"""
8056741f740SMichael Walsh    The main loop body for the loop in main_py.
8066741f740SMichael Walsh
8076741f740SMichael Walsh    Description of arguments:
8086741f740SMichael Walsh    boot_count  The iteration number (starts at 1).
8096741f740SMichael Walsh    """
8106741f740SMichael Walsh
8116741f740SMichael Walsh    global boot_count
8126741f740SMichael Walsh    global state
8136741f740SMichael Walsh    global next_boot
8146741f740SMichael Walsh    global boot_success
815*325eb548SSunil M    global boot_end_time
8166741f740SMichael Walsh
817b5839d00SMichael Walsh    gp.qprintn()
8186741f740SMichael Walsh
8196741f740SMichael Walsh    next_boot = select_boot()
820b5839d00SMichael Walsh    if next_boot == "":
821b5839d00SMichael Walsh        return True
8226741f740SMichael Walsh
823b5839d00SMichael Walsh    boot_count += 1
824b5839d00SMichael Walsh    gp.qprint_timen("Starting boot " + str(boot_count) + ".")
8256741f740SMichael Walsh
826e0cf8d70SMichael Walsh    pre_boot_plug_in_setup()
8276741f740SMichael Walsh
8286741f740SMichael Walsh    cmd_buf = ["run_boot", next_boot]
8296741f740SMichael Walsh    boot_status, msg = BuiltIn().run_keyword_and_ignore_error(*cmd_buf)
8306741f740SMichael Walsh    if boot_status == "FAIL":
831b5839d00SMichael Walsh        gp.qprint(msg)
8326741f740SMichael Walsh
833b5839d00SMichael Walsh    gp.qprintn()
8346741f740SMichael Walsh    if boot_status == "PASS":
8356741f740SMichael Walsh        boot_success = 1
836*325eb548SSunil M        completion_msg = gp.sprint_time("BOOT_SUCCESS: \"" + next_boot +
837*325eb548SSunil M                                        "\" succeeded.")
8386741f740SMichael Walsh    else:
8396741f740SMichael Walsh        boot_success = 0
840*325eb548SSunil M        completion_msg = gp.sprint_time("BOOT_FAILED: \"" + next_boot +
841*325eb548SSunil M                                        "\" failed.")
842*325eb548SSunil M
843*325eb548SSunil M    # Set boot_end_time for use by plug-ins.
844*325eb548SSunil M    boot_end_time = completion_msg[1:33]
845*325eb548SSunil M    gp.qprint_var(boot_end_time)
846*325eb548SSunil M
847*325eb548SSunil M    gp.qprint(completion_msg)
8486741f740SMichael Walsh
8496741f740SMichael Walsh    boot_results.update(next_boot, boot_status)
8506741f740SMichael Walsh
8516741f740SMichael Walsh    plug_in_setup()
8526741f740SMichael Walsh    # NOTE: A post_test_case call point failure is NOT counted as a boot
8536741f740SMichael Walsh    # failure.
8546741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
855600876daSMichael Walsh        call_point='post_test_case', stop_on_plug_in_failure=0)
8566741f740SMichael Walsh
8576741f740SMichael Walsh    plug_in_setup()
8586741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
8596741f740SMichael Walsh        call_point='ffdc_check', shell_rc=0x00000200,
8606741f740SMichael Walsh        stop_on_plug_in_failure=1, stop_on_non_zero_rc=1)
8616741f740SMichael Walsh    if boot_status != "PASS" or ffdc_check == "All" or shell_rc == 0x00000200:
86283f4bc77SMichael Walsh        status, ret_values = grk.run_key_u("my_ffdc", ignore=1)
86383f4bc77SMichael Walsh        if status != 'PASS':
8643328caffSMichael Walsh            gp.print_error("Call to my_ffdc failed.\n")
8656741f740SMichael Walsh
866d139f286SMichael Walsh    # We need to purge error logs between boots or they build up.
867b5839d00SMichael Walsh    grk.run_key("Delete Error logs", ignore=1)
868d139f286SMichael Walsh
869952f9b09SMichael Walsh    boot_results.print_report()
870b5839d00SMichael Walsh    gp.qprint_timen("Finished boot " + str(boot_count) + ".")
871952f9b09SMichael Walsh
8726741f740SMichael Walsh    plug_in_setup()
8736741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
8746741f740SMichael Walsh        call_point='stop_check')
8756741f740SMichael Walsh    if rc != 0:
8766741f740SMichael Walsh        error_message = "Stopping as requested by user.\n"
8776741f740SMichael Walsh        grp.rprint_error_report(error_message)
8786741f740SMichael Walsh        BuiltIn().fail(error_message)
8796741f740SMichael Walsh
880d139f286SMichael Walsh    # This should help prevent ConnectionErrors.
8810960b384SMichael Walsh    grk.run_key_u("Close All Connections")
882d139f286SMichael Walsh
8836741f740SMichael Walsh    return True
8846741f740SMichael Walsh
8856741f740SMichael Walsh###############################################################################
8866741f740SMichael Walsh
8876741f740SMichael Walsh
8886741f740SMichael Walsh###############################################################################
88983f4bc77SMichael Walshdef obmc_boot_test_teardown():
8906741f740SMichael Walsh
8916741f740SMichael Walsh    r"""
892c9116811SMichael Walsh    Clean up after the Main keyword.
8936741f740SMichael Walsh    """
8946741f740SMichael Walsh
8956741f740SMichael Walsh    if cp_setup_called:
8966741f740SMichael Walsh        plug_in_setup()
8976741f740SMichael Walsh        rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
898600876daSMichael Walsh            call_point='cleanup', stop_on_plug_in_failure=0)
8996741f740SMichael Walsh
900600876daSMichael Walsh    if 'boot_results_file_path' in globals():
9010b93fbf8SMichael Walsh        # Save boot_results object to a file in case it is needed again.
902b5839d00SMichael Walsh        gp.qprint_timen("Saving boot_results to the following path.")
903b5839d00SMichael Walsh        gp.qprint_var(boot_results_file_path)
9040b93fbf8SMichael Walsh        pickle.dump(boot_results, open(boot_results_file_path, 'wb'),
9050b93fbf8SMichael Walsh                    pickle.HIGHEST_PROTOCOL)
9060b93fbf8SMichael Walsh
9076741f740SMichael Walsh###############################################################################
9086741f740SMichael Walsh
9096741f740SMichael Walsh
9106741f740SMichael Walsh###############################################################################
911c9116811SMichael Walshdef test_teardown():
912c9116811SMichael Walsh
913c9116811SMichael Walsh    r"""
914c9116811SMichael Walsh    Clean up after this test case.
915c9116811SMichael Walsh    """
916c9116811SMichael Walsh
917c9116811SMichael Walsh    gp.qprintn()
918c9116811SMichael Walsh    cmd_buf = ["Print Error",
919c9116811SMichael Walsh               "A keyword timeout occurred ending this program.\n"]
920c9116811SMichael Walsh    BuiltIn().run_keyword_if_timeout_occurred(*cmd_buf)
921c9116811SMichael Walsh
922b5839d00SMichael Walsh    grp.rqprint_pgm_footer()
923b5839d00SMichael Walsh
924c9116811SMichael Walsh###############################################################################
925c9116811SMichael Walsh
926c9116811SMichael Walsh
927c9116811SMichael Walsh###############################################################################
92883f4bc77SMichael Walshdef obmc_boot_test_py(alt_boot_stack=None):
9296741f740SMichael Walsh
9306741f740SMichael Walsh    r"""
9316741f740SMichael Walsh    Do main program processing.
9326741f740SMichael Walsh    """
9336741f740SMichael Walsh
934b5839d00SMichael Walsh    if alt_boot_stack is not None:
935b5839d00SMichael Walsh        BuiltIn().set_global_variable("${boot_stack}", alt_boot_stack)
936b5839d00SMichael Walsh
9376741f740SMichael Walsh    setup()
9386741f740SMichael Walsh
939a20da401SMichael Walsh    if ffdc_only:
940a20da401SMichael Walsh        gp.qprint_timen("Caller requested ffdc_only.")
941e0cf8d70SMichael Walsh        pre_boot_plug_in_setup()
94283f4bc77SMichael Walsh        grk.run_key_u("my_ffdc")
943764d2f83SMichael Walsh        return
944a20da401SMichael Walsh
9456741f740SMichael Walsh    # Process caller's boot_stack.
9466741f740SMichael Walsh    while (len(boot_stack) > 0):
9476741f740SMichael Walsh        test_loop_body()
9486741f740SMichael Walsh
949b5839d00SMichael Walsh    gp.qprint_timen("Finished processing stack.")
95030dadae2SMichael Walsh
9516741f740SMichael Walsh    # Process caller's boot_list.
9526741f740SMichael Walsh    if len(boot_list) > 0:
9536741f740SMichael Walsh        for ix in range(1, max_num_tests + 1):
9546741f740SMichael Walsh            test_loop_body()
9556741f740SMichael Walsh
956b5839d00SMichael Walsh    gp.qprint_timen("Completed all requested boot tests.")
957b5839d00SMichael Walsh
958b5839d00SMichael Walsh    boot_pass, boot_fail = boot_results.return_total_pass_fail()
959b5839d00SMichael Walsh    if boot_fail > boot_fail_threshold:
960b5839d00SMichael Walsh        error_message = "Boot failures exceed the boot failure" +\
961b5839d00SMichael Walsh                        " threshold:\n" +\
962b5839d00SMichael Walsh                        gp.sprint_var(boot_fail) +\
963b5839d00SMichael Walsh                        gp.sprint_var(boot_fail_threshold)
964b5839d00SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
9656741f740SMichael Walsh
9666741f740SMichael Walsh###############################################################################
967