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
120b93fbf8SMichael Walshimport cPickle as pickle
130b93fbf8SMichael Walsh
140b93fbf8SMichael Walshfrom robot.utils import DotDict
150b93fbf8SMichael Walshfrom robot.libraries.BuiltIn import BuiltIn
160b93fbf8SMichael Walsh
176741f740SMichael Walshfrom boot_data import *
18c9116811SMichael Walshimport gen_print as gp
190bbd860fSMichael Walshimport gen_robot_print as grp
2055302295SMichael Walshimport gen_robot_plug_in as grpi
216741f740SMichael Walshimport gen_robot_valid as grv
226741f740SMichael Walshimport gen_misc as gm
236741f740SMichael Walshimport gen_cmd as gc
2455302295SMichael Walshimport state as st
250bbd860fSMichael Walsh
260b93fbf8SMichael Walshbase_path = os.path.dirname(os.path.dirname(
270b93fbf8SMichael Walsh                            imp.find_module("gen_robot_print")[1])) +\
280b93fbf8SMichael Walsh    os.sep
290b93fbf8SMichael Walshsys.path.append(base_path + "extended/")
300b93fbf8SMichael Walshimport run_keyword as rk
310bbd860fSMichael Walsh
326741f740SMichael Walsh# Program parameter processing.
336741f740SMichael Walsh# Assign all program parms to python variables which are global to this module.
346741f740SMichael Walshparm_list = BuiltIn().get_variable_value("${parm_list}")
35a20da401SMichael Walshint_list = ['max_num_tests', 'boot_pass', 'boot_fail', 'ffdc_only', 'quiet',
36a20da401SMichael Walsh            'test_mode', 'debug']
376741f740SMichael Walshfor parm in parm_list:
386741f740SMichael Walsh    if parm in int_list:
396741f740SMichael Walsh        sub_cmd = "int(BuiltIn().get_variable_value(\"${" + parm +\
406741f740SMichael Walsh                  "}\", \"0\"))"
416741f740SMichael Walsh    else:
426741f740SMichael Walsh        sub_cmd = "BuiltIn().get_variable_value(\"${" + parm + "}\")"
436741f740SMichael Walsh    cmd_buf = parm + " = " + sub_cmd
446741f740SMichael Walsh    exec(cmd_buf)
450bbd860fSMichael Walsh
466741f740SMichael Walshif ffdc_dir_path_style == "":
476741f740SMichael Walsh    ffdc_dir_path_style = int(os.environ.get('FFDC_DIR_PATH_STYLE', '0'))
486741f740SMichael Walsh
496741f740SMichael Walsh# Set up boot data structures.
506741f740SMichael Walshboot_table = create_boot_table()
516741f740SMichael Walshvalid_boot_types = create_valid_boot_list(boot_table)
520b93fbf8SMichael Walsh
53e1e26448SMichael Walsh# Setting master_pid correctly influences the behavior of plug-ins like
54e1e26448SMichael Walsh# DB_Logging
55e1e26448SMichael Walshprogram_pid = os.getpid()
56e1e26448SMichael Walshmaster_pid = os.environ.get('AUTOBOOT_MASTER_PID', program_pid)
57e1e26448SMichael Walsh
58e1e26448SMichael Walshboot_results_file_path = "/tmp/" + openbmc_nickname + ":pid_" +\
59e1e26448SMichael Walsh                         str(master_pid) + ":boot_results"
60e1e26448SMichael Walshif os.path.isfile(boot_results_file_path):
610b93fbf8SMichael Walsh    # We've been called before in this run so we'll load the saved
620b93fbf8SMichael Walsh    # boot_results object.
630b93fbf8SMichael Walsh    boot_results = pickle.load(open(boot_results_file_path, 'rb'))
640b93fbf8SMichael Walshelse:
656741f740SMichael Walsh    boot_results = boot_results(boot_table, boot_pass, boot_fail)
660b93fbf8SMichael Walsh
676741f740SMichael Walshboot_lists = read_boot_lists()
686741f740SMichael Walshlast_ten = []
696741f740SMichael Walsh# Convert these program parms to more useable lists.
706741f740SMichael Walshboot_list = filter(None, boot_list.split(":"))
716741f740SMichael Walshboot_stack = filter(None, boot_stack.split(":"))
726741f740SMichael Walsh
736741f740SMichael Walshstate = st.return_default_state()
746741f740SMichael Walshcp_setup_called = 0
756741f740SMichael Walshnext_boot = ""
766741f740SMichael Walshbase_tool_dir_path = os.path.normpath(os.environ.get(
776741f740SMichael Walsh    'AUTOBOOT_BASE_TOOL_DIR_PATH', "/tmp")) + os.sep
786741f740SMichael Walshffdc_dir_path = os.path.normpath(os.environ.get('FFDC_DIR_PATH', '')) + os.sep
796741f740SMichael Walshffdc_list_file_path = base_tool_dir_path + openbmc_nickname + "/FFDC_FILE_LIST"
806741f740SMichael Walshboot_success = 0
816741f740SMichael Walshstatus_dir_path = os.environ.get('STATUS_DIR_PATH', "")
826741f740SMichael Walshif status_dir_path != "":
836741f740SMichael Walsh    status_dir_path = os.path.normpath(status_dir_path) + os.sep
840b93fbf8SMichael Walshdefault_power_on = "REST Power On"
850b93fbf8SMichael Walshdefault_power_off = "REST Power Off"
866741f740SMichael Walshboot_count = 0
870bbd860fSMichael Walsh
8885678948SMichael WalshLOG_LEVEL = BuiltIn().get_variable_value("${LOG_LEVEL}")
8985678948SMichael Walsh
9085678948SMichael Walsh
9185678948SMichael Walsh###############################################################################
9285678948SMichael Walshdef initial_plug_in_setup():
9385678948SMichael Walsh
9485678948SMichael Walsh    r"""
9585678948SMichael Walsh    Initialize all plug-in environment variables which do not change for the
9685678948SMichael Walsh    duration of the program.
9785678948SMichael Walsh
9885678948SMichael Walsh    """
9985678948SMichael Walsh
10085678948SMichael Walsh    global LOG_LEVEL
10185678948SMichael Walsh    BuiltIn().set_log_level("NONE")
10285678948SMichael Walsh
10385678948SMichael Walsh    BuiltIn().set_global_variable("${master_pid}", master_pid)
10485678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_DIR_PATH}", ffdc_dir_path)
10585678948SMichael Walsh    BuiltIn().set_global_variable("${STATUS_DIR_PATH}", status_dir_path)
10685678948SMichael Walsh    BuiltIn().set_global_variable("${BASE_TOOL_DIR_PATH}", base_tool_dir_path)
10785678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_LIST_FILE_PATH}",
10885678948SMichael Walsh                                  ffdc_list_file_path)
10985678948SMichael Walsh
11085678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_DIR_PATH_STYLE}",
11185678948SMichael Walsh                                  ffdc_dir_path_style)
11285678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_CHECK}",
11385678948SMichael Walsh                                  ffdc_check)
11485678948SMichael Walsh
11585678948SMichael Walsh    # For each program parameter, set the corresponding AUTOBOOT_ environment
11685678948SMichael Walsh    # variable value.  Also, set an AUTOBOOT_ environment variable for every
11785678948SMichael Walsh    # element in additional_values.
11885678948SMichael Walsh    additional_values = ["program_pid", "master_pid", "ffdc_dir_path",
11985678948SMichael Walsh                         "status_dir_path", "base_tool_dir_path",
12085678948SMichael Walsh                         "ffdc_list_file_path"]
12185678948SMichael Walsh
12285678948SMichael Walsh    plug_in_vars = parm_list + additional_values
12385678948SMichael Walsh
12485678948SMichael Walsh    for var_name in plug_in_vars:
12585678948SMichael Walsh        var_value = BuiltIn().get_variable_value("${" + var_name + "}")
12685678948SMichael Walsh        var_name = var_name.upper()
12785678948SMichael Walsh        if var_value is None:
12885678948SMichael Walsh            var_value = ""
12985678948SMichael Walsh        os.environ["AUTOBOOT_" + var_name] = str(var_value)
13085678948SMichael Walsh
13185678948SMichael Walsh    BuiltIn().set_log_level(LOG_LEVEL)
13285678948SMichael Walsh
13385678948SMichael Walsh
13485678948SMichael Walsh###############################################################################
13585678948SMichael Walsh
1360bbd860fSMichael Walsh
1370bbd860fSMichael Walsh###############################################################################
1380bbd860fSMichael Walshdef plug_in_setup():
1390bbd860fSMichael Walsh
1400bbd860fSMichael Walsh    r"""
14185678948SMichael Walsh    Initialize all changing plug-in environment variables for use by the
14285678948SMichael Walsh    plug-in programs.
1430bbd860fSMichael Walsh    """
1440bbd860fSMichael Walsh
14585678948SMichael Walsh    global LOG_LEVEL
14685678948SMichael Walsh    global test_really_running
14785678948SMichael Walsh
14885678948SMichael Walsh    BuiltIn().set_log_level("NONE")
14985678948SMichael Walsh
1506741f740SMichael Walsh    boot_pass, boot_fail = boot_results.return_total_pass_fail()
1510bbd860fSMichael Walsh    if boot_pass > 1:
1520bbd860fSMichael Walsh        test_really_running = 1
1530bbd860fSMichael Walsh    else:
1540bbd860fSMichael Walsh        test_really_running = 0
1550bbd860fSMichael Walsh
1560bbd860fSMichael Walsh    seconds = time.time()
1570bbd860fSMichael Walsh    loc_time = time.localtime(seconds)
1580bbd860fSMichael Walsh    time_string = time.strftime("%y%m%d.%H%M%S.", loc_time)
1590bbd860fSMichael Walsh
1606741f740SMichael Walsh    ffdc_prefix = openbmc_nickname + "." + time_string
1610bbd860fSMichael Walsh
1626741f740SMichael Walsh    BuiltIn().set_global_variable("${test_really_running}",
1636741f740SMichael Walsh                                  test_really_running)
1646741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_type_desc}", next_boot)
1656741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_pass}", boot_pass)
1666741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_fail}", boot_fail)
1676741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_success}", boot_success)
1686741f740SMichael Walsh    BuiltIn().set_global_variable("${ffdc_prefix}", ffdc_prefix)
1694c9a6453SMichael Walsh
1700bbd860fSMichael Walsh    # For each program parameter, set the corresponding AUTOBOOT_ environment
1710bbd860fSMichael Walsh    # variable value.  Also, set an AUTOBOOT_ environment variable for every
1720bbd860fSMichael Walsh    # element in additional_values.
1730bbd860fSMichael Walsh    additional_values = ["boot_type_desc", "boot_success", "boot_pass",
17485678948SMichael Walsh                         "boot_fail", "test_really_running", "ffdc_prefix"]
1750bbd860fSMichael Walsh
17685678948SMichael Walsh    plug_in_vars = additional_values
1770bbd860fSMichael Walsh
1780bbd860fSMichael Walsh    for var_name in plug_in_vars:
1790bbd860fSMichael Walsh        var_value = BuiltIn().get_variable_value("${" + var_name + "}")
1800bbd860fSMichael Walsh        var_name = var_name.upper()
1810bbd860fSMichael Walsh        if var_value is None:
1820bbd860fSMichael Walsh            var_value = ""
1836741f740SMichael Walsh        os.environ["AUTOBOOT_" + var_name] = str(var_value)
1840bbd860fSMichael Walsh
1850bbd860fSMichael Walsh    if debug:
1866741f740SMichael Walsh        shell_rc, out_buf = \
1876741f740SMichael Walsh            gc.cmd_fnc_u("printenv | egrep AUTOBOOT_ | sort -u")
1880bbd860fSMichael Walsh
18985678948SMichael Walsh    BuiltIn().set_log_level(LOG_LEVEL)
19085678948SMichael Walsh
1910bbd860fSMichael Walsh###############################################################################
1920bbd860fSMichael Walsh
1930bbd860fSMichael Walsh
1940bbd860fSMichael Walsh###############################################################################
1956741f740SMichael Walshdef setup():
1960bbd860fSMichael Walsh
1970bbd860fSMichael Walsh    r"""
1986741f740SMichael Walsh    Do general program setup tasks.
1990bbd860fSMichael Walsh    """
2000bbd860fSMichael Walsh
2016741f740SMichael Walsh    global cp_setup_called
2020bbd860fSMichael Walsh
2036741f740SMichael Walsh    grp.rqprintn()
2046741f740SMichael Walsh
2056741f740SMichael Walsh    validate_parms()
2066741f740SMichael Walsh
2076741f740SMichael Walsh    grp.rqprint_pgm_header()
2086741f740SMichael Walsh
20911cfc8c0SMichael Walsh    cmd_buf = ["Set BMC Power Policy", "RESTORE_LAST_STATE"]
21011cfc8c0SMichael Walsh    grp.rpissuing_keyword(cmd_buf, test_mode)
21111cfc8c0SMichael Walsh    if not test_mode:
21211cfc8c0SMichael Walsh        BuiltIn().run_keyword(*cmd_buf)
21311cfc8c0SMichael Walsh
21485678948SMichael Walsh    initial_plug_in_setup()
21585678948SMichael Walsh
2166741f740SMichael Walsh    plug_in_setup()
2176741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
2186741f740SMichael Walsh        call_point='setup')
2196741f740SMichael Walsh    if rc != 0:
2206741f740SMichael Walsh        error_message = "Plug-in setup failed.\n"
2216741f740SMichael Walsh        grp.rprint_error_report(error_message)
2226741f740SMichael Walsh        BuiltIn().fail(error_message)
2236741f740SMichael Walsh    # Setting cp_setup_called lets our Teardown know that it needs to call
2246741f740SMichael Walsh    # the cleanup plug-in call point.
2256741f740SMichael Walsh    cp_setup_called = 1
2266741f740SMichael Walsh
2276741f740SMichael Walsh    # Keyword "FFDC" will fail if TEST_MESSAGE is not set.
2286741f740SMichael Walsh    BuiltIn().set_global_variable("${TEST_MESSAGE}", "${EMPTY}")
22985678948SMichael Walsh    # FFDC_LOG_PATH is used by "FFDC" keyword.
23085678948SMichael Walsh    BuiltIn().set_global_variable("${FFDC_LOG_PATH}", ffdc_dir_path)
2316741f740SMichael Walsh
2326741f740SMichael Walsh    grp.rdprint_var(boot_table, 1)
2336741f740SMichael Walsh    grp.rdprint_var(boot_lists)
2340bbd860fSMichael Walsh
2350bbd860fSMichael Walsh###############################################################################
2360bbd860fSMichael Walsh
2370bbd860fSMichael Walsh
2380bbd860fSMichael Walsh###############################################################################
2396741f740SMichael Walshdef validate_parms():
2400bbd860fSMichael Walsh
2410bbd860fSMichael Walsh    r"""
2426741f740SMichael Walsh    Validate all program parameters.
2430bbd860fSMichael Walsh    """
2440bbd860fSMichael Walsh
2456741f740SMichael Walsh    grp.rqprintn()
2460bbd860fSMichael Walsh
2476741f740SMichael Walsh    grv.rvalid_value("openbmc_host")
2486741f740SMichael Walsh    grv.rvalid_value("openbmc_username")
2496741f740SMichael Walsh    grv.rvalid_value("openbmc_password")
2506741f740SMichael Walsh    if os_host != "":
2516741f740SMichael Walsh        grv.rvalid_value("os_username")
2526741f740SMichael Walsh        grv.rvalid_value("os_password")
2530bbd860fSMichael Walsh
2546741f740SMichael Walsh    if pdu_host != "":
2556741f740SMichael Walsh        grv.rvalid_value("pdu_username")
2566741f740SMichael Walsh        grv.rvalid_value("pdu_password")
2576741f740SMichael Walsh        grv.rvalid_integer("pdu_slot_no")
2586741f740SMichael Walsh    if openbmc_serial_host != "":
2596741f740SMichael Walsh        grv.rvalid_integer("openbmc_serial_port")
2606741f740SMichael Walsh    grv.rvalid_integer("max_num_tests")
2616741f740SMichael Walsh    grv.rvalid_value("openbmc_model")
2626741f740SMichael Walsh    grv.rvalid_integer("boot_pass")
2636741f740SMichael Walsh    grv.rvalid_integer("boot_fail")
2646741f740SMichael Walsh
2656741f740SMichael Walsh    plug_in_packages_list = grpi.rvalidate_plug_ins(plug_in_dir_paths)
2666741f740SMichael Walsh    BuiltIn().set_global_variable("${plug_in_packages_list}",
2676741f740SMichael Walsh                                  plug_in_packages_list)
2686741f740SMichael Walsh
269a20da401SMichael Walsh    if len(boot_list) == 0 and len(boot_stack) == 0 and not ffdc_only:
2706741f740SMichael Walsh        error_message = "You must provide either a value for either the" +\
2716741f740SMichael Walsh            " boot_list or the boot_stack parm.\n"
2726741f740SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
2736741f740SMichael Walsh
2746741f740SMichael Walsh    valid_boot_list(boot_list, valid_boot_types)
2756741f740SMichael Walsh    valid_boot_list(boot_stack, valid_boot_types)
2766741f740SMichael Walsh
27711cfc8c0SMichael Walsh    selected_PDU_boots = list(set(boot_list + boot_stack) &
27811cfc8c0SMichael Walsh                              set(boot_lists['PDU_reboot']))
27911cfc8c0SMichael Walsh
28011cfc8c0SMichael Walsh    if len(selected_PDU_boots) > 0 and pdu_host == "":
28111cfc8c0SMichael Walsh        error_message = "You have selected the following boots which" +\
28211cfc8c0SMichael Walsh                        " require a PDU host but no value for pdu_host:\n"
28311cfc8c0SMichael Walsh        error_message += gp.sprint_var(selected_PDU_boots)
28411cfc8c0SMichael Walsh        error_message += gp.sprint_var(pdu_host, 2)
28511cfc8c0SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
28611cfc8c0SMichael Walsh
2876741f740SMichael Walsh    return
2880bbd860fSMichael Walsh
2890bbd860fSMichael Walsh###############################################################################
2900bbd860fSMichael Walsh
2910bbd860fSMichael Walsh
2920bbd860fSMichael Walsh###############################################################################
2936741f740SMichael Walshdef my_get_state():
2940bbd860fSMichael Walsh
2950bbd860fSMichael Walsh    r"""
2966741f740SMichael Walsh    Get the system state plus a little bit of wrapping.
2970bbd860fSMichael Walsh    """
2980bbd860fSMichael Walsh
2996741f740SMichael Walsh    global state
3006741f740SMichael Walsh
3016741f740SMichael Walsh    req_states = ['epoch_seconds'] + st.default_req_states
3026741f740SMichael Walsh
3036741f740SMichael Walsh    grp.rqprint_timen("Getting system state.")
3046741f740SMichael Walsh    if test_mode:
3056741f740SMichael Walsh        state['epoch_seconds'] = int(time.time())
3066741f740SMichael Walsh    else:
3076741f740SMichael Walsh        state = st.get_state(req_states=req_states, quiet=0)
3086741f740SMichael Walsh    grp.rprint_var(state)
309341c21ebSMichael Walsh
310341c21ebSMichael Walsh###############################################################################
311341c21ebSMichael Walsh
312341c21ebSMichael Walsh
313341c21ebSMichael Walsh###############################################################################
3146741f740SMichael Walshdef select_boot():
315341c21ebSMichael Walsh
316341c21ebSMichael Walsh    r"""
317341c21ebSMichael Walsh    Select a boot test to be run based on our current state and return the
318341c21ebSMichael Walsh    chosen boot type.
319341c21ebSMichael Walsh
320341c21ebSMichael Walsh    Description of arguments:
3216741f740SMichael Walsh    state  The state of the machine.
322341c21ebSMichael Walsh    """
323341c21ebSMichael Walsh
32430dadae2SMichael Walsh    global boot_stack
32530dadae2SMichael Walsh
3266741f740SMichael Walsh    grp.rprint_timen("Selecting a boot test.")
3276741f740SMichael Walsh
3286741f740SMichael Walsh    my_get_state()
3296741f740SMichael Walsh
3306741f740SMichael Walsh    stack_popped = 0
3316741f740SMichael Walsh    if len(boot_stack) > 0:
3326741f740SMichael Walsh        stack_popped = 1
3336741f740SMichael Walsh        grp.rprint_dashes()
3346741f740SMichael Walsh        grp.rprint_var(boot_stack)
3356741f740SMichael Walsh        grp.rprint_dashes()
3366741f740SMichael Walsh        boot_candidate = boot_stack.pop()
3376741f740SMichael Walsh        if st.compare_states(state, boot_table[boot_candidate]['start']):
3386741f740SMichael Walsh            grp.rprint_timen("The machine state is valid for a '" +
3396741f740SMichael Walsh                             boot_candidate + "' boot test.")
3406741f740SMichael Walsh            grp.rprint_dashes()
3416741f740SMichael Walsh            grp.rprint_var(boot_stack)
3426741f740SMichael Walsh            grp.rprint_dashes()
3436741f740SMichael Walsh            return boot_candidate
344341c21ebSMichael Walsh        else:
3456741f740SMichael Walsh            grp.rprint_timen("The machine state is not valid for a '" +
3466741f740SMichael Walsh                             boot_candidate + "' boot test.")
3476741f740SMichael Walsh            boot_stack.append(boot_candidate)
3486741f740SMichael Walsh            popped_boot = boot_candidate
3496741f740SMichael Walsh
3506741f740SMichael Walsh    # Loop through your list selecting a boot_candidates
3516741f740SMichael Walsh    boot_candidates = []
3526741f740SMichael Walsh    for boot_candidate in boot_list:
3536741f740SMichael Walsh        if st.compare_states(state, boot_table[boot_candidate]['start']):
3546741f740SMichael Walsh            if stack_popped:
3556741f740SMichael Walsh                if st.compare_states(boot_table[boot_candidate]['end'],
3566741f740SMichael Walsh                   boot_table[popped_boot]['start']):
3576741f740SMichael Walsh                    boot_candidates.append(boot_candidate)
358341c21ebSMichael Walsh            else:
3596741f740SMichael Walsh                boot_candidates.append(boot_candidate)
3606741f740SMichael Walsh
3616741f740SMichael Walsh    if len(boot_candidates) == 0:
3626741f740SMichael Walsh        grp.rprint_timen("The user's boot list contained no boot tests" +
3636741f740SMichael Walsh                         " which are valid for the current machine state.")
3646741f740SMichael Walsh        boot_candidate = default_power_on
3656741f740SMichael Walsh        if not st.compare_states(state, boot_table[default_power_on]['start']):
3666741f740SMichael Walsh            boot_candidate = default_power_off
3676741f740SMichael Walsh        boot_candidates.append(boot_candidate)
3686741f740SMichael Walsh        grp.rprint_timen("Using default '" + boot_candidate +
3696741f740SMichael Walsh                         "' boot type to transtion to valid state.")
3706741f740SMichael Walsh
3716741f740SMichael Walsh    grp.rdprint_var(boot_candidates)
3726741f740SMichael Walsh
3736741f740SMichael Walsh    # Randomly select a boot from the candidate list.
3746741f740SMichael Walsh    boot = random.choice(boot_candidates)
375341c21ebSMichael Walsh
376341c21ebSMichael Walsh    return boot
3770bbd860fSMichael Walsh
3780bbd860fSMichael Walsh###############################################################################
37955302295SMichael Walsh
38055302295SMichael Walsh
38155302295SMichael Walsh###############################################################################
382341c21ebSMichael Walshdef print_last_boots():
383341c21ebSMichael Walsh
384341c21ebSMichael Walsh    r"""
385341c21ebSMichael Walsh    Print the last ten boots done with their time stamps.
386341c21ebSMichael Walsh    """
387341c21ebSMichael Walsh
388341c21ebSMichael Walsh    # indent 0, 90 chars wide, linefeed, char is "="
389341c21ebSMichael Walsh    grp.rqprint_dashes(0, 90)
390341c21ebSMichael Walsh    grp.rqprintn("Last 10 boots:\n")
391341c21ebSMichael Walsh
392341c21ebSMichael Walsh    for boot_entry in last_ten:
393341c21ebSMichael Walsh        grp.rqprint(boot_entry)
394341c21ebSMichael Walsh    grp.rqprint_dashes(0, 90)
395341c21ebSMichael Walsh
396341c21ebSMichael Walsh###############################################################################
397341c21ebSMichael Walsh
398341c21ebSMichael Walsh
399341c21ebSMichael Walsh###############################################################################
400341c21ebSMichael Walshdef print_defect_report():
401341c21ebSMichael Walsh
402341c21ebSMichael Walsh    r"""
403341c21ebSMichael Walsh    Print a defect report.
404341c21ebSMichael Walsh    """
405341c21ebSMichael Walsh
406341c21ebSMichael Walsh    grp.rqprintn()
407341c21ebSMichael Walsh    # indent=0, width=90, linefeed=1, char="="
408341c21ebSMichael Walsh    grp.rqprint_dashes(0, 90, 1, "=")
409341c21ebSMichael Walsh    grp.rqprintn("Copy this data to the defect:\n")
410341c21ebSMichael Walsh
411341c21ebSMichael Walsh    grp.rqpvars(*parm_list)
412341c21ebSMichael Walsh
413341c21ebSMichael Walsh    grp.rqprintn()
414341c21ebSMichael Walsh
415341c21ebSMichael Walsh    print_last_boots()
416341c21ebSMichael Walsh    grp.rqprintn()
417341c21ebSMichael Walsh    grp.rqpvar(state)
418341c21ebSMichael Walsh
419341c21ebSMichael Walsh    # At some point I'd like to have the 'Call FFDC Methods' return a list
420341c21ebSMichael Walsh    # of files it has collected.  In that case, the following "ls" command
421341c21ebSMichael Walsh    # would no longer be needed.  For now, however, glob shows the files
422341c21ebSMichael Walsh    # named in FFDC_LIST_FILE_PATH so I will refrain from printing those
423341c21ebSMichael Walsh    # out (so we don't see duplicates in the list).
424341c21ebSMichael Walsh
425341c21ebSMichael Walsh    LOG_PREFIX = BuiltIn().get_variable_value("${LOG_PREFIX}")
426341c21ebSMichael Walsh
427341c21ebSMichael Walsh    output = '\n'.join(glob.glob(LOG_PREFIX + '*'))
428341c21ebSMichael Walsh    try:
4296741f740SMichael Walsh        ffdc_list = open(ffdc_list_file_path, 'r')
430341c21ebSMichael Walsh    except IOError:
431341c21ebSMichael Walsh        ffdc_list = ""
432341c21ebSMichael Walsh
433341c21ebSMichael Walsh    grp.rqprintn()
434341c21ebSMichael Walsh    grp.rqprintn("FFDC data files:")
435341c21ebSMichael Walsh    if status_file_path != "":
436341c21ebSMichael Walsh        grp.rqprintn(status_file_path)
437341c21ebSMichael Walsh
438341c21ebSMichael Walsh    grp.rqprintn(output)
439341c21ebSMichael Walsh    # grp.rqprintn(ffdc_list)
440341c21ebSMichael Walsh    grp.rqprintn()
441341c21ebSMichael Walsh
442341c21ebSMichael Walsh    grp.rqprint_dashes(0, 90, 1, "=")
443341c21ebSMichael Walsh
444341c21ebSMichael Walsh###############################################################################
4456741f740SMichael Walsh
4466741f740SMichael Walsh
4476741f740SMichael Walsh###############################################################################
4486741f740SMichael Walshdef my_ffdc():
4496741f740SMichael Walsh
4506741f740SMichael Walsh    r"""
4516741f740SMichael Walsh    Collect FFDC data.
4526741f740SMichael Walsh    """
4536741f740SMichael Walsh
4546741f740SMichael Walsh    global state
4556741f740SMichael Walsh
4566741f740SMichael Walsh    plug_in_setup()
4576741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
4586741f740SMichael Walsh        call_point='ffdc', stop_on_plug_in_failure=1)
4596741f740SMichael Walsh
4606741f740SMichael Walsh    AUTOBOOT_FFDC_PREFIX = os.environ['AUTOBOOT_FFDC_PREFIX']
4616741f740SMichael Walsh
4626741f740SMichael Walsh    cmd_buf = ["FFDC", "ffdc_prefix=" + AUTOBOOT_FFDC_PREFIX]
4636741f740SMichael Walsh    grp.rpissuing_keyword(cmd_buf)
4643328caffSMichael Walsh    try:
465c9116811SMichael Walsh        BuiltIn().run_keyword_and_continue_on_failure(*cmd_buf)
4663328caffSMichael Walsh    except:
4673328caffSMichael Walsh        gp.print_error("Call to ffdc failed.\n")
4686741f740SMichael Walsh
4696741f740SMichael Walsh    my_get_state()
4706741f740SMichael Walsh
4716741f740SMichael Walsh    print_defect_report()
4726741f740SMichael Walsh
4736741f740SMichael Walsh###############################################################################
4746741f740SMichael Walsh
4756741f740SMichael Walsh
4766741f740SMichael Walsh###############################################################################
4776741f740SMichael Walshdef print_test_start_message(boot_keyword):
4786741f740SMichael Walsh
4796741f740SMichael Walsh    r"""
4806741f740SMichael Walsh    Print a message indicating what boot test is about to run.
4816741f740SMichael Walsh
4826741f740SMichael Walsh    Description of arguments:
4836741f740SMichael Walsh    boot_keyword  The name of the boot which is to be run
4846741f740SMichael Walsh                  (e.g. "BMC Power On").
4856741f740SMichael Walsh    """
4866741f740SMichael Walsh
4876741f740SMichael Walsh    global last_ten
4886741f740SMichael Walsh
4896741f740SMichael Walsh    doing_msg = gp.sprint_timen("Doing \"" + boot_keyword + "\".")
4906741f740SMichael Walsh    grp.rqprint(doing_msg)
4916741f740SMichael Walsh
4926741f740SMichael Walsh    last_ten.append(doing_msg)
4936741f740SMichael Walsh
4946741f740SMichael Walsh    if len(last_ten) > 10:
4956741f740SMichael Walsh        del last_ten[0]
4966741f740SMichael Walsh
4976741f740SMichael Walsh###############################################################################
4986741f740SMichael Walsh
4996741f740SMichael Walsh
5006741f740SMichael Walsh###############################################################################
5016741f740SMichael Walshdef run_boot(boot):
5026741f740SMichael Walsh
5036741f740SMichael Walsh    r"""
5046741f740SMichael Walsh    Run the specified boot.
5056741f740SMichael Walsh
5066741f740SMichael Walsh    Description of arguments:
5076741f740SMichael Walsh    boot  The name of the boot test to be performed.
5086741f740SMichael Walsh    """
5096741f740SMichael Walsh
5106741f740SMichael Walsh    global state
5116741f740SMichael Walsh
5126741f740SMichael Walsh    print_test_start_message(boot)
5136741f740SMichael Walsh
5146741f740SMichael Walsh    plug_in_setup()
5156741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = \
5166741f740SMichael Walsh        grpi.rprocess_plug_in_packages(call_point="pre_boot")
5176741f740SMichael Walsh    if rc != 0:
5186741f740SMichael Walsh        error_message = "Plug-in failed with non-zero return code.\n" +\
5196741f740SMichael Walsh            gp.sprint_var(rc, 1)
5206741f740SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
5216741f740SMichael Walsh
5226741f740SMichael Walsh    if test_mode:
5236741f740SMichael Walsh        # In test mode, we'll pretend the boot worked by assigning its
5246741f740SMichael Walsh        # required end state to the default state value.
52530dadae2SMichael Walsh        state = st.strip_anchor_state(boot_table[boot]['end'])
5266741f740SMichael Walsh    else:
5276741f740SMichael Walsh        # Assertion:  We trust that the state data was made fresh by the
5286741f740SMichael Walsh        # caller.
5296741f740SMichael Walsh
5306741f740SMichael Walsh        grp.rprintn()
5316741f740SMichael Walsh
5326741f740SMichael Walsh        if boot_table[boot]['method_type'] == "keyword":
5330b93fbf8SMichael Walsh            rk.my_run_keywords(boot_table[boot].get('lib_file_path', ''),
5340b93fbf8SMichael Walsh                               boot_table[boot]['method'])
5356741f740SMichael Walsh
5366741f740SMichael Walsh        if boot_table[boot]['bmc_reboot']:
5376741f740SMichael Walsh            st.wait_for_comm_cycle(int(state['epoch_seconds']))
53830dadae2SMichael Walsh            plug_in_setup()
53930dadae2SMichael Walsh            rc, shell_rc, failed_plug_in_name = \
54030dadae2SMichael Walsh                grpi.rprocess_plug_in_packages(call_point="post_reboot")
54130dadae2SMichael Walsh            if rc != 0:
5420b93fbf8SMichael Walsh                error_message = "Plug-in failed with non-zero return code.\n"
5430b93fbf8SMichael Walsh                error_message += gp.sprint_var(rc, 1)
54430dadae2SMichael Walsh                BuiltIn().fail(gp.sprint_error(error_message))
5456741f740SMichael Walsh        else:
5466741f740SMichael Walsh            match_state = st.anchor_state(state)
5476741f740SMichael Walsh            del match_state['epoch_seconds']
5486741f740SMichael Walsh            # Wait for the state to change in any way.
5496741f740SMichael Walsh            st.wait_state(match_state, wait_time=state_change_timeout,
5506741f740SMichael Walsh                          interval="3 seconds", invert=1)
5516741f740SMichael Walsh
5526741f740SMichael Walsh        grp.rprintn()
5536741f740SMichael Walsh        if boot_table[boot]['end']['chassis'] == "Off":
5546741f740SMichael Walsh            boot_timeout = power_off_timeout
5556741f740SMichael Walsh        else:
5566741f740SMichael Walsh            boot_timeout = power_on_timeout
5576741f740SMichael Walsh        st.wait_state(boot_table[boot]['end'], wait_time=boot_timeout,
5586741f740SMichael Walsh                      interval="3 seconds")
5596741f740SMichael Walsh
5606741f740SMichael Walsh    plug_in_setup()
5616741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = \
5626741f740SMichael Walsh        grpi.rprocess_plug_in_packages(call_point="post_boot")
5636741f740SMichael Walsh    if rc != 0:
5646741f740SMichael Walsh        error_message = "Plug-in failed with non-zero return code.\n" +\
5656741f740SMichael Walsh            gp.sprint_var(rc, 1)
5666741f740SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
5676741f740SMichael Walsh
5686741f740SMichael Walsh###############################################################################
5696741f740SMichael Walsh
5706741f740SMichael Walsh
5716741f740SMichael Walsh###############################################################################
5726741f740SMichael Walshdef test_loop_body():
5736741f740SMichael Walsh
5746741f740SMichael Walsh    r"""
5756741f740SMichael Walsh    The main loop body for the loop in main_py.
5766741f740SMichael Walsh
5776741f740SMichael Walsh    Description of arguments:
5786741f740SMichael Walsh    boot_count  The iteration number (starts at 1).
5796741f740SMichael Walsh    """
5806741f740SMichael Walsh
5816741f740SMichael Walsh    global boot_count
5826741f740SMichael Walsh    global state
5836741f740SMichael Walsh    global next_boot
5846741f740SMichael Walsh    global boot_success
5856741f740SMichael Walsh
5866741f740SMichael Walsh    grp.rqprintn()
5876741f740SMichael Walsh
5886741f740SMichael Walsh    boot_count += 1
5896741f740SMichael Walsh
5906741f740SMichael Walsh    next_boot = select_boot()
5916741f740SMichael Walsh
5926741f740SMichael Walsh    grp.rqprint_timen("Starting boot " + str(boot_count) + ".")
5936741f740SMichael Walsh
5946741f740SMichael Walsh    # Clear the ffdc_list_file_path file.  Plug-ins may now write to it.
5956741f740SMichael Walsh    try:
5966741f740SMichael Walsh        os.remove(ffdc_list_file_path)
5976741f740SMichael Walsh    except OSError:
5986741f740SMichael Walsh        pass
5996741f740SMichael Walsh
6006741f740SMichael Walsh    cmd_buf = ["run_boot", next_boot]
6016741f740SMichael Walsh    boot_status, msg = BuiltIn().run_keyword_and_ignore_error(*cmd_buf)
6026741f740SMichael Walsh    if boot_status == "FAIL":
6036741f740SMichael Walsh        grp.rprint(msg)
6046741f740SMichael Walsh
6056741f740SMichael Walsh    grp.rqprintn()
6066741f740SMichael Walsh    if boot_status == "PASS":
6076741f740SMichael Walsh        boot_success = 1
6086741f740SMichael Walsh        grp.rqprint_timen("BOOT_SUCCESS: \"" + next_boot + "\" succeeded.")
6096741f740SMichael Walsh    else:
6106741f740SMichael Walsh        boot_success = 0
6116741f740SMichael Walsh        grp.rqprint_timen("BOOT_FAILED: \"" + next_boot + "\" failed.")
6126741f740SMichael Walsh
6136741f740SMichael Walsh    boot_results.update(next_boot, boot_status)
6146741f740SMichael Walsh
6156741f740SMichael Walsh    plug_in_setup()
6166741f740SMichael Walsh    # NOTE: A post_test_case call point failure is NOT counted as a boot
6176741f740SMichael Walsh    # failure.
6186741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
6196741f740SMichael Walsh        call_point='post_test_case', stop_on_plug_in_failure=1)
6206741f740SMichael Walsh
6216741f740SMichael Walsh    plug_in_setup()
6226741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
6236741f740SMichael Walsh        call_point='ffdc_check', shell_rc=0x00000200,
6246741f740SMichael Walsh        stop_on_plug_in_failure=1, stop_on_non_zero_rc=1)
6256741f740SMichael Walsh    if boot_status != "PASS" or ffdc_check == "All" or shell_rc == 0x00000200:
6266741f740SMichael Walsh        cmd_buf = ["my_ffdc"]
6276741f740SMichael Walsh        grp.rpissuing_keyword(cmd_buf)
6283328caffSMichael Walsh        try:
6296741f740SMichael Walsh            BuiltIn().run_keyword_and_continue_on_failure(*cmd_buf)
6303328caffSMichael Walsh        except:
6313328caffSMichael Walsh            gp.print_error("Call to my_ffdc failed.\n")
6326741f740SMichael Walsh
633*d139f286SMichael Walsh    # We need to purge error logs between boots or they build up.
634*d139f286SMichael Walsh    cmd_buf = ["Delete Error logs"]
635*d139f286SMichael Walsh    grp.rpissuing_keyword(cmd_buf, test_mode)
636*d139f286SMichael Walsh    BuiltIn().run_keyword(*cmd_buf)
637*d139f286SMichael Walsh
638952f9b09SMichael Walsh    boot_results.print_report()
639952f9b09SMichael Walsh    grp.rqprint_timen("Finished boot " + str(boot_count) + ".")
640952f9b09SMichael Walsh
6416741f740SMichael Walsh    plug_in_setup()
6426741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
6436741f740SMichael Walsh        call_point='stop_check')
6446741f740SMichael Walsh    if rc != 0:
6456741f740SMichael Walsh        error_message = "Stopping as requested by user.\n"
6466741f740SMichael Walsh        grp.rprint_error_report(error_message)
6476741f740SMichael Walsh        BuiltIn().fail(error_message)
6486741f740SMichael Walsh
649*d139f286SMichael Walsh    # This should help prevent ConnectionErrors.
650*d139f286SMichael Walsh    cmd_buf = ["Delete All Sessions"]
651*d139f286SMichael Walsh    grp.rpissuing_keyword(cmd_buf, test_mode)
652*d139f286SMichael Walsh    BuiltIn().run_keyword(*cmd_buf)
653*d139f286SMichael Walsh
6546741f740SMichael Walsh    return True
6556741f740SMichael Walsh
6566741f740SMichael Walsh###############################################################################
6576741f740SMichael Walsh
6586741f740SMichael Walsh
6596741f740SMichael Walsh###############################################################################
660c9116811SMichael Walshdef main_keyword_teardown():
6616741f740SMichael Walsh
6626741f740SMichael Walsh    r"""
663c9116811SMichael Walsh    Clean up after the Main keyword.
6646741f740SMichael Walsh    """
6656741f740SMichael Walsh
6666741f740SMichael Walsh    if cp_setup_called:
6676741f740SMichael Walsh        plug_in_setup()
6686741f740SMichael Walsh        rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
6696741f740SMichael Walsh            call_point='cleanup', stop_on_plug_in_failure=1)
6706741f740SMichael Walsh
6710b93fbf8SMichael Walsh    # Save boot_results object to a file in case it is needed again.
6720b93fbf8SMichael Walsh    grp.rprint_timen("Saving boot_results to the following path.")
6730b93fbf8SMichael Walsh    grp.rprint_var(boot_results_file_path)
6740b93fbf8SMichael Walsh    pickle.dump(boot_results, open(boot_results_file_path, 'wb'),
6750b93fbf8SMichael Walsh                pickle.HIGHEST_PROTOCOL)
6760b93fbf8SMichael Walsh
6776741f740SMichael Walsh###############################################################################
6786741f740SMichael Walsh
6796741f740SMichael Walsh
6806741f740SMichael Walsh###############################################################################
681c9116811SMichael Walshdef test_teardown():
682c9116811SMichael Walsh
683c9116811SMichael Walsh    r"""
684c9116811SMichael Walsh    Clean up after this test case.
685c9116811SMichael Walsh    """
686c9116811SMichael Walsh
687c9116811SMichael Walsh    gp.qprintn()
688c9116811SMichael Walsh    cmd_buf = ["Print Error",
689c9116811SMichael Walsh               "A keyword timeout occurred ending this program.\n"]
690c9116811SMichael Walsh    BuiltIn().run_keyword_if_timeout_occurred(*cmd_buf)
691c9116811SMichael Walsh
692c9116811SMichael Walsh###############################################################################
693c9116811SMichael Walsh
694c9116811SMichael Walsh
695c9116811SMichael Walsh###############################################################################
6966741f740SMichael Walshdef main_py():
6976741f740SMichael Walsh
6986741f740SMichael Walsh    r"""
6996741f740SMichael Walsh    Do main program processing.
7006741f740SMichael Walsh    """
7016741f740SMichael Walsh
7026741f740SMichael Walsh    setup()
7036741f740SMichael Walsh
704a20da401SMichael Walsh    if ffdc_only:
705a20da401SMichael Walsh        gp.qprint_timen("Caller requested ffdc_only.")
706a20da401SMichael Walsh        cmd_buf = ["my_ffdc"]
707a20da401SMichael Walsh        grp.rpissuing_keyword(cmd_buf)
708a20da401SMichael Walsh        try:
709a20da401SMichael Walsh            BuiltIn().run_keyword_and_continue_on_failure(*cmd_buf)
710a20da401SMichael Walsh        except:
711a20da401SMichael Walsh            gp.print_error("Call to my_ffdc failed.\n")
712a20da401SMichael Walsh
7136741f740SMichael Walsh    # Process caller's boot_stack.
7146741f740SMichael Walsh    while (len(boot_stack) > 0):
7156741f740SMichael Walsh        test_loop_body()
7166741f740SMichael Walsh
71730dadae2SMichael Walsh    grp.rprint_timen("Finished processing stack.")
71830dadae2SMichael Walsh
7196741f740SMichael Walsh    # Process caller's boot_list.
7206741f740SMichael Walsh    if len(boot_list) > 0:
7216741f740SMichael Walsh        for ix in range(1, max_num_tests + 1):
7226741f740SMichael Walsh            test_loop_body()
7236741f740SMichael Walsh
7246741f740SMichael Walsh    grp.rqprint_timen("Completed all requested boot tests.")
7256741f740SMichael Walsh
7266741f740SMichael Walsh###############################################################################
727